diff --git a/.gitattributes b/.gitattributes index c98f97bae4..f9ada1ac16 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,6 +9,9 @@ *.fsproj merge=union *.dbproj merge=union +# Custom for Xcode +*.pbxproj merge=union + # Standard to msysgit *.doc diff=astextplain *.DOC diff=astextplain diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..0f27246e28 --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,21 @@ +**OS:** +**Version:** +**Commit:** + +Explanation of the issue... + +- [ ] Reproducible in RCT2 (vanilla)? +- [ ] Multiplayer? + +**Steps to reproduce:** +1. +2. + +**Dump file** +If you have a dump file, zip it and drag&drop it here. + +**Screenshots / Video:** +Drag / drop screenshots here. Use https://vid.me to upload video. + +**Save game:** +Change the file extension to .txt or package to a .zip so that it can be drag / dropped here... diff --git a/.gitignore b/.gitignore index 20ea9aed3a..1f0786c614 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,14 @@ sdl # Compiled dll openrct2.dll +# Compiled linux executable +openrct2 + # Distribution distribution/windows/*.exe # Build artifacts +artifacts .cache #lib @@ -104,11 +108,14 @@ ipch/ *.opensdf *.sdf *.cachefile +*.VC.opendb +*.VC.db # Visual Studio profiler *.psess *.vsp *.vspx +*.diagsession # Guidance Automation Toolkit *.gpState @@ -198,9 +205,38 @@ Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ +############# +## Xcode +############# + +# Build generated +build/ +DerivedData + +# Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +# Other +*.xccheckout +*.moved-aside +*.xcuserstate + # Mac crap .DS_Store +# We link logo files to .xcassets in Xcode project, so don't sync them +distribution/osx/Assets.xcassets/AppIcon.appiconset/*.png + +# Extra Xcode-specific lib files +libxc ############# ## Python @@ -238,3 +274,10 @@ openrct2.id* openrct2.nam openrct2.til data/g2.dat + +################# +## Linux +################# + +# KDE folder settings +.directory diff --git a/.travis.yml b/.travis.yml index 4a7ae74da1..eb64adf3f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,69 @@ language: c before_install: - - bash install.sh + - if [[ $TRAVIS_OS_NAME == "linux" ]]; then bash scripts/linux/install.sh; fi + - if [[ $TRAVIS_OS_NAME == "osx" ]]; then sudo gem install xcpretty-travis-formatter; fi + +sudo: required +dist: trusty +env: + global: + - OPENRCT2_VERSION="0.0.4.0" + +matrix: + include: + - os: linux + env: + - OPENRCT2_CMAKE_OPTS="-DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX=OpenRCT2" + - OPENRCT2_MAKE_OPTS="-j2" + - secure: "S3u2VCE2Vy8KNXoeh+DhnzjCmgTX0r95uEZrXDU+IKANOOCKn7Dg4OFDZE3LY/i1y2/EUDpnR5yLC38Ks795EUP/sv/OoMl4tjQ20yERjqWh+gcIRrgx7SdVabuAh3t4aBdaLD4Pfnj5avxeCt6rL7yGnj0wdbrbJSBZPsgSnuQ=" + after_success: + - cd build + - make install + - mv OpenRCT2/bin/openrct2 OpenRCT2/ && mv OpenRCT2/share/openrct2 OpenRCT2/data && mv OpenRCT2/share/doc/openrct2 OpenRCT2/doc + - rm -rf OpenRCT2/bin OpenRCT2/share # remove empty dirs + - tar cvzf openrct2-linux.tar.gz OpenRCT2/ + - if [[ "z$OPENRCT2_ORG_TOKEN" != "z" && ("${TRAVIS_BRANCH}" =~ "^(develop|push/)" || "z${TRAVIS_TAG}" != "z") ]] ; then curl -o - -v --form "key=$OPENRCT2_ORG_TOKEN" --form "fileName=OpenRCT2-${OPENRCT2_VERSION}-${TRAVIS_BRANCH}-${TRAVIS_COMMIT:0:7}-linux.tar.gz" --form "version=${OPENRCT2_VERSION}" --form "gitHash=$TRAVIS_COMMIT" --form "gitBranch=$TRAVIS_BRANCH" --form "flavourId=4" --form "file=@openrct2-linux.tar.gz" "https://openrct2.org/altapi/?command=push-build"; fi + - os: linux + env: OPENRCT2_CMAKE_OPTS="-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++" + - os: linux + env: OPENRCT2_CMAKE_OPTS="-DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows + - os: linux + env: TARGET=docker32 + services: + - docker + - os: linux + env: OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON" TARGET=docker32 + services: + - docker + - os: osx + osx_image: xcode7.2 + env: + - secure: "OXn/i72FxW/oh6RGlaN+gHSbkt1ToFe36etaiDOsJQznt6fe9CpFdnE8U1XBHlGokcEjbGNErRU7CFDKYHQuGrPZyHXwgqG2/0emIqFaFt5ti5ypyYKf5qH9x1LLLfdZxDyHkxXdlJ7Etxbp3G7qrV8CGRQiYRNHm1f98AmuufE=" + after_success: + - cd build/Release + - zip -r openrct2-osx.zip OpenRCT2.app + - if [[ "z$OPENRCT2_ORG_TOKEN" != "z" && ("${TRAVIS_BRANCH}" =~ "^(develop|push/)" || "z${TRAVIS_TAG}" != "z") ]] ; then curl -o - -v --form "key=$OPENRCT2_ORG_TOKEN" --form "fileName=OpenRCT2-${OPENRCT2_VERSION}-${TRAVIS_BRANCH}-${TRAVIS_COMMIT:0:7}-osx.zip" --form "version=${OPENRCT2_VERSION}" --form "gitHash=$TRAVIS_COMMIT" --form "gitBranch=$TRAVIS_BRANCH" --form "flavourId=3" --form "file=@openrct2-osx.zip" "https://openrct2.org/altapi/?command=push-build"; fi + # 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 + # - os: linux + # env: OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + # - os: linux + # env: OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++" + # - os: linux + # env: OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=ON -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + # - os: linux + # env: OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=OFF -DDISABLE_HTTP_TWITCH=OFF -DCMAKE_C_COMPILER=gcc-4.8 -DCMAKE_CXX_COMPILER=g++-4.8" + # - os: linux + # env: OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows + # - os: linux + # env: OPENRCT2_CMAKE_OPTS="-DDISABLE_NETWORK=ON -DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows + # - os: linux + # env: OPENRCT2_CMAKE_OPTS="-DDISABLE_HTTP_TWITCH=ON -DCMAKE_TOOLCHAIN_FILE=../CMakeLists_mingw.txt" TARGET=windows script: - - bash build.sh + - if [[ $TRAVIS_OS_NAME == "linux" ]]; then bash scripts/linux/build.sh ; fi + - if [[ $TRAVIS_OS_NAME == "osx" ]]; then set -o pipefail && xcodebuild | xcpretty -f `xcpretty-travis-formatter`; fi notifications: on_failure: change @@ -14,21 +73,3 @@ cache: directories: - .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_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 - -sudo: required -dist: trusty - -services: - - docker diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eba8200d9..c087e91808 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,10 @@ set (ORCT2_RESOURCE_DIR ${CMAKE_INSTALL_PREFIX}/share/${PROJECT}/) project(${PROJECT}) +if (CMAKE_BINARY_DIR STREQUAL CMAKE_SOURCE_DIR) + message(FATAL_ERROR "Building in-source is not supported! Create a build dir and remove ${CMAKE_SOURCE_DIR}/CMakeCache.txt") +endif() + add_definitions(-DORCT2_RESOURCE_DIR="${ORCT2_RESOURCE_DIR}") add_definitions(-DHAVE_CONFIG_H) add_definitions(-DCURL_STATICLIB) @@ -32,13 +36,6 @@ INCLUDE(FindPkgConfig) option(DISABLE_HTTP_TWITCH "Disable HTTP and Twitch support.") if (DISABLE_HTTP_TWITCH) add_definitions(-DDISABLE_HTTP -DDISABLE_TWITCH) -else (DISABLE_HTTP_TWITCH) - PKG_CHECK_MODULES(LIBCURL REQUIRED libcurl) - PKG_CHECK_MODULES(JANSSON REQUIRED jansson) - SET(HTTPLIBS ${LIBCURL_LIBRARIES} ${JANSSON_LIBRARIES}) - if (WIN32) - SET(HTTPLIBS ${HTTPLIBS} ssl crypto winmm.lib ws2_32) - endif (WIN32) endif (DISABLE_HTTP_TWITCH) option(DISABLE_NETWORK "Disable multiplayer functionality. Mainly for testing.") @@ -50,6 +47,69 @@ else (DISABLE_NETWORK) endif (WIN32) endif (DISABLE_NETWORK) +option(STATIC "Create a static build.") + +PKG_CHECK_MODULES(PNG libpng>=1.6) +if (NOT PNG_FOUND) + PKG_CHECK_MODULES(PNG libpng16) +endif (NOT PNG_FOUND) +if (NOT PNG_FOUND) + PKG_CHECK_MODULES(PNG libpng>=1.2) +endif (NOT PNG_FOUND) +if (NOT PNG_FOUND) + PKG_CHECK_MODULES(PNG REQUIRED libpng12) +endif (NOT PNG_FOUND) + +PKG_CHECK_MODULES(ZLIB REQUIRED zlib) +PKG_CHECK_MODULES(JANSSON REQUIRED jansson>=2.7) + +# Handle creating the rct2 text and data files on OS X and Linux +# See details in src/openrct2.c:openrct2_setup_rct2_segment for how the values +# were derived. +if (UNIX) + add_custom_command( + OUTPUT openrct2_text + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_text bs=4096 skip=1 count=1187 + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe + ) + add_custom_command( + OUTPUT openrct2_data + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 skip=1188 count=318 + COMMAND dd if=/dev/zero of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 seek=318 count=2630 conv=notrunc + COMMAND dd if=${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe of=${CMAKE_BINARY_DIR}/openrct2_data bs=4096 skip=1506 seek=2948 count=1 conv=notrunc + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/openrct2.exe + ) + add_custom_target(segfiles DEPENDS openrct2_text openrct2_data) + if (APPLE) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -sectcreate rct2_text __text ${CMAKE_CURRENT_SOURCE_DIR}/build/openrct2_text -sectcreate rct2_data __data ${CMAKE_CURRENT_SOURCE_DIR}/build/openrct2_data -segaddr rct2_data 0x8a4000 -segprot rct2_data rwx rwx -segaddr rct2_text 0x401000 -segprot rct2_text rwx rwx -fno-pie -read_only_relocs suppress") + else (APPLE) + # For Linux we have to use objcopy to wrap regular binaries into a linkable + # format. We use specific section names which are then referenced in a + # bespoke linker script so they can be placed at predefined VMAs. + add_custom_command( + OUTPUT openrct2_text_section.o + COMMAND objcopy --input binary --output elf32-i386 --binary-architecture i386 openrct2_text openrct2_text_section.o --rename-section .data=.rct2_text,contents,alloc,load,readonly,code + DEPENDS segfiles + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + add_custom_command( + OUTPUT openrct2_data_section.o + COMMAND objcopy --input binary --output elf32-i386 --binary-architecture i386 openrct2_data openrct2_data_section.o --rename-section .data=.rct2_data,contents,alloc,load,readonly,data + DEPENDS segfiles + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + add_custom_target(linkable_sections DEPENDS openrct2_text_section.o openrct2_data_section.o) + SET_SOURCE_FILES_PROPERTIES( + openrct2_text_section.o openrct2_data_section.o + PROPERTIES + EXTERNAL_OBJECT true + GENERATED true + ) + # can't use GLOB here, as the files don't exist yet at cmake-time + set(RCT2_SECTIONS "${CMAKE_BINARY_DIR}/openrct2_data_section.o" "${CMAKE_BINARY_DIR}/openrct2_text_section.o") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-T,\"${CMAKE_CURRENT_SOURCE_DIR}/distribution/linux/ld_script.xc\"") + endif (APPLE) +endif (UNIX) set(DEBUG_LEVEL 0 CACHE STRING "Select debug level for compilation. Use value in range 0–3.") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG=${DEBUG_LEVEL}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG=${DEBUG_LEVEL}") @@ -57,49 +117,134 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDEBUG=${DEBUG_LEVEL}") # include lib include_directories("lib/") # add source files -file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "src/*.cpp" "lib/argparse/*.c" "lib/cutest/*.c" "lib/lodepng/*.c") +file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "src/*.cpp" "src/*.h" "src/*.hpp") +if (APPLE) + file(GLOB_RECURSE ORCT2_MM_SOURCES "src/*.m") + set_source_files_properties(${ORCT2_MM_SOURCES} PROPERTIES COMPILE_FLAGS "-x objective-c -fmodules") +endif (APPLE) -if (UNIX) - # 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") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -std=gnu++11 -fno-omit-frame-pointer") - set(CMAKE_SHARED_LINKER_FLAGS "-m32") - set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS}) -endif (UNIX) +# 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 -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}") + +if (MINGW) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fpack-struct=1") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpack-struct=1") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++") +endif () + +if (STATIC) + if (WIN32) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static") + else (WIN32) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") + endif (WIN32) +endif () + +option(WITH_BREAKPAD "Enable breakpad") +if (WITH_BREAKPAD) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_BREAKPAD") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DUSE_BREAKPAD") + set(BREAKPAD_DIR "/home/janisozaur/workspace/breakpad/src") + set(BREAKPAD_INCLUDE_DIR "${BREAKPAD_DIR}/src") + set(BREAKPAD_LIBRARY_DIR "${BREAKPAD_DIR}/src/client/linux") + set(BREAKPAD_LIBS breakpad_client pthread) +endif (WITH_BREAKPAD) # find and include SDL2 PKG_CHECK_MODULES(SDL2 REQUIRED sdl2 SDL2_ttf) +if (STATIC) + # FreeType is required by SDL2_ttf, but not wired up properly in package + PKG_CHECK_MODULES(FREETYPE REQUIRED freetype2) + SET(SDL2LIBS ${SDL2_STATIC_LIBRARIES} ${FREETYPE_STATIC_LIBRARIES}) +else (STATIC) + SET(SDL2LIBS ${SDL2_LIBRARIES}) +endif (STATIC) -# speex v1.1.15 is supplied in our zipped library, but distributions provide -# updated version, with required functions extracted out to libspeexdsp. -# This largely takes care of the problem -if (WIN32) - include_directories("lib/libspeex/") - file(GLOB_RECURSE SPEEX_SOURCES "lib/libspeex/*.c") -else (WIN32) - PKG_CHECK_MODULES(SPEEX REQUIRED speexdsp) -endif (WIN32) +if (STATIC) + SET(REQUIREDLIBS ${PNG_STATIC_LIBRARIES} ${JANSSON_STATIC_LIBRARIES} ${ZLIB_STATIC_LIBRARIES}) +else (STATIC) + SET(REQUIREDLIBS ${PNG_LIBRARIES} ${JANSSON_LIBRARIES} ${ZLIB_LIBRARIES}) +endif (STATIC) + +if (NOT DISABLE_HTTP_TWITCH) + PKG_CHECK_MODULES(LIBCURL REQUIRED libcurl) + if (WIN32) + # Curl depends on openssl and ws2 in mingw builds, but is not wired up in pkg-config + PKG_CHECK_MODULES(SSL REQUIRED openssl) + set(WSLIBS ws2_32) + endif (WIN32) + if (STATIC) + SET(HTTPLIBS ${LIBCURL_STATIC_LIBRARIES} ${SSL_STATIC_LIBRARIES} ${WSLIBS}) + else (STATIC) + SET(HTTPLIBS ${LIBCURL_LIBRARIES} ${SSL_LIBRARIES} ${WSLIBS}) + endif (STATIC) +endif (NOT DISABLE_HTTP_TWITCH) + +PKG_CHECK_MODULES(SPEEX REQUIRED speexdsp) -# Include libdl for dlopen if (UNIX) + # Include libdl for dlopen set(DLLIB dl) endif (UNIX) -INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${LIBCURL_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS} ${SPEEX_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS} ${LIBCURL_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS} ${SPEEX_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ${BREAKPAD_INCLUDE_DIR}) -LINK_DIRECTORIES(${SDL2_LIBRARY_DIRS} ${JANSSON_LIBRARY_DIRS} ${LIBCURL_LIBRARY_DIRS}) +LINK_DIRECTORIES(${SDL2_LIBRARY_DIRS} ${JANSSON_LIBRARY_DIRS} ${LIBCURL_LIBRARY_DIRS} ${PNG_LIBRARY_DIRS} ${ZLIB_LIBRARY_DIRS} ${BREAKPAD_LIBRARY_DIR}) if (WIN32) # build as library for now, replace with add_executable add_library(${PROJECT} SHARED ${ORCT2_SOURCES} ${SPEEX_SOURCES}) else (WIN32) - add_executable(${PROJECT} ${ORCT2_SOURCES}) + add_executable(${PROJECT} ${ORCT2_SOURCES} ${ORCT2_MM_SOURCES} ${RCT2_SECTIONS}) + add_dependencies(${PROJECT} segfiles) + if (NOT APPLE) + add_dependencies(${PROJECT} linkable_sections) + endif () + add_custom_command( + OUTPUT g2.dat + COMMAND ./openrct2 sprite build ${CMAKE_BINARY_DIR}/g2.dat ${CMAKE_CURRENT_SOURCE_DIR}/resources/g2/ + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + add_custom_target(g2 DEPENDS ${PROJECT} g2.dat) endif (WIN32) +if (UNIX AND NOT APPLE) + # FontConfig for TrueType fonts. + PKG_CHECK_MODULES(FONTCONFIG REQUIRED fontconfig) + INCLUDE_DIRECTORIES(${FONTCONFIG_INCLUDE_DIRS}) + TARGET_LINK_LIBRARIES(${PROJECT} ${FONTCONFIG_LIBRARIES}) +endif (UNIX AND NOT APPLE) + + # install into ${CMAKE_INSTALL_PREFIX}/bin/ #install (TARGETS ${PROJECT} DESTINATION bin) # libopenrct2.dll -> openrct2.dll set_target_properties(${PROJECT} PROPERTIES PREFIX "") -TARGET_LINK_LIBRARIES(${PROJECT} ${SDL2_LIBRARIES} ${ORCTLIBS_LIB} ${JANSSON_LIBRARIES} ${HTTPLIBS} ${NETWORKLIBS} ${SPEEX_LIBRARIES} ${DLLIB}) +TARGET_LINK_LIBRARIES(${PROJECT} ${SDL2LIBS} ${HTTPLIBS} ${NETWORKLIBS} ${SPEEX_LIBRARIES} ${DLLIB} ${REQUIREDLIBS} ${BREAKPAD_LIBS}) + +if (APPLE OR STATIC) + FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c) + TARGET_LINK_LIBRARIES(${PROJECT} ${ICONV_LIBRARIES}) +endif (APPLE OR STATIC) + +# Don't recurse, grab all *.txt and *.md files +file(GLOB DOC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/distribution/*.txt") +list(APPEND DOC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/contributors.md" "${CMAKE_CURRENT_SOURCE_DIR}/licence.txt") + +# CMake does not allow specifying a dependency chain which includes built-in +# targets, like `install`, so we have to trick it and execute dependency ourselves. +install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" --build \"${CMAKE_CURRENT_BINARY_DIR}\" --target g2)") +install(TARGETS ${PROJECT} RUNTIME DESTINATION bin) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/g2.dat" DESTINATION share/${PROJECT}) +install(DIRECTORY data/ DESTINATION share/${PROJECT}) +install(FILES ${DOC_FILES} DESTINATION share/doc/${PROJECT}) + +set(CPACK_PACKAGE_VERSION_MAJOR 0) +set(CPACK_PACKAGE_VERSION_MINOR 0) +set(CPACK_PACKAGE_VERSION_PATCH 4) +INCLUDE(CPack) diff --git a/CMakeLists_mingw.txt b/CMakeLists_mingw.txt index d4817994d1..f633585f43 100644 --- a/CMakeLists_mingw.txt +++ b/CMakeLists_mingw.txt @@ -1,4 +1,3 @@ -SET(ACTUAL_SYSTEM ${CMAKE_SYSTEM_NAME}) SET(CMAKE_SYSTEM_NAME Windows) SET(COMPILER_PREFIX i686-w64-mingw32) @@ -8,17 +7,6 @@ SET(CMAKE_RC_COMPILER ${COMPILER_PREFIX}-windres) SET(CMAKE_PKGCONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config) SET(PKG_CONFIG_EXECUTABLE ${COMPILER_PREFIX}-pkg-config) -# potential flags to make code more similar to MSVC: -# -fshort-wchar -fshort-enums -mms-bitfields -# -set(CMAKE_C_FLAGS "-std=gnu99 -fpack-struct=1" CACHE STRING "" FORCE) -set(CMAKE_CXX_FLAGS "-std=c++0x -std=gnu++0x -fpack-struct=1" CACHE STRING "" FORCE) -if(${ACTUAL_SYSTEM} MATCHES "Linux") - set(CMAKE_SHARED_LINKER_FLAGS "-O3 -static-libgcc -static-libstdc++ -static -lpthread" CACHE STRING "" FORCE) -else() - set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++" CACHE STRING "" FORCE) -endif(${ACTUAL_SYSTEM} MATCHES "Linux") - if(APPLE) SET(TARGET_ENVIRONMENT /usr/local/mingw-w32-bin_i686-darwin/i686-w64-mingw32) else() diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj new file mode 100644 index 0000000000..fa60aa53af --- /dev/null +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -0,0 +1,1717 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 426da7e58564472ba1b7991f /* crash.cpp in Sources */ = {isa = PBXBuildFile; fileRef = a9793fe06a4244938f5d4b61 /* crash.cpp */; }; + 001085F01C90FD030075A2AD /* textinputbuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 001085EE1C90FD030075A2AD /* textinputbuffer.c */; }; + C62A08D51C787C2A00F3AA76 /* drawing_fast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C62A08D41C787C2A00F3AA76 /* drawing_fast.cpp */; }; + D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73EE1C2101890080A7B9 /* libcurl.tbd */; }; + D41B73F11C21018C0080A7B9 /* libssl.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B73F01C21018C0080A7B9 /* libssl.tbd */; }; + D41B741D1C210A7A0080A7B9 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D41B741C1C210A7A0080A7B9 /* libiconv.tbd */; }; + 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 */; }; + D47304D51C4FF8250015C0EA /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D47304D41C4FF8250015C0EA /* libz.tbd */; }; + D4A3511E1C6067C400CBCBA4 /* Json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4A3511C1C6067C400CBCBA4 /* Json.cpp */; }; + D4A351211C60680300CBCBA4 /* Theme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4A351201C60680300CBCBA4 /* Theme.cpp */; }; + D4ABAB061C2F812B0080CAD9 /* news_options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4ABAB051C2F812B0080CAD9 /* news_options.c */; }; + D4B63B8F1C43025600367A37 /* CommandLine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B8A1C43025600367A37 /* CommandLine.cpp */; }; + D4B63B901C43025600367A37 /* RootCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B8C1C43025600367A37 /* RootCommands.cpp */; }; + D4B63B911C43025600367A37 /* ScreenshotCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B8D1C43025600367A37 /* ScreenshotCommands.cpp */; }; + D4B63B921C43025600367A37 /* SpriteCommands.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B8E1C43025600367A37 /* SpriteCommands.cpp */; }; + D4B63B951C43028200367A37 /* Console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B931C43028200367A37 /* Console.cpp */; }; + D4B63B981C43028F00367A37 /* String.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4B63B961C43028F00367A37 /* String.cpp */; }; + D4B85B5B1C41C7F3005C568A /* cable_lift.c in Sources */ = {isa = PBXBuildFile; fileRef = D4B85B591C41C7F3005C568A /* cable_lift.c */; }; + D4C0EDCF1C52EA5000A03A06 /* multiplayer.c in Sources */ = {isa = PBXBuildFile; fileRef = D4C0EDCE1C52EA5000A03A06 /* multiplayer.c */; }; + D4C0EDD11C52EA6400A03A06 /* player.c in Sources */ = {isa = PBXBuildFile; fileRef = D4C0EDD01C52EA6400A03A06 /* player.c */; }; + D4D35E2C1C45BD9B00AAFCB4 /* Path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4D35E2A1C45BD9B00AAFCB4 /* Path.cpp */; }; + D4D4DF141C34697B0048BE43 /* image_io.c in Sources */ = {isa = PBXBuildFile; fileRef = D4D4DF121C34697B0048BE43 /* image_io.c */; }; + D4EC47DF1C26342F0024B507 /* addresses.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46D61C26342F0024B507 /* addresses.c */; }; + D4EC47E01C26342F0024B507 /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46D91C26342F0024B507 /* audio.c */; }; + D4EC47E11C26342F0024B507 /* mixer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46DB1C26342F0024B507 /* mixer.cpp */; }; + D4EC47E21C26342F0024B507 /* cheats.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46DD1C26342F0024B507 /* cheats.c */; }; + D4EC47E31C26342F0024B507 /* cmdline_sprite.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46DF1C26342F0024B507 /* cmdline_sprite.c */; }; + D4EC47E51C26342F0024B507 /* config.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46E31C26342F0024B507 /* config.c */; }; + D4EC47E61C26342F0024B507 /* cursors.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46EF1C26342F0024B507 /* cursors.c */; }; + D4EC47E71C26342F0024B507 /* diagnostic.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46F11C26342F0024B507 /* diagnostic.c */; }; + D4EC47E81C26342F0024B507 /* drawing.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46F41C26342F0024B507 /* drawing.c */; }; + D4EC47E91C26342F0024B507 /* font.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46F61C26342F0024B507 /* font.c */; }; + D4EC47EA1C26342F0024B507 /* line.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46F81C26342F0024B507 /* line.c */; }; + D4EC47EB1C26342F0024B507 /* rain.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46F91C26342F0024B507 /* rain.c */; }; + D4EC47EC1C26342F0024B507 /* rect.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46FA1C26342F0024B507 /* rect.c */; }; + D4EC47ED1C26342F0024B507 /* scrolling_text.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46FB1C26342F0024B507 /* scrolling_text.c */; }; + D4EC47EE1C26342F0024B507 /* sprite.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46FC1C26342F0024B507 /* sprite.c */; }; + D4EC47EF1C26342F0024B507 /* string.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46FD1C26342F0024B507 /* string.c */; }; + D4EC47F01C26342F0024B507 /* supports.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC46FE1C26342F0024B507 /* supports.c */; }; + D4EC47F11C26342F0024B507 /* editor.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47001C26342F0024B507 /* editor.c */; }; + D4EC47F21C26342F0024B507 /* game.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47021C26342F0024B507 /* game.c */; }; + D4EC47F31C26342F0024B507 /* hook.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47041C26342F0024B507 /* hook.c */; }; + D4EC47F41C26342F0024B507 /* input.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47061C26342F0024B507 /* input.c */; }; + D4EC47F51C26342F0024B507 /* chat.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47091C26342F0024B507 /* chat.c */; }; + D4EC47F61C26342F0024B507 /* colour.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC470B1C26342F0024B507 /* colour.c */; }; + D4EC47F71C26342F0024B507 /* console.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC470D1C26342F0024B507 /* console.c */; }; + D4EC47F81C26342F0024B507 /* graph.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC470F1C26342F0024B507 /* graph.c */; }; + D4EC47F91C26342F0024B507 /* keyboard_shortcut.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47111C26342F0024B507 /* keyboard_shortcut.c */; }; + D4EC47FA1C26342F0024B507 /* screenshot.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47131C26342F0024B507 /* screenshot.c */; }; + D4EC47FC1C26342F0024B507 /* title_sequences.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47171C26342F0024B507 /* title_sequences.c */; }; + D4EC47FD1C26342F0024B507 /* viewport.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47191C26342F0024B507 /* viewport.c */; }; + D4EC47FE1C26342F0024B507 /* viewport_interaction.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC471B1C26342F0024B507 /* viewport_interaction.c */; }; + D4EC47FF1C26342F0024B507 /* widget.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC471C1C26342F0024B507 /* widget.c */; }; + D4EC48001C26342F0024B507 /* window.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC471E1C26342F0024B507 /* window.c */; }; + D4EC48011C26342F0024B507 /* intro.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47201C26342F0024B507 /* intro.c */; }; + D4EC48021C26342F0024B507 /* convert.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47231C26342F0024B507 /* convert.c */; }; + D4EC48031C26342F0024B507 /* currency.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47241C26342F0024B507 /* currency.c */; }; + D4EC48041C26342F0024B507 /* date.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47261C26342F0024B507 /* date.c */; }; + D4EC48051C26342F0024B507 /* language.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47291C26342F0024B507 /* language.cpp */; }; + D4EC48061C26342F0024B507 /* LanguagePack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4EC472B1C26342F0024B507 /* LanguagePack.cpp */; }; + D4EC48071C26342F0024B507 /* localisation.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC472D1C26342F0024B507 /* localisation.c */; }; + D4EC48081C26342F0024B507 /* real_names.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC472F1C26342F0024B507 /* real_names.c */; }; + D4EC48091C26342F0024B507 /* user.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47311C26342F0024B507 /* user.c */; }; + D4EC480A1C26342F0024B507 /* utf8.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47331C26342F0024B507 /* utf8.c */; }; + D4EC480B1C26342F0024B507 /* award.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47351C26342F0024B507 /* award.c */; }; + D4EC480C1C26342F0024B507 /* finance.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47371C26342F0024B507 /* finance.c */; }; + D4EC480D1C26342F0024B507 /* marketing.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47391C26342F0024B507 /* marketing.c */; }; + D4EC480E1C26342F0024B507 /* news_item.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC473B1C26342F0024B507 /* news_item.c */; }; + D4EC480F1C26342F0024B507 /* research.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC473D1C26342F0024B507 /* research.c */; }; + D4EC48101C26342F0024B507 /* http.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47401C26342F0024B507 /* http.cpp */; }; + D4EC48111C26342F0024B507 /* network.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47421C26342F0024B507 /* network.cpp */; }; + D4EC48121C26342F0024B507 /* twitch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47441C26342F0024B507 /* twitch.cpp */; }; + D4EC48131C26342F0024B507 /* object_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47461C26342F0024B507 /* object_list.c */; }; + D4EC48141C26342F0024B507 /* object.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47471C26342F0024B507 /* object.c */; }; + D4EC48151C26342F0024B507 /* openrct2.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47491C26342F0024B507 /* openrct2.c */; }; + D4EC48161C26342F0024B507 /* peep.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC474C1C26342F0024B507 /* peep.c */; }; + D4EC48171C26342F0024B507 /* staff.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC474E1C26342F0024B507 /* staff.c */; }; + D4EC48181C26342F0024B507 /* linux.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47511C26342F0024B507 /* linux.c */; }; + D4EC48191C26342F0024B507 /* osx.m in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47521C26342F0024B507 /* osx.m */; }; + D4EC481A1C26342F0024B507 /* posix.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47541C26342F0024B507 /* posix.c */; }; + D4EC481B1C26342F0024B507 /* shared.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47551C26342F0024B507 /* shared.c */; }; + D4EC481C1C26342F0024B507 /* windows.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47561C26342F0024B507 /* windows.c */; }; + D4EC481D1C26342F0024B507 /* rct1.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47571C26342F0024B507 /* rct1.c */; }; + D4EC481E1C26342F0024B507 /* rct2.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47591C26342F0024B507 /* rct2.c */; }; + D4EC48201C26342F0024B507 /* ride.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC475D1C26342F0024B507 /* ride.c */; }; + D4EC48211C26342F0024B507 /* ride_data.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC475F1C26342F0024B507 /* ride_data.c */; }; + D4EC48221C26342F0024B507 /* ride_ratings.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47611C26342F0024B507 /* ride_ratings.c */; }; + D4EC48231C26342F0024B507 /* station.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47631C26342F0024B507 /* station.c */; }; + D4EC48241C26342F0024B507 /* track.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47651C26342F0024B507 /* track.c */; }; + D4EC48251C26342F0024B507 /* track_data.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47671C26342F0024B507 /* track_data.c */; }; + D4EC48261C26342F0024B507 /* track_paint.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47691C26342F0024B507 /* track_paint.c */; }; + D4EC48271C26342F0024B507 /* vehicle.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC476B1C26342F0024B507 /* vehicle.c */; }; + 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 */; }; + 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 */; }; + D4EC482F1C26342F0024B507 /* banner.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC477C1C26342F0024B507 /* banner.c */; }; + D4EC48301C26342F0024B507 /* changelog.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC477D1C26342F0024B507 /* changelog.c */; }; + D4EC48311C26342F0024B507 /* cheats.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC477E1C26342F0024B507 /* cheats.c */; }; + D4EC48321C26342F0024B507 /* clear_scenery.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC477F1C26342F0024B507 /* clear_scenery.c */; }; + D4EC48331C26342F0024B507 /* demolish_ride_prompt.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47801C26342F0024B507 /* demolish_ride_prompt.c */; }; + D4EC48341C26342F0024B507 /* dropdown.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47811C26342F0024B507 /* dropdown.c */; }; + D4EC48351C26342F0024B507 /* editor_bottom_toolbar.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47831C26342F0024B507 /* editor_bottom_toolbar.c */; }; + D4EC48361C26342F0024B507 /* editor_inventions_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47841C26342F0024B507 /* editor_inventions_list.c */; }; + D4EC48371C26342F0024B507 /* editor_main.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47851C26342F0024B507 /* editor_main.c */; }; + D4EC48381C26342F0024B507 /* editor_object_selection.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47861C26342F0024B507 /* editor_object_selection.c */; }; + D4EC48391C26342F0024B507 /* editor_objective_options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47871C26342F0024B507 /* editor_objective_options.c */; }; + D4EC483A1C26342F0024B507 /* editor_scenario_options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47881C26342F0024B507 /* editor_scenario_options.c */; }; + D4EC483B1C26342F0024B507 /* error.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47891C26342F0024B507 /* error.c */; }; + D4EC483C1C26342F0024B507 /* finances.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC478B1C26342F0024B507 /* finances.c */; }; + D4EC483D1C26342F0024B507 /* footpath.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC478C1C26342F0024B507 /* footpath.c */; }; + D4EC483E1C26342F0024B507 /* game_bottom_toolbar.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC478D1C26342F0024B507 /* game_bottom_toolbar.c */; }; + D4EC483F1C26342F0024B507 /* guest.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC478E1C26342F0024B507 /* guest.c */; }; + D4EC48401C26342F0024B507 /* guest_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC478F1C26342F0024B507 /* guest_list.c */; }; + D4EC48411C26342F0024B507 /* install_track.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47901C26342F0024B507 /* install_track.c */; }; + D4EC48421C26342F0024B507 /* land.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47911C26342F0024B507 /* land.c */; }; + D4EC48431C26342F0024B507 /* land_rights.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47921C26342F0024B507 /* land_rights.c */; }; + D4EC48441C26342F0024B507 /* loadsave.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47931C26342F0024B507 /* loadsave.c */; }; + D4EC48451C26342F0024B507 /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47941C26342F0024B507 /* main.c */; }; + D4EC48461C26342F0024B507 /* map.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47951C26342F0024B507 /* map.c */; }; + D4EC48471C26342F0024B507 /* map_tooltip.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47961C26342F0024B507 /* map_tooltip.c */; }; + D4EC48481C26342F0024B507 /* mapgen.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47971C26342F0024B507 /* mapgen.c */; }; + D4EC48491C26342F0024B507 /* maze_construction.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47981C26342F0024B507 /* maze_construction.c */; }; + D4EC484A1C26342F0024B507 /* music_credits.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47991C26342F0024B507 /* music_credits.c */; }; + D4EC484B1C26342F0024B507 /* network_status.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC479A1C26342F0024B507 /* network_status.c */; }; + D4EC484C1C26342F0024B507 /* new_campaign.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC479B1C26342F0024B507 /* new_campaign.c */; }; + D4EC484D1C26342F0024B507 /* new_ride.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC479C1C26342F0024B507 /* new_ride.c */; }; + D4EC484E1C26342F0024B507 /* news.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC479D1C26342F0024B507 /* news.c */; }; + D4EC484F1C26342F0024B507 /* options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC479E1C26342F0024B507 /* options.c */; }; + D4EC48501C26342F0024B507 /* park.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC479F1C26342F0024B507 /* park.c */; }; + D4EC48521C26342F0024B507 /* publisher_credits.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A11C26342F0024B507 /* publisher_credits.c */; }; + D4EC48531C26342F0024B507 /* research.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A21C26342F0024B507 /* research.c */; }; + D4EC48541C26342F0024B507 /* ride.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A31C26342F0024B507 /* ride.c */; }; + D4EC48551C26342F0024B507 /* ride_construction.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A41C26342F0024B507 /* ride_construction.c */; }; + D4EC48561C26342F0024B507 /* ride_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A51C26342F0024B507 /* ride_list.c */; }; + D4EC48571C26342F0024B507 /* save_prompt.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A61C26342F0024B507 /* save_prompt.c */; }; + D4EC48581C26342F0024B507 /* scenery.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A71C26342F0024B507 /* scenery.c */; }; + D4EC48591C26342F0024B507 /* server_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A81C26342F0024B507 /* server_list.c */; }; + D4EC485A1C26342F0024B507 /* server_start.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47A91C26342F0024B507 /* server_start.c */; }; + D4EC485B1C26342F0024B507 /* shortcut_key_change.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47AA1C26342F0024B507 /* shortcut_key_change.c */; }; + D4EC485C1C26342F0024B507 /* shortcut_keys.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47AB1C26342F0024B507 /* shortcut_keys.c */; }; + D4EC485D1C26342F0024B507 /* sign.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47AC1C26342F0024B507 /* sign.c */; }; + D4EC485E1C26342F0024B507 /* staff.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47AD1C26342F0024B507 /* staff.c */; }; + D4EC485F1C26342F0024B507 /* staff_fire_prompt.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47AE1C26342F0024B507 /* staff_fire_prompt.c */; }; + D4EC48601C26342F0024B507 /* staff_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47AF1C26342F0024B507 /* staff_list.c */; }; + D4EC48611C26342F0024B507 /* text_input.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B01C26342F0024B507 /* text_input.c */; }; + D4EC48621C26342F0024B507 /* themes.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B11C26342F0024B507 /* themes.c */; }; + D4EC48631C26342F0024B507 /* tile_inspector.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B21C26342F0024B507 /* tile_inspector.c */; }; + D4EC48641C26342F0024B507 /* title_command_editor.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B31C26342F0024B507 /* title_command_editor.c */; }; + D4EC48651C26342F0024B507 /* title_editor.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B41C26342F0024B507 /* title_editor.c */; }; + D4EC48661C26342F0024B507 /* title_exit.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B51C26342F0024B507 /* title_exit.c */; }; + D4EC48671C26342F0024B507 /* title_logo.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B61C26342F0024B507 /* title_logo.c */; }; + D4EC48681C26342F0024B507 /* title_menu.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B71C26342F0024B507 /* title_menu.c */; }; + D4EC48691C26342F0024B507 /* title_options.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B81C26342F0024B507 /* title_options.c */; }; + D4EC486A1C26342F0024B507 /* title_scenarioselect.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47B91C26342F0024B507 /* title_scenarioselect.c */; }; + D4EC486B1C26342F0024B507 /* tooltip.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47BA1C26342F0024B507 /* tooltip.c */; }; + D4EC486C1C26342F0024B507 /* top_toolbar.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47BC1C26342F0024B507 /* top_toolbar.c */; }; + D4EC486D1C26342F0024B507 /* track_list.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47BD1C26342F0024B507 /* track_list.c */; }; + D4EC486E1C26342F0024B507 /* track_manage.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47BE1C26342F0024B507 /* track_manage.c */; }; + D4EC486F1C26342F0024B507 /* track_place.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47BF1C26342F0024B507 /* track_place.c */; }; + D4EC48701C26342F0024B507 /* viewport.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47C01C26342F0024B507 /* viewport.c */; }; + D4EC48711C26342F0024B507 /* water.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47C11C26342F0024B507 /* water.c */; }; + D4EC48721C26342F0024B507 /* balloon.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47C31C26342F0024B507 /* balloon.c */; }; + D4EC48731C26342F0024B507 /* banner.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47C41C26342F0024B507 /* banner.c */; }; + D4EC48741C26342F0024B507 /* climate.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47C61C26342F0024B507 /* climate.c */; }; + D4EC48751C26342F0024B507 /* duck.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47C81C26342F0024B507 /* duck.c */; }; + D4EC48761C26342F0024B507 /* footpath.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47CA1C26342F0024B507 /* footpath.c */; }; + D4EC48771C26342F0024B507 /* fountain.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47CC1C26342F0024B507 /* fountain.c */; }; + D4EC48781C26342F0024B507 /* map.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47CE1C26342F0024B507 /* map.c */; }; + D4EC48791C26342F0024B507 /* map_animation.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47D01C26342F0024B507 /* map_animation.c */; }; + D4EC487A1C26342F0024B507 /* map_helpers.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47D21C26342F0024B507 /* map_helpers.c */; }; + D4EC487B1C26342F0024B507 /* mapgen.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47D41C26342F0024B507 /* mapgen.c */; }; + D4EC487C1C26342F0024B507 /* money_effect.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47D61C26342F0024B507 /* money_effect.c */; }; + D4EC487D1C26342F0024B507 /* park.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47D71C26342F0024B507 /* park.c */; }; + D4EC487E1C26342F0024B507 /* particle.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47D91C26342F0024B507 /* particle.c */; }; + D4EC487F1C26342F0024B507 /* scenery.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47DA1C26342F0024B507 /* scenery.c */; }; + D4EC48801C26342F0024B507 /* sprite.c in Sources */ = {isa = PBXBuildFile; fileRef = D4EC47DC1C26342F0024B507 /* sprite.c */; }; + D4EC48CA1C2634870024B507 /* libjansson.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C51C2634870024B507 /* libjansson.dylib */; }; + D4EC48CB1C2634870024B507 /* libSDL2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C61C2634870024B507 /* libSDL2.dylib */; }; + D4EC48CC1C2634870024B507 /* libSDL2_ttf.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C71C2634870024B507 /* libSDL2_ttf.dylib */; }; + D4EC48CD1C2634870024B507 /* libspeexdsp.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C81C2634870024B507 /* libspeexdsp.dylib */; }; + D4EC48D01C2634C70024B507 /* libfreetype.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C41C2634870024B507 /* libfreetype.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + D4EC48D11C2634C70024B507 /* libjansson.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C51C2634870024B507 /* libjansson.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + D4EC48D21C2634C70024B507 /* libSDL2.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C61C2634870024B507 /* libSDL2.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + D4EC48D31C2634C70024B507 /* libSDL2_ttf.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C71C2634870024B507 /* libSDL2_ttf.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + D4EC48D41C2634C70024B507 /* libspeexdsp.dylib in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D4EC48C81C2634870024B507 /* libspeexdsp.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + D4EC48E61C2637710024B507 /* g2.dat in Resources */ = {isa = PBXBuildFile; fileRef = D4EC48E31C2637710024B507 /* g2.dat */; }; + D4EC48E71C2637710024B507 /* language in Resources */ = {isa = PBXBuildFile; fileRef = D4EC48E41C2637710024B507 /* language */; }; + D4EC48E81C2637710024B507 /* title in Resources */ = {isa = PBXBuildFile; fileRef = D4EC48E51C2637710024B507 /* title */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + D41B74201C210B190080A7B9 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D43532601C34730200BA219B /* libpng.dylib in Embed Frameworks */, + D4EC48D01C2634C70024B507 /* libfreetype.dylib in Embed Frameworks */, + D4EC48D11C2634C70024B507 /* libjansson.dylib in Embed Frameworks */, + D4EC48D21C2634C70024B507 /* libSDL2.dylib in Embed Frameworks */, + D4EC48D31C2634C70024B507 /* libSDL2_ttf.dylib in Embed Frameworks */, + D4EC48D41C2634C70024B507 /* libspeexdsp.dylib in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + a9793fe06a4244938f5d4b61 /* crash.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = crash.cpp; path = src/platform/crash.cpp; sourceTree = ""; }; + 001085EE1C90FD030075A2AD /* textinputbuffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = textinputbuffer.c; sourceTree = ""; }; + 001085EF1C90FD030075A2AD /* textinputbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = textinputbuffer.h; sourceTree = ""; }; + C62A08D41C787C2A00F3AA76 /* drawing_fast.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drawing_fast.cpp; sourceTree = ""; }; + D4163F671C2A044D00B83136 /* version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = version.h; path = src/version.h; sourceTree = ""; }; + D41B73EE1C2101890080A7B9 /* libcurl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libcurl.tbd; path = usr/lib/libcurl.tbd; sourceTree = SDKROOT; }; + D41B73F01C21018C0080A7B9 /* libssl.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libssl.tbd; path = usr/lib/libssl.tbd; sourceTree = SDKROOT; }; + 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 = ""; }; + D46105CD1C38828D00DB1EE3 /* scenario_sources.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scenario_sources.c; path = src/scenario_sources.c; sourceTree = ""; }; + D47304D41C4FF8250015C0EA /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 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; }; + D4A3511A1C6067B000CBCBA4 /* Diagnostics.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Diagnostics.hpp; sourceTree = ""; }; + D4A3511B1C6067B900CBCBA4 /* Guard.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = Guard.hpp; sourceTree = ""; }; + D4A3511C1C6067C400CBCBA4 /* Json.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Json.cpp; sourceTree = ""; }; + D4A3511D1C6067C400CBCBA4 /* Json.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Json.hpp; sourceTree = ""; }; + D4A3511F1C6067E500CBCBA4 /* List.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = List.hpp; sourceTree = ""; }; + D4A351201C60680300CBCBA4 /* Theme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Theme.cpp; sourceTree = ""; }; + D4ABAB051C2F812B0080CAD9 /* news_options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = news_options.c; sourceTree = ""; }; + D4B63B8A1C43025600367A37 /* CommandLine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CommandLine.cpp; sourceTree = ""; }; + D4B63B8B1C43025600367A37 /* CommandLine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CommandLine.hpp; sourceTree = ""; }; + D4B63B8C1C43025600367A37 /* RootCommands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RootCommands.cpp; sourceTree = ""; }; + D4B63B8D1C43025600367A37 /* ScreenshotCommands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScreenshotCommands.cpp; sourceTree = ""; }; + D4B63B8E1C43025600367A37 /* SpriteCommands.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SpriteCommands.cpp; sourceTree = ""; }; + D4B63B931C43028200367A37 /* Console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Console.cpp; sourceTree = ""; }; + D4B63B941C43028200367A37 /* Console.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Console.hpp; sourceTree = ""; }; + D4B63B961C43028F00367A37 /* String.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = String.cpp; sourceTree = ""; }; + D4B63B971C43028F00367A37 /* String.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = String.hpp; sourceTree = ""; }; + D4B85B591C41C7F3005C568A /* cable_lift.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cable_lift.c; sourceTree = ""; }; + D4B85B5A1C41C7F3005C568A /* cable_lift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cable_lift.h; sourceTree = ""; }; + D4C0EDCE1C52EA5000A03A06 /* multiplayer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = multiplayer.c; sourceTree = ""; }; + D4C0EDD01C52EA6400A03A06 /* player.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = player.c; sourceTree = ""; }; + D4D35E2A1C45BD9B00AAFCB4 /* Path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Path.cpp; sourceTree = ""; }; + D4D35E2B1C45BD9B00AAFCB4 /* Path.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Path.hpp; sourceTree = ""; }; + D4D4DF121C34697B0048BE43 /* image_io.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = image_io.c; path = src/image_io.c; sourceTree = ""; }; + D4D4DF131C34697B0048BE43 /* image_io.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = image_io.h; path = src/image_io.h; sourceTree = ""; }; + D4EC46D61C26342F0024B507 /* addresses.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = addresses.c; path = src/addresses.c; sourceTree = ""; }; + D4EC46D71C26342F0024B507 /* addresses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = addresses.h; path = src/addresses.h; sourceTree = ""; }; + D4EC46D91C26342F0024B507 /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audio.c; sourceTree = ""; }; + D4EC46DA1C26342F0024B507 /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = ""; }; + D4EC46DB1C26342F0024B507 /* mixer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mixer.cpp; sourceTree = ""; }; + D4EC46DC1C26342F0024B507 /* mixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mixer.h; sourceTree = ""; }; + D4EC46DD1C26342F0024B507 /* cheats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cheats.c; path = src/cheats.c; sourceTree = ""; }; + D4EC46DE1C26342F0024B507 /* cheats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cheats.h; path = src/cheats.h; sourceTree = ""; }; + D4EC46DF1C26342F0024B507 /* cmdline_sprite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cmdline_sprite.c; path = src/cmdline_sprite.c; sourceTree = ""; }; + D4EC46E21C26342F0024B507 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = common.h; path = src/common.h; sourceTree = ""; }; + D4EC46E31C26342F0024B507 /* config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = config.c; path = src/config.c; sourceTree = ""; }; + D4EC46E41C26342F0024B507 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = src/config.h; sourceTree = ""; }; + D4EC46E61C26342F0024B507 /* Exception.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Exception.hpp; sourceTree = ""; }; + D4EC46E71C26342F0024B507 /* FileStream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = FileStream.hpp; sourceTree = ""; }; + D4EC46E81C26342F0024B507 /* IDisposable.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IDisposable.hpp; sourceTree = ""; }; + D4EC46E91C26342F0024B507 /* IStream.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = IStream.hpp; sourceTree = ""; }; + D4EC46EA1C26342F0024B507 /* Math.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Math.hpp; sourceTree = ""; }; + D4EC46EB1C26342F0024B507 /* Memory.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Memory.hpp; sourceTree = ""; }; + D4EC46EC1C26342F0024B507 /* StringBuilder.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StringBuilder.hpp; sourceTree = ""; }; + D4EC46ED1C26342F0024B507 /* StringReader.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = StringReader.hpp; sourceTree = ""; }; + D4EC46EE1C26342F0024B507 /* Util.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Util.hpp; sourceTree = ""; }; + D4EC46EF1C26342F0024B507 /* cursors.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cursors.c; path = src/cursors.c; sourceTree = ""; }; + D4EC46F01C26342F0024B507 /* cursors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cursors.h; path = src/cursors.h; sourceTree = ""; }; + D4EC46F11C26342F0024B507 /* diagnostic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = diagnostic.c; path = src/diagnostic.c; sourceTree = ""; }; + D4EC46F21C26342F0024B507 /* diagnostic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = diagnostic.h; path = src/diagnostic.h; sourceTree = ""; }; + D4EC46F41C26342F0024B507 /* drawing.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = drawing.c; sourceTree = ""; }; + D4EC46F51C26342F0024B507 /* drawing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drawing.h; sourceTree = ""; }; + D4EC46F61C26342F0024B507 /* font.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = font.c; sourceTree = ""; }; + D4EC46F71C26342F0024B507 /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = ""; }; + D4EC46F81C26342F0024B507 /* line.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = line.c; sourceTree = ""; }; + D4EC46F91C26342F0024B507 /* rain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rain.c; sourceTree = ""; }; + D4EC46FA1C26342F0024B507 /* rect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rect.c; sourceTree = ""; }; + D4EC46FB1C26342F0024B507 /* scrolling_text.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scrolling_text.c; sourceTree = ""; }; + D4EC46FC1C26342F0024B507 /* sprite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sprite.c; sourceTree = ""; }; + D4EC46FD1C26342F0024B507 /* string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = string.c; sourceTree = ""; }; + D4EC46FE1C26342F0024B507 /* supports.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = supports.c; sourceTree = ""; }; + D4EC46FF1C26342F0024B507 /* supports.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = supports.h; sourceTree = ""; }; + D4EC47001C26342F0024B507 /* editor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = editor.c; path = src/editor.c; sourceTree = ""; }; + D4EC47011C26342F0024B507 /* editor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = editor.h; path = src/editor.h; sourceTree = ""; }; + D4EC47021C26342F0024B507 /* game.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = game.c; path = src/game.c; sourceTree = ""; }; + D4EC47031C26342F0024B507 /* game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = game.h; path = src/game.h; sourceTree = ""; }; + D4EC47041C26342F0024B507 /* hook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hook.c; path = src/hook.c; sourceTree = ""; }; + D4EC47051C26342F0024B507 /* hook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hook.h; path = src/hook.h; sourceTree = ""; }; + D4EC47061C26342F0024B507 /* input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = input.c; path = src/input.c; sourceTree = ""; }; + D4EC47071C26342F0024B507 /* input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = input.h; path = src/input.h; sourceTree = ""; }; + D4EC47091C26342F0024B507 /* chat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = chat.c; sourceTree = ""; }; + D4EC470A1C26342F0024B507 /* chat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = chat.h; sourceTree = ""; }; + D4EC470B1C26342F0024B507 /* colour.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = colour.c; sourceTree = ""; }; + D4EC470C1C26342F0024B507 /* colour.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colour.h; sourceTree = ""; }; + D4EC470D1C26342F0024B507 /* console.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = console.c; sourceTree = ""; }; + D4EC470E1C26342F0024B507 /* console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = console.h; sourceTree = ""; }; + D4EC470F1C26342F0024B507 /* graph.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = graph.c; sourceTree = ""; }; + D4EC47101C26342F0024B507 /* graph.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = graph.h; sourceTree = ""; }; + D4EC47111C26342F0024B507 /* keyboard_shortcut.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keyboard_shortcut.c; sourceTree = ""; }; + D4EC47121C26342F0024B507 /* keyboard_shortcut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keyboard_shortcut.h; sourceTree = ""; }; + D4EC47131C26342F0024B507 /* screenshot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = screenshot.c; sourceTree = ""; }; + D4EC47141C26342F0024B507 /* screenshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = screenshot.h; sourceTree = ""; }; + D4EC47161C26342F0024B507 /* themes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = themes.h; sourceTree = ""; }; + D4EC47171C26342F0024B507 /* title_sequences.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_sequences.c; sourceTree = ""; }; + D4EC47181C26342F0024B507 /* title_sequences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = title_sequences.h; sourceTree = ""; }; + D4EC47191C26342F0024B507 /* viewport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = viewport.c; sourceTree = ""; }; + D4EC471A1C26342F0024B507 /* viewport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = viewport.h; sourceTree = ""; }; + D4EC471B1C26342F0024B507 /* viewport_interaction.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = viewport_interaction.c; sourceTree = ""; }; + D4EC471C1C26342F0024B507 /* widget.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = widget.c; sourceTree = ""; }; + D4EC471D1C26342F0024B507 /* widget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = widget.h; sourceTree = ""; }; + D4EC471E1C26342F0024B507 /* window.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = window.c; sourceTree = ""; }; + D4EC471F1C26342F0024B507 /* window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = ""; }; + D4EC47201C26342F0024B507 /* intro.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = intro.c; path = src/intro.c; sourceTree = ""; }; + D4EC47211C26342F0024B507 /* intro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = intro.h; path = src/intro.h; sourceTree = ""; }; + D4EC47231C26342F0024B507 /* convert.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = convert.c; sourceTree = ""; }; + D4EC47241C26342F0024B507 /* currency.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = currency.c; sourceTree = ""; }; + D4EC47251C26342F0024B507 /* currency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = currency.h; sourceTree = ""; }; + D4EC47261C26342F0024B507 /* date.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = date.c; sourceTree = ""; }; + D4EC47271C26342F0024B507 /* date.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = date.h; sourceTree = ""; }; + D4EC47281C26342F0024B507 /* format_codes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = format_codes.h; sourceTree = ""; }; + D4EC47291C26342F0024B507 /* language.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = language.cpp; sourceTree = ""; }; + D4EC472A1C26342F0024B507 /* language.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = language.h; sourceTree = ""; }; + D4EC472B1C26342F0024B507 /* LanguagePack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LanguagePack.cpp; sourceTree = ""; }; + D4EC472C1C26342F0024B507 /* LanguagePack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LanguagePack.h; sourceTree = ""; }; + D4EC472D1C26342F0024B507 /* localisation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = localisation.c; sourceTree = ""; }; + D4EC472E1C26342F0024B507 /* localisation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = localisation.h; sourceTree = ""; }; + D4EC472F1C26342F0024B507 /* real_names.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = real_names.c; sourceTree = ""; }; + D4EC47301C26342F0024B507 /* string_ids.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_ids.h; sourceTree = ""; }; + D4EC47311C26342F0024B507 /* user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = user.c; sourceTree = ""; }; + D4EC47321C26342F0024B507 /* user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user.h; sourceTree = ""; }; + D4EC47331C26342F0024B507 /* utf8.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utf8.c; sourceTree = ""; }; + D4EC47351C26342F0024B507 /* award.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = award.c; sourceTree = ""; }; + D4EC47361C26342F0024B507 /* award.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = award.h; sourceTree = ""; }; + D4EC47371C26342F0024B507 /* finance.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = finance.c; sourceTree = ""; }; + D4EC47381C26342F0024B507 /* finance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = finance.h; sourceTree = ""; }; + D4EC47391C26342F0024B507 /* marketing.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = marketing.c; sourceTree = ""; }; + D4EC473A1C26342F0024B507 /* marketing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = marketing.h; sourceTree = ""; }; + D4EC473B1C26342F0024B507 /* news_item.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = news_item.c; sourceTree = ""; }; + D4EC473C1C26342F0024B507 /* news_item.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = news_item.h; sourceTree = ""; }; + D4EC473D1C26342F0024B507 /* research.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = research.c; sourceTree = ""; }; + D4EC473E1C26342F0024B507 /* research.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = research.h; sourceTree = ""; }; + D4EC47401C26342F0024B507 /* http.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = http.cpp; sourceTree = ""; }; + D4EC47411C26342F0024B507 /* http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = http.h; sourceTree = ""; }; + D4EC47421C26342F0024B507 /* network.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = network.cpp; sourceTree = ""; }; + D4EC47431C26342F0024B507 /* network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = network.h; sourceTree = ""; }; + D4EC47441C26342F0024B507 /* twitch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = twitch.cpp; sourceTree = ""; }; + D4EC47451C26342F0024B507 /* twitch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = twitch.h; sourceTree = ""; }; + D4EC47461C26342F0024B507 /* object_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = object_list.c; path = src/object_list.c; sourceTree = ""; }; + D4EC47471C26342F0024B507 /* object.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = object.c; path = src/object.c; sourceTree = ""; }; + D4EC47481C26342F0024B507 /* object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = object.h; path = src/object.h; sourceTree = ""; }; + D4EC47491C26342F0024B507 /* openrct2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = openrct2.c; path = src/openrct2.c; sourceTree = ""; }; + D4EC474A1C26342F0024B507 /* openrct2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = openrct2.h; path = src/openrct2.h; sourceTree = ""; }; + D4EC474C1C26342F0024B507 /* peep.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = peep.c; sourceTree = ""; }; + D4EC474D1C26342F0024B507 /* peep.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = peep.h; sourceTree = ""; }; + D4EC474E1C26342F0024B507 /* staff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = staff.c; sourceTree = ""; }; + D4EC474F1C26342F0024B507 /* staff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = staff.h; sourceTree = ""; }; + D4EC47511C26342F0024B507 /* linux.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = linux.c; sourceTree = ""; }; + D4EC47521C26342F0024B507 /* osx.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = osx.m; sourceTree = ""; }; + D4EC47531C26342F0024B507 /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = platform.h; sourceTree = ""; }; + D4EC47541C26342F0024B507 /* posix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = posix.c; sourceTree = ""; }; + D4EC47551C26342F0024B507 /* shared.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = shared.c; sourceTree = ""; }; + D4EC47561C26342F0024B507 /* windows.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = windows.c; sourceTree = ""; }; + D4EC47571C26342F0024B507 /* rct1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rct1.c; path = src/rct1.c; sourceTree = ""; }; + D4EC47581C26342F0024B507 /* rct1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rct1.h; path = src/rct1.h; sourceTree = ""; }; + D4EC47591C26342F0024B507 /* rct2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rct2.c; path = src/rct2.c; sourceTree = ""; }; + D4EC475A1C26342F0024B507 /* rct2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rct2.h; path = src/rct2.h; sourceTree = ""; }; + D4EC475D1C26342F0024B507 /* ride.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ride.c; sourceTree = ""; }; + D4EC475E1C26342F0024B507 /* ride.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ride.h; sourceTree = ""; }; + D4EC475F1C26342F0024B507 /* ride_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ride_data.c; sourceTree = ""; }; + D4EC47601C26342F0024B507 /* ride_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ride_data.h; sourceTree = ""; }; + D4EC47611C26342F0024B507 /* ride_ratings.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ride_ratings.c; sourceTree = ""; }; + D4EC47621C26342F0024B507 /* ride_ratings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ride_ratings.h; sourceTree = ""; }; + D4EC47631C26342F0024B507 /* station.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = station.c; sourceTree = ""; }; + D4EC47641C26342F0024B507 /* station.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = station.h; sourceTree = ""; }; + D4EC47651C26342F0024B507 /* track.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track.c; sourceTree = ""; }; + D4EC47661C26342F0024B507 /* track.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = track.h; sourceTree = ""; }; + D4EC47671C26342F0024B507 /* track_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_data.c; sourceTree = ""; }; + D4EC47681C26342F0024B507 /* track_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = track_data.h; sourceTree = ""; }; + D4EC47691C26342F0024B507 /* track_paint.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_paint.c; sourceTree = ""; }; + D4EC476A1C26342F0024B507 /* track_paint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = track_paint.h; sourceTree = ""; }; + D4EC476B1C26342F0024B507 /* vehicle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vehicle.c; sourceTree = ""; }; + D4EC476C1C26342F0024B507 /* vehicle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vehicle.h; sourceTree = ""; }; + D4EC476D1C26342F0024B507 /* scenario_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scenario_list.c; path = src/scenario_list.c; sourceTree = ""; }; + D4EC476E1C26342F0024B507 /* scenario.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scenario.c; path = src/scenario.c; sourceTree = ""; }; + D4EC476F1C26342F0024B507 /* scenario.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = scenario.h; path = src/scenario.h; sourceTree = ""; }; + D4EC47701C26342F0024B507 /* sprites.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sprites.h; path = src/sprites.h; sourceTree = ""; }; + D4EC47711C26342F0024B507 /* title.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = title.c; path = src/title.c; sourceTree = ""; }; + D4EC47721C26342F0024B507 /* title.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = title.h; path = src/title.h; sourceTree = ""; }; + D4EC47761C26342F0024B507 /* sawyercoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sawyercoding.c; sourceTree = ""; }; + D4EC47771C26342F0024B507 /* sawyercoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sawyercoding.h; sourceTree = ""; }; + D4EC47781C26342F0024B507 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; + D4EC47791C26342F0024B507 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; + D4EC477B1C26342F0024B507 /* about.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = about.c; sourceTree = ""; }; + D4EC477C1C26342F0024B507 /* banner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = banner.c; sourceTree = ""; }; + D4EC477D1C26342F0024B507 /* changelog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = changelog.c; sourceTree = ""; }; + D4EC477E1C26342F0024B507 /* cheats.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cheats.c; sourceTree = ""; }; + D4EC477F1C26342F0024B507 /* clear_scenery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = clear_scenery.c; sourceTree = ""; }; + D4EC47801C26342F0024B507 /* demolish_ride_prompt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = demolish_ride_prompt.c; sourceTree = ""; }; + D4EC47811C26342F0024B507 /* dropdown.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dropdown.c; sourceTree = ""; }; + D4EC47821C26342F0024B507 /* dropdown.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dropdown.h; sourceTree = ""; }; + D4EC47831C26342F0024B507 /* editor_bottom_toolbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = editor_bottom_toolbar.c; sourceTree = ""; }; + D4EC47841C26342F0024B507 /* editor_inventions_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = editor_inventions_list.c; sourceTree = ""; }; + D4EC47851C26342F0024B507 /* editor_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = editor_main.c; sourceTree = ""; }; + D4EC47861C26342F0024B507 /* editor_object_selection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = editor_object_selection.c; sourceTree = ""; }; + D4EC47871C26342F0024B507 /* editor_objective_options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = editor_objective_options.c; sourceTree = ""; }; + D4EC47881C26342F0024B507 /* editor_scenario_options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = editor_scenario_options.c; sourceTree = ""; }; + D4EC47891C26342F0024B507 /* error.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = error.c; sourceTree = ""; }; + D4EC478A1C26342F0024B507 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = error.h; sourceTree = ""; }; + D4EC478B1C26342F0024B507 /* finances.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = finances.c; sourceTree = ""; }; + D4EC478C1C26342F0024B507 /* footpath.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = footpath.c; sourceTree = ""; }; + D4EC478D1C26342F0024B507 /* game_bottom_toolbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = game_bottom_toolbar.c; sourceTree = ""; }; + D4EC478E1C26342F0024B507 /* guest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = guest.c; sourceTree = ""; }; + D4EC478F1C26342F0024B507 /* guest_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = guest_list.c; sourceTree = ""; }; + D4EC47901C26342F0024B507 /* install_track.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = install_track.c; sourceTree = ""; }; + D4EC47911C26342F0024B507 /* land.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = land.c; sourceTree = ""; }; + D4EC47921C26342F0024B507 /* land_rights.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = land_rights.c; sourceTree = ""; }; + D4EC47931C26342F0024B507 /* loadsave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadsave.c; sourceTree = ""; }; + D4EC47941C26342F0024B507 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; }; + D4EC47951C26342F0024B507 /* map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map.c; sourceTree = ""; }; + D4EC47961C26342F0024B507 /* map_tooltip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map_tooltip.c; sourceTree = ""; }; + D4EC47971C26342F0024B507 /* mapgen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapgen.c; sourceTree = ""; }; + D4EC47981C26342F0024B507 /* maze_construction.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = maze_construction.c; sourceTree = ""; }; + D4EC47991C26342F0024B507 /* music_credits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = music_credits.c; sourceTree = ""; }; + D4EC479A1C26342F0024B507 /* network_status.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = network_status.c; sourceTree = ""; }; + D4EC479B1C26342F0024B507 /* new_campaign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = new_campaign.c; sourceTree = ""; }; + D4EC479C1C26342F0024B507 /* new_ride.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = new_ride.c; sourceTree = ""; }; + D4EC479D1C26342F0024B507 /* news.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = news.c; sourceTree = ""; }; + D4EC479E1C26342F0024B507 /* options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = options.c; sourceTree = ""; }; + D4EC479F1C26342F0024B507 /* park.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = park.c; sourceTree = ""; }; + D4EC47A11C26342F0024B507 /* publisher_credits.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = publisher_credits.c; sourceTree = ""; }; + D4EC47A21C26342F0024B507 /* research.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = research.c; sourceTree = ""; }; + D4EC47A31C26342F0024B507 /* ride.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ride.c; sourceTree = ""; }; + D4EC47A41C26342F0024B507 /* ride_construction.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ride_construction.c; sourceTree = ""; }; + D4EC47A51C26342F0024B507 /* ride_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ride_list.c; sourceTree = ""; }; + D4EC47A61C26342F0024B507 /* save_prompt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = save_prompt.c; sourceTree = ""; }; + D4EC47A71C26342F0024B507 /* scenery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scenery.c; sourceTree = ""; }; + D4EC47A81C26342F0024B507 /* server_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server_list.c; sourceTree = ""; }; + D4EC47A91C26342F0024B507 /* server_start.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = server_start.c; sourceTree = ""; }; + D4EC47AA1C26342F0024B507 /* shortcut_key_change.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = shortcut_key_change.c; sourceTree = ""; }; + D4EC47AB1C26342F0024B507 /* shortcut_keys.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = shortcut_keys.c; sourceTree = ""; }; + D4EC47AC1C26342F0024B507 /* sign.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sign.c; sourceTree = ""; }; + D4EC47AD1C26342F0024B507 /* staff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = staff.c; sourceTree = ""; }; + D4EC47AE1C26342F0024B507 /* staff_fire_prompt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = staff_fire_prompt.c; sourceTree = ""; }; + D4EC47AF1C26342F0024B507 /* staff_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = staff_list.c; sourceTree = ""; }; + D4EC47B01C26342F0024B507 /* text_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = text_input.c; sourceTree = ""; }; + D4EC47B11C26342F0024B507 /* themes.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = themes.c; sourceTree = ""; }; + D4EC47B21C26342F0024B507 /* tile_inspector.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tile_inspector.c; sourceTree = ""; }; + D4EC47B31C26342F0024B507 /* title_command_editor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_command_editor.c; sourceTree = ""; }; + D4EC47B41C26342F0024B507 /* title_editor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_editor.c; sourceTree = ""; }; + D4EC47B51C26342F0024B507 /* title_exit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_exit.c; sourceTree = ""; }; + D4EC47B61C26342F0024B507 /* title_logo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_logo.c; sourceTree = ""; }; + D4EC47B71C26342F0024B507 /* title_menu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_menu.c; sourceTree = ""; }; + D4EC47B81C26342F0024B507 /* title_options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_options.c; sourceTree = ""; }; + D4EC47B91C26342F0024B507 /* title_scenarioselect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = title_scenarioselect.c; sourceTree = ""; }; + D4EC47BA1C26342F0024B507 /* tooltip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tooltip.c; sourceTree = ""; }; + D4EC47BB1C26342F0024B507 /* tooltip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tooltip.h; sourceTree = ""; }; + D4EC47BC1C26342F0024B507 /* top_toolbar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = top_toolbar.c; sourceTree = ""; }; + D4EC47BD1C26342F0024B507 /* track_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_list.c; sourceTree = ""; }; + D4EC47BE1C26342F0024B507 /* track_manage.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_manage.c; sourceTree = ""; }; + D4EC47BF1C26342F0024B507 /* track_place.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = track_place.c; sourceTree = ""; }; + D4EC47C01C26342F0024B507 /* viewport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = viewport.c; sourceTree = ""; }; + D4EC47C11C26342F0024B507 /* water.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = water.c; sourceTree = ""; }; + D4EC47C31C26342F0024B507 /* balloon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = balloon.c; sourceTree = ""; }; + D4EC47C41C26342F0024B507 /* banner.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = banner.c; sourceTree = ""; }; + D4EC47C51C26342F0024B507 /* banner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = banner.h; sourceTree = ""; }; + D4EC47C61C26342F0024B507 /* climate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = climate.c; sourceTree = ""; }; + D4EC47C71C26342F0024B507 /* climate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = climate.h; sourceTree = ""; }; + D4EC47C81C26342F0024B507 /* duck.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = duck.c; sourceTree = ""; }; + D4EC47C91C26342F0024B507 /* entrance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = entrance.h; sourceTree = ""; }; + D4EC47CA1C26342F0024B507 /* footpath.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = footpath.c; sourceTree = ""; }; + D4EC47CB1C26342F0024B507 /* footpath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = footpath.h; sourceTree = ""; }; + D4EC47CC1C26342F0024B507 /* fountain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fountain.c; sourceTree = ""; }; + D4EC47CD1C26342F0024B507 /* fountain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fountain.h; sourceTree = ""; }; + D4EC47CE1C26342F0024B507 /* map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map.c; sourceTree = ""; }; + D4EC47CF1C26342F0024B507 /* map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = map.h; sourceTree = ""; }; + D4EC47D01C26342F0024B507 /* map_animation.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map_animation.c; sourceTree = ""; }; + D4EC47D11C26342F0024B507 /* map_animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = map_animation.h; sourceTree = ""; }; + D4EC47D21C26342F0024B507 /* map_helpers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = map_helpers.c; sourceTree = ""; }; + D4EC47D31C26342F0024B507 /* map_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = map_helpers.h; sourceTree = ""; }; + D4EC47D41C26342F0024B507 /* mapgen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mapgen.c; sourceTree = ""; }; + D4EC47D51C26342F0024B507 /* mapgen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mapgen.h; sourceTree = ""; }; + D4EC47D61C26342F0024B507 /* money_effect.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = money_effect.c; sourceTree = ""; }; + D4EC47D71C26342F0024B507 /* park.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = park.c; sourceTree = ""; }; + D4EC47D81C26342F0024B507 /* park.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = park.h; sourceTree = ""; }; + D4EC47D91C26342F0024B507 /* particle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = particle.c; sourceTree = ""; }; + D4EC47DA1C26342F0024B507 /* scenery.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scenery.c; sourceTree = ""; }; + D4EC47DB1C26342F0024B507 /* scenery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scenery.h; sourceTree = ""; }; + D4EC47DC1C26342F0024B507 /* sprite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sprite.c; sourceTree = ""; }; + D4EC47DD1C26342F0024B507 /* sprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sprite.h; sourceTree = ""; }; + D4EC47DE1C26342F0024B507 /* water.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = water.h; sourceTree = ""; }; + D4EC48821C2634870024B507 /* jansson.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jansson.h; sourceTree = ""; }; + D4EC48831C2634870024B507 /* jansson_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jansson_config.h; sourceTree = ""; }; + D4EC48851C2634870024B507 /* begin_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = begin_code.h; sourceTree = ""; }; + D4EC48861C2634870024B507 /* close_code.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = close_code.h; sourceTree = ""; }; + D4EC48871C2634870024B507 /* SDL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL.h; sourceTree = ""; }; + D4EC48881C2634870024B507 /* SDL_assert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_assert.h; sourceTree = ""; }; + D4EC48891C2634870024B507 /* SDL_atomic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_atomic.h; sourceTree = ""; }; + D4EC488A1C2634870024B507 /* SDL_audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio.h; sourceTree = ""; }; + D4EC488B1C2634870024B507 /* SDL_bits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_bits.h; sourceTree = ""; }; + D4EC488C1C2634870024B507 /* SDL_blendmode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_blendmode.h; sourceTree = ""; }; + D4EC488D1C2634870024B507 /* SDL_clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_clipboard.h; sourceTree = ""; }; + D4EC488E1C2634870024B507 /* SDL_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_config.h; sourceTree = ""; }; + D4EC488F1C2634870024B507 /* SDL_config_macosx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_config_macosx.h; sourceTree = ""; }; + D4EC48901C2634870024B507 /* SDL_copying.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_copying.h; sourceTree = ""; }; + D4EC48911C2634870024B507 /* SDL_cpuinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cpuinfo.h; sourceTree = ""; }; + D4EC48921C2634870024B507 /* SDL_endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_endian.h; sourceTree = ""; }; + D4EC48931C2634870024B507 /* SDL_error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_error.h; sourceTree = ""; }; + D4EC48941C2634870024B507 /* SDL_events.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_events.h; sourceTree = ""; }; + D4EC48951C2634870024B507 /* SDL_filesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_filesystem.h; sourceTree = ""; }; + D4EC48961C2634870024B507 /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = ""; }; + D4EC48971C2634870024B507 /* SDL_gesture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gesture.h; sourceTree = ""; }; + D4EC48981C2634870024B507 /* SDL_haptic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_haptic.h; sourceTree = ""; }; + D4EC48991C2634870024B507 /* SDL_hints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_hints.h; sourceTree = ""; }; + D4EC489A1C2634870024B507 /* SDL_joystick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_joystick.h; sourceTree = ""; }; + D4EC489B1C2634870024B507 /* SDL_keyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_keyboard.h; sourceTree = ""; }; + D4EC489C1C2634870024B507 /* SDL_keycode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_keycode.h; sourceTree = ""; }; + D4EC489D1C2634870024B507 /* SDL_loadso.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_loadso.h; sourceTree = ""; }; + D4EC489E1C2634870024B507 /* SDL_log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_log.h; sourceTree = ""; }; + D4EC489F1C2634870024B507 /* SDL_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_main.h; sourceTree = ""; }; + D4EC48A01C2634870024B507 /* SDL_messagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_messagebox.h; sourceTree = ""; }; + D4EC48A11C2634870024B507 /* SDL_mouse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_mouse.h; sourceTree = ""; }; + D4EC48A21C2634870024B507 /* SDL_mutex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_mutex.h; sourceTree = ""; }; + D4EC48A31C2634870024B507 /* SDL_name.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_name.h; sourceTree = ""; }; + D4EC48A41C2634870024B507 /* SDL_opengl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_opengl.h; sourceTree = ""; }; + D4EC48A51C2634870024B507 /* SDL_opengles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_opengles.h; sourceTree = ""; }; + D4EC48A61C2634870024B507 /* SDL_opengles2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_opengles2.h; sourceTree = ""; }; + D4EC48A71C2634870024B507 /* SDL_pixels.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_pixels.h; sourceTree = ""; }; + D4EC48A81C2634870024B507 /* SDL_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_platform.h; sourceTree = ""; }; + D4EC48A91C2634870024B507 /* SDL_power.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_power.h; sourceTree = ""; }; + D4EC48AA1C2634870024B507 /* SDL_quit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_quit.h; sourceTree = ""; }; + D4EC48AB1C2634870024B507 /* SDL_rect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rect.h; sourceTree = ""; }; + D4EC48AC1C2634870024B507 /* SDL_render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_render.h; sourceTree = ""; }; + D4EC48AD1C2634870024B507 /* SDL_revision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_revision.h; sourceTree = ""; }; + D4EC48AE1C2634870024B507 /* SDL_rwops.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_rwops.h; sourceTree = ""; }; + D4EC48AF1C2634870024B507 /* SDL_scancode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_scancode.h; sourceTree = ""; }; + D4EC48B01C2634870024B507 /* SDL_shape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_shape.h; sourceTree = ""; }; + D4EC48B11C2634870024B507 /* SDL_stdinc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_stdinc.h; sourceTree = ""; }; + D4EC48B21C2634870024B507 /* SDL_surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_surface.h; sourceTree = ""; }; + D4EC48B31C2634870024B507 /* SDL_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_system.h; sourceTree = ""; }; + D4EC48B41C2634870024B507 /* SDL_syswm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_syswm.h; sourceTree = ""; }; + D4EC48B51C2634870024B507 /* SDL_thread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_thread.h; sourceTree = ""; }; + D4EC48B61C2634870024B507 /* SDL_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_timer.h; sourceTree = ""; }; + D4EC48B71C2634870024B507 /* SDL_touch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_touch.h; sourceTree = ""; }; + D4EC48B81C2634870024B507 /* SDL_ttf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_ttf.h; sourceTree = ""; }; + D4EC48B91C2634870024B507 /* SDL_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_types.h; sourceTree = ""; }; + D4EC48BA1C2634870024B507 /* SDL_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_version.h; sourceTree = ""; }; + D4EC48BB1C2634870024B507 /* SDL_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video.h; sourceTree = ""; }; + D4EC48BD1C2634870024B507 /* speex_echo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speex_echo.h; sourceTree = ""; }; + D4EC48BE1C2634870024B507 /* speex_jitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speex_jitter.h; sourceTree = ""; }; + D4EC48BF1C2634870024B507 /* speex_preprocess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speex_preprocess.h; sourceTree = ""; }; + D4EC48C01C2634870024B507 /* speex_resampler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speex_resampler.h; sourceTree = ""; }; + D4EC48C11C2634870024B507 /* speexdsp_config_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speexdsp_config_types.h; sourceTree = ""; }; + D4EC48C21C2634870024B507 /* speexdsp_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = speexdsp_types.h; sourceTree = ""; }; + D4EC48C41C2634870024B507 /* libfreetype.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libfreetype.dylib; sourceTree = ""; }; + D4EC48C51C2634870024B507 /* libjansson.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libjansson.dylib; sourceTree = ""; }; + D4EC48C61C2634870024B507 /* libSDL2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libSDL2.dylib; sourceTree = ""; }; + D4EC48C71C2634870024B507 /* libSDL2_ttf.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libSDL2_ttf.dylib; sourceTree = ""; }; + D4EC48C81C2634870024B507 /* libspeexdsp.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libspeexdsp.dylib; sourceTree = ""; }; + D4EC48E31C2637710024B507 /* g2.dat */ = {isa = PBXFileReference; lastKnownFileType = file; name = g2.dat; path = data/g2.dat; sourceTree = SOURCE_ROOT; }; + D4EC48E41C2637710024B507 /* language */ = {isa = PBXFileReference; lastKnownFileType = folder; name = language; path = data/language; sourceTree = SOURCE_ROOT; }; + D4EC48E51C2637710024B507 /* title */ = {isa = PBXFileReference; lastKnownFileType = folder; name = title; path = data/title; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D497D0751C20FD52002BF46A /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D47304D51C4FF8250015C0EA /* libz.tbd in Frameworks */, + D41B73EF1C2101890080A7B9 /* libcurl.tbd in Frameworks */, + D41B741D1C210A7A0080A7B9 /* libiconv.tbd in Frameworks */, + D435325F1C3472E500BA219B /* libpng.dylib in Frameworks */, + D4EC48CA1C2634870024B507 /* libjansson.dylib in Frameworks */, + D4EC48CB1C2634870024B507 /* libSDL2.dylib in Frameworks */, + D4EC48CC1C2634870024B507 /* libSDL2_ttf.dylib in Frameworks */, + D4EC48CD1C2634870024B507 /* libspeexdsp.dylib in Frameworks */, + D41B73F11C21018C0080A7B9 /* libssl.tbd in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + D41B72431C21015A0080A7B9 /* Sources */ = { + isa = PBXGroup; + children = ( + D4EC46D81C26342F0024B507 /* audio */, + D4B63B891C43025600367A37 /* cmdline */, + D4EC46E51C26342F0024B507 /* core */, + D4EC46F31C26342F0024B507 /* drawing */, + D4EC47081C26342F0024B507 /* interface */, + D4EC47221C26342F0024B507 /* localisation */, + D4EC47341C26342F0024B507 /* management */, + D4EC473F1C26342F0024B507 /* network */, + D4EC474B1C26342F0024B507 /* peep */, + D4EC47501C26342F0024B507 /* platform */, + D4EC475C1C26342F0024B507 /* ride */, + D4EC47751C26342F0024B507 /* util */, + D4EC477A1C26342F0024B507 /* windows */, + D4EC47C21C26342F0024B507 /* world */, + D4EC46D61C26342F0024B507 /* addresses.c */, + D4EC46D71C26342F0024B507 /* addresses.h */, + D4EC46DD1C26342F0024B507 /* cheats.c */, + D4EC46DE1C26342F0024B507 /* cheats.h */, + D4EC46DF1C26342F0024B507 /* cmdline_sprite.c */, + D4EC46E21C26342F0024B507 /* common.h */, + D4EC46E31C26342F0024B507 /* config.c */, + D4EC46E41C26342F0024B507 /* config.h */, + D4EC46EF1C26342F0024B507 /* cursors.c */, + D4EC46F01C26342F0024B507 /* cursors.h */, + D4EC46F11C26342F0024B507 /* diagnostic.c */, + D4EC46F21C26342F0024B507 /* diagnostic.h */, + D4EC47001C26342F0024B507 /* editor.c */, + D4EC47011C26342F0024B507 /* editor.h */, + D4EC47021C26342F0024B507 /* game.c */, + D4EC47031C26342F0024B507 /* game.h */, + D4EC47041C26342F0024B507 /* hook.c */, + D4EC47051C26342F0024B507 /* hook.h */, + D4D4DF121C34697B0048BE43 /* image_io.c */, + D4D4DF131C34697B0048BE43 /* image_io.h */, + D4EC47061C26342F0024B507 /* input.c */, + D4EC47071C26342F0024B507 /* input.h */, + D4EC47201C26342F0024B507 /* intro.c */, + D4EC47211C26342F0024B507 /* intro.h */, + D4EC47461C26342F0024B507 /* object_list.c */, + D4EC47471C26342F0024B507 /* object.c */, + D4EC47481C26342F0024B507 /* object.h */, + D4EC47491C26342F0024B507 /* openrct2.c */, + D4EC474A1C26342F0024B507 /* openrct2.h */, + D4EC47571C26342F0024B507 /* rct1.c */, + D4EC47581C26342F0024B507 /* rct1.h */, + 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 */, + D4163F671C2A044D00B83136 /* version.h */, + a9793fe06a4244938f5d4b61 /* crash.cpp */, +); + name = Sources; + sourceTree = ""; + }; + D41B73ED1C21017D0080A7B9 /* Libraries */ = { + isa = PBXGroup; + children = ( + D4EC48811C2634870024B507 /* include */, + D4EC48C31C2634870024B507 /* lib */, + D4EC48CE1C26348E0024B507 /* system */, + ); + name = Libraries; + sourceTree = ""; + }; + D497D06F1C20FD52002BF46A = { + isa = PBXGroup; + children = ( + D41B72431C21015A0080A7B9 /* Sources */, + D497D07A1C20FD52002BF46A /* Resources */, + D41B73ED1C21017D0080A7B9 /* Libraries */, + D497D0791C20FD52002BF46A /* Products */, + ); + sourceTree = ""; + usesTabs = 1; + }; + D497D0791C20FD52002BF46A /* Products */ = { + isa = PBXGroup; + children = ( + D497D0781C20FD52002BF46A /* OpenRCT2.app */, + ); + name = Products; + sourceTree = ""; + }; + D497D07A1C20FD52002BF46A /* Resources */ = { + isa = PBXGroup; + children = ( + D41B74721C2125E50080A7B9 /* Assets.xcassets */, + D4895D321C23EFDD000CD788 /* Info.plist */, + D4C1EDD01C266A0B00F71B63 /* data */, + ); + name = Resources; + path = OpenRCT2; + sourceTree = ""; + }; + D4B63B891C43025600367A37 /* cmdline */ = { + isa = PBXGroup; + children = ( + D4B63B8A1C43025600367A37 /* CommandLine.cpp */, + D4B63B8B1C43025600367A37 /* CommandLine.hpp */, + D4B63B8C1C43025600367A37 /* RootCommands.cpp */, + D4B63B8D1C43025600367A37 /* ScreenshotCommands.cpp */, + D4B63B8E1C43025600367A37 /* SpriteCommands.cpp */, + ); + name = cmdline; + path = src/cmdline; + sourceTree = SOURCE_ROOT; + }; + D4C1EDD01C266A0B00F71B63 /* data */ = { + isa = PBXGroup; + children = ( + D4EC48E31C2637710024B507 /* g2.dat */, + D4EC48E41C2637710024B507 /* language */, + D4EC48E51C2637710024B507 /* title */, + ); + name = data; + sourceTree = ""; + }; + D4EC46D81C26342F0024B507 /* audio */ = { + isa = PBXGroup; + children = ( + D4EC46D91C26342F0024B507 /* audio.c */, + D4EC46DA1C26342F0024B507 /* audio.h */, + D4EC46DB1C26342F0024B507 /* mixer.cpp */, + D4EC46DC1C26342F0024B507 /* mixer.h */, + ); + name = audio; + path = src/audio; + sourceTree = ""; + }; + D4EC46E51C26342F0024B507 /* core */ = { + isa = PBXGroup; + children = ( + 001085EE1C90FD030075A2AD /* textinputbuffer.c */, + 001085EF1C90FD030075A2AD /* textinputbuffer.h */, + D4B63B931C43028200367A37 /* Console.cpp */, + D4B63B941C43028200367A37 /* Console.hpp */, + D4A3511A1C6067B000CBCBA4 /* Diagnostics.hpp */, + D4EC46E61C26342F0024B507 /* Exception.hpp */, + D4EC46E71C26342F0024B507 /* FileStream.hpp */, + D4A3511B1C6067B900CBCBA4 /* Guard.hpp */, + D4EC46E81C26342F0024B507 /* IDisposable.hpp */, + D4EC46E91C26342F0024B507 /* IStream.hpp */, + D4A3511C1C6067C400CBCBA4 /* Json.cpp */, + D4A3511D1C6067C400CBCBA4 /* Json.hpp */, + D4A3511F1C6067E500CBCBA4 /* List.hpp */, + D4EC46EA1C26342F0024B507 /* Math.hpp */, + D4EC46EB1C26342F0024B507 /* Memory.hpp */, + D4D35E2A1C45BD9B00AAFCB4 /* Path.cpp */, + D4D35E2B1C45BD9B00AAFCB4 /* Path.hpp */, + D4B63B961C43028F00367A37 /* String.cpp */, + D4B63B971C43028F00367A37 /* String.hpp */, + D4EC46EC1C26342F0024B507 /* StringBuilder.hpp */, + D4EC46ED1C26342F0024B507 /* StringReader.hpp */, + D4EC46EE1C26342F0024B507 /* Util.hpp */, + ); + name = core; + path = src/core; + sourceTree = ""; + }; + D4EC46F31C26342F0024B507 /* drawing */ = { + isa = PBXGroup; + children = ( + D4EC46F41C26342F0024B507 /* drawing.c */, + D4EC46F51C26342F0024B507 /* drawing.h */, + C62A08D41C787C2A00F3AA76 /* drawing_fast.cpp */, + D4EC46F61C26342F0024B507 /* font.c */, + D4EC46F71C26342F0024B507 /* font.h */, + D4EC46F81C26342F0024B507 /* line.c */, + D4EC46F91C26342F0024B507 /* rain.c */, + D4EC46FA1C26342F0024B507 /* rect.c */, + D4EC46FB1C26342F0024B507 /* scrolling_text.c */, + D4EC46FC1C26342F0024B507 /* sprite.c */, + D4EC46FD1C26342F0024B507 /* string.c */, + D4EC46FE1C26342F0024B507 /* supports.c */, + D4EC46FF1C26342F0024B507 /* supports.h */, + ); + name = drawing; + path = src/drawing; + sourceTree = ""; + }; + D4EC47081C26342F0024B507 /* interface */ = { + isa = PBXGroup; + children = ( + D4EC47091C26342F0024B507 /* chat.c */, + D4EC470A1C26342F0024B507 /* chat.h */, + D4EC470B1C26342F0024B507 /* colour.c */, + D4EC470C1C26342F0024B507 /* colour.h */, + D4EC470D1C26342F0024B507 /* console.c */, + D4EC470E1C26342F0024B507 /* console.h */, + D4EC470F1C26342F0024B507 /* graph.c */, + D4EC47101C26342F0024B507 /* graph.h */, + D4EC47111C26342F0024B507 /* keyboard_shortcut.c */, + D4EC47121C26342F0024B507 /* keyboard_shortcut.h */, + D4EC47131C26342F0024B507 /* screenshot.c */, + D4EC47141C26342F0024B507 /* screenshot.h */, + D4A351201C60680300CBCBA4 /* Theme.cpp */, + D4EC47161C26342F0024B507 /* themes.h */, + D4EC47171C26342F0024B507 /* title_sequences.c */, + D4EC47181C26342F0024B507 /* title_sequences.h */, + D4EC47191C26342F0024B507 /* viewport.c */, + D4EC471A1C26342F0024B507 /* viewport.h */, + D4EC471B1C26342F0024B507 /* viewport_interaction.c */, + D4EC471C1C26342F0024B507 /* widget.c */, + D4EC471D1C26342F0024B507 /* widget.h */, + D4EC471E1C26342F0024B507 /* window.c */, + D4EC471F1C26342F0024B507 /* window.h */, + ); + name = interface; + path = src/interface; + sourceTree = ""; + }; + D4EC47221C26342F0024B507 /* localisation */ = { + isa = PBXGroup; + children = ( + D4EC47231C26342F0024B507 /* convert.c */, + D4EC47241C26342F0024B507 /* currency.c */, + D4EC47251C26342F0024B507 /* currency.h */, + D4EC47261C26342F0024B507 /* date.c */, + D4EC47271C26342F0024B507 /* date.h */, + D4EC47281C26342F0024B507 /* format_codes.h */, + D4EC47291C26342F0024B507 /* language.cpp */, + D4EC472A1C26342F0024B507 /* language.h */, + D4EC472B1C26342F0024B507 /* LanguagePack.cpp */, + D4EC472C1C26342F0024B507 /* LanguagePack.h */, + D4EC472D1C26342F0024B507 /* localisation.c */, + D4EC472E1C26342F0024B507 /* localisation.h */, + D4EC472F1C26342F0024B507 /* real_names.c */, + D4EC47301C26342F0024B507 /* string_ids.h */, + D4EC47311C26342F0024B507 /* user.c */, + D4EC47321C26342F0024B507 /* user.h */, + D4EC47331C26342F0024B507 /* utf8.c */, + ); + name = localisation; + path = src/localisation; + sourceTree = ""; + }; + D4EC47341C26342F0024B507 /* management */ = { + isa = PBXGroup; + children = ( + D4EC47351C26342F0024B507 /* award.c */, + D4EC47361C26342F0024B507 /* award.h */, + D4EC47371C26342F0024B507 /* finance.c */, + D4EC47381C26342F0024B507 /* finance.h */, + D4EC47391C26342F0024B507 /* marketing.c */, + D4EC473A1C26342F0024B507 /* marketing.h */, + D4EC473B1C26342F0024B507 /* news_item.c */, + D4EC473C1C26342F0024B507 /* news_item.h */, + D4EC473D1C26342F0024B507 /* research.c */, + D4EC473E1C26342F0024B507 /* research.h */, + ); + name = management; + path = src/management; + sourceTree = ""; + }; + D4EC473F1C26342F0024B507 /* network */ = { + isa = PBXGroup; + children = ( + D4EC47401C26342F0024B507 /* http.cpp */, + D4EC47411C26342F0024B507 /* http.h */, + D4EC47421C26342F0024B507 /* network.cpp */, + D4EC47431C26342F0024B507 /* network.h */, + D4EC47441C26342F0024B507 /* twitch.cpp */, + D4EC47451C26342F0024B507 /* twitch.h */, + ); + name = network; + path = src/network; + sourceTree = ""; + }; + D4EC474B1C26342F0024B507 /* peep */ = { + isa = PBXGroup; + children = ( + D4EC474C1C26342F0024B507 /* peep.c */, + D4EC474D1C26342F0024B507 /* peep.h */, + D4EC474E1C26342F0024B507 /* staff.c */, + D4EC474F1C26342F0024B507 /* staff.h */, + ); + name = peep; + path = src/peep; + sourceTree = ""; + }; + D4EC47501C26342F0024B507 /* platform */ = { + isa = PBXGroup; + children = ( + D4EC47511C26342F0024B507 /* linux.c */, + D4EC47521C26342F0024B507 /* osx.m */, + D4EC47531C26342F0024B507 /* platform.h */, + D4EC47541C26342F0024B507 /* posix.c */, + D4EC47551C26342F0024B507 /* shared.c */, + D4EC47561C26342F0024B507 /* windows.c */, + ); + name = platform; + path = src/platform; + sourceTree = ""; + }; + D4EC475C1C26342F0024B507 /* ride */ = { + isa = PBXGroup; + children = ( + D4B85B591C41C7F3005C568A /* cable_lift.c */, + D4B85B5A1C41C7F3005C568A /* cable_lift.h */, + D4EC475D1C26342F0024B507 /* ride.c */, + D4EC475E1C26342F0024B507 /* ride.h */, + D4EC475F1C26342F0024B507 /* ride_data.c */, + D4EC47601C26342F0024B507 /* ride_data.h */, + D4EC47611C26342F0024B507 /* ride_ratings.c */, + D4EC47621C26342F0024B507 /* ride_ratings.h */, + D4EC47631C26342F0024B507 /* station.c */, + D4EC47641C26342F0024B507 /* station.h */, + D4EC47651C26342F0024B507 /* track.c */, + D4EC47661C26342F0024B507 /* track.h */, + D4EC47671C26342F0024B507 /* track_data.c */, + D4EC47681C26342F0024B507 /* track_data.h */, + D4EC47691C26342F0024B507 /* track_paint.c */, + D4EC476A1C26342F0024B507 /* track_paint.h */, + D4EC476B1C26342F0024B507 /* vehicle.c */, + D4EC476C1C26342F0024B507 /* vehicle.h */, + ); + name = ride; + path = src/ride; + sourceTree = ""; + }; + D4EC47751C26342F0024B507 /* util */ = { + isa = PBXGroup; + children = ( + D4EC47761C26342F0024B507 /* sawyercoding.c */, + D4EC47771C26342F0024B507 /* sawyercoding.h */, + D4EC47781C26342F0024B507 /* util.c */, + D4EC47791C26342F0024B507 /* util.h */, + ); + name = util; + path = src/util; + sourceTree = ""; + }; + D4EC477A1C26342F0024B507 /* windows */ = { + isa = PBXGroup; + children = ( + D4EC477B1C26342F0024B507 /* about.c */, + D4EC477C1C26342F0024B507 /* banner.c */, + D4EC477D1C26342F0024B507 /* changelog.c */, + D4EC477E1C26342F0024B507 /* cheats.c */, + D4EC477F1C26342F0024B507 /* clear_scenery.c */, + D4EC47801C26342F0024B507 /* demolish_ride_prompt.c */, + D4EC47811C26342F0024B507 /* dropdown.c */, + D4EC47821C26342F0024B507 /* dropdown.h */, + D4EC47831C26342F0024B507 /* editor_bottom_toolbar.c */, + D4EC47841C26342F0024B507 /* editor_inventions_list.c */, + D4EC47851C26342F0024B507 /* editor_main.c */, + D4EC47861C26342F0024B507 /* editor_object_selection.c */, + D4EC47871C26342F0024B507 /* editor_objective_options.c */, + D4EC47881C26342F0024B507 /* editor_scenario_options.c */, + D4EC47891C26342F0024B507 /* error.c */, + D4EC478A1C26342F0024B507 /* error.h */, + D4EC478B1C26342F0024B507 /* finances.c */, + D4EC478C1C26342F0024B507 /* footpath.c */, + D4EC478D1C26342F0024B507 /* game_bottom_toolbar.c */, + D4EC478E1C26342F0024B507 /* guest.c */, + D4EC478F1C26342F0024B507 /* guest_list.c */, + D4EC47901C26342F0024B507 /* install_track.c */, + D4EC47911C26342F0024B507 /* land.c */, + D4EC47921C26342F0024B507 /* land_rights.c */, + D4EC47931C26342F0024B507 /* loadsave.c */, + D4EC47941C26342F0024B507 /* main.c */, + D4EC47951C26342F0024B507 /* map.c */, + D4EC47961C26342F0024B507 /* map_tooltip.c */, + D4EC47971C26342F0024B507 /* mapgen.c */, + D4EC47981C26342F0024B507 /* maze_construction.c */, + D4C0EDCE1C52EA5000A03A06 /* multiplayer.c */, + D4EC47991C26342F0024B507 /* music_credits.c */, + D4EC479A1C26342F0024B507 /* network_status.c */, + D4EC479B1C26342F0024B507 /* new_campaign.c */, + D4EC479C1C26342F0024B507 /* new_ride.c */, + D4ABAB051C2F812B0080CAD9 /* news_options.c */, + D4EC479D1C26342F0024B507 /* news.c */, + D4EC479E1C26342F0024B507 /* options.c */, + D4EC479F1C26342F0024B507 /* park.c */, + D4C0EDD01C52EA6400A03A06 /* player.c */, + D4EC47A11C26342F0024B507 /* publisher_credits.c */, + D4EC47A21C26342F0024B507 /* research.c */, + D4EC47A31C26342F0024B507 /* ride.c */, + D4EC47A41C26342F0024B507 /* ride_construction.c */, + D4EC47A51C26342F0024B507 /* ride_list.c */, + D4EC47A61C26342F0024B507 /* save_prompt.c */, + D4EC47A71C26342F0024B507 /* scenery.c */, + D4EC47A81C26342F0024B507 /* server_list.c */, + D4EC47A91C26342F0024B507 /* server_start.c */, + D4EC47AA1C26342F0024B507 /* shortcut_key_change.c */, + D4EC47AB1C26342F0024B507 /* shortcut_keys.c */, + D4EC47AC1C26342F0024B507 /* sign.c */, + D4EC47AD1C26342F0024B507 /* staff.c */, + D4EC47AE1C26342F0024B507 /* staff_fire_prompt.c */, + D4EC47AF1C26342F0024B507 /* staff_list.c */, + D4EC47B01C26342F0024B507 /* text_input.c */, + D4EC47B11C26342F0024B507 /* themes.c */, + D4EC47B21C26342F0024B507 /* tile_inspector.c */, + D4EC47B31C26342F0024B507 /* title_command_editor.c */, + D4EC47B41C26342F0024B507 /* title_editor.c */, + D4EC47B51C26342F0024B507 /* title_exit.c */, + D4EC47B61C26342F0024B507 /* title_logo.c */, + D4EC47B71C26342F0024B507 /* title_menu.c */, + D4EC47B81C26342F0024B507 /* title_options.c */, + D4EC47B91C26342F0024B507 /* title_scenarioselect.c */, + D4EC47BA1C26342F0024B507 /* tooltip.c */, + D4EC47BB1C26342F0024B507 /* tooltip.h */, + D4EC47BC1C26342F0024B507 /* top_toolbar.c */, + D4EC47BD1C26342F0024B507 /* track_list.c */, + D4EC47BE1C26342F0024B507 /* track_manage.c */, + D4EC47BF1C26342F0024B507 /* track_place.c */, + D4EC47C01C26342F0024B507 /* viewport.c */, + D4EC47C11C26342F0024B507 /* water.c */, + ); + name = windows; + path = src/windows; + sourceTree = ""; + }; + D4EC47C21C26342F0024B507 /* world */ = { + isa = PBXGroup; + children = ( + D4EC47C31C26342F0024B507 /* balloon.c */, + D4EC47C41C26342F0024B507 /* banner.c */, + D4EC47C51C26342F0024B507 /* banner.h */, + D4EC47C61C26342F0024B507 /* climate.c */, + D4EC47C71C26342F0024B507 /* climate.h */, + D4EC47C81C26342F0024B507 /* duck.c */, + D4EC47C91C26342F0024B507 /* entrance.h */, + D4EC47CA1C26342F0024B507 /* footpath.c */, + D4EC47CB1C26342F0024B507 /* footpath.h */, + D4EC47CC1C26342F0024B507 /* fountain.c */, + D4EC47CD1C26342F0024B507 /* fountain.h */, + D4EC47CE1C26342F0024B507 /* map.c */, + D4EC47CF1C26342F0024B507 /* map.h */, + D4EC47D01C26342F0024B507 /* map_animation.c */, + D4EC47D11C26342F0024B507 /* map_animation.h */, + D4EC47D21C26342F0024B507 /* map_helpers.c */, + D4EC47D31C26342F0024B507 /* map_helpers.h */, + D4EC47D41C26342F0024B507 /* mapgen.c */, + D4EC47D51C26342F0024B507 /* mapgen.h */, + D4EC47D61C26342F0024B507 /* money_effect.c */, + D4EC47D71C26342F0024B507 /* park.c */, + D4EC47D81C26342F0024B507 /* park.h */, + D4EC47D91C26342F0024B507 /* particle.c */, + D4EC47DA1C26342F0024B507 /* scenery.c */, + D4EC47DB1C26342F0024B507 /* scenery.h */, + D4EC47DC1C26342F0024B507 /* sprite.c */, + D4EC47DD1C26342F0024B507 /* sprite.h */, + D4EC47DE1C26342F0024B507 /* water.h */, + ); + name = world; + path = src/world; + sourceTree = ""; + }; + D4EC48811C2634870024B507 /* include */ = { + isa = PBXGroup; + children = ( + D4EC48CF1C2634A30024B507 /* jansson */, + D4EC48841C2634870024B507 /* SDL2 */, + D4EC48BC1C2634870024B507 /* speex */, + ); + name = include; + path = libxc/include; + sourceTree = ""; + }; + D4EC48841C2634870024B507 /* SDL2 */ = { + isa = PBXGroup; + children = ( + D4EC48851C2634870024B507 /* begin_code.h */, + D4EC48861C2634870024B507 /* close_code.h */, + D4EC48871C2634870024B507 /* SDL.h */, + D4EC48881C2634870024B507 /* SDL_assert.h */, + D4EC48891C2634870024B507 /* SDL_atomic.h */, + D4EC488A1C2634870024B507 /* SDL_audio.h */, + D4EC488B1C2634870024B507 /* SDL_bits.h */, + D4EC488C1C2634870024B507 /* SDL_blendmode.h */, + D4EC488D1C2634870024B507 /* SDL_clipboard.h */, + D4EC488E1C2634870024B507 /* SDL_config.h */, + D4EC488F1C2634870024B507 /* SDL_config_macosx.h */, + D4EC48901C2634870024B507 /* SDL_copying.h */, + D4EC48911C2634870024B507 /* SDL_cpuinfo.h */, + D4EC48921C2634870024B507 /* SDL_endian.h */, + D4EC48931C2634870024B507 /* SDL_error.h */, + D4EC48941C2634870024B507 /* SDL_events.h */, + D4EC48951C2634870024B507 /* SDL_filesystem.h */, + D4EC48961C2634870024B507 /* SDL_gamecontroller.h */, + D4EC48971C2634870024B507 /* SDL_gesture.h */, + D4EC48981C2634870024B507 /* SDL_haptic.h */, + D4EC48991C2634870024B507 /* SDL_hints.h */, + D4EC489A1C2634870024B507 /* SDL_joystick.h */, + D4EC489B1C2634870024B507 /* SDL_keyboard.h */, + D4EC489C1C2634870024B507 /* SDL_keycode.h */, + D4EC489D1C2634870024B507 /* SDL_loadso.h */, + D4EC489E1C2634870024B507 /* SDL_log.h */, + D4EC489F1C2634870024B507 /* SDL_main.h */, + D4EC48A01C2634870024B507 /* SDL_messagebox.h */, + D4EC48A11C2634870024B507 /* SDL_mouse.h */, + D4EC48A21C2634870024B507 /* SDL_mutex.h */, + D4EC48A31C2634870024B507 /* SDL_name.h */, + D4EC48A41C2634870024B507 /* SDL_opengl.h */, + D4EC48A51C2634870024B507 /* SDL_opengles.h */, + D4EC48A61C2634870024B507 /* SDL_opengles2.h */, + D4EC48A71C2634870024B507 /* SDL_pixels.h */, + D4EC48A81C2634870024B507 /* SDL_platform.h */, + D4EC48A91C2634870024B507 /* SDL_power.h */, + D4EC48AA1C2634870024B507 /* SDL_quit.h */, + D4EC48AB1C2634870024B507 /* SDL_rect.h */, + D4EC48AC1C2634870024B507 /* SDL_render.h */, + D4EC48AD1C2634870024B507 /* SDL_revision.h */, + D4EC48AE1C2634870024B507 /* SDL_rwops.h */, + D4EC48AF1C2634870024B507 /* SDL_scancode.h */, + D4EC48B01C2634870024B507 /* SDL_shape.h */, + D4EC48B11C2634870024B507 /* SDL_stdinc.h */, + D4EC48B21C2634870024B507 /* SDL_surface.h */, + D4EC48B31C2634870024B507 /* SDL_system.h */, + D4EC48B41C2634870024B507 /* SDL_syswm.h */, + D4EC48B51C2634870024B507 /* SDL_thread.h */, + D4EC48B61C2634870024B507 /* SDL_timer.h */, + D4EC48B71C2634870024B507 /* SDL_touch.h */, + D4EC48B81C2634870024B507 /* SDL_ttf.h */, + D4EC48B91C2634870024B507 /* SDL_types.h */, + D4EC48BA1C2634870024B507 /* SDL_version.h */, + D4EC48BB1C2634870024B507 /* SDL_video.h */, + ); + path = SDL2; + sourceTree = ""; + }; + D4EC48BC1C2634870024B507 /* speex */ = { + isa = PBXGroup; + children = ( + D4EC48BD1C2634870024B507 /* speex_echo.h */, + D4EC48BE1C2634870024B507 /* speex_jitter.h */, + D4EC48BF1C2634870024B507 /* speex_preprocess.h */, + D4EC48C01C2634870024B507 /* speex_resampler.h */, + D4EC48C11C2634870024B507 /* speexdsp_config_types.h */, + D4EC48C21C2634870024B507 /* speexdsp_types.h */, + ); + path = speex; + sourceTree = ""; + }; + D4EC48C31C2634870024B507 /* lib */ = { + isa = PBXGroup; + children = ( + D4EC48C41C2634870024B507 /* libfreetype.dylib */, + D4EC48C51C2634870024B507 /* libjansson.dylib */, + D435325E1C3472E500BA219B /* libpng.dylib */, + D4EC48C61C2634870024B507 /* libSDL2.dylib */, + D4EC48C71C2634870024B507 /* libSDL2_ttf.dylib */, + D4EC48C81C2634870024B507 /* libspeexdsp.dylib */, + ); + name = lib; + path = libxc/lib; + sourceTree = ""; + }; + D4EC48CE1C26348E0024B507 /* system */ = { + isa = PBXGroup; + children = ( + D41B73EE1C2101890080A7B9 /* libcurl.tbd */, + D41B741C1C210A7A0080A7B9 /* libiconv.tbd */, + D41B73F01C21018C0080A7B9 /* libssl.tbd */, + D47304D41C4FF8250015C0EA /* libz.tbd */, + ); + name = system; + sourceTree = ""; + }; + D4EC48CF1C2634A30024B507 /* jansson */ = { + isa = PBXGroup; + children = ( + D4EC48821C2634870024B507 /* jansson.h */, + D4EC48831C2634870024B507 /* jansson_config.h */, + ); + name = jansson; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + D497D0771C20FD52002BF46A /* OpenRCT2 */ = { + isa = PBXNativeTarget; + buildConfigurationList = D497D0891C20FD53002BF46A /* Build configuration list for PBXNativeTarget "OpenRCT2" */; + buildPhases = ( + D4EC48E91C264FC20024B507 /* Download Libraries */, + D4EC012A1C25532B00DAFE69 /* Setup AppIcon */, + D40F4E1D1C2528D5009582C9 /* Create Segment Files */, + D497D0741C20FD52002BF46A /* Sources */, + D497D0751C20FD52002BF46A /* Frameworks */, + D41B74201C210B190080A7B9 /* Embed Frameworks */, + D42C09D21C254F4E00309751 /* Build g2.dat */, + D497D0761C20FD52002BF46A /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = OpenRCT2; + productName = OpenRCT2; + productReference = D497D0781C20FD52002BF46A /* OpenRCT2.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D497D0701C20FD52002BF46A /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = OpenRCT2; + TargetAttributes = { + D497D0771C20FD52002BF46A = { + CreatedOnToolsVersion = 7.2; + }; + }; + }; + buildConfigurationList = D497D0731C20FD52002BF46A /* Build configuration list for PBXProject "OpenRCT2" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = D497D06F1C20FD52002BF46A; + productRefGroup = D497D0791C20FD52002BF46A /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D497D0771C20FD52002BF46A /* OpenRCT2 */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D497D0761C20FD52002BF46A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D41B74731C2125E50080A7B9 /* Assets.xcassets in Resources */, + D4EC48E61C2637710024B507 /* g2.dat in Resources */, + D4EC48E71C2637710024B507 /* language in Resources */, + D4EC48E81C2637710024B507 /* title in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + D40F4E1D1C2528D5009582C9 /* Create Segment Files */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/openrct2.exe", + ); + name = "Create Segment Files"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/openrct2_text", + "$(DERIVED_FILE_DIR)/openrct2_data", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "dd if=\"${SRCROOT}/openrct2.exe\" of=\"${DERIVED_FILE_DIR}/openrct2_text\" bs=4096 skip=1 count=1187\ndd if=\"${SRCROOT}/openrct2.exe\" of=\"${DERIVED_FILE_DIR}/openrct2_data\" bs=4096 skip=1188 count=318\ndd if=/dev/zero of=\"${DERIVED_FILE_DIR}/openrct2_data\" bs=4096 seek=318 count=2630 conv=notrunc\ndd if=\"${SRCROOT}/openrct2.exe\" of=\"${DERIVED_FILE_DIR}/openrct2_data\" bs=4096 skip=1506 seek=2948 count=1 conv=notrunc"; + }; + D42C09D21C254F4E00309751 /* Build g2.dat */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/resources/g2/*", + ); + name = "Build g2.dat"; + outputPaths = ( + "$(SRCROOT)/data/g2.dat", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${TARGET_BUILD_DIR}/${EXECUTABLE_PATH}\" sprite build \"${SRCROOT}/data/g2.dat\" \"${SRCROOT}/resources/g2/\""; + }; + D4EC012A1C25532B00DAFE69 /* Setup AppIcon */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/resources/logo/icon_x16.png", + "$(SRCROOT)/resources/logo/icon_x32.png", + "$(SRCROOT)/resources/logo/icon_x64.png", + "$(SRCROOT)/resources/logo/icon_x128.png", + "$(SRCROOT)/resources/logo/icon_x256.png", + "$(SRCROOT)/resources/logo/icon_x512.png", + "$(SRCROOT)/resources/logo/icon_x1024.png", + ); + name = "Setup AppIcon"; + outputPaths = ( + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_16x16.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_32x32.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_128x128.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_256x256.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_512x512.png", + "$(SRCROOT)/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_16x16.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x16.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_16x16.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x32.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_32x32.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x32.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_32x32.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x64.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_128x128.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x128.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_128x128.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x256.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_256x256.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x256.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_256x256.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x512.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_512x512.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x512.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_512x512.png\"; fi\nif [[ ! -e \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png\" ]]; then ln \"${SRCROOT}/resources/logo/icon_x1024.png\" \"${SRCROOT}/distribution/osx/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png\"; fi"; + }; + D4EC48E91C264FC20024B507 /* Download Libraries */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Download Libraries"; + outputPaths = ( + ); + 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=\"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 */ + +/* Begin PBXSourcesBuildPhase section */ + D497D0741C20FD52002BF46A /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D4EC485D1C26342F0024B507 /* sign.c in Sources */, + D4EC47E61C26342F0024B507 /* cursors.c in Sources */, + D4EC48251C26342F0024B507 /* track_data.c in Sources */, + D4EC48661C26342F0024B507 /* title_exit.c in Sources */, + D4EC480C1C26342F0024B507 /* finance.c in Sources */, + D4EC47EB1C26342F0024B507 /* rain.c in Sources */, + D4EC48221C26342F0024B507 /* ride_ratings.c in Sources */, + D4EC48371C26342F0024B507 /* editor_main.c in Sources */, + D4EC48321C26342F0024B507 /* clear_scenery.c in Sources */, + D4EC48211C26342F0024B507 /* ride_data.c in Sources */, + D4EC47F11C26342F0024B507 /* editor.c in Sources */, + D4EC483A1C26342F0024B507 /* editor_scenario_options.c in Sources */, + D4EC48551C26342F0024B507 /* ride_construction.c in Sources */, + D4EC48461C26342F0024B507 /* map.c in Sources */, + D4EC481D1C26342F0024B507 /* rct1.c in Sources */, + D4B63B911C43025600367A37 /* ScreenshotCommands.cpp in Sources */, + D4EC48291C26342F0024B507 /* scenario.c in Sources */, + D4EC485B1C26342F0024B507 /* shortcut_key_change.c in Sources */, + D4EC48741C26342F0024B507 /* climate.c in Sources */, + D4EC48201C26342F0024B507 /* ride.c in Sources */, + D4EC485F1C26342F0024B507 /* staff_fire_prompt.c in Sources */, + D4EC48381C26342F0024B507 /* editor_object_selection.c in Sources */, + D4EC482C1C26342F0024B507 /* sawyercoding.c in Sources */, + D4EC48631C26342F0024B507 /* tile_inspector.c in Sources */, + D4EC48181C26342F0024B507 /* linux.c in Sources */, + D4EC48651C26342F0024B507 /* title_editor.c in Sources */, + D4EC47EC1C26342F0024B507 /* rect.c in Sources */, + D4EC48101C26342F0024B507 /* http.cpp in Sources */, + D4ABAB061C2F812B0080CAD9 /* news_options.c in Sources */, + D4EC47F21C26342F0024B507 /* game.c in Sources */, + D4EC48761C26342F0024B507 /* footpath.c in Sources */, + D4EC48031C26342F0024B507 /* currency.c in Sources */, + D4B63B8F1C43025600367A37 /* CommandLine.cpp in Sources */, + D4EC48011C26342F0024B507 /* intro.c in Sources */, + D4EC47EF1C26342F0024B507 /* string.c in Sources */, + D4EC48531C26342F0024B507 /* research.c in Sources */, + D4EC48401C26342F0024B507 /* guest_list.c in Sources */, + D4EC482F1C26342F0024B507 /* banner.c in Sources */, + D4EC47E91C26342F0024B507 /* font.c in Sources */, + D4A3511E1C6067C400CBCBA4 /* Json.cpp in Sources */, + D4EC48021C26342F0024B507 /* convert.c in Sources */, + D4EC48481C26342F0024B507 /* mapgen.c in Sources */, + D4EC48441C26342F0024B507 /* loadsave.c in Sources */, + D4EC47E21C26342F0024B507 /* cheats.c in Sources */, + D4EC481B1C26342F0024B507 /* shared.c in Sources */, + D4EC47FD1C26342F0024B507 /* viewport.c in Sources */, + D4EC480E1C26342F0024B507 /* news_item.c in Sources */, + D4EC48141C26342F0024B507 /* object.c in Sources */, + D4EC487F1C26342F0024B507 /* scenery.c in Sources */, + D4EC480A1C26342F0024B507 /* utf8.c in Sources */, + D4EC48681C26342F0024B507 /* title_menu.c in Sources */, + D4EC48751C26342F0024B507 /* duck.c in Sources */, + D4EC484F1C26342F0024B507 /* options.c in Sources */, + D4EC485C1C26342F0024B507 /* shortcut_keys.c in Sources */, + D4EC481A1C26342F0024B507 /* posix.c in Sources */, + D4D35E2C1C45BD9B00AAFCB4 /* Path.cpp in Sources */, + D4B63B981C43028F00367A37 /* String.cpp in Sources */, + 001085F01C90FD030075A2AD /* textinputbuffer.c in Sources */, + D4A351211C60680300CBCBA4 /* Theme.cpp in Sources */, + D4EC47E31C26342F0024B507 /* cmdline_sprite.c in Sources */, + D4EC48611C26342F0024B507 /* text_input.c in Sources */, + D4EC48431C26342F0024B507 /* land_rights.c in Sources */, + D4EC486B1C26342F0024B507 /* tooltip.c in Sources */, + D4EC48231C26342F0024B507 /* station.c in Sources */, + D4EC484D1C26342F0024B507 /* new_ride.c in Sources */, + D4EC484A1C26342F0024B507 /* music_credits.c in Sources */, + D4EC48241C26342F0024B507 /* track.c in Sources */, + D4EC47DF1C26342F0024B507 /* addresses.c in Sources */, + D4EC484B1C26342F0024B507 /* network_status.c in Sources */, + D4EC483E1C26342F0024B507 /* game_bottom_toolbar.c in Sources */, + D4EC48731C26342F0024B507 /* banner.c in Sources */, + D4EC47F51C26342F0024B507 /* chat.c in Sources */, + D4B63B901C43025600367A37 /* RootCommands.cpp in Sources */, + D4EC48591C26342F0024B507 /* server_list.c in Sources */, + D4EC48001C26342F0024B507 /* window.c in Sources */, + D4EC47F61C26342F0024B507 /* colour.c in Sources */, + D4EC486E1C26342F0024B507 /* track_manage.c in Sources */, + D4D4DF141C34697B0048BE43 /* image_io.c in Sources */, + D4EC48331C26342F0024B507 /* demolish_ride_prompt.c in Sources */, + D4EC48131C26342F0024B507 /* object_list.c in Sources */, + D4EC47ED1C26342F0024B507 /* scrolling_text.c in Sources */, + D4EC483D1C26342F0024B507 /* footpath.c in Sources */, + D4EC47E81C26342F0024B507 /* drawing.c in Sources */, + D4C0EDCF1C52EA5000A03A06 /* multiplayer.c in Sources */, + D4EC47F71C26342F0024B507 /* console.c in Sources */, + D4EC47FA1C26342F0024B507 /* screenshot.c in Sources */, + D4EC485A1C26342F0024B507 /* server_start.c in Sources */, + D4EC486D1C26342F0024B507 /* track_list.c in Sources */, + D4EC487B1C26342F0024B507 /* mapgen.c in Sources */, + D4EC48151C26342F0024B507 /* openrct2.c in Sources */, + D4EC48781C26342F0024B507 /* map.c in Sources */, + D4EC48411C26342F0024B507 /* install_track.c in Sources */, + D4EC48341C26342F0024B507 /* dropdown.c in Sources */, + D4EC48301C26342F0024B507 /* changelog.c in Sources */, + D4EC48521C26342F0024B507 /* publisher_credits.c in Sources */, + D4EC485E1C26342F0024B507 /* staff.c in Sources */, + D4EC486F1C26342F0024B507 /* track_place.c in Sources */, + D4EC48261C26342F0024B507 /* track_paint.c in Sources */, + D4EC48601C26342F0024B507 /* staff_list.c in Sources */, + D4EC48501C26342F0024B507 /* park.c in Sources */, + D4EC48041C26342F0024B507 /* date.c in Sources */, + D4EC486A1C26342F0024B507 /* title_scenarioselect.c in Sources */, + D4EC482A1C26342F0024B507 /* title.c in Sources */, + D4EC48491C26342F0024B507 /* maze_construction.c in Sources */, + D4EC48361C26342F0024B507 /* editor_inventions_list.c in Sources */, + D4EC482E1C26342F0024B507 /* about.c in Sources */, + D4EC487E1C26342F0024B507 /* particle.c in Sources */, + D4EC48071C26342F0024B507 /* localisation.c in Sources */, + D4EC47E01C26342F0024B507 /* audio.c in Sources */, + D4EC487D1C26342F0024B507 /* park.c in Sources */, + D4EC48161C26342F0024B507 /* peep.c in Sources */, + D4EC47FE1C26342F0024B507 /* viewport_interaction.c in Sources */, + D4EC48171C26342F0024B507 /* staff.c in Sources */, + D4EC48191C26342F0024B507 /* osx.m in Sources */, + D4EC48771C26342F0024B507 /* fountain.c in Sources */, + D4EC48711C26342F0024B507 /* water.c in Sources */, + D4EC48541C26342F0024B507 /* ride.c in Sources */, + D4EC484E1C26342F0024B507 /* news.c in Sources */, + D4EC47F31C26342F0024B507 /* hook.c in Sources */, + D4EC47F91C26342F0024B507 /* keyboard_shortcut.c in Sources */, + D4EC48351C26342F0024B507 /* editor_bottom_toolbar.c in Sources */, + D4EC487C1C26342F0024B507 /* money_effect.c in Sources */, + D4B63B921C43025600367A37 /* SpriteCommands.cpp in Sources */, + D4EC48641C26342F0024B507 /* title_command_editor.c in Sources */, + D4EC48671C26342F0024B507 /* title_logo.c in Sources */, + D4EC484C1C26342F0024B507 /* new_campaign.c in Sources */, + D4EC483B1C26342F0024B507 /* error.c in Sources */, + D4EC48121C26342F0024B507 /* twitch.cpp in Sources */, + D4EC48311C26342F0024B507 /* cheats.c in Sources */, + D4EC48051C26342F0024B507 /* language.cpp in Sources */, + D4EC48451C26342F0024B507 /* main.c in Sources */, + 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 */, + D4EC48091C26342F0024B507 /* user.c in Sources */, + D4EC47E11C26342F0024B507 /* mixer.cpp in Sources */, + D4B63B951C43028200367A37 /* Console.cpp in Sources */, + D4EC481E1C26342F0024B507 /* rct2.c in Sources */, + D4C0EDD11C52EA6400A03A06 /* player.c in Sources */, + C62A08D51C787C2A00F3AA76 /* drawing_fast.cpp in Sources */, + D4EC48801C26342F0024B507 /* sprite.c in Sources */, + D4EC486C1C26342F0024B507 /* top_toolbar.c in Sources */, + D4EC48621C26342F0024B507 /* themes.c in Sources */, + D4EC48081C26342F0024B507 /* real_names.c in Sources */, + D4EC481C1C26342F0024B507 /* windows.c in Sources */, + D4EC47EE1C26342F0024B507 /* sprite.c in Sources */, + D4EC480B1C26342F0024B507 /* award.c in Sources */, + D4EC47F81C26342F0024B507 /* graph.c in Sources */, + D4EC48111C26342F0024B507 /* network.cpp in Sources */, + D4EC47FF1C26342F0024B507 /* widget.c in Sources */, + D4EC48691C26342F0024B507 /* title_options.c in Sources */, + D4B85B5B1C41C7F3005C568A /* cable_lift.c in Sources */, + D4EC48471C26342F0024B507 /* map_tooltip.c in Sources */, + D4EC483F1C26342F0024B507 /* guest.c in Sources */, + D4EC487A1C26342F0024B507 /* map_helpers.c in Sources */, + D4EC480F1C26342F0024B507 /* research.c in Sources */, + D4EC48561C26342F0024B507 /* ride_list.c in Sources */, + D4EC47E71C26342F0024B507 /* diagnostic.c in Sources */, + D4EC47F41C26342F0024B507 /* input.c in Sources */, + D4EC48391C26342F0024B507 /* editor_objective_options.c in Sources */, + D4EC47E51C26342F0024B507 /* config.c in Sources */, + D4EC483C1C26342F0024B507 /* finances.c in Sources */, + D4EC47F01C26342F0024B507 /* supports.c in Sources */, + D4EC47FC1C26342F0024B507 /* title_sequences.c in Sources */, + D4EC48421C26342F0024B507 /* land.c in Sources */, + D4EC48791C26342F0024B507 /* map_animation.c in Sources */, + D4EC480D1C26342F0024B507 /* marketing.c in Sources */, + D4EC48721C26342F0024B507 /* balloon.c in Sources */, + D4EC48571C26342F0024B507 /* save_prompt.c in Sources */, + D4EC48701C26342F0024B507 /* viewport.c in Sources */, + 426da7e58564472ba1b7991f /* crash.cpp in Sources */, +); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + D497D0871C20FD53002BF46A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = NO; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_VARIABLE = NO; + LD_NO_PIE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + VALID_ARCHS = i386; + }; + name = Debug; + }; + D497D0881C20FD53002BF46A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = NO; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = NO; + GCC_WARN_UNUSED_VARIABLE = NO; + LD_NO_PIE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + VALID_ARCHS = i386; + }; + name = Release; + }; + D497D08A1C20FD53002BF46A /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(SRCROOT)/libxc/include", + "$(SRCROOT)/libxc/include/SDL2", + "$(SRCROOT)/libxc/include/libpng16", + "$(SRCROOT)/lib/", + ); + INFOPLIST_FILE = "$(SRCROOT)/distribution/osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/libxc/lib", + ); + OTHER_LDFLAGS = ( + "-sectcreate", + rct2_text, + __text, + "$(DERIVED_FILE_DIR)/openrct2_text", + "-segaddr", + rct2_text, + 0x401000, + "-segprot", + rct2_text, + rwx, + rx, + "-sectcreate", + rct2_data, + __data, + "$(DERIVED_FILE_DIR)/openrct2_data", + "-segaddr", + rct2_data, + 0x8a4000, + "-segprot", + rct2_data, + rw, + rw, + ); + PRODUCT_BUNDLE_IDENTIFIER = website.openrct2.OpenRCT2; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + D497D08B1C20FD53002BF46A /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMBINE_HIDPI_IMAGES = YES; + HEADER_SEARCH_PATHS = ( + "$(SRCROOT)/libxc/include", + "$(SRCROOT)/libxc/include/SDL2", + "$(SRCROOT)/libxc/include/libpng16", + "$(SRCROOT)/lib/", + ); + INFOPLIST_FILE = "$(SRCROOT)/distribution/osx/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/libxc/lib", + ); + OTHER_LDFLAGS = ( + "-sectcreate", + rct2_text, + __text, + "$(DERIVED_FILE_DIR)/openrct2_text", + "-segaddr", + rct2_text, + 0x401000, + "-segprot", + rct2_text, + rwx, + rx, + "-sectcreate", + rct2_data, + __data, + "$(DERIVED_FILE_DIR)/openrct2_data", + "-segaddr", + rct2_data, + 0x8a4000, + "-segprot", + rct2_data, + rw, + rw, + ); + PRODUCT_BUNDLE_IDENTIFIER = website.openrct2.OpenRCT2; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D497D0731C20FD52002BF46A /* Build configuration list for PBXProject "OpenRCT2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D497D0871C20FD53002BF46A /* Debug */, + D497D0881C20FD53002BF46A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D497D0891C20FD53002BF46A /* Build configuration list for PBXNativeTarget "OpenRCT2" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D497D08A1C20FD53002BF46A /* Debug */, + D497D08B1C20FD53002BF46A /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D497D0701C20FD52002BF46A /* Project object */; +} diff --git a/OpenRCT2.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/OpenRCT2.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000000..872dc2754b --- /dev/null +++ b/OpenRCT2.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/OpenRCT2.xcodeproj/project.xcworkspace/xcshareddata/OpenRCT2.xcscmblueprint b/OpenRCT2.xcodeproj/project.xcworkspace/xcshareddata/OpenRCT2.xcscmblueprint new file mode 100644 index 0000000000..adc84574df --- /dev/null +++ b/OpenRCT2.xcodeproj/project.xcworkspace/xcshareddata/OpenRCT2.xcscmblueprint @@ -0,0 +1,16 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "E48FB7C08C6966C4BACE7D0390CDFA7C64DD04D8", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "E48FB7C08C6966C4BACE7D0390CDFA7C64DD04D8" : 0 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "6B7243E0-B9B8-4E6D-ACE9-4DF346FA52C7", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "E48FB7C08C6966C4BACE7D0390CDFA7C64DD04D8" : "OpenRCT2\/" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "OpenRCT2", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "OpenRCT2.xcodeproj" +} diff --git a/OpenRCT2.xcodeproj/xcshareddata/xcschemes/OpenRCT2.xcscheme b/OpenRCT2.xcodeproj/xcshareddata/xcschemes/OpenRCT2.xcscheme new file mode 100644 index 0000000000..0e26d05bd5 --- /dev/null +++ b/OpenRCT2.xcodeproj/xcshareddata/xcschemes/OpenRCT2.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SDL2.dll b/SDL2.dll deleted file mode 100644 index 18d707f481..0000000000 Binary files a/SDL2.dll and /dev/null differ diff --git a/appveyor.yml b/appveyor.yml index b9d7498dca..7d093c2141 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,32 @@ -version: 0.0.3.{build} +version: 0.0.4.{build} +os: Visual Studio 2015 +environment: + ENCKEY: + secure: saYAIpqXzpq0U+JH+MNi/isRQ6Y51PZhm4BrnePDiAPptFO5htxFOLegrYqxdy67 + CODE-SIGN-KEY-OPENRCT2.ORG.PFX.PASSWORD: + secure: bzYmf0ElxisSGyZnIjUOYQ== + OPENRCT2.ORG_TOKEN: + secure: leQX3xCQpmBLGuMqrxjFlzexDt96ypNRMM5TTRVHbGE8PwVg9crgeykLc2BIZU6HDHveJCHqh2cGMdHtHYJYcw== +install: +- cmd: >- + IF DEFINED ENCKEY ( nuget install secure-file -ExcludeVersion && secure-file\tools\secure-file -decrypt distribution\windows\code-sign-key-openrct2.org.pfx.enc -secret %ENCKEY% ) + + cinst nsis.portable --version=3.01-beta1 > nul +- ps: >- + curl "http://nsis.sourceforge.net/mediawiki/images/5/53/KillProcDll%26FindProcDll.zip" -OutFile nsisxtra.zip + + 7z x nsisxtra.zip > $null + + cp FindProcDLL.dll "C:\ProgramData\chocolatey\lib\nsis.portable\tools\nsis-3.0b1\Plugins\x86-ansi" build_script: -- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% -- .\build.bat \ No newline at end of file +- ps: >- + .\setenv.ps1 + + appveyor_run +artifacts: +- path: .\artifacts\openrct2.zip + name: OpenRCT2-portable +- path: .\artifacts\*.exe + name: OpenRCT2-installer +- path: .\artifacts\openrct2-symbols-*.zip + name: OpenRCT2 debug symbols diff --git a/build.bat b/build.bat deleted file mode 100644 index c60e247902..0000000000 --- a/build.bat +++ /dev/null @@ -1 +0,0 @@ -msbuild .\projects\openrct2.sln /p:Configuration=Release /p:Platform=Win32 \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100755 index d1dc442fa3..0000000000 --- a/build.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash - -set -e - -cachedir=.cache -mkdir -p $cachedir - -# Sets default target to "linux", if none specified -TARGET=${TARGET-linux} - -if [[ ! -d build ]]; then - mkdir -p build -fi - -# keep in sync with version in install.sh -sha256sum=69ff98c9544838fb16384bc78af9dc1c452b9d01d919e43f5fec686d02c9bdd8 -libVFile="./libversion" -libdir="./lib" -currentversion=0 -needsdownload="true" - -if [ -f $libVFile ]; then - while read line; do - currentversion=$line - continue - done < $libVFile -fi - -if [ "z$currentversion" == "z$sha256sum" ]; then - needsdownload="false" -fi - -if [ ! -d $libdir ]; then - needsdownload="true" -fi - -if [[ "$needsdownload" = "true" ]]; then - echo "Found library had sha256sum $currentversion, expected $sha256sum" - echo "New libraries need to be downloaded. Clearing cache and calling ./install.sh" - rm -rf ./lib - if [[ -f $cachedir/orctlibs.zip ]]; then - rm -rf $cachedir/orctlibs.zip - fi - if [[ -d /usr/local/cross-tools/orctlibs ]]; then - sudo rm -rf /usr/local/cross-tools/orctlibs - fi - if [[ -d $cachedir/orctlibs ]]; then - rm -rf $cachedir/orctlibs - fi - ./install.sh -fi - -pushd build - echo OPENRCT2_CMAKE_OPTS = $OPENRCT2_CMAKE_OPTS - if [[ $TARGET == "docker32" ]] - then - PARENT=$(readlink -f ../) - chmod a+rwx $(pwd) - chmod g+s $(pwd) - docker run -u travis -v $PARENT:/work/openrct2 -w /work/openrct2/build -i -t openrct2/openrct2:32bit-only bash -c "cmake ../ $OPENRCT2_CMAKE_OPTS && make" - else - cmake -DCMAKE_BUILD_TYPE=Debug $OPENRCT2_CMAKE_OPTS .. - make - fi -popd - -if [[ $TARGET == "windows" ]]; then - if [[ ! -h openrct2.dll ]]; then - ln -s build/openrct2.dll openrct2.dll - fi -fi - -if [[ ! -h build/data ]]; then - ln -s ../data build/data -fi - -if [[ $TARGET == "linux" ]] || [[ $TARGET == "docker32" ]]; then - if [[ ! -h openrct2 ]]; then - ln -s build/openrct2 openrct2 - fi -fi - -if [[ -z "$DISABLE_G2_BUILD" ]]; then - echo Building: data/g2.dat - ./build_g2.sh > /dev/null 2>&1 -fi - -if [[ $TARGET == "windows" ]]; then - if [[ -t 1 ]]; then - echo -e "\nDone! Run OpenRCT2 by typing:\n\n\033[95mwine openrct2.exe\n\033[0m" - else - echo -e "\nDone! Run OpenRCT2 by typing:\n\nwine openrct2.exe\n" - fi -else - if [[ -t 1 ]]; then - echo -e "\nDone! Run OpenRCT2 by typing:\n\n\033[95m./openrct2\n\033[0m" - else - echo -e "\nDone! Run OpenRCT2 by typing:\n\n./openrct2\n" - fi -fi diff --git a/build_g2.bat b/build_g2.bat deleted file mode 100644 index c2bf10d049..0000000000 --- a/build_g2.bat +++ /dev/null @@ -1 +0,0 @@ -.\build\release\openrct2.exe sprite build "data\g2.dat" "resources\g2" \ No newline at end of file diff --git a/build_g2.sh b/build_g2.sh deleted file mode 100755 index 3d3a72b307..0000000000 --- a/build_g2.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -if [[ $TARGET == "windows" ]]; then - wine openrct2.exe sprite build data/g2.dat resources/g2/ -else - ./openrct2 sprite build data/g2.dat resources/g2/ -fi diff --git a/contributors.md b/contributors.md index 358ba95111..6920b61bf1 100644 --- a/contributors.md +++ b/contributors.md @@ -34,6 +34,7 @@ Includes all git commit authors. Aliases are GitHub user names. * (Vijfhoek) - Misc. * (wolfreak99) - Misc. * Inseok Lee (dlunch) - Original command line +* Lewis Fox (LRFLEW) - Misc. ## Additional implementation (OpenRCT2) * (atmaxinger) - User configuration @@ -48,6 +49,8 @@ Includes all git commit authors. Aliases are GitHub user names. * Thomas den Hollander (ThomasdenH) - Misc. * James Robertson (rd3k) - Misc. * Robert Jordan (trigger-death) - UI theming, title sequence editor, misc. +* Aaron van Geffen (AaronVanGeffen) - scenario select screen, font detection, misc. +* Kelson Blakewood - title sequence for 0.0.4 ## Bug fixes * (halfbro) @@ -56,6 +59,11 @@ Includes all git commit authors. Aliases are GitHub user names. * Ed Foley (e-foley) * Michael Pham (nightroan) * Hielke Morsink (Broxzier) +* Lucas Riutzel (jackinloadup) +* Youngjae Yu (YJSoft) +* Chanwoong Kim (kexplo) +* Josué Acevedo (Wirlie) +* Martin Černáč (octaroot) ## Toolchain * (Balletie) - OSX @@ -64,6 +72,7 @@ Includes all git commit authors. Aliases are GitHub user names. * Jarno Veuger (JarnoVgr) - Windows build server * Ted John (IntelOrca) - Windows * Michał Janiszewski (janisozaur) - Linux, Travis CI +* Lewis Fox (LRFLEW) - OSX ## Documentation * (honzi) @@ -78,23 +87,26 @@ Includes all git commit authors. Aliases are GitHub user names. * Extracting from original files: Ted John (IntelOrca) * Reviewing and merging: Rune Laenen (runelaenen), Michael Steenbeek (Gymnasiast) * Fixing unmaintained languages: Michael Steenbeek (Gymnasiast) +* Miscellaneous fixes: Alexander Overvoorde (Overv), Ed Foley (e-foley) * English (UK) - Ted John (IntelOrca), (Tinytimrob) -* English (US) - Ted John (IntelOrca), Michael Steenbeek (Gymnasiast) -* Dutch - Michael Steenbeek (Gymnasiast), (xzbobzx), (mrtnptrs), Thomas den Hollander (ThomasdenH), (hostbrute); reviewing and discussion: Aaron van Geffen (AaronVanGeffen), (Balletie) and Sijmen Schoon (Vijfhoek). -* Finnish - (DJHasis) -* French - (fbourigault), Joël Troch (JoelTroch), Michael Steenbeek (Gymnasiast) -* German - (danidoedel), (atmaxinger), (Yepoleb), Daniel Kessel (dkessel), Leon (AllGoodNamesAreTaken) -* Korean - "TELK" (telk5093) -* Polish - Adrian Wielgosik (adrian17) -* Portuguese (BR) - (kaudy) +* English (US) - Ted John (IntelOrca), Michael Steenbeek (Gymnasiast); small fixes: LRFLEW, mike-koch +* Czech - Martin Černáč (octaroot), (Clonewayx), Tomáš Pazdiora (Aroidzap) +* Dutch - Michael Steenbeek (Gymnasiast), Yannic Geurts (xzbobzx), (mrtnptrs), Thomas den Hollander (ThomasdenH), (hostbrute), Marijn van de Werf (marijnvdwerf); reviewing and discussion: Aaron van Geffen (AaronVanGeffen), (Balletie) and Sijmen Schoon (Vijfhoek). +* Finnish - (DJHasis), (Zode), (TheWing) +* French - (fbourigault), Joël Troch (JoelTroch), Michael Steenbeek (Gymnasiast), Romain Vigier (rvgr), (AziasYur), Hugo Courtial (s0r00t), David Delobel (incyclum) +* German - (danidoedel), (atmaxinger), (Yepoleb), Daniel Kessel (dkessel), Leon (AllGoodNamesAreTaken), (raidcookie) +* Japanese - Aaron van Geffen (AaronVanGeffen), Nick Hall (nickhall), (jhako) +* Korean - "TELK" (telk5093), (NeverDruid); small fixes: (kexplo) +* Polish - Adrian Wielgosik (adrian17), (lopezloo), Michał Janiszewski (janisozaur) +* Portuguese (BR) - (kaudy), (renansimoes) * Russian - (Soosisya) -* Simplified Chinese - Naiji Ma (naijim) -* Spanish - (mdtrooper) -* Swedish - (Jinxit), (mharrys), (Slimeyo) +* Simplified Chinese - Naiji Ma (naijim), (izhangfei), Eric Zhao (sczyh30) +* Spanish - (mdtrooper), Josué Acevedo (Wirlie), Daniel Trujillo Viedma (gdabi); small fixes: (teapartycthulu) +* Swedish - (Jinxit), (mharrys), (Slimeyo), (Nubbie) * Traditional Chinese - Harry Lam (daihakken) ## Graphics -* OpenRCT2 Logo - xzbobzx +* OpenRCT2 Logo - Yannic Geurts (xzbobzx) ## RollerCoaster Tycoon 2 credits Design and programming by Chris Sawyer diff --git a/data/language/chinese_simplified.txt b/data/language/chinese_simplified.txt index e6e1d54475..d6e793ca86 100644 --- a/data/language/chinese_simplified.txt +++ b/data/language/chinese_simplified.txt @@ -4,9 +4,9 @@ STR_0000 : STR_0001 :{STRINGID} {COMMA16} STR_0002 :螺旋过山车 -STR_0003 :站立过山车 +STR_0003 :站立式过山车 STR_0004 :悬挂摇摆过山车 -STR_0005 :回转过山车 +STR_0005 :翻转式过山车 STR_0006 :儿童过山车 STR_0007 :迷你火车 STR_0008 :单轨电车 @@ -19,12 +19,12 @@ STR_0014 :喷射-自由落体 STR_0015 :雪橇过山车 STR_0016 :观景塔 # I could not find this thing in the game -STR_0017 :Looping Roller Coaster +STR_0017 :回环式过山车 STR_0018 :充气小艇滑道 STR_0019 :矿车过山车 STR_0020 :缆车 # STR_0021 has the same meaning as STR_0001 in chinese -STR_0021 :Corkscrew Roller Coaster +STR_0021 :螺旋过山车 STR_0022 :迷宫 STR_0023 :螺旋滑梯 STR_0024 :卡丁车 @@ -57,8 +57,8 @@ STR_0048 :龙卷风 STR_0049 :鬼屋 STR_0050 :急救室 STR_0051 :马戏表演 -STR_0052 :Tunnel Of Horror -STR_0053 :Steel Twister Roller Coaster +STR_0052 :恐怖隧道 +STR_0053 :铁架旋转式过山车 STR_0054 :木制过山车 STR_0055 :Side-Friction Roller Coaster STR_0056 :疯狂老鼠过山车 @@ -67,26 +67,26 @@ STR_0058 :Unknown Ride (38) STR_0059 :飞翔过山车 STR_0060 :Unknown Ride (3A) STR_0061 :弗吉尼亚卷轴 -STR_0062 :Splash Boats +STR_0062 :激流勇进 STR_0063 :迷你直升机 -STR_0064 :躺卧过山车 +STR_0064 :躺卧式过山车 STR_0065 :悬挂式单轨电车 STR_0066 :Unknown Ride (40) STR_0067 :反转过山车 STR_0068 :Heartline Twister Coaster STR_0069 :迷你高尔夫 STR_0070 :巨型过山车 -STR_0071 :Roto-Drop +STR_0071 :旋转落体 STR_0072 :转转飞碟 STR_0073 :鬼怪屋 STR_0074 :单轨自行车 STR_0075 :紧凑回转过山车 -STR_0076 :Water Coaster +STR_0076 :水上过山车 STR_0077 :喷气弹射过山车 STR_0078 :回转发卡过山车 STR_0079 :魔毯 STR_0080 :迷你潜艇 -STR_0081 :小木筏 +STR_0081 :水上木筏 STR_0082 :Unknown Ride (50) STR_0083 :Enterprise STR_0084 :Unknown Ride (52) @@ -95,7 +95,7 @@ STR_0086 :Unknown Ride (54) STR_0087 :Unknown Ride (55) STR_0088 :回转冲力过山车 STR_0089 :迷你过山车 -STR_0090 :Mine Ride +STR_0090 :矿车式过山车 STR_0091 :Unknown Ride (59) # LIM: Linear Induction Motors STR_0092 :LIM喷射过山车 @@ -886,8 +886,8 @@ STR_0875 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP STR_0876 :{BLACK}{DOWN} STR_0877 :太低! STR_0878 :太高! -STR_0879 :不能降低土地... -STR_0880 :不能抬升土地... +STR_0879 :不能在这里降低土地... +STR_0880 :不能在这里抬升土地... STR_0881 :有物体挡住去路 STR_0882 :载入游戏 STR_0883 :保存游戏 @@ -909,13 +909,13 @@ STR_0898 :{SMALLFONT}{BLACK}左转 STR_0899 :{SMALLFONT}{BLACK}右转 STR_0900 :{SMALLFONT}{BLACK}左转 (小弧度) STR_0901 :{SMALLFONT}{BLACK}右转 (小弧度) -STR_0902 :{SMALLFONT}{BLACK}Left-hand curve (very small radius) -STR_0903 :{SMALLFONT}{BLACK}Right-hand curve (very small radius) -STR_0904 :{SMALLFONT}{BLACK}Left-hand curve (large radius) -STR_0905 :{SMALLFONT}{BLACK}Right-hand curve (large radius) -STR_0906 :{SMALLFONT}{BLACK}Straight -STR_0907 :Slope -STR_0908 :Roll/Banking +STR_0902 :{SMALLFONT}{BLACK}左转(很小的弧度) +STR_0903 :{SMALLFONT}{BLACK}右转(很小的弧度) +STR_0904 :{SMALLFONT}{BLACK}左转(大弧度) +STR_0905 :{SMALLFONT}{BLACK}右转(大弧度) +STR_0906 :{SMALLFONT}{BLACK}直行 +STR_0907 :坡度 +STR_0908 :滚动/倾斜 STR_0909 :Seat Rot. STR_0910 :{SMALLFONT}{BLACK}Roll for left-hand curve STR_0911 :{SMALLFONT}{BLACK}Roll for right-hand curve @@ -924,43 +924,43 @@ STR_0913 :{SMALLFONT}{BLACK}Move to previous section STR_0914 :{SMALLFONT}{BLACK}Move to next section STR_0915 :{SMALLFONT}{BLACK}Construct the selected section STR_0916 :{SMALLFONT}{BLACK}Remove the highlighted section -STR_0917 :{SMALLFONT}{BLACK}Vertical drop -STR_0918 :{SMALLFONT}{BLACK}Steep slope down -STR_0919 :{SMALLFONT}{BLACK}Slope down -STR_0920 :{SMALLFONT}{BLACK}Level -STR_0921 :{SMALLFONT}{BLACK}Slope up -STR_0922 :{SMALLFONT}{BLACK}Steep slope up -STR_0923 :{SMALLFONT}{BLACK}Vertical rise -STR_0924 :{SMALLFONT}{BLACK}Helix down -STR_0925 :{SMALLFONT}{BLACK}Helix up -STR_0926 :Can't remove this... -STR_0927 :Can't construct this here... +STR_0917 :{SMALLFONT}{BLACK}垂直下坡 +STR_0918 :{SMALLFONT}{BLACK}陡峭下坡 +STR_0919 :{SMALLFONT}{BLACK}下坡 +STR_0920 :{SMALLFONT}{BLACK}水平 +STR_0921 :{SMALLFONT}{BLACK}上坡 +STR_0922 :{SMALLFONT}{BLACK}陡峭上坡 +STR_0923 :{SMALLFONT}{BLACK}垂直上坡 +STR_0924 :{SMALLFONT}{BLACK}向下螺旋 +STR_0925 :{SMALLFONT}{BLACK}向上螺旋 +STR_0926 :不能移除此物... +STR_0927 :不能在此建造... STR_0928 :{SMALLFONT}{BLACK}Chain lift, to pull cars up slopes -STR_0929 :'S' Bend (left) -STR_0930 :'S' Bend (right) -STR_0931 :Vertical Loop (left) -STR_0932 :Vertical Loop (right) -STR_0933 :Raise or lower land first -STR_0934 :Ride entrance in the way -STR_0935 :Ride exit in the way -STR_0936 :Park entrance in the way +STR_0929 :'S'型弯道 (向左) +STR_0930 :'S'型弯道 (向右) +STR_0931 :垂直回环 (向左) +STR_0932 :垂直回环 (向右) +STR_0933 :请先将地面抬升或降低 +STR_0934 :游乐设施入口挡在此处 +STR_0935 :游乐设施出口挡在此处 +STR_0936 :游乐场的入口挡在此处 STR_0937 :{SMALLFONT}{BLACK}View options -STR_0938 :{SMALLFONT}{BLACK}Adjust land height and slope -STR_0939 :Underground/Inside View -STR_0940 :Remove Base Land -STR_0941 :Remove Vertical Faces -STR_0942 :See-Through Rides -STR_0943 :See-Through Scenery -STR_0944 :Save -STR_0945 :Don't Save -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_0953 :Load Landscape +STR_0938 :{SMALLFONT}{BLACK}调整地势高低及陡峭程度 +STR_0939 :地下/内部 视图模式 +STR_0940 :移除地表 +STR_0941 :移除垂直地面 +STR_0942 :略过游乐设施 +STR_0943 :掠过景物 +STR_0944 :保存 +STR_0945 :不保存 +STR_0946 :取消 +STR_0947 :是否在载入其他存档之前保存游戏 ? +STR_0948 :是否在退出之前保存游戏 ? +STR_0949 :是否在退出之前保存游戏 ? +STR_0950 :加载游戏 +STR_0951 :退出游戏 +STR_0952 :退出游戏 +STR_0953 :载入地形 STR_0954 : STR_0955 :{SMALLFONT}{BLACK}Select seat rotation angle for this track section STR_0956 :-180{DEGREE} @@ -979,18 +979,18 @@ STR_0968 :+360{DEGREE} STR_0969 :+405{DEGREE} STR_0970 :+450{DEGREE} STR_0971 :+495{DEGREE} -STR_0972 :Cancel -STR_0973 :OK -STR_0974 :Rides -STR_0975 :Shops and Stalls -STR_0976 :Restrooms and Information Kiosks -STR_0977 :New Transport Rides -STR_0978 :New Gentle Rides -STR_0979 :New Roller Coasters -STR_0980 :New Thrill Rides -STR_0981 :New Water Rides -STR_0982 :New Shops & Stalls -STR_0983 :Research & Development +STR_0972 :取消 +STR_0973 :确定 +STR_0974 :游乐设施 +STR_0975 :商店及摊贩 +STR_0976 :洗手间及服务台 +STR_0977 :建造新的运输类游乐设施 +STR_0978 :建造新的温和类游乐设施 +STR_0979 :建造新的过山车 +STR_0980 :建造新的刺激类游乐设施 +STR_0981 :建造新的水上游乐设施 +STR_0982 :建造新的商店及摊贩 +STR_0983 :研究及开发 STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP} STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP} STR_0986 :{BLACK}{CURRENCY2DP} @@ -998,30 +998,30 @@ STR_0987 :Too many rides/attractions STR_0988 :Can't create new ride/attraction... STR_0989 :{STRINGID} STR_0990 :{SMALLFONT}{BLACK}Construction -STR_0991 :Station platform +STR_0991 :车站站台 STR_0992 :{SMALLFONT}{BLACK}Demolish entire ride/attraction STR_0993 :Demolish ride/attraction STR_0994 :Demolish STR_0995 :{WINDOW_COLOUR_1}Are you sure you want to completely demolish {STRINGID}? -STR_0996 :Overall view +STR_0996 :整体外观 STR_0997 :{SMALLFONT}{BLACK}View selection STR_0998 :No more stations allowed on this ride -STR_0999 :Requires a station platform -STR_1000 :Track is not a complete circuit -STR_1001 :Track unsuitable for type of train +STR_0999 :需要一个车站站台 +STR_1000 :轨道没有连接完整 +STR_1001 :轨道不适合此类型的车 STR_1002 :Can't open {POP16}{POP16}{POP16}{STRINGID}... STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID}... STR_1004 :Can't close {POP16}{POP16}{POP16}{STRINGID}... STR_1005 :Can't start construction on {POP16}{POP16}{POP16}{STRINGID}... -STR_1006 :Must be closed first +STR_1006 :必须先关闭 STR_1007 :Unable to create enough vehicles STR_1008 :{SMALLFONT}{BLACK}Open, close, or test ride/attraction STR_1009 :{SMALLFONT}{BLACK}Open or close all rides/attractions STR_1010 :{SMALLFONT}{BLACK}Open or close park -STR_1011 :Close all -STR_1012 :Open all -STR_1013 :Close park -STR_1014 :Open park +STR_1011 :关闭所有游乐设施 +STR_1012 :开启所有游乐设施 +STR_1013 :关闭游乐场 +STR_1014 :开放游乐场 STR_1015 :Unable to operate with more than one station platform in this mode STR_1016 :Unable to operate with less than two stations in this mode STR_1017 :Can't change operating mode... @@ -1043,21 +1043,21 @@ STR_1032 :Can only build this on water! STR_1033 :Can only build this above ground! STR_1034 :Can only build this on land! STR_1035 :Local authority won't allow construction above tree-height! -STR_1036 :Load Game -STR_1037 :Load Landscape -STR_1038 :Convert saved game to scenario -STR_1039 :Install new track design -STR_1040 :Save Game -STR_1041 :Save Scenario -STR_1042 :Save Landscape -STR_1043 :OpenRCT2 Saved Game -STR_1044 :OpenRCT2 Scenario File -STR_1045 :OpenRCT2 Landscape File -STR_1046 :OpenRCT2 Track Design File -STR_1047 :Game save failed! -STR_1048 :Scenario save failed! -STR_1049 :Landscape save failed! -STR_1050 :Failed to load...{NEWLINE}File contains invalid data! +STR_1036 :载入游戏 +STR_1037 :载入存档 +STR_1038 :将存档转换为关卡 +STR_1039 :添加新的轨道设计 +STR_1040 :保存游戏 +STR_1041 :保存关卡 +STR_1042 :保存地形 +STR_1043 :OpenRCT2 游戏存档 +STR_1044 :OpenRCT2 关卡文件 +STR_1045 :OpenRCT2 地形文件 +STR_1046 :OpenRCT2 轨道设计文件 +STR_1047 :存储游戏失败! +STR_1048 :存储关卡失败! +STR_1049 :存储地形失败! +STR_1050 :载入失败...{NEWLINE}文件中含有不可读取的数据! STR_1051 :Invisible Supports STR_1052 :Invisible People STR_1053 :{SMALLFONT}{BLACK}Rides/attractions in park @@ -3826,4 +3826,4 @@ STR_5477 :Map rendering STR_5478 :Controls STR_5479 :Toolbar STR_5480 :Show toolbar buttons for: -STR_5481 :Themes +STR_5481 :主题 diff --git a/data/language/chinese_traditional.txt b/data/language/chinese_traditional.txt index f7c6349065..307afc714e 100644 --- a/data/language/chinese_traditional.txt +++ b/data/language/chinese_traditional.txt @@ -1201,8 +1201,8 @@ STR_1195 :測試中 STR_1196 :已開啟 STR_1197 :故障了 STR_1198 :毀壞了! -STR_1199 :{COMMA16} 個遊客在這個遊樂設施上 -STR_1200 :{COMMA16} 個遊客在這個遊樂設施上 +STR_1199 :{COMMA16}個遊客在這個遊樂設施上 +STR_1200 :{COMMA16}個遊客在這個遊樂設施上 STR_1201 :無人在排隊 STR_1202 :1個遊客在排隊 STR_1203 :{COMMA16}個遊客在排隊 @@ -1925,7 +1925,7 @@ STR_1917 :{POP16}{POP16}{POP16}{CURRENCY} STR_1918 :不能再借貸更多錢! STR_1919 :沒有足夠的現金! STR_1920 :不能償還貸款! -STR_1921 :{SMALLFONT}{BLACK}開新遊戲 +STR_1921 :{SMALLFONT}{BLACK}開始新遊戲 STR_1922 :{SMALLFONT}{BLACK}繼續遊玩存檔 STR_1923 :{SMALLFONT}{BLACK}開始教學 STR_1924 :{SMALLFONT}{BLACK}退出遊戲 @@ -2748,7 +2748,7 @@ STR_2739 :無 STR_2740 :夢幻遊樂園 (RCT1) STR_2741 :模擬樂園 (RCT2) STR_2742 :找不到css50.dat -STR_2743 :複製夢幻遊樂園(RCT1)文件夾中的'data\css17.dat'到模擬樂園(RCT2)的文件夾, 並重新命名為'data\css50.dat'. +STR_2743 :請複製夢幻遊樂園(RCT1)文件夾中的'data\css17.dat'到模擬樂園(RCT2)的文件夾, 並重新命名為'data\css50.dat'. STR_2744 :[ STR_2745 :\ STR_2746 :] @@ -2763,8 +2763,8 @@ STR_2753 :除好草的草地 STR_2754 :灌溉花圃 STR_2755 :修復被毀壞的物件 STR_2756 :移除垃圾 -STR_2757 :強制晴天 -STR_2758 :強制雷暴 +STR_2757 : +STR_2758 : STR_2759 :無'擋在路上'檢查 STR_2760 :+{CURRENCY} STR_2761 : @@ -2781,7 +2781,7 @@ STR_2771 :減慢遊戲速度 STR_2772 :加快遊戲速度 STR_2773 :視窗化 STR_2774 :全螢幕 -STR_2775 :全螢幕 (桌面尺寸) +STR_2775 :全螢幕 (無邊框視窗) STR_2776 :語言: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} @@ -3228,16 +3228,16 @@ STR_3217 :已擁有的土地 STR_3218 :已擁有建造權的土地 STR_3219 :可供購買的土地 STR_3220 :可供購買建造權的土地 -STR_3221 :{SMALLFONT}{BLACK}將樂園設置成為土地的擁有者 -STR_3222 :{SMALLFONT}{BLACK}尤樂園擁有土地的建造權 +STR_3221 :{SMALLFONT}{BLACK}令樂園成為土地的擁有者 +STR_3222 :{SMALLFONT}{BLACK}令樂園擁有土地的建造權 STR_3223 :{SMALLFONT}{BLACK}將土地設置成為可供樂園購買 STR_3224 :{SMALLFONT}{BLACK}將土地的建造權設置成為可供樂園購買 -STR_3225 :{SMALLFONT}{BLACK}設置是否在選中的位置中建造一些隨機物件 +STR_3225 :{SMALLFONT}{BLACK}設置是否在選中的位置中隨機建造一些物件 STR_3226 :{SMALLFONT}{BLACK}建造樂園入口 STR_3227 :太多樂園入口! STR_3228 :{SMALLFONT}{BLACK}設置遊客的開始步行位置 STR_3229 :區域煞車不能建造在車站之後 -STR_3230 :區域煞車不能建造在自己之後 +STR_3230 :區域煞車不能建造在另一個區域煞車之後 STR_3231 :區域煞車不能建造在這個鏈條坡道的頂部之後 STR_3232 :選項 - 財政 STR_3233 :選項 - 遊客 @@ -3281,9 +3281,9 @@ STR_3270 :{SMALLFONT}{BLACK}禁止對地形作任何調整 STR_3271 :禁止高空建造 STR_3272 :{SMALLFONT}{BLACK}禁止任何高空發展 STR_3273 :較高難度的樂園評價公式 -STR_3274 :{SMALLFONT}{BLACK}使增加樂園評價更加有挑戰性 +STR_3274 :{SMALLFONT}{BLACK}使增加樂園評價更具挑戰性 STR_3275 :較難生成遊客 -STR_3276 :{SMALLFONT}{BLACK}使吸引遊客更加有挑戰性 +STR_3276 :{SMALLFONT}{BLACK}使吸引遊客更具挑戰性 STR_3277 :{WINDOW_COLOUR_2}購買土地的費用: STR_3278 :{WINDOW_COLOUR_2}購買建造權利的費用: STR_3279 :免費進入樂園 / 需費乘搭遊樂設施 @@ -3331,7 +3331,7 @@ STR_3320 :無法儲存劇情檔案... STR_3321 :成功安裝新物件 STR_3322 :{WINDOW_COLOUR_2}目標: {BLACK}{STRINGID} STR_3323 :缺少物件資料, ID為: -STR_3324 :需要資料片: +STR_3324 :需要資料片: {STRINGID} STR_3325 :需要一隻資料片 STR_3326 :{WINDOW_COLOUR_2}(暫無圖片) STR_3327 :尚未設定遊客的開始步行位置 @@ -3341,7 +3341,7 @@ STR_3330 :樂園必需有一些己擁有的土地 STR_3331 :由地圖邊緣到樂園入口的道路尚未連接好, 或者太複雜 - 這些道路必需是一格寬度, 並以越少交界及彎位越好 STR_3332 :樂園入口倒轉了, 或沒有道路連接至地圖邊緣 STR_3333 :在存檔中導出附加物件 -STR_3334 :{SMALLFONT}{BLACK}選擇是否儲存附加物件(額外加入的附加物件)到存檔, 以便存檔給沒有那些附加物件的人載入 +STR_3334 :{SMALLFONT}{BLACK}選擇是否儲存附加物件(額外加入的附加物件)到存檔, 以便沒有那些附加物件的人載入存檔 STR_3335 :雲霄飛車設計工具 - 選擇要設計的雲霄飛車的類型及車輛種類 STR_3336 :軌道設計管理工具 - 選擇要管理的遊樂設施的類型 STR_3337 : @@ -3360,8 +3360,8 @@ STR_3349 :刪除 STR_3350 :軌道設計名稱 STR_3351 :請輸入這個軌道設計的新名稱: STR_3352 :不能重命名這個軌道設計... -STR_3353 :新名稱含有不適合的字符 -STR_3354 :已有另外一個檔案為相同名稱, 或檔案被寫入保護 +STR_3353 :新名稱含有不合適的字符 +STR_3354 :已有另外一個相同名稱的檔案, 或檔案被寫入保護 STR_3355 :檔案被寫入保護或被鎖定 STR_3356 :刪除檔案 STR_3357 :{WINDOW_COLOUR_2}你確定要永久刪除{STRINGID} ? @@ -3465,7 +3465,7 @@ STR_5123 :翻新遊樂設施 STR_5124 : STR_5125 :全可拆卸 STR_5126 :隨機播放主題曲 -STR_5127 :{SMALLFONT}{BLACK}禁止調整地勢 +STR_5127 :{SMALLFONT}{BLACK}拖曳調整地形, 而不調整地勢 STR_5128 :選擇大小 STR_5129 :請輸入介於{COMMA16}及{COMMA16}的選擇大小 STR_5130 :地圖大小 @@ -3475,7 +3475,7 @@ STR_5133 :{SMALLFONT}{BLACK}選擇較小的土地範圍 STR_5134 :{SMALLFONT}{BLACK}選擇較大的土地範圍 STR_5135 :{SMALLFONT}{BLACK}購買土地擁有權或建造權 STR_5136 :土地擁有權 -STR_5137 :允許鏈條上拉及發車速度高至{VELOCITY} +STR_5137 :移除遊樂設施的運行限制 STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} STR_5140 :去除煞車組件故障 @@ -3515,7 +3515,7 @@ STR_5173 :將Twitch聊天室的內容推送為新聞 STR_5174 :{SMALLFONT}{BLACK}會將Twitch聊天室所有標'!news'的內容以最近消息顯示於遊戲內 STR_5175 :請輸入你的Twitch頻道名稱 STR_5176 :准許Twitch頻道融合於遊戲之中 -STR_5177 :全屏幕模式: +STR_5177 :顯示模式: STR_5178 :{SMALLFONT}{BLACK}顯示用於財政的密技 STR_5179 :{SMALLFONT}{BLACK}顯示用於遊客的密技 STR_5180 :{SMALLFONT}{BLACK}顯示用於樂園的密技 @@ -3617,14 +3617,14 @@ STR_5275 :搜尋物件 STR_5276 :請輸入你要搜尋的物件名稱 STR_5277 :清除 STR_5278 :沙盒模式 -STR_5279 :沙盒模式關閉 +STR_5279 :關閉沙盒模式 STR_5280 :{SMALLFONT}{BLACK}允許從地圖視窗中修改土地擁有權, 以及其他平常只適用於劇情編輯工具的選項 STR_5281 :{SMALLFONT}{BLACK}功能 STR_5282 :夢幻遊樂場 (RCT1)遊樂設施開關燈號 STR_5283 :夢幻遊樂場 (RCT1)樂園開關燈號 STR_5284 :夢幻遊樂場 (RCT1)選擇劇情字體 STR_5285 :人肉炸彈!!! -STR_5286 :{SMALLFONT}{BLACK}將某些遊客爆炸,嘻嘻! +STR_5286 :{SMALLFONT}{BLACK}令某些遊客立即爆炸, 嘻嘻! STR_5287 :遊樂設施已經故障了 STR_5288 :遊樂設施已關閉了 STR_5289 :沒有故障可適用於此遊樂設施 @@ -3642,7 +3642,7 @@ STR_5300 :{SMALLFONT}{BLACK}一鍵解僱員工 STR_5301 :{MEDIUMFONT}{BLACK}付清你的貸款 STR_5302 :付清貸款 STR_5303 :暫停時可以建造物件 -STR_5304 :主畫面動畫: +STR_5304 :主選單動畫: STR_5305 :夢幻遊樂場 (RCT1) STR_5306 :夢幻遊樂場 (RCT1) (+資料片1 - AA) STR_5307 :夢幻遊樂場 (RCT1) (+資料片1&2 - AA+LL) @@ -3742,7 +3742,7 @@ STR_5399 :按'暫停'按鈕繼續編輯 STR_5400 :不能更改此主選單動畫 STR_5401 :建立新的主選單動畫, 並作出更改 STR_5402 :載入主選單動畫失敗 -STR_5403 :非法的存檔或沒有'Load'或'Wait'指令 +STR_5403 :非法的存檔或沒有'載入'或'等候'指令 STR_5404 :名稱已經存在 STR_5405 :請輸入存檔名稱 STR_5406 :請輸入主選單動畫存檔名稱 @@ -3780,7 +3780,7 @@ STR_5437 :暫無存檔被選中 STR_5438 :當命令編輯工具開啟不能作出改變 STR_5439 :4秒以上的等待(Wait)命令需要加上重新開始(Restart)命令 STR_5440 :當焦點失去時最小化全螢幕的遊戲 -STR_5441 :{SMALLFONT}{BLACK}以軌道類別分別遊樂設施,{NEWLINE}令到車輔風格可以在建造後更改,{NEWLINE}就像夢幻遊樂園1(RCT1)一樣. +STR_5441 :{SMALLFONT}{BLACK}以軌道類別分別遊樂設施,{NEWLINE}就像夢幻遊樂園1(RCT1)一樣,{NEWLINE}令到車輔風格可以在建造後更改. STR_5442 :固定樂園評價: STR_5443 :速度{MOVE_X}{87}{STRINGID} STR_5444 :速度: @@ -3840,7 +3840,7 @@ STR_5497 :延遲值 (Ping): STR_5498 :伺服器列表 STR_5499 :玩家名稱: STR_5500 :新增伺服器 -STR_5501 :開始伺服器 +STR_5501 :開設伺服器 STR_5502 :多人連線模式 STR_5503 :請輸入主機名稱或IP地址: STR_5504 :{SMALLFONT}{BLACK}顯示多人連線狀態 @@ -3849,7 +3849,7 @@ STR_5506 :遊客無視設施的刺激度 STR_5507 :預設清潔工人會修剪草皮 STR_5508 :允許載入校驗失敗的檔案 STR_5509 :{SMALLFONT}{BLACK}允許載入校驗失敗的劇情及存檔, 例如試玩版的劇情或已損壞的存檔. -STR_5510 :預設聲效裝置 +STR_5510 :預設音效裝置 STR_5511 :(未知) STR_5512 :另存遊戲 STR_5513 :(快速)儲存遊戲 @@ -3895,7 +3895,7 @@ STR_5552 :{POP16}{POP16}第{COMMA16}年, {PUSH16}{PUSH16}{PUSH16}{STRINGID} { STR_5553 :當Steam overlay開啟時暫停遊戲 STR_5554 :{SMALLFONT}{BLACK}啟用山丘工具 STR_5555 :顯示來自其他類型軌道的車輛種類 -STR_5556 :踢走玩家 +STR_5556 :{SMALLFONT}{BLACK}踢除玩家 STR_5557 :多人遊戲不同步時依然保持連線 STR_5558 :此設定會於重啟遊戲後生效 STR_5559 :檢查時距為10分鐘 @@ -3906,7 +3906,7 @@ STR_5563 :此功能暫未穩定地使用, 請多加留意. STR_5564 :插入已損壞元素 STR_5565 :{SMALLFONT}{BLACK}在一個網格的最上插入一個已損壞的地圖元素. 此插入會隱藏其他元素. STR_5566 :密碼: -STR_5567 :推廣 +STR_5567 :推廣由主伺服器列表中 STR_5568 :輸入密碼 STR_5569 :此伺服器被密碼保護 STR_5570 :索取伺服器 @@ -3914,14 +3914,316 @@ STR_5571 :加入遊戲 STR_5572 :加入最愛 STR_5573 :由最愛中移除 STR_5574 :伺服器名稱: -STR_5575 :最多玩家數: +STR_5575 :最大玩家數量: STR_5576 :連接埠: STR_5577 :南韓園 (₩) STR_5578 :俄羅斯盧布 (R) STR_5579 :顥示縮放因子: STR_5580 :捷克克朗 (Kc) +STR_5581 :顥示幀數 +STR_5582 :限制滑鼠游標於視窗中移動 +STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} +STR_5584 :SI +STR_5585 :{SMALLFONT}{BLACK}移除遊樂設施的運行限制, 例如容許鏈條上拉速度高達{VELOCITY} +STR_5586 :自動開啟商店及攤販 +STR_5587 :{SMALLFONT}{BLACK}當此設定啟用後, 商店及攤販將會於建造後自動開啟 +STR_5588 :{SMALLFONT}{BLACK}與其他玩家一起遊玩 +STR_5589 :消息設定 +STR_5590 :樂園獎項 +STR_5591 :推廣計劃已完結 +STR_5592 :有關樂園的警告 +STR_5593 :有關樂園評價的警告 +STR_5594 :遊樂設施發生故障 +STR_5595 :遊樂設施毀壞了 +STR_5596 :有關遊樂設施的警告 +STR_5597 :研發好的遊樂設施,商店或景物 +STR_5598 :有關遊客的警告 +STR_5599 :遊客迷路了 +STR_5600 :遊客已離開樂園 +STR_5601 :遊客正在排隊遊玩某個遊樂設施 +STR_5602 :遊客已乘上遊樂設施 +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 :建設你的.. +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}已花費金錢: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}已運行命名: {BLACK}{COMMA16}個 +STR_5637 :無法進行此動作... +STR_5638 :並沒有足夠的權限 +STR_5639 :{SMALLFONT}{BLACK}顯示玩家列表 +STR_5640 :{SMALLFONT}{BLACK}管理組別 +STR_5641 :預設組別: +STR_5642 :組別: +STR_5643 :新增組別 +STR_5644 :移除組別 +STR_5645 :聊天 +STR_5646 :修改地勢 +STR_5647 :暫停遊戲 +STR_5648 :修改湖泊及水塘 +STR_5649 :開始建造遊樂設施 +STR_5650 :移除遊樂設施 +STR_5651 :建造遊樂設施 +STR_5652 :修改遊樂設施的設置 +STR_5653 :修改景物 +STR_5654 :放置道路 +STR_5655 :修改遊客 +STR_5656 :修改員工 +STR_5657 :修改樂園的設置 +STR_5658 :修改樂園資金的設置 +STR_5659 :踢除玩家 +STR_5660 :修改組別 +STR_5661 :將玩家分配到個別組別 +STR_5662 :N/A +STR_5663 :清除景物 +STR_5664 :密技 +STR_5665 :啟用/禁用景物批量放置 +STR_5701 :{WINDOW_COLOUR_2}最近的動作: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}將這個玩家的最近的動作定位 +STR_5703 :無法踢除架設者 +STR_5704 :最近的動作: +STR_5705 :無法將此玩家分配到此組別 +STR_5706 :無法移除有玩家在內的組別 +STR_5707 :無法修改此組別 +STR_5708 :無法改變架設者身處的組別 +STR_5709 :重命名組別 +STR_5710 :組別名稱 +STR_5711 :請輸入這個組別的新名稱: +STR_5712 :無法修改你沒有的權限 +STR_5713 :踢除玩家 +STR_5714 :顯示設定視窗 +STR_5715 :開新遊戲 +STR_5716 :無法於多人連線模式中使用 +# For identifying client network version in server list window +STR_5717 :多人連線版本: {STRING} +STR_5718 :{SMALLFONT}{BLACK}多人連線版本: {STRING} +STR_5719 :晴天 +STR_5720 :間中陰天 +STR_5721 :陰天 +STR_5722 :有雨 +STR_5723 :大雨 +STR_5724 :雷暴 +STR_5725 :{BLACK}強制設定天氣為: +STR_5726 :{SMALLFONT}{BLACK}設定樂園目前的天氣 +STR_5727 :縮放品質 +STR_5728 :需要啟用硬體渲染 +STR_5729 :{SMALLFONT}{BLACK}需要啟用硬體渲染 +STR_5730 :最鄰近 +STR_5731 :線性 +STR_5732 :各向異性 +STR_5733 :以整數比例調整最鄰近式縮放 +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}渲染 +STR_5735 :網絡狀況 +STR_5736 :玩家 +STR_5737 :已關閉, {COMMA16}個遊客依然在這個遊樂設施上 +STR_5738 :已關閉, {COMMA16}個遊客依然在這個遊樂設施上 +STR_5739 :{WINDOW_COLOUR_2}在這個遊樂設施上的遊客: {BLACK}{COMMA16} +STR_5740 :永不完結的推廣計劃 +STR_5741 :{SMALLFONT}{BLACK}推廣計劃將會不斷推行下去 +STR_5742 :認證中... +STR_5743 :連線中... +STR_5744 :索取伺服器地址中... +STR_5745 :網絡不同步已被偵察 +STR_5746 :已斷線 +STR_5747 :已斷線: {STRING} +STR_5748 :已被踢除 +STR_5749 :請離開這個伺服器! +STR_5750 :連線已關閉 +STR_5751 :接收不到任何資料 +STR_5752 :{OUTLINE}{RED}{STRING}已離開遊戲 +STR_5753 :{OUTLINE}{RED}{STRING}已離開遊戲 ({STRING}) +STR_5754 :不合適的玩家名字 +STR_5755 :不合適的遊戲版本 +STR_5756 :密碼錯誤 +STR_5757 :伺服器人數已滿 +STR_5758 :{OUTLINE}{GREEN}{STRING}已加入遊戲 +STR_5759 :下載劇情中... ({INT32} / {INT32}) +STR_5760 :港幣 (HK$) +STR_5761 :新台幣 (NT$) +STR_5762 :人民幣 (CN{YEN}) +STR_5763 :所有檔案 +STR_5764 :不正確的遊樂設施類別 +STR_5765 :無法修改不正確類別的遊樂設施 +STR_5766 : +STR_5767 :收入 +STR_5768 :總乘客數 +STR_5769 :總利潤 +STR_5770 :每小時服務的遊客 +STR_5771 :運行費用 +STR_5772 :年齡 +STR_5773 :總乘客數: {COMMA32} +STR_5774 :總利潤: {CURRENCY2DP} +STR_5775 :乘客: {BLACK}每小時{COMMA32}個 +STR_5776 :落成年份: {BLACK}今年 +STR_5777 :落成年份: {BLACK}去年 +STR_5778 :落成年份: {BLACK}{COMMA16}年前 +STR_5779 :利潤: 每小時{CURRENCY2DP} +STR_5780 :運作成本: {BLACK}每小時{CURRENCY2DP} +STR_5781 :運作成本: {BLACK}未知 +STR_5782 :你已經連接到伺服器. 按 '{STRING}' 來聊天. +STR_5783 :{WINDOW_COLOUR_2}劇情未解開 +STR_5784 :{BLACK}完成已解開的劇情來解開此劇情. +STR_5785 :不能重命名組別... +STR_5786 :不正確的組別名稱 +STR_5787 :{COMMA32} 玩家在線 +STR_5788 :預設檢查遊樂設施的時隔: +STR_5789 :禁用光影效果 +STR_5790 :{SMALLFONT}{BLACK}開啟/關閉夢幻遊樂園式的收費系統-{NEWLINE}(例如同時收取遊樂設施及進場費用) +STR_5791 :{SMALLFONT}{BLACK}設定所有遊樂設施的可靠度為100%{NEWLINE}並重設他們的落成年份為"今年" +STR_5792 :{SMALLFONT}{BLACK}修理所有已故障的遊樂設施 +STR_5793 :{SMALLFONT}{BLACK}重設指定遊樂設施的毀壞記錄,{NEWLINE}令遊客不覺得該設施不安全 +STR_5794 :{SMALLFONT}{BLACK}此密技移除某些劇情禁止修改{NEWLINE}某些已預先建設好的遊樂設施的限制 +STR_5795 :{SMALLFONT}{BLACK}遊客會乘坐所有樂園內的遊樂設施{NEWLINE}即使它們的刺激度極端地高 +STR_5796 :{SMALLFONT}{BLACK}強制開放或關閉樂園 +STR_5797 :{SMALLFONT}{BLACK}禁止天氣轉變並{NEWLINE}固定於選定的天氣 +STR_5798 :{SMALLFONT}{BLACK}允許暫停時建造物件 +STR_5799 :{SMALLFONT}{BLACK}禁止所有因煞車故障發生的故障及毀壞 +STR_5800 :{SMALLFONT}{BLACK}防止遊樂設施發生故障 +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :在隱藏於森林深處的清空範圍中, 建造一個很受歡迎的樂園 + + +STR_SCNR :Dynamite Dunes +STR_PARK :Dynamite Dunes +STR_DTLS :這個座立於沙漠中的樂園只有一座雲霄飛車, 但不缺乏可供擴充的位置 + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :在一個大型湖泊的旁邊, 由零開始建造一個樂園 + + +STR_SCNR :Diamond Heights +STR_PARK :Diamond Heights +STR_DTLS :Diamond Heights已經是一個擁有極佳遊樂設施, 並且很發展得很成功的樂園 - 繼續發展它讓它的價值翻倍 + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :將景色優美的Evergreen Gardens轉型成一個很受歡迎的樂園 + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :將Bumbly Beach這個小型樂園發展成一個很受歡迎的樂園 + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :幾個鄰近的島嶼組成了這個新樂園的基本地勢 + + +STR_SCNR :Katie's Dreamland +STR_PARK :Katie's Dreamland +STR_DTLS :一個只有幾個遊樂設施但有擴展空間的小型樂園 - 你的目標是讓它的價值翻倍 + + +STR_SCNR :Pokey Park +STR_PARK :Pokey Park +STR_DTLS :一個擠迫的小型樂園, 它需要重大擴張 + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :一個附有優良水文類遊樂設施的樂園, 它需要重大擴張 + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :將一個已被遺棄的大型礦坑由景點轉型成一個樂園 + + +STR_SCNR :Karts & Coasters +STR_PARK :Karts & Coasters +STR_DTLS :一個隱藏在森林的大型樂園, 但當中只有小型賽車及木製雲霄飛車 + + +STR_SCNR :Mel's World +STR_PARK :Mel's World +STR_DTLS :這個樂園已經有一些既優秀又現代的遊樂設施, 但它亦有很大的擴充空間 + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :在Mystic Mountain的崎嶇不平森林中, 由零開始建造一個樂園 + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park + + +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 + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :將這個平凡無奇的小鎮碼頭轉型成一個很受歡迎的樂園 + + +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 + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :一個有數項問題的知名樂園 + + +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 + + +STR_SCNR :Thunder Rock +STR_PARK :Thunder Rock +STR_DTLS :Thunder Rock豎立一個在沙漠中部, 並因此吸引遊客 - 將可用的空間建造遊樂設施來吸引更多遊客 + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :盡情玩吧! + ##################### # Rides/attractions # ##################### @@ -3931,92 +4233,92 @@ STR_5580 :捷克克朗 (Kc) [AML1] STR_NAME :美式蒸氣火車 STR_DESC :配備著復刻蒸氣火車頭及煤水車的小型蒸氣火車, 拉著帶有帆布車頂的木製車廂 -STR_CPTY :每車廂6個乘客 +STR_CPTY :每車廂6位乘客 [CLIFT1] STR_NAME :纜車車卡 STR_DESC :供纜車使用的開放式車卡 -STR_CPTY :每車卡2個乘客 +STR_CPTY :每車卡2位乘客 [CLIFT2] STR_NAME :登頂滑雪纜車車椅 STR_DESC :供纜車使用的開放式車卡 -STR_CPTY :每車卡2個乘客 +STR_CPTY :每車卡2位乘客 [LIFT1] STR_NAME :升降機 STR_DESC :遊客乘搭升降機上下穿梭於垂直的管道中, 並借此訪問另一層 -STR_CPTY :16個乘客 +STR_CPTY :16位乘客 [MONO1] STR_NAME :流線型單軌電車 STR_DESC :大載客量的單軌電車, 車頭車尾都配備著流線型設計 -STR_CPTY :每車卡5或10個乘客 +STR_CPTY :每車卡5或10位乘客 [MONO2] STR_NAME :小型單軌電車 STR_DESC :附有開放式側邊的小型單軌電車 -STR_CPTY :每車卡4個乘客 +STR_CPTY :每車卡4位乘客 [MONO3] STR_NAME :懷舊風格單軌電車 STR_DESC :使用開放式設計車廂的單軌電車 -STR_CPTY :每車卡4個乘客 +STR_CPTY :每車卡4位乘客 [NRL] STR_NAME :蒸氣火車 STR_DESC :配備著復刻蒸氣火車頭及煤水車的小型蒸氣火車, 拉著開放式的木製車廂 -STR_CPTY :每車廂6個乘客 +STR_CPTY :每車廂6位乘客 [NRL2] STR_NAME :有蓋蒸氣火車 STR_DESC :配備著復刻蒸氣火車頭及煤水車的小型蒸氣火車, 拉著帶有織布車頂的木製車廂 -STR_CPTY :每車廂6個乘客 +STR_CPTY :每車廂6位乘客 [SMONO] STR_NAME :懸掛式單軌電車 STR_DESC :大載客量的單軌電車 -STR_CPTY :每車卡8個乘客 +STR_CPTY :每車卡8位乘客 [TRAM1] STR_NAME :電車 STR_DESC :復刻的懷舊電車 -STR_CPTY :每車卡10個乘客 +STR_CPTY :每車卡10位乘客 [4X4] STR_NAME :怪獸卡車 STR_DESC :能爬上陡斜坡道, 而且帶有動力的巨型4 x 4卡車 -STR_CPTY :每卡車2個乘客 +STR_CPTY :每卡車2位乘客 [CHBUILD] STR_NAME :古怪屋 STR_DESC :一座建築物, 含有扭曲房間及傾斜走道使人於行走中失去方向感 -STR_CPTY :5個遊客 +STR_CPTY :5位遊客 [CIRCUS1] STR_NAME :馬戲團 STR_DESC :於大型帳幕內進行動物馬戲團表演 -STR_CPTY :30個遊客 +STR_CPTY :30位遊客 [CTCAR] STR_NAME :笑臉貓遊 -STR_DESC :帶有動力的貓班車輛跟隨著軌道的路線遊覽周邊 -STR_CPTY :每輛車2個乘客 +STR_DESC :帶有動力的貓型車輛跟隨著軌道的路線遊覽周邊 +STR_CPTY :每輛車2位乘客 [DODG1] STR_NAME :碰碰車 STR_DESC :自助駕駛的電力碰碰車 -STR_CPTY :每車輛1個乘客 +STR_CPTY :每車輛1位乘客 [FSAUC] STR_NAME :碰碰飛碟 STR_DESC :自助駕駛的飛碟型車輛 -STR_CPTY :每飛碟1個乘客 +STR_CPTY :每飛碟1位乘客 [FWH1] STR_NAME :摩天輪 STR_DESC :不斷旋轉, 附有露天座椅的巨大輪環 -STR_CPTY :32乘客 +STR_CPTY :32位乘客 [GOLF1] STR_NAME :迷你高爾夫 @@ -4027,4 +4329,4 @@ STR_CPTY : [CONDORRD] STR_NAME :神鷹暢遊 STR_DESC :乘客乘坐於軌道下的神鷹造型列車上, 將會於飛馳中體驗飛一般的快感 -STR_CPTY :每車卡4個乘客 +STR_CPTY :每車卡4位乘客 diff --git a/data/language/czech.txt b/data/language/czech.txt index 36d9d08486..565df92599 100644 --- a/data/language/czech.txt +++ b/data/language/czech.txt @@ -10,90 +10,90 @@ STR_0005 :Obrácená horská dráha STR_0006 :Dorostenecká horská dráha STR_0007 :Miniaturní železnice STR_0008 :Vysutá jednokolejka -STR_0009 :Malá zavěsná dráha -STR_0010 :Lodní dráha -STR_0011 :Divoká myš -STR_0012 :Překážkový dostih -STR_0013 :Automobilová dráha -STR_0014 :Vystřelovaný volný pád +STR_0009 :Malá zavěšená dráha +STR_0010 :Půjčovna lodí +STR_0011 :Dřevěná divoká myš +STR_0012 :Dostihy +STR_0013 :Autodráha +STR_0014 :Volný pád STR_0015 :Bobová dráha -STR_0016 :Vyhlídková věž -STR_0017 :Smyčkující horská dráha -STR_0018 :Sjezd na člunech -STR_0019 :Dráha důlního vlaku +STR_0016 :Pozorovací věž +STR_0017 :Horská dráha s lopinky +STR_0018 :Nafukovací čluny +STR_0019 :Dulní horská dráha STR_0020 :Lanovka STR_0021 :Vývrtková horská dráha STR_0022 :Bludiště STR_0023 :Točitá skluzavka STR_0024 :Motokáry -STR_0025 :Žlab s kládamy -STR_0026 :Říční peřeje +STR_0025 :Divoká řeka +STR_0026 :Divoká voda STR_0027 :Autodrom STR_0028 :Pirátská loď -STR_0029 :Houpací obracecí loď +STR_0029 :Houpající se obrácená loď STR_0030 :Stánek s jídlem STR_0031 :Neznámý obchod (1D) STR_0032 :Stánek s pitím STR_0033 :Neznámý obchod (1F) STR_0034 :Obchod -STR_0035 :Merry-Go-Round +STR_0035 :Kolotoč STR_0036 :Neznámý obchod (22) -STR_0037 :Informačí kiosek +STR_0037 :Informační kiosek STR_0038 :Toalety STR_0039 :Ruské kolo STR_0040 :Simulátor pohybu STR_0041 :3D Kino STR_0042 :Top Spin -STR_0043 :Space Rings -STR_0044 :Reverse Freefall Coaster +STR_0043 :Vesmírné kruhy +STR_0044 :Horská dráha s volným pádem pozpátku STR_0045 :Výtah -STR_0046 :Vertical Drop Roller Coaster +STR_0046 :Horská dráha s vertikálním pádem STR_0047 :Bankomat STR_0048 :Twist -STR_0049 :Strašidelný dům +STR_0049 :Dům hrůzy STR_0050 :První pomoc STR_0051 :Cirkus STR_0052 :Vlak duchů -STR_0053 :Steel Twister Roller Coaster +STR_0053 :Ocelová horská dráha STR_0054 :Dřevěná horská dráha -STR_0055 :Side-Friction Roller Coaster +STR_0055 :Horská dráha s bočním třením STR_0056 :Divoká myš STR_0057 :Mnohorozměrná horská dráha STR_0058 :Neznámá atrakce (38) STR_0059 :Létající horská dráha STR_0060 :Neznámá atrakce (3A) -STR_0061 :VIrginský moták +STR_0061 :Virginský moták STR_0062 :Cákající lodě STR_0063 :Mini helikoptéra -STR_0064 :HOrská dráha v leže +STR_0064 :Horská dráha v leže STR_0065 :Vysutá jednokolejka STR_0066 :Neznámá atrakce (40) STR_0067 :Obrácená horská dráha STR_0068 :Heartline Twister Coaster STR_0069 :Mini Golf STR_0070 :Obří dráha -STR_0071 :Roto-Drop +STR_0071 :Roto-pád STR_0072 :Létající talíř STR_0073 :Křivý dům -STR_0074 :Jenostopá kola -STR_0075 :Compact Inverted Coaster -STR_0076 :Vodní dráha -STR_0077 :Air Powered Vertical Coaster -STR_0078 :Inverted Hairpin Coaster +STR_0074 :Jednokolejná jízdní kola +STR_0075 :Malá zavěšená horská dráha +STR_0076 :Vodní atrakce +STR_0077 :Svislá dráha na stlačený vzduch +STR_0078 :Ostrá zavěšená horská dráha STR_0079 :Kouzelný koberec STR_0080 :Podmořská jízda -STR_0081 :Rafty +STR_0081 :Říční rafty STR_0082 :Neznámá atrakce (50) -STR_0083 :Enterprise +STR_0083 :Loď Enterprise STR_0084 :Neznámá atrakce (52) STR_0085 :Neznámá atrakce (53) STR_0086 :Neznámá atrakce (54) STR_0087 :Neznámá atrakce (55) -STR_0088 :Inverted Impulse Coaster +STR_0088 :Horská dráha ve tvaru "U" STR_0089 :Malá horská dráha STR_0090 :Mini dráha STR_0091 :Neznámá atrakce (59) -STR_0092 :LIM Launched Roller Coaster +STR_0092 :Horská dráha s elektromotorem STR_0093 : STR_0094 : STR_0095 : @@ -513,31 +513,31 @@ STR_0508 : STR_0509 : STR_0510 : STR_0511 : -STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. -STR_0513 :Horská dráha se smyčkami na které se jezdí ve stoje -STR_0514 :Vlaky zavješené pod kolejí se v zatáčkách houpají do stran +STR_0512 :Malá ocelová horská dráha se spirálovitým profilem a vozy se sedadly za sebou +STR_0513 :Návětěvníci jedou po horské dráze s lopinky ve stoje +STR_0514 :Vlaky zavěšené pod kolejí se v zatáčkách houpají do stran STR_0515 :Ocelová horská dráha s vlaky držícími zespod tratí, s mnoha složitími a otáčivímy prvky STR_0516 :Pozvolná horská dráha pro ty kdo se zatím neodvažují na větší dráhy STR_0517 :Pasažeři jedou v miniaturních vlacích po úzkorozchodné koleji. STR_0518 :Cestujíci jedou v elektických vlacích po vysuté jednokolejné dráze. -STR_0519 :Cestujíci jedou zavěšení pod jednou kolejí v malích kabinách, volně se houpajících ze strany na stranu -STR_0520 :Přístavní molo kde hosté mohou řídit osobní plavidlo na vodní hladině -STR_0521 :Rychlá a mrštná horská dráha s ostrými zákrutami a strmími svahy. Dráha je předurčená k vysoké intensitě. -STR_0522 :Menší horská dráha na které hosté sedí nad dráhou bez kabiny kolem sebe -STR_0523 :Hosté jedou pomalu v hnaných vozidlech po určené trati. -STR_0524 :Kabina Freefall je pneumaticky vstřelena nahorů po vysoké ocelové věži a pak padá zpět volným pádem -STR_0525 :Riders career down a twisting track guided only by the curvature and banking of the semi-circular track -STR_0526 :Pasažéři jsou v otáčející se rozhledně která vyjede na vysokou věž -STR_0527 :Plynulá ocelová pásová horská dráha schopná vertikálních smyček -STR_0528 :Hosté sjíždí v nafukovacích člunech zatáčejícím korytem nebo uzavřenou trubicí -STR_0529 :Ocelová horská dráha ve stylu důlního vlaku s věrnými důlními kolejemi. -STR_0530 :Kabiny vysí na ocelovém laně které nepřetržitě jede z jednoho konce na druhý a zpět -STR_0531 :Kompaktní ocelová horská dráha na které vlak projíždí smyčky a vývrtky +STR_0519 :Cestujíci jedou zavěšení pod jednou kolejí v malích kabinách, volně se houpajících ze strany na stranu +STR_0520 :Přístavní molo, kde návštěvníci mohou řídit osobní plavidlo na vodní hladině +STR_0521 :Rychlá a mrštná horská dráha s ostrými zatáčkami a strmými svahy. Dráha je předurčená k vysoké intenzitě. +STR_0522 :Menší horská dráha, na které návštěvníci sedí nad dráhou bez kabiny kolem sebe +STR_0523 :Návštěvníci jedou pomalu ve vozidlech po postavené dráze. +STR_0524 :Kabina pro volný pád je pneumaticky vystřelena vzhůru po vysoké ocelové věži a následně volně padá k zemi +STR_0525 :Návštěvníci jedou po propletené bobové dráze +STR_0526 :Otáčející se pozorovací kabina, která postupně vyjíždí na vysokou věž +STR_0527 :Plynulá ocelová horská dráha s lopinky +STR_0528 :Návštěvníci jedou v nafukovacích člunech po tobogánu +STR_0529 :Ocelová horská dráha ve stylu důlního vlaku s věrně vypadjícími důlními kolejemi. +STR_0530 :Kabiny visí na ocelovém laně, které nepřetržitě jede z jednoho konce na druhý a zpět +STR_0531 :Malá ocelová horská dráha, na které vlak projíždí smyčky a vývrtky STR_0532 : STR_0533 : -STR_0534 :Hosté sami řídí benzínové motokáry -STR_0535 :Lodě ve tvaru klády jedou po vodní kanále, splavujíse se po strmích kopcích. Žádny host nezůstane suchý. -STR_0536 :Loď pluje po šírokých maeandrech, přes stříkající vodpoády a po vzrušujících pěnících přejích +STR_0534 :Návštěvníci sami řídí benzínové motokáry +STR_0535 :Lodě ve tvaru klády se plaví po vodní kanále a sjíždí strmé úseky. Žádný návštěvník nezůstane suchý +STR_0536 :Loď pluje po širokých meandrech, přes stříkající vodpoády a po vzrušujících pěnících přejích STR_0537 : STR_0538 : STR_0539 : @@ -555,224 +555,224 @@ STR_0550 : STR_0551 : STR_0552 : STR_0553 : -STR_0554 :The car is accelerated out of the station along a long level track using Linear Induction Motors, then heads straight up a vertical spike of track, freefalling back down to return to the station -STR_0555 :Hosté jedou ve výtahu nahoů nebo dolů ve svislé věži aby se dostaly z jedné výsky do jiné -STR_0556 :Extra široké vozy se vrhaji střemhlav dolů za zážitky úplného volného pádu na horské dráze +STR_0554 :Po mocném startu pomocí elektromotorů se vozy rozjedou po svislé dráze, přes vrchol a svisle dolů zpět do stanice +STR_0555 :Návštěvníci jezdí ve výtahu nahoru a dolů +STR_0556 :Extra široké vozy se vrhají střemhlav dolů za zážitky úplného volného pádu na horské dráze STR_0557 : STR_0558 : STR_0559 : STR_0560 : STR_0561 : -STR_0562 :Hnané vozy jedou po několika-patrové dráze plné strašidelných kulis a speciálních efektů -STR_0563 :Sitting in comfortable trains with only simple lap restraints riders enjoy giant smooth drops and twisting track as well as plenty of 'air time' over the hills -STR_0564 :Při jízdou po dřevěné dráze je tato horská dráha rychlá, drsná, hlučná a poskytuje pocit „vymuknutí řízení“ s mnoha „pocity beztíže“ +STR_0562 :Vozy jezdí po vícepatrovém okruhu okolo strašidelných kulis a speciálních efektů +STR_0563 :Horská dráha s dlouhými pády, velkou rychlostí a pohodlnými vlaky, kde se jezdí s opěrkou v klíně, která přelétává vrcholky kopců +STR_0564 :Dřevěná, rychlá, hlučná a drsná horská dráha jede jako utržená ze řetězů a přelétává vrcholky kopců STR_0565 :Jednoduchá dřevěná horská tráha schopná jen mírných kopců a zatáček, na které je vůz držen jen bočnímy kolečky a gravitací -STR_0566 :Individual roller coaster cars zip around a tight zig-zag layout of track with sharp corners and short sharp drops -STR_0567 :Sitting in seats suspended either side of the track, riders are pitched head-over-heels while they plunge down steep drops and travel through various inversions +STR_0566 :Malá horská dráha, na které vozy po jednom projíždí cik-cak trať s kroucenými pády a ostrými zatáčkami +STR_0567 :Vozy se sedadly schopny otáčet návštěvníky vzhůru nohama STR_0568 : -STR_0569 :Jíza ve speciálních postrojích zavěšených pod tratí, poskytuje pocit letu, jako když se vrhnete do prázdna +STR_0569 :Jízda ve speciálních postrojích zavěšených pod tratí, poskytuje pocit letu jako pták STR_0570 : -STR_0571 :Kulaté vozy se otáčeí dokola tím jak projíždějí dřevěnou klikatou tratí -STR_0572 :Lodě s velkou kapacitou jedou po širokém vodním kanále, vzhůru poháněné bežícím pásem, zrychlují z prudkých svahů aby obrovským šplouchnutím namočili všechny hosty -STR_0573 :Hnané vozy ve tvaru helikoptér jedou na ocelové trati -STR_0574 :Hosté ve speciálních postrojích zavěšení v leže pod tratí, jedou přes zákruty a obraty pozadu nebo čelem k zemi -STR_0575 :Poháněné vlaky vysící pod vysuto kolejí převážejí lidi po parku +STR_0571 :Kulaté vozy se otáčeí dokola tím, jak projíždějí dřevěnou klikatou tratí +STR_0572 :Lodě s velkou kapacitou jedou po širokém vodním kanále, vzhůru poháněné bežícím pásem, zrychlují z prudkých svahů, aby obrovským šplouchnutím namočily všechny návštěvníky +STR_0573 :Vozy ve tvaru helikoptér jedou na postavení dráze +STR_0574 :Návštěvníci ve speciálních postrojích zavěšení v leže pod tratí, jedou přes zatáčky a obraty pozadu, nebo čelem k zemi +STR_0575 :Poháněné vlaky vysící pod vysutou kolejí převážejí návštěvníky po parku STR_0576 : STR_0577 :Vozy s dvěma podvozky jedou po dřevěné trati, otáčející se dokola na speciálních místech -STR_0578 :Cars run along track enclosed by circular hoops, traversing steep drops and heartline twists +STR_0578 :Horská dráha, která se točí dokola tak, že návštěvníci jsou pořád na stejném místě. STR_0579 : -STR_0580 :Obrovská ocelová horská dráha s hladkými obraty a svahy přes 90 metrů -STR_0581 :Kruh sedadel je za pomalého otáčení vyzdvyhnut na vrchol věže, poté se vrátí volným pádem a postupně zastaví ve stanici pomocí magnetických brzd +STR_0580 :Gigantická ocelová horská dráha schopna volných pádů a kopců přes 90 metrů dlouhých +STR_0581 :Kruh sedadel je za pomalé rotace vytažen navrchol vysoké věže, spuštěn volným pádem k zemi a opatrně zastaven pomocí magnetických brzd STR_0582 : STR_0583 : STR_0584 :Speciální kola jezdí po ocelové koleji, poháněná šlapáním jezdců -STR_0585 :Riders sit in pairs of seats suspended beneath the track as they loop and twist through tight inversions -STR_0586 :Boat shaped cars run on roller coaster track to allow twisting curves and steep drops, splashing down into sections of water for gentle river sections -STR_0587 :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station -STR_0588 :Individual cars run beneath a zig-zagging track with hairpin turns and sharp drops +STR_0585 :Návštěvníci sedí po dvou zavěšení pod tratí a jedou skrze lopinky a ostré zatáčky +STR_0586 :Vozy ve tvaru lodí jedou po trati horské dráhy, což umožňuje ostré zatáčky, strmé klesání a cákající zpomalení pro mírnější říční úseky +STR_0587 :Po mocném startu na stlačený vzduch se vozy rozjedou po svislé dráze, přes vrchol a svisle dolů zpět do stanice +STR_0588 :Vozy po jednom jedou pod cik-cak tratí s ostrými zatáčkami a pády STR_0589 : -STR_0590 :Riders ride in a submerged submarine through an underwater course -STR_0591 :Raft-shaped boats gently meander around a river track +STR_0590 :Návštěvníci vyrazí na podvodní jízdu v ponorce +STR_0591 :Rafty se plaví po meandrech na vodním kanále STR_0592 : STR_0593 : STR_0594 : STR_0595 : STR_0596 : STR_0597 : -STR_0598 :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track -STR_0599 :A compact roller coaster with individual cars and smooth twisting drops -STR_0600 :Powered mine trains career along a smooth and twisted track layout +STR_0598 :Vozy vyrazí vstříc jednomu konci trati, poté prosviští pozpátku stanicí a vyletí až na druhý konec trati +STR_0599 :Malá horská dráha, na které vozy po jednom projíždí trať s kroucenými pády +STR_0600 :Horská dráha s vozy ve stylu důlních vagónů, které jedou po hladkých kolejnících skrze propletenou dráhu STR_0601 : -STR_0602 :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions -STR_0603 :Host {INT32} -STR_0604 :Host {INT32} -STR_0605 :Host {INT32} -STR_0606 :Host {INT32} -STR_0607 :Host {INT32} -STR_0608 :Host {INT32} -STR_0609 :Host {INT32} -STR_0610 :Host {INT32} -STR_0611 :Host {INT32} -STR_0612 :Host {INT32} -STR_0613 :Host {INT32} -STR_0614 :Host {INT32} -STR_0615 :Host {INT32} -STR_0616 :Host {INT32} -STR_0617 :Host {INT32} -STR_0618 :Host {INT32} -STR_0619 :Host {INT32} -STR_0620 :Host {INT32} -STR_0621 :Host {INT32} -STR_0622 :Host {INT32} -STR_0623 :Host {INT32} -STR_0624 :Host {INT32} -STR_0625 :Host {INT32} -STR_0626 :Host {INT32} -STR_0627 :Host {INT32} -STR_0628 :Host {INT32} -STR_0629 :Host {INT32} -STR_0630 :Host {INT32} -STR_0631 :Host {INT32} -STR_0632 :Host {INT32} -STR_0633 :Host {INT32} -STR_0634 :Host {INT32} -STR_0635 :Host {INT32} -STR_0636 :Host {INT32} -STR_0637 :Host {INT32} -STR_0638 :Host {INT32} -STR_0639 :Host {INT32} -STR_0640 :Host {INT32} -STR_0641 :Host {INT32} -STR_0642 :Host {INT32} -STR_0643 :Host {INT32} -STR_0644 :Host {INT32} -STR_0645 :Host {INT32} -STR_0646 :Host {INT32} -STR_0647 :Host {INT32} -STR_0648 :Host {INT32} -STR_0649 :Host {INT32} -STR_0650 :Host {INT32} -STR_0651 :Host {INT32} -STR_0652 :Host {INT32} -STR_0653 :Host {INT32} -STR_0654 :Host {INT32} -STR_0655 :Host {INT32} -STR_0656 :Host {INT32} -STR_0657 :Host {INT32} -STR_0658 :Host {INT32} -STR_0659 :Host {INT32} -STR_0660 :Host {INT32} -STR_0661 :Host {INT32} -STR_0662 :Host {INT32} -STR_0663 :Host {INT32} -STR_0664 :Host {INT32} -STR_0665 :Host {INT32} -STR_0666 :Host {INT32} -STR_0667 :Host {INT32} -STR_0668 :Host {INT32} -STR_0669 :Host {INT32} -STR_0670 :Host {INT32} -STR_0671 :Host {INT32} -STR_0672 :Host {INT32} -STR_0673 :Host {INT32} -STR_0674 :Host {INT32} -STR_0675 :Host {INT32} -STR_0676 :Host {INT32} -STR_0677 :Host {INT32} -STR_0678 :Host {INT32} -STR_0679 :Host {INT32} -STR_0680 :Host {INT32} -STR_0681 :Host {INT32} -STR_0682 :Host {INT32} -STR_0683 :Host {INT32} -STR_0684 :Host {INT32} -STR_0685 :Host {INT32} -STR_0686 :Host {INT32} -STR_0687 :Host {INT32} -STR_0688 :Host {INT32} -STR_0689 :Host {INT32} -STR_0690 :Host {INT32} -STR_0691 :Host {INT32} -STR_0692 :Host {INT32} -STR_0693 :Host {INT32} -STR_0694 :Host {INT32} -STR_0695 :Host {INT32} -STR_0696 :Host {INT32} -STR_0697 :Host {INT32} -STR_0698 :Host {INT32} -STR_0699 :Host {INT32} -STR_0700 :Host {INT32} -STR_0701 :Host {INT32} -STR_0702 :Host {INT32} -STR_0703 :Host {INT32} -STR_0704 :Host {INT32} -STR_0705 :Host {INT32} -STR_0706 :Host {INT32} -STR_0707 :Host {INT32} -STR_0708 :Host {INT32} -STR_0709 :Host {INT32} -STR_0710 :Host {INT32} -STR_0711 :Host {INT32} -STR_0712 :Host {INT32} -STR_0713 :Host {INT32} -STR_0714 :Host {INT32} -STR_0715 :Host {INT32} -STR_0716 :Host {INT32} -STR_0717 :Host {INT32} -STR_0718 :Host {INT32} -STR_0719 :Host {INT32} -STR_0720 :Host {INT32} -STR_0721 :Host {INT32} -STR_0722 :Host {INT32} -STR_0723 :Host {INT32} -STR_0724 :Host {INT32} -STR_0725 :Host {INT32} -STR_0726 :Host {INT32} -STR_0727 :Host {INT32} -STR_0728 :Host {INT32} -STR_0729 :Host {INT32} -STR_0730 :Host {INT32} -STR_0731 :Host {INT32} -STR_0732 :Host {INT32} -STR_0733 :Host {INT32} -STR_0734 :Host {INT32} -STR_0735 :Host {INT32} -STR_0736 :Host {INT32} -STR_0737 :Host {INT32} -STR_0738 :Host {INT32} -STR_0739 :Host {INT32} -STR_0740 :Host {INT32} -STR_0741 :Host {INT32} -STR_0742 :Host {INT32} -STR_0743 :Host {INT32} -STR_0744 :Host {INT32} -STR_0745 :Host {INT32} -STR_0746 :Host {INT32} -STR_0747 :Host {INT32} -STR_0748 :Host {INT32} -STR_0749 :Host {INT32} -STR_0750 :Host {INT32} -STR_0751 :Host {INT32} -STR_0752 :Host {INT32} -STR_0753 :Host {INT32} -STR_0754 :Host {INT32} -STR_0755 :Host {INT32} -STR_0756 :Host {INT32} -STR_0757 :Host {INT32} -STR_0758 :Host {INT32} -STR_0759 :Host {INT32} -STR_0760 :Host {INT32} -STR_0761 :Host {INT32} -STR_0762 :Host {INT32} -STR_0763 :Host {INT32} -STR_0764 :Host {INT32} -STR_0765 :Host {INT32} -STR_0766 :Host {INT32} -STR_0767 :Host {INT32} -STR_0768 :Uklizeč {INT32} -STR_0769 :Technik {INT32} +STR_0602 :Horská dráha s vozy poháněnými elektromotorem, které sviští skrze propletenou dráhu +STR_0603 :Návštěvník {INT32} +STR_0604 :Návštěvník {INT32} +STR_0605 :Návštěvník {INT32} +STR_0606 :Návštěvník {INT32} +STR_0607 :Návštěvník {INT32} +STR_0608 :Návštěvník {INT32} +STR_0609 :Návštěvník {INT32} +STR_0610 :Návštěvník {INT32} +STR_0611 :Návštěvník {INT32} +STR_0612 :Návštěvník {INT32} +STR_0613 :Návštěvník {INT32} +STR_0614 :Návštěvník {INT32} +STR_0615 :Návštěvník {INT32} +STR_0616 :Návštěvník {INT32} +STR_0617 :Návštěvník {INT32} +STR_0618 :Návštěvník {INT32} +STR_0619 :Návštěvník {INT32} +STR_0620 :Návštěvník {INT32} +STR_0621 :Návštěvník {INT32} +STR_0622 :Návštěvník {INT32} +STR_0623 :Návštěvník {INT32} +STR_0624 :Návštěvník {INT32} +STR_0625 :Návštěvník {INT32} +STR_0626 :Návštěvník {INT32} +STR_0627 :Návštěvník {INT32} +STR_0628 :Návštěvník {INT32} +STR_0629 :Návštěvník {INT32} +STR_0630 :Návštěvník {INT32} +STR_0631 :Návštěvník {INT32} +STR_0632 :Návštěvník {INT32} +STR_0633 :Návštěvník {INT32} +STR_0634 :Návštěvník {INT32} +STR_0635 :Návštěvník {INT32} +STR_0636 :Návštěvník {INT32} +STR_0637 :Návštěvník {INT32} +STR_0638 :Návštěvník {INT32} +STR_0639 :Návštěvník {INT32} +STR_0640 :Návštěvník {INT32} +STR_0641 :Návštěvník {INT32} +STR_0642 :Návštěvník {INT32} +STR_0643 :Návštěvník {INT32} +STR_0644 :Návštěvník {INT32} +STR_0645 :Návštěvník {INT32} +STR_0646 :Návštěvník {INT32} +STR_0647 :Návštěvník {INT32} +STR_0648 :Návštěvník {INT32} +STR_0649 :Návštěvník {INT32} +STR_0650 :Návštěvník {INT32} +STR_0651 :Návštěvník {INT32} +STR_0652 :Návštěvník {INT32} +STR_0653 :Návštěvník {INT32} +STR_0654 :Návštěvník {INT32} +STR_0655 :Návštěvník {INT32} +STR_0656 :Návštěvník {INT32} +STR_0657 :Návštěvník {INT32} +STR_0658 :Návštěvník {INT32} +STR_0659 :Návštěvník {INT32} +STR_0660 :Návštěvník {INT32} +STR_0661 :Návštěvník {INT32} +STR_0662 :Návštěvník {INT32} +STR_0663 :Návštěvník {INT32} +STR_0664 :Návštěvník {INT32} +STR_0665 :Návštěvník {INT32} +STR_0666 :Návštěvník {INT32} +STR_0667 :Návštěvník {INT32} +STR_0668 :Návštěvník {INT32} +STR_0669 :Návštěvník {INT32} +STR_0670 :Návštěvník {INT32} +STR_0671 :Návštěvník {INT32} +STR_0672 :Návštěvník {INT32} +STR_0673 :Návštěvník {INT32} +STR_0674 :Návštěvník {INT32} +STR_0675 :Návštěvník {INT32} +STR_0676 :Návštěvník {INT32} +STR_0677 :Návštěvník {INT32} +STR_0678 :Návštěvník {INT32} +STR_0679 :Návštěvník {INT32} +STR_0680 :Návštěvník {INT32} +STR_0681 :Návštěvník {INT32} +STR_0682 :Návštěvník {INT32} +STR_0683 :Návštěvník {INT32} +STR_0684 :Návštěvník {INT32} +STR_0685 :Návštěvník {INT32} +STR_0686 :Návštěvník {INT32} +STR_0687 :Návštěvník {INT32} +STR_0688 :Návštěvník {INT32} +STR_0689 :Návštěvník {INT32} +STR_0690 :Návštěvník {INT32} +STR_0691 :Návštěvník {INT32} +STR_0692 :Návštěvník {INT32} +STR_0693 :Návštěvník {INT32} +STR_0694 :Návštěvník {INT32} +STR_0695 :Návštěvník {INT32} +STR_0696 :Návštěvník {INT32} +STR_0697 :Návštěvník {INT32} +STR_0698 :Návštěvník {INT32} +STR_0699 :Návštěvník {INT32} +STR_0700 :Návštěvník {INT32} +STR_0701 :Návštěvník {INT32} +STR_0702 :Návštěvník {INT32} +STR_0703 :Návštěvník {INT32} +STR_0704 :Návštěvník {INT32} +STR_0705 :Návštěvník {INT32} +STR_0706 :Návštěvník {INT32} +STR_0707 :Návštěvník {INT32} +STR_0708 :Návštěvník {INT32} +STR_0709 :Návštěvník {INT32} +STR_0710 :Návštěvník {INT32} +STR_0711 :Návštěvník {INT32} +STR_0712 :Návštěvník {INT32} +STR_0713 :Návštěvník {INT32} +STR_0714 :Návštěvník {INT32} +STR_0715 :Návštěvník {INT32} +STR_0716 :Návštěvník {INT32} +STR_0717 :Návštěvník {INT32} +STR_0718 :Návštěvník {INT32} +STR_0719 :Návštěvník {INT32} +STR_0720 :Návštěvník {INT32} +STR_0721 :Návštěvník {INT32} +STR_0722 :Návštěvník {INT32} +STR_0723 :Návštěvník {INT32} +STR_0724 :Návštěvník {INT32} +STR_0725 :Návštěvník {INT32} +STR_0726 :Návštěvník {INT32} +STR_0727 :Návštěvník {INT32} +STR_0728 :Návštěvník {INT32} +STR_0729 :Návštěvník {INT32} +STR_0730 :Návštěvník {INT32} +STR_0731 :Návštěvník {INT32} +STR_0732 :Návštěvník {INT32} +STR_0733 :Návštěvník {INT32} +STR_0734 :Návštěvník {INT32} +STR_0735 :Návštěvník {INT32} +STR_0736 :Návštěvník {INT32} +STR_0737 :Návštěvník {INT32} +STR_0738 :Návštěvník {INT32} +STR_0739 :Návštěvník {INT32} +STR_0740 :Návštěvník {INT32} +STR_0741 :Návštěvník {INT32} +STR_0742 :Návštěvník {INT32} +STR_0743 :Návštěvník {INT32} +STR_0744 :Návštěvník {INT32} +STR_0745 :Návštěvník {INT32} +STR_0746 :Návštěvník {INT32} +STR_0747 :Návštěvník {INT32} +STR_0748 :Návštěvník {INT32} +STR_0749 :Návštěvník {INT32} +STR_0750 :Návštěvník {INT32} +STR_0751 :Návštěvník {INT32} +STR_0752 :Návštěvník {INT32} +STR_0753 :Návštěvník {INT32} +STR_0754 :Návštěvník {INT32} +STR_0755 :Návštěvník {INT32} +STR_0756 :Návštěvník {INT32} +STR_0757 :Návštěvník {INT32} +STR_0758 :Návštěvník {INT32} +STR_0759 :Návštěvník {INT32} +STR_0760 :Návštěvník {INT32} +STR_0761 :Návštěvník {INT32} +STR_0762 :Návštěvník {INT32} +STR_0763 :Návštěvník {INT32} +STR_0764 :Návštěvník {INT32} +STR_0765 :Návštěvník {INT32} +STR_0766 :Návštěvník {INT32} +STR_0767 :Návštěvník {INT32} +STR_0768 :Údržbář {INT32} +STR_0769 :Mechanik {INT32} STR_0770 :Hlídač {INT32} -STR_0771 :Bavič {INT32} +STR_0771 :Maskot {INT32} STR_0772 :Nepojmenovaný park{POP16}{POP16} STR_0773 :Nepojmenovaný park{POP16}{POP16} STR_0774 :Nepojmenovaný park{POP16}{POP16} @@ -811,34 +811,34 @@ STR_0806 :28. STR_0807 :29. STR_0808 :30. STR_0809 :31. -STR_0810 :Jan -STR_0811 :Feb -STR_0812 :Mar -STR_0813 :Apr -STR_0814 :May -STR_0815 :Jun -STR_0816 :Jul -STR_0817 :Aug -STR_0818 :Sep -STR_0819 :Oct -STR_0820 :Nov -STR_0821 :Dec +STR_0810 :Led +STR_0811 :Úno +STR_0812 :Bře +STR_0813 :Dub +STR_0814 :Kvě +STR_0815 :Čvn +STR_0816 :Čvc +STR_0817 :Srp +STR_0818 :Zář +STR_0819 :Říj +STR_0820 :Lis +STR_0821 :Pro STR_0822 :Nedostupný grafický soubor STR_0823 :Chybějicí nebo nedostupný soubor STR_0824 :{BLACK}{CROSS} STR_0825 :Zvolené jméno je již používáno STR_0826 :Definováno příliš mnoho jmen -STR_0827 :Nedostatek financí - potřeba {CURRENCY2DP} +STR_0827 :Nedostatek financí - je potřeba {CURRENCY2DP} STR_0828 :{SMALLFONT}{BLACK}Zavřít okno -STR_0829 :{SMALLFONT}{BLACK}Window title - Drag this to move window +STR_0829 :{SMALLFONT}{BLACK}Titulek okna - lze s ním posunout okno STR_0830 :{SMALLFONT}{BLACK}Přiblížit pohled -STR_0831 :{SMALLFONT}{BLACK}ZOddálit pohled -STR_0832 :{SMALLFONT}{BLACK}Otočit o 90{DEGREE} po směru hodinových ručiček +STR_0831 :{SMALLFONT}{BLACK}Oddálit pohled +STR_0832 :{SMALLFONT}{BLACK}Otočit o 90{DEGREE} po směru hod. ruč. STR_0833 :{SMALLFONT}{BLACK}Pozastavit hru -STR_0834 :{SMALLFONT}{BLACK}Disk and game options -STR_0835 :Game initialisation failed +STR_0834 :{SMALLFONT}{BLACK}Uložení a nastavení hry +STR_0835 :Inicializace hry selhala STR_0836 :Nelze spustit hru minimalizovanou. -STR_0837 :Unable to initialise graphics system +STR_0837 :Inicializace grafického systému selhala STR_0838 : STR_0839 :{UINT16} x {UINT16} STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16} @@ -849,7 +849,7 @@ STR_0843 : STR_0844 : STR_0845 : STR_0846 : -STR_0847 :O 'OpenRCT2' +STR_0847 :O hře OpenRCT2 STR_0848 :RollerCoaster Tycoon 2 STR_0849 :{WINDOW_COLOUR_2}Verze 2.01.028 STR_0850 :{WINDOW_COLOUR_2}Copyright {COPYRIGHT} 2002 Chris Sawyer, všechna práva vyhrazena @@ -879,11 +879,11 @@ STR_0873 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0874 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0875 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0876 :{BLACK}{DOWN} -STR_0877 :Příliš nízko! ! -STR_0878 :Moc vysoko! ! +STR_0877 :Příliš nízko! +STR_0878 :Moc vysoko! STR_0879 :Tady nelze zemi snížit... STR_0880 :Tady nelze zemi zvíšit... -STR_0881 :Předmět v cestě +STR_0881 :Objekt v cestě STR_0882 :Nahrát hru STR_0883 :Uložit hru STR_0884 :Nahrát krajinu @@ -895,11 +895,11 @@ STR_0889 :Ukončit Track Designs Manager STR_0890 :SCR{COMMA16}.BMP STR_0891 :Snímek obrazovky STR_0892 :Snímek obrazovky byl uložen jako '{STRINGID}' -STR_0893 :Snímaní obrazovky selhalo ! -STR_0894 :Landscape data area full ! +STR_0893 :Snímaní obrazovky selhalo! +STR_0894 :Datová oblast krajiny zaplněna! STR_0895 :Nelze stavět částečně pod a nad zemí -STR_0896 :{POP16}{POP16}{STRINGID} Construction -STR_0897 :Direction +STR_0896 :{POP16}{POP16}{STRINGID} - stavba +STR_0897 :Směr STR_0898 :{SMALLFONT}{BLACK}Zatáčka vlevo STR_0899 :{SMALLFONT}{BLACK}Zatáčka vpravo STR_0900 :{SMALLFONT}{BLACK}Zatáčka vlevo (malý poloměr) @@ -910,11 +910,11 @@ STR_0904 :{SMALLFONT}{BLACK}Zatáčka vlevo (velký poloměr) STR_0905 :{SMALLFONT}{BLACK}Zatáčka vpravo (velký poloměr) STR_0906 :{SMALLFONT}{BLACK}Rovinka STR_0907 :Svah -STR_0908 :Roll/Banking +STR_0908 :Náklon STR_0909 :Otáčení sedadel -STR_0910 :{SMALLFONT}{BLACK}Roll for left-hand curve -STR_0911 :{SMALLFONT}{BLACK}Roll for right-hand curve -STR_0912 :{SMALLFONT}{BLACK}No roll +STR_0910 :{SMALLFONT}{BLACK}Levý náklon +STR_0911 :{SMALLFONT}{BLACK}Právý náklon +STR_0912 :{SMALLFONT}{BLACK}Bez náklonu STR_0913 :{SMALLFONT}{BLACK}Posunout na předchozí část STR_0914 :{SMALLFONT}{BLACK}Posunout na následující část STR_0915 :{SMALLFONT}{BLACK}Postavit vybranou část @@ -930,20 +930,20 @@ STR_0924 :{SMALLFONT}{BLACK}Šroubovice dolů STR_0925 :{SMALLFONT}{BLACK}Šroubovice vzhůru STR_0926 :Tohle nelze odstranit... STR_0927 :Tohle zde nejde postavit... -STR_0928 :{SMALLFONT}{BLACK}Řetězový vlek, pro pohon vozů do svahu +STR_0928 :{SMALLFONT}{BLACK}Řetězový vlek - výtah vozů do kopce STR_0929 :'S' Ohyb (levý) STR_0930 :'S' Ohyb (pravý) -STR_0931 :Svislá Smyčka (levá) -STR_0932 :Svislá Smyčka (pravá) -STR_0933 :Nejdříve zvyš nebo sniž povrch +STR_0931 :Svislá smyčka (levá) +STR_0932 :Svislá smyčka (pravá) +STR_0933 :Nejdříve zvyšte nebo snižte povrch STR_0934 :Vstup na atrakci v cestě STR_0935 :Výtup z atrakce v cestě STR_0936 :Vchod do parku v cestě -STR_0937 :{SMALLFONT}{BLACK}View options -STR_0938 :{SMALLFONT}{BLACK}Adjust land height and slope -STR_0939 :POdzemní/Vnitří pohled -STR_0940 :Remove Base Land -STR_0941 :Remove Vertical Faces +STR_0937 :{SMALLFONT}{BLACK}Nastavení zobrazení +STR_0938 :{SMALLFONT}{BLACK}Upravit výšku a sklon povrchu +STR_0939 :Podzemní/Vnitří pohled +STR_0940 :Skrýt povrch země +STR_0941 :Skrýt hrany mapy STR_0942 :Průhledné atrakce STR_0943 :Průhledná výzdoba STR_0944 :Uložit @@ -979,69 +979,69 @@ STR_0973 :OK STR_0974 :Atrakce STR_0975 :Obchody a stánky STR_0976 :Toalety a Informační kiosky -STR_0977 :New Transport Rides -STR_0978 :New Gentle Rides -STR_0979 :New Roller Coasters -STR_0980 :New Thrill Rides -STR_0981 :New Water Rides -STR_0982 :New Shops & Stalls -STR_0983 :Research & Development +STR_0977 :Nové atrakce pro přepravu +STR_0978 :Nové mírné atrakce +STR_0979 :Nové horské dráhy +STR_0980 :Nové adrenalinové atrakce +STR_0981 :Nové vodní atrakce +STR_0982 :Nové obchody & stánky +STR_0983 :Výzkum a vývoj STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP} STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP} STR_0986 :{BLACK}{CURRENCY2DP} -STR_0987 :Too many rides/attractions -STR_0988 :Can't create new ride/attraction... +STR_0987 :Příliš mnoho atrakcí +STR_0988 :Nelze vytvořit novou atrakci... STR_0989 :{STRINGID} -STR_0990 :{SMALLFONT}{BLACK}Construction -STR_0991 :Station platform -STR_0992 :{SMALLFONT}{BLACK}Demolish entire ride/attraction -STR_0993 :Demolish ride/attraction -STR_0994 :Demolish -STR_0995 :{WINDOW_COLOUR_1}Are you sure you want to completely demolish {STRINGID}? -STR_0996 :Overall view -STR_0997 :{SMALLFONT}{BLACK}View selection +STR_0990 :{SMALLFONT}{BLACK}Stavba +STR_0991 :Stanice +STR_0992 :{SMALLFONT}{BLACK}Zbourat celou atrakci +STR_0993 :Zbourat atrakci +STR_0994 :Zbourat +STR_0995 :{WINDOW_COLOUR_1}Opravdu chcete zbourat celou atrakci {STRINGID}? +STR_0996 :Celkový přehled +STR_0997 :{SMALLFONT}{BLACK}Zobrazit výběr STR_0998 :Na této trati nelze postavit více nástupišť STR_0999 :Vyžaduje nástupiště STR_1000 :Trať není uzavřený okruh. -STR_1001 :Track unsuitable for type of train -STR_1002 :Can't open {POP16}{POP16}{POP16}{STRINGID}... -STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID}... -STR_1004 :Can't close {POP16}{POP16}{POP16}{STRINGID}... -STR_1005 :Can't start construction on {POP16}{POP16}{POP16}{STRINGID}... -STR_1006 :Must be closed first -STR_1007 :Unable to create enough vehicles -STR_1008 :{SMALLFONT}{BLACK}Open, close, or test ride/attraction -STR_1009 :{SMALLFONT}{BLACK}Open or close all rides/attractions -STR_1010 :{SMALLFONT}{BLACK}Open or close park +STR_1001 :Trať není vhodná pro tento typ vozů +STR_1002 :Nelze otevřít {POP16}{POP16}{POP16}{STRINGID}... +STR_1003 :Nelze testovat {POP16}{POP16}{POP16}{STRINGID}... +STR_1004 :Nelze zavřít {POP16}{POP16}{POP16}{STRINGID}... +STR_1005 :Nelze začít stavět {POP16}{POP16}{POP16}{STRINGID}... +STR_1006 :Napřed musí být zavřeno +STR_1007 :Nelze vytvořit dostatečný počet vozů +STR_1008 :{SMALLFONT}{BLACK}Otevřít, zavřít nebo testovat atrakci +STR_1009 :{SMALLFONT}{BLACK}Otevřít nebo zavřít všechny atrakce +STR_1010 :{SMALLFONT}{BLACK}Otevřít nebo zavřít park STR_1011 :Zvařít vše STR_1012 :Otevřít vše STR_1013 :Zvařít park STR_1014 :Otevřít park -STR_1015 :Unable to operate with more than one station platform in this mode -STR_1016 :Unable to operate with less than two stations in this mode -STR_1017 :Can't change operating mode... -STR_1018 :Can't make changes... -STR_1019 :Can't make changes... -STR_1020 :Can't make changes... +STR_1015 :Tento mód nefunguje s více než jednou stanicí +STR_1016 :Tento mód nefunguje s méně než dvěmi stanicemi +STR_1017 :Nelze změnit mód běhu... +STR_1018 :Nelze vytvářet změny... +STR_1019 :Nelze vytvářet změny... +STR_1020 :Nelze vytvářet změny... STR_1021 :{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_1022 :{POP16}{POP16}{POP16}{COMMA16} vagon na vlak STR_1023 :{POP16}{POP16}{POP16}{COMMA16} vagónů na vlak STR_1024 :{COMMA16} vagon na vlak STR_1025 :{COMMA16} vagónů na vlak STR_1026 :Nástupiště je příliš dlouhé! -STR_1027 :{SMALLFONT}{BLACK}Locate this on Main View -STR_1028 :Off edge of map! -STR_1029 :Cannot build partly above and partly below water! +STR_1027 :{SMALLFONT}{BLACK}Najet na toto místo +STR_1028 :Mimo mapu! +STR_1029 :Nelze stavět částečně pod a nad vodní hladinou! STR_1030 :Tohle lze stavět jen pod vodou! STR_1031 :Tohle nejde stavět pod vodou! STR_1032 :Tohle jde stavět jen na hladině! STR_1033 :Tohle jde stavět jen nad zemí! STR_1034 :Tohle jde stavět jen na povrchu! -STR_1035 :Local authority won't allow construction above tree-height! +STR_1035 :Místní správa nepovoluje stavby vyšší, než stromy! STR_1036 :Nahrát hru STR_1037 :Nahrát krajinu -STR_1038 :Convert saved game to scenario -STR_1039 :Install new track design +STR_1038 :Převést uloženou hru na sénář +STR_1039 :Nainstalovat novou trať STR_1040 :Uložit hru STR_1041 :Uložit Scenario STR_1042 :Uložit krajinu @@ -1050,123 +1050,123 @@ STR_1044 :Soubor scénáře OpenRCT2 STR_1045 :Soubor krajiny OpenRCT2 STR_1046 :Soubor designu dráhy OpenRCT2 STR_1047 :Uložení hry selhalo! -STR_1048 :Scenario save failed! -STR_1049 :Landscape save failed! -STR_1050 :Failed to load...{NEWLINE}File contains invalid data! -STR_1051 :Nevyditelné podpěry -STR_1052 :Nevyditelní lidé -STR_1053 :{SMALLFONT}{BLACK}Rides/attractions in park -STR_1054 :{SMALLFONT}{BLACK}Name ride/attraction -STR_1055 :{SMALLFONT}{BLACK}Name person -STR_1056 :{SMALLFONT}{BLACK}Name staff member -STR_1057 :Ride/attraction name -STR_1058 :Enter new name for this ride/attraction: -STR_1059 :Can't rename ride/attraction... -STR_1060 :Invalid ride/attraction name -STR_1061 :Normal mode -STR_1062 :Continuous circuit mode -STR_1063 :Reverse-Incline launched shuttle mode -STR_1064 :Powered launch (passing station) -STR_1065 :Shuttle mode -STR_1066 :Boat hire mode -STR_1067 :Upward launch -STR_1068 :Rotating lift mode -STR_1069 :Station to station mode -STR_1070 :Single ride per admission -STR_1071 :Unlimited rides per admission -STR_1072 :Maze mode -STR_1073 :Race mode -STR_1074 :Bumper-car mode -STR_1075 :Swing mode -STR_1076 :Shop stall mode -STR_1077 :Rotation mode -STR_1078 :Forward rotation -STR_1079 :Backward rotation -STR_1080 :Film: {ENDQUOTES}Avenging aviators{ENDQUOTES} -STR_1081 :3D film: {ENDQUOTES}Mouse tails{ENDQUOTES} -STR_1082 :Space rings mode -STR_1083 :Beginners mode -STR_1084 :LIM-powered launch -STR_1085 :Film: {ENDQUOTES}Thrill riders{ENDQUOTES} -STR_1086 :3D film: {ENDQUOTES}Storm chasers{ENDQUOTES} -STR_1087 :3D film: {ENDQUOTES}Space raiders{ENDQUOTES} -STR_1088 :Intense mode -STR_1089 :Berserk mode -STR_1090 :Haunted house mode -STR_1091 :Circus show mode -STR_1092 :Downward launch -STR_1093 :Crooked house mode -STR_1094 :Freefall drop mode -STR_1095 :Continuous circuit block sectioned mode -STR_1096 :Powered launch (without passing station) -STR_1097 :Powered launch block sectioned mode -STR_1098 :Moving to end of {POP16}{STRINGID} -STR_1099 :Waiting for passengers at {POP16}{STRINGID} -STR_1100 :Waiting to depart {POP16}{STRINGID} -STR_1101 :Departing {POP16}{STRINGID} -STR_1102 :Travelling at {VELOCITY} -STR_1103 :Arriving at {POP16}{STRINGID} -STR_1104 :Unloading passengers at {POP16}{STRINGID} -STR_1105 :Travelling at {VELOCITY} -STR_1106 :Crashing! -STR_1107 :Crashed! -STR_1108 :Travelling at {VELOCITY} -STR_1109 :Swinging -STR_1110 :Rotating -STR_1111 :Rotating -STR_1112 :Operating -STR_1113 :Showing film -STR_1114 :Rotating -STR_1115 :Operating -STR_1116 :Operating -STR_1117 :Doing circus show -STR_1118 :Operating -STR_1119 :Waiting for cable lift -STR_1120 :Travelling at {VELOCITY} -STR_1121 :Stopping -STR_1122 :Waiting for passengers -STR_1123 :Waiting to start -STR_1124 :Starting -STR_1125 :Operating -STR_1126 :Stopping -STR_1127 :Unloading passengers -STR_1128 :Stopped by block brakes -STR_1129 :All vehicles in same colours -STR_1130 :Different colours per {STRINGID} -STR_1131 :Different colours per vehicle -STR_1132 :Vehicle {POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} -STR_1133 :Vehicle {POP16}{COMMA16} +STR_1048 :Uložení scénáře selhalo! +STR_1049 :Uložení krajiny selhalo! +STR_1050 :Nepodařilo se načíst...{NEWLINE}Soubor obsahuje neplatná data! +STR_1051 :Neviditelné podpěry +STR_1052 :Neviditelní lidé +STR_1053 :{SMALLFONT}{BLACK}Atrakce v parku +STR_1054 :{SMALLFONT}{BLACK}Přejmenovat atrakci +STR_1055 :{SMALLFONT}{BLACK}Přejmenovat návštěvníka +STR_1056 :{SMALLFONT}{BLACK}Přejmenovat zaměstnance +STR_1057 :Název atrakce +STR_1058 :Zadejte nové jméno atrakce: +STR_1059 :Tuto atrakci nelze přejmenovat... +STR_1060 :Neplatný název atrakce +STR_1061 :Normalní běh +STR_1062 :Mód okruhu +STR_1063 :Mód jízdy pozpátku s konečnou stanicí +STR_1064 :Rychlý start (s průjezdem stanicí) +STR_1065 :Mód konečné stanice +STR_1066 :Mód lodě k pronájmu +STR_1067 :Start nahorů +STR_1068 :Mód rotujícího výtahu +STR_1069 :Mód stanice-stanice +STR_1070 :Jedna jízda za vstupné +STR_1071 :Neomezené jízdy za vstupné +STR_1072 :Mód bludiště +STR_1073 :Mód závodů +STR_1074 :Mód autodronu +STR_1075 :Mód houpání +STR_1076 :Mód stánku/obchodu +STR_1077 :Mód rotace +STR_1078 :Dopředná rotace +STR_1079 :Zpětná rotace +STR_1080 :Film: {ENDQUOTES}Pomsta letců{ENDQUOTES} +STR_1081 :3D film: {ENDQUOTES}Myší ocásky{ENDQUOTES} +STR_1082 :Mód vesmírnýh kruhů +STR_1083 :Mód pro začátečníky +STR_1084 :Start s LIM +STR_1085 :Film: {ENDQUOTES}Adrenaliňáci{ENDQUOTES} +STR_1086 :3D film: {ENDQUOTES}Páni bouřek{ENDQUOTES} +STR_1087 :3D film: {ENDQUOTES}Vesmírní piráti{ENDQUOTES} +STR_1088 :Intenzivní mód +STR_1089 :Masakr +STR_1090 :Mód strašidelného domu +STR_1091 :Mód cirkusového představení +STR_1092 :Start dolů +STR_1093 :Mód křivého domu +STR_1094 :Mód volného pádu +STR_1095 :Mód okruhu se sekcemi +STR_1096 :Rychlý start (bez průjezdu stanicí) +STR_1097 :Rychlý start módu se sekcemi +STR_1098 :Přesouvá se na konec {POP16}{STRINGID} +STR_1099 :Čeká na návštěvníky na {POP16}{STRINGID} +STR_1100 :Čeká na odjedz {POP16}{STRINGID} +STR_1101 :Odjíždí {POP16}{STRINGID} +STR_1102 :Jede rychlostí {VELOCITY} +STR_1103 :Přijíždí do {POP16}{STRINGID} +STR_1104 :Vykládá návštěvníky {POP16}{STRINGID} +STR_1105 :Jede rychlostí {VELOCITY} +STR_1106 :Bourá! +STR_1107 :Naboural! +STR_1108 :Jede rychlostí {VELOCITY} +STR_1109 :Houpe se +STR_1110 :Rotuje +STR_1111 :Rotuje +STR_1112 :V provozu +STR_1113 :Promítá film +STR_1114 :Rotuje +STR_1115 :V provozu +STR_1116 :V provozu +STR_1117 :Předvádí cirkusové představení +STR_1118 :V provozu +STR_1119 :Čeká na výtah +STR_1120 :Jede rychlostí {VELOCITY} +STR_1121 :Zastavuje +STR_1122 :Čeká na návštěvníky +STR_1123 :Čeká na start +STR_1124 :Startuje +STR_1125 :V provozu +STR_1126 :Zastavuje +STR_1127 :Vykládá návštěvníky +STR_1128 :Zastavuje na brzdících blocích +STR_1129 :Všechny vozidla mají stejnou barvu +STR_1130 :Rozdílné barvy pro každý {STRINGID} +STR_1131 :Rozdílné barvy pro každé vozidlo +STR_1132 :Vozidlo {POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1133 :Vozidlo {POP16}{COMMA16} STR_1134 :{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} {COMMA16} STR_1135 :{STRINGID} {COMMA16} -STR_1136 :{SMALLFONT}{BLACK}Vybrat hlavní barvy -STR_1137 :{SMALLFONT}{BLACK}Vybrat doplňkové barvy 1 -STR_1138 :{SMALLFONT}{BLACK}Vybrat doplňkové barvy 2 +STR_1136 :{SMALLFONT}{BLACK}Vybrat hlavní barvu +STR_1137 :{SMALLFONT}{BLACK}Vybrat doplňkovou barvu 1 +STR_1138 :{SMALLFONT}{BLACK}Vybrat doplňkovou barvu 2 STR_1139 :{SMALLFONT}{BLACK}Vybrat barvu podpěr STR_1140 :{SMALLFONT}{BLACK}Vybrat barevné schéma vozidel -STR_1141 :{SMALLFONT}{BLACK}Select which vehicle/train to modify +STR_1141 :{SMALLFONT}{BLACK}Vyberte, které vozidlo/vlak chtete urpavit STR_1142 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1143 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRINGID} -STR_1144 :Can't build/move entrance for this ride/attraction... -STR_1145 :Can't build/move exit for this ride/attraction... +STR_1144 :Nelze postavit/přesunout vstup této atrakce... +STR_1145 :Nelze postavit/přesunout výstup z této atrakce... STR_1146 :Vstup ještě není postaven STR_1147 :Výstup ještě není postaven -STR_1148 :Quarter load -STR_1149 :Half load -STR_1150 :Three-quarter load -STR_1151 :Full load -STR_1152 :Any load -STR_1153 :Height Marks on Ride Tracks -STR_1154 :Height Marks on Land -STR_1155 :Height Marks on Paths +STR_1148 :naložit na 25% +STR_1149 :naložit na 50% +STR_1150 :naložit na 75% +STR_1151 :plně naložit +STR_1152 :naložit jakkoliv +STR_1153 :Výškové popisky atrakcí +STR_1154 :Výškové popisky krajiny +STR_1155 :Výškové popisky cest STR_1156 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1157 :{TICK}{MOVE_X}{SMALLFONT}{STRINGID} STR_1158 :Tohle nelze odstranit... -STR_1159 :{SMALLFONT}{BLACK}Place scenery, gardens, and other accessories -STR_1160 :{SMALLFONT}{BLACK}Create/adjust lakes & water -STR_1161 :Tohle tafy nemůže být... +STR_1159 :{SMALLFONT}{BLACK}Nástroj pro kulisy, květiny a ostatní doplňky +STR_1160 :{SMALLFONT}{BLACK}Nástroj pro vodní plochy +STR_1161 :Tohle tady nemůže být... STR_1162 :{OUTLINE}{TOPAZ}{STRINGID} -STR_1163 :{STRINGID}{NEWLINE}(Right-Click to Modify) -STR_1164 :{STRINGID}{NEWLINE}(Right-Click to Remove) +STR_1163 :{STRINGID}{NEWLINE}(Upravít pravým kliknutím) +STR_1164 :{STRINGID}{NEWLINE}(Odebrat pravým kliknutím) STR_1165 :{STRINGID} - {STRINGID} {COMMA16} STR_1166 :Tady nelze snížit hladinu vody... STR_1167 :Tady nelze zvýšit hladinu vody... @@ -1175,24 +1175,25 @@ STR_1169 :(None) STR_1170 :{STRING} STR_1171 :{RED}Zavřeno - - STR_1172 :{YELLOW}{STRINGID} - - -STR_1173 :{SMALLFONT}{BLACK}Build footpaths and queue lines -STR_1174 :Banner sign in the way -STR_1175 :Can't build this on sloped footpath -STR_1176 :Can't build footpath here... -STR_1177 :Can't remove footpath from here... -STR_1178 :Land slope unsuitable -STR_1179 :Footpath in the way -STR_1180 :Can't build this underwater! +STR_1173 :{SMALLFONT}{BLACK}Nástroj pro cesty a fronty +STR_1174 :Baner v cestě +STR_1175 :Toto nelze postavit na strmé cestě +STR_1176 :Nelze stavět cestu... +STR_1177 :Tuto cestu nelze odstranit... +STR_1178 :Příliš velký sklon terénu +# hehe :-) +STR_1179 :Cesta v cestě +STR_1180 :Nelze stavět pod vodou! STR_1181 :Cesty -STR_1182 :Druh +STR_1182 :Typ cesty STR_1183 :Směr -STR_1184 :Slope +STR_1184 :Sklon STR_1185 :{SMALLFONT}{BLACK}Směr -STR_1186 :{SMALLFONT}{BLACK}Slope down -STR_1187 :{SMALLFONT}{BLACK}Level -STR_1188 :{SMALLFONT}{BLACK}Slope up -STR_1189 :{SMALLFONT}{BLACK}Construct the selected footpath section -STR_1190 :{SMALLFONT}{BLACK}Remove previous footpath section +STR_1186 :{SMALLFONT}{BLACK}Klesání +STR_1187 :{SMALLFONT}{BLACK}Rovně +STR_1188 :{SMALLFONT}{BLACK}Stoupání +STR_1189 :{SMALLFONT}{BLACK}Postavit cestu +STR_1190 :{SMALLFONT}{BLACK}Odstranit naposledy položenou cestu STR_1191 :{BLACK}{STRINGID} STR_1192 :{OUTLINE}{RED}{STRINGID} STR_1193 :{WINDOW_COLOUR_2}{STRINGID} @@ -1201,36 +1202,36 @@ STR_1195 :Testovací kolo STR_1196 :Otevřeno STR_1197 :Porucha STR_1198 :Nehoda! -STR_1199 :{COMMA16} person on ride -STR_1200 :{COMMA16} people on ride -STR_1201 :Nobody in queue line -STR_1202 :1 person in queue line -STR_1203 :{COMMA16} people in queue line -STR_1204 :{COMMA16} minute queue time -STR_1205 :{COMMA16} minutes queue time -STR_1206 :{WINDOW_COLOUR_2}Čekat na: +STR_1199 :{COMMA16} návštěvník na atrakci +STR_1200 :{COMMA16} návštěvníků na atrakci +STR_1201 :Nikdo ve frontě +STR_1202 :1 návštěvník ve frontě +STR_1203 :{COMMA16} návštěvníků ve frontě +STR_1204 :{COMMA16} minutu čekání ve frontě +STR_1205 :{COMMA16} minut čekání ve frontě +STR_1206 :{WINDOW_COLOUR_2}Naložit: STR_1207 :{WINDOW_COLOUR_2}Vyjet když jiný vlak přijede do stanice STR_1208 :{WINDOW_COLOUR_2}Vyplout když jiná loď přijede do přístavu -STR_1209 :{SMALLFONT}{BLACK}Select whether should wait for passengers before departing -STR_1210 :{SMALLFONT}{BLACK}Select whether should leave if another vehicle arrives at the same station +STR_1209 :{SMALLFONT}{BLACK}Vyberte, zda se má čekat na návštěvníky před odjezdem +STR_1210 :{SMALLFONT}{BLACK}Vyberte, zda se má vyrazit, když do stanice dorazí jiný vůz STR_1211 :{WINDOW_COLOUR_2}Čekat nejméně: STR_1212 :{WINDOW_COLOUR_2}Čekat nejdéle: -STR_1213 :{SMALLFONT}{BLACK}Select minimum length of time to wait before departing -STR_1214 :{SMALLFONT}{BLACK}Select maximum length of time to wait before departing -STR_1215 :{WINDOW_COLOUR_2}Synchronise with adjacent stations -STR_1216 :{SMALLFONT}{BLACK}Select whether to synchronise departure with all adjacent stations (for 'racing') +STR_1213 :{SMALLFONT}{BLACK}Vyberte minimální délku čekání před odjezdem +STR_1214 :{SMALLFONT}{BLACK}Vyberte maximální délku čekání před odjezdem +STR_1215 :{WINDOW_COLOUR_2}Synchronizovat se sousedícími stanicemi +STR_1216 :{SMALLFONT}{BLACK}Vyberte, zda synchronizovat odjezdy se sousedícími stanicemi (pro "závodění") STR_1217 :{COMMA16} sekund STR_1218 :{BLACK}{SMALLUP} STR_1219 :{BLACK}{SMALLDOWN} STR_1220 :Jen východ STR_1221 :Nemá vchod STR_1222 :Chybí východ -STR_1223 :{SMALLFONT}{BLACK}Transport rides -STR_1224 :{SMALLFONT}{BLACK}Gentle rides -STR_1225 :{SMALLFONT}{BLACK}Roller coasters -STR_1226 :{SMALLFONT}{BLACK}Thrill rides -STR_1227 :{SMALLFONT}{BLACK}Water rides -STR_1228 :{SMALLFONT}{BLACK}Shops & stalls +STR_1223 :{SMALLFONT}{BLACK}Atrakce pro přepravu +STR_1224 :{SMALLFONT}{BLACK}Mírné atrakce +STR_1225 :{SMALLFONT}{BLACK}Horské dráhy +STR_1226 :{SMALLFONT}{BLACK}Adrenalinové atrakce +STR_1227 :{SMALLFONT}{BLACK}Vodní atrakce +STR_1228 :{SMALLFONT}{BLACK}Obchody & stánky STR_1229 :vlak STR_1230 :vlaky STR_1231 :Vlak @@ -1252,41 +1253,41 @@ STR_1246 :Dráhy STR_1247 :{COMMA16} dráha STR_1248 :{COMMA16} dráhy STR_1249 :Dráha {COMMA16} -STR_1250 :docking platform -STR_1251 :docking platforms -STR_1252 :Docking platform -STR_1253 :Docking platforms -STR_1254 :{COMMA16} docking platform -STR_1255 :{COMMA16} docking platforms -STR_1256 :Docking platform {COMMA16} -STR_1257 :station -STR_1258 :stations -STR_1259 :Station -STR_1260 :Stations -STR_1261 :{COMMA16} station -STR_1262 :{COMMA16} stations -STR_1263 :Station {COMMA16} -STR_1264 :car -STR_1265 :cars -STR_1266 :Car -STR_1267 :Cars -STR_1268 :{COMMA16} car -STR_1269 :{COMMA16} cars -STR_1270 :Car {COMMA16} -STR_1271 :building -STR_1272 :buildings -STR_1273 :Building -STR_1274 :Buildings -STR_1275 :{COMMA16} building -STR_1276 :{COMMA16} buildings -STR_1277 :Building {COMMA16} -STR_1278 :structure -STR_1279 :structures -STR_1280 :Structure -STR_1281 :Structures -STR_1282 :{COMMA16} structure -STR_1283 :{COMMA16} structures -STR_1284 :Structure {COMMA16} +STR_1250 :dok +STR_1251 :doky +STR_1252 :Dok +STR_1253 :Doky +STR_1254 :{COMMA16} dok +STR_1255 :{COMMA16} doky +STR_1256 :Dok {COMMA16} +STR_1257 :stanice +STR_1258 :stanice +STR_1259 :Stanice +STR_1260 :Stanice +STR_1261 :{COMMA16} stanice +STR_1262 :{COMMA16} stanice +STR_1263 :Stanice {COMMA16} +STR_1264 :vůz +STR_1265 :vozy +STR_1266 :Vůz +STR_1267 :Vozy +STR_1268 :{COMMA16} vůz +STR_1269 :{COMMA16} vozy +STR_1270 :Vůz {COMMA16} +STR_1271 :budova +STR_1272 :budovy +STR_1273 :Budova +STR_1274 :Budovy +STR_1275 :{COMMA16} budova +STR_1276 :{COMMA16} budovy +STR_1277 :Budova {COMMA16} +STR_1278 :stavba +STR_1279 :stavby +STR_1280 :Stavba +STR_1281 :Stavby +STR_1282 :{COMMA16} stavba +STR_1283 :{COMMA16} stavby +STR_1284 :Stavba {COMMA16} STR_1285 :loď STR_1286 :lodě STR_1287 :Loď @@ -1308,13 +1309,13 @@ STR_1302 :Kol STR_1303 :{COMMA16} kolo STR_1304 :{COMMA16} kol STR_1305 :Kolo {COMMA16} -STR_1306 :ring -STR_1307 :rings -STR_1308 :Ring -STR_1309 :Rings -STR_1310 :{COMMA16} ring -STR_1311 :{COMMA16} rings -STR_1312 :Ring {COMMA16} +STR_1306 :kruh +STR_1307 :kruhy +STR_1308 :Kruh +STR_1309 :Kruhy +STR_1310 :{COMMA16} kruh +STR_1311 :{COMMA16} kruhy +STR_1312 :Kruh {COMMA16} STR_1313 :hráč STR_1314 :hráči STR_1315 :Hráč @@ -1322,61 +1323,61 @@ STR_1316 :Hráči STR_1317 :{COMMA16} hráč STR_1318 :{COMMA16} hráči STR_1319 :Hráč {COMMA16} -STR_1320 :course -STR_1321 :courses -STR_1322 :Course -STR_1323 :Courses -STR_1324 :{COMMA16} course -STR_1325 :{COMMA16} courses -STR_1326 :Course {COMMA16} -STR_1327 :{SMALLFONT}{BLACK}Rotate objects by 90{DEGREE} -STR_1328 :Level land required -STR_1329 :{WINDOW_COLOUR_2}Launch speed: -STR_1330 :{SMALLFONT}{BLACK}Maximum speed when leaving station +STR_1320 :hřiště +STR_1321 :hřiště +STR_1322 :Hřiště +STR_1323 :Hřiště +STR_1324 :{COMMA16} hřiště +STR_1325 :{COMMA16} hřiště +STR_1326 :Hřiště {COMMA16} +STR_1327 :{SMALLFONT}{BLACK}Otočit objekty o 90{DEGREE} +STR_1328 :Vyžadována rovná zem +STR_1329 :{WINDOW_COLOUR_2}Startovní rychlost: +STR_1330 :{SMALLFONT}{BLACK}Maximální rychlost opuštění stanice STR_1331 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} STR_1332 :{VELOCITY} STR_1333 :{STRINGID} - {STRINGID}{POP16} STR_1334 :{STRINGID} - {STRINGID} {COMMA16} -STR_1335 :{STRINGID} - Entrance{POP16}{POP16} -STR_1336 :{STRINGID} - Station {POP16}{COMMA16} Entrance -STR_1337 :{STRINGID} - Exit{POP16}{POP16} -STR_1338 :{STRINGID} - Station {POP16}{COMMA16} Exit -STR_1339 :{BLACK}V7sledky testů nejsou hotovy... +STR_1335 :{STRINGID} - Vstup{POP16}{POP16} +STR_1336 :{STRINGID} - Vstup do stanice {POP16}{COMMA16} +STR_1337 :{STRINGID} - Východ{POP16}{POP16} +STR_1338 :{STRINGID} - Východ ze stanice {POP16}{COMMA16} +STR_1339 :{BLACK}Testování zatím nebylo dokončeno... STR_1340 :{WINDOW_COLOUR_2}Max. rychlost: {BLACK}{VELOCITY} -STR_1341 :{WINDOW_COLOUR_2}Ride time: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1341 :{WINDOW_COLOUR_2}Doba jízdy: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1342 :{DURATION} STR_1343 :{DURATION} / -STR_1344 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1344 :{WINDOW_COLOUR_2}Délka jízdy: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1345 :{LENGTH} STR_1346 :{LENGTH} / STR_1347 :{WINDOW_COLOUR_2}Průměrná rychlost: {BLACK}{VELOCITY} -STR_1348 :{WINDOW_COLOUR_2}Max. positive vertical G's: {BLACK}{COMMA2DP32}g -STR_1349 :{WINDOW_COLOUR_2}Max. positive vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1350 :{WINDOW_COLOUR_2}Max. negative vertical G's: {BLACK}{COMMA2DP32}g -STR_1351 :{WINDOW_COLOUR_2}Max. negative vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1352 :{WINDOW_COLOUR_2}Max. lateral G's: {BLACK}{COMMA2DP32}g -STR_1353 :{WINDOW_COLOUR_2}Max. lateral G's: {OUTLINE}{RED}{COMMA2DP32}g +STR_1348 :{WINDOW_COLOUR_2}Max. kladné vertikální zrychlení: {BLACK}{COMMA2DP32}g +STR_1349 :{WINDOW_COLOUR_2}Max. kladné vertikální zrychlení: {OUTLINE}{RED}{COMMA2DP32}g +STR_1350 :{WINDOW_COLOUR_2}Max. záporné vertikální zrychlení: {BLACK}{COMMA2DP32}g +STR_1351 :{WINDOW_COLOUR_2}Max. záporné vertikální zrychlení: {OUTLINE}{RED}{COMMA2DP32}g +STR_1352 :{WINDOW_COLOUR_2}Max. laterální zrychlení (ze strany na stranu): {BLACK}{COMMA2DP32}g +STR_1353 :{WINDOW_COLOUR_2}Max. laterální zrychlení (ze strany na stranu): {OUTLINE}{RED}{COMMA2DP32}g STR_1354 :{WINDOW_COLOUR_2}Nejvyšší pád: {BLACK}{LENGTH} STR_1355 :{WINDOW_COLOUR_2}Pádů: {BLACK}{COMMA16} STR_1356 :{WINDOW_COLOUR_2}Obratů: {BLACK}{COMMA16} -STR_1357 :{WINDOW_COLOUR_2}Holes: {BLACK}{COMMA16} +STR_1357 :{WINDOW_COLOUR_2}Děr: {BLACK}{COMMA16} STR_1358 :{WINDOW_COLOUR_2}Celkem ve stav beztíže: {BLACK}{COMMA2DP32}sekund -STR_1359 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minute -STR_1360 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minutes -STR_1361 :Can't change speed... -STR_1362 :Can't change launch speed... -STR_1363 :Too high for supports! -STR_1364 :Supports for track above can't be extended any further! +STR_1359 :{WINDOW_COLOUR_2}Doba čekání: {BLACK}{COMMA16} minuta +STR_1360 :{WINDOW_COLOUR_2}Doba čekání: {BLACK}{COMMA16} minut +STR_1361 :Nelze změnit rychlost... +STR_1362 :Nelze změnit startovací rychlost... +STR_1363 :Příliš vysoké podpěry! +STR_1364 :Podpěry tratě nelze více zvyšovat! STR_1365 :Otočka kolem trati (levá) STR_1366 :Otočka kolem trati (pravá) STR_1367 :Poloviční smyčka -STR_1368 :Poloviční Vývrtka (levá) -STR_1369 :Poloviční Vývrtka (pravá) +STR_1368 :Poloviční vývrtka (levá) +STR_1369 :Poloviční vývrtka (pravá) STR_1370 :Sudový výkrut (levý) STR_1371 :Sudový výkrut (pravý) -STR_1372 :Launched Lift Hill -STR_1373 :Velká Poloviční Vývrtka (levá) -STR_1374 :Velká Poloviční Vývrtka (pravá) +STR_1372 :Řetězový vlek s vypuštěním +STR_1373 :Velká poloviční vývrtka (levá) +STR_1374 :Velká poloviční vývrtka (pravá) STR_1375 :Přechod vzhůru STR_1376 :Přechod dolů STR_1377 :Otočka kolem těla (levá) @@ -1387,165 +1388,165 @@ STR_1381 :Zahnutý vlečný svah (vlevo) STR_1382 :Zahnutý vlečný svah (vpravo) STR_1383 :Čtvrt smyčky STR_1384 :{YELLOW}{STRINGID} -STR_1385 :{SMALLFONT}{BLACK}Other track configurations -STR_1386 :Zvláštní... -STR_1387 :Can't change land type... +STR_1385 :{SMALLFONT}{BLACK}Jiné možnosti tratě +STR_1386 :Speciální... +STR_1387 :Typ povrchu nelze změnit... STR_1388 :{OUTLINE}{GREEN}+ {CURRENCY} STR_1389 :{OUTLINE}{RED}- {CURRENCY} STR_1390 :{CURRENCY2DP} STR_1391 :{RED}{CURRENCY2DP} -STR_1392 :{SMALLFONT}{BLACK}View of ride/attraction -STR_1393 :{SMALLFONT}{BLACK}Vehicle details and options -STR_1394 :{SMALLFONT}{BLACK}Operating options -STR_1395 :{SMALLFONT}{BLACK}Maintenance options -STR_1396 :{SMALLFONT}{BLACK}Colour scheme options -STR_1397 :{SMALLFONT}{BLACK}Sound & music options -STR_1398 :{SMALLFONT}{BLACK}Measurements and test data -STR_1399 :{SMALLFONT}{BLACK}Graphs +STR_1392 :{SMALLFONT}{BLACK}Pohled na atrakci +STR_1393 :{SMALLFONT}{BLACK}Nastavení a detaily vozidel +STR_1394 :{SMALLFONT}{BLACK}Nastavení chování +STR_1395 :{SMALLFONT}{BLACK}Nastavení údržby +STR_1396 :{SMALLFONT}{BLACK}Nastavení barevných kombinací +STR_1397 :{SMALLFONT}{BLACK}Nastavení zvuků a hudby +STR_1398 :{SMALLFONT}{BLACK}Měření a data z testování +STR_1399 :{SMALLFONT}{BLACK}Grafy STR_1400 :Vchod STR_1401 :Východ -STR_1402 :{SMALLFONT}{BLACK}Build or move entrance to ride/attraction -STR_1403 :{SMALLFONT}{BLACK}Build or move exit from ride/attraction +STR_1402 :{SMALLFONT}{BLACK}Postavit nebo posunout vstup na atrakci +STR_1403 :{SMALLFONT}{BLACK}Postavit nebo posunout výstup z atrakce STR_1404 :{SMALLFONT}{BLACK}Otočit o 90{DEGREE} STR_1405 :{SMALLFONT}{BLACK}Zrcadlový obraz -STR_1406 :{SMALLFONT}{BLACK}Toggle scenery on/off (if available for this design) -STR_1407 :{WINDOW_COLOUR_2}Build this... +STR_1406 :{SMALLFONT}{BLACK}Přepnout zobrazení kulis (pokud je trať má) +STR_1407 :{WINDOW_COLOUR_2}Postavit STR_1408 :{WINDOW_COLOUR_2}Cena: {BLACK}{CURRENCY} -STR_1409 :Entry/Exit Platform +STR_1409 :Nástuní/výstupní stanice STR_1410 :Svislá věž STR_1411 :{STRINGID} v cestě -STR_1412 :{WINDOW_COLOUR_3}Data logging not available for this type of ride -STR_1413 :{WINDOW_COLOUR_3}Data logging will start when next {STRINGID} leaves {STRINGID} +STR_1412 :{WINDOW_COLOUR_3}Měření dat není pro tento typ atrakcí dostupné +STR_1413 :{WINDOW_COLOUR_3}Měření dat začne, až další {STRINGID} vyrazí z {STRINGID} STR_1414 :{SMALLFONT}{BLACK}{DURATION} STR_1415 :{WINDOW_COLOUR_2}Rychlost STR_1416 :{WINDOW_COLOUR_2}Výška -STR_1417 :{WINDOW_COLOUR_2}Vert.G's -STR_1418 :{WINDOW_COLOUR_2}Lat.G's +STR_1417 :{WINDOW_COLOUR_2}Vert.zrych. +STR_1418 :{WINDOW_COLOUR_2}Late.zrych. STR_1419 :{SMALLFONT}{BLACK}{VELOCITY} STR_1420 :{SMALLFONT}{BLACK}{LENGTH} STR_1421 :{SMALLFONT}{BLACK}{COMMA16}g -STR_1422 :{SMALLFONT}{BLACK}Logging data from {POP16}{STRINGID} -STR_1423 :{SMALLFONT}{BLACK}Queue line path -STR_1424 :{SMALLFONT}{BLACK}Footpath -STR_1425 :Footpath -STR_1426 :Queue Line -STR_1427 :{WINDOW_COLOUR_2}Customers: {BLACK}{COMMA32} per hour -STR_1428 :{WINDOW_COLOUR_2}Admission price: +STR_1422 :{SMALLFONT}{BLACK}Měření dat z {POP16}{STRINGID} +STR_1423 :{SMALLFONT}{BLACK}Fronta +STR_1424 :{SMALLFONT}{BLACK}Cesta +STR_1425 :Pěší cesta +STR_1426 :Fronta +STR_1427 :{WINDOW_COLOUR_2}Návštěvníci: {BLACK}{COMMA32} za hodinu +STR_1428 :{WINDOW_COLOUR_2}Cena vstupenky: STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} -STR_1430 :Free -STR_1431 :Walking -STR_1432 :Heading for {STRINGID} -STR_1433 :Queuing for {STRINGID} -STR_1434 :Drowning -STR_1435 :On {STRINGID} -STR_1436 :In {STRINGID} -STR_1437 :At {STRINGID} -STR_1438 :Sitting -STR_1439 :(select location) +STR_1430 :Zdarma +STR_1431 :Prochází se +STR_1432 :Jde na {STRINGID} +STR_1433 :Čeká na {STRINGID} +STR_1434 :Topí se +STR_1435 :na {STRINGID} +STR_1436 :v {STRINGID} +STR_1437 :v {STRINGID} +STR_1438 :Sedí +STR_1439 :(vyberte umístění) STR_1440 :Seká trávu STR_1441 :Zametá cestu -STR_1442 :Vynáši odpadkový koš +STR_1442 :Vynáší odpadkový koš STR_1443 :Zalévá záhon STR_1444 :Sleduje {STRINGID} STR_1445 :Sleduje vystavbu {STRINGID} -STR_1446 :Prohlíží si prostředí -STR_1447 :Opouští park -STR_1448 :Sleduje výstavbu nové trti +STR_1446 :Prohlíží si kulisy +STR_1447 :Opouští zábavní park +STR_1448 :Sleduje výstavbu nové trati STR_1449 :{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1450 :{INLINE_SPRITE}{09}{20}{00}{00}{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1451 :{STRINGID}{NEWLINE}({STRINGID}) -STR_1452 :Jméno hosta -STR_1453 :Vložte jméno tohoto hosta: -STR_1454 :Nelze pojmenovat hosta... -STR_1455 :Neplatné jméno pro hosta +STR_1452 :Jméno návštěvníka +STR_1453 :Vložte jméno tohoto návštěvníka: +STR_1454 :Nelze pojmenovat návštěvníka... +STR_1455 :Neplatné jméno pro návštěvníka STR_1456 :{WINDOW_COLOUR_2}Utracených peněz: {BLACK}{CURRENCY2DP} STR_1457 :{WINDOW_COLOUR_2}Peněz v kapse: {BLACK}{CURRENCY2DP} STR_1458 :{WINDOW_COLOUR_2}Čas strávený v parku: {BLACK}{REALTIME} -STR_1459 :Track style +STR_1459 :Typ trati STR_1460 :{SMALLFONT}{BLACK}otevřená trať ve tvaru 'U' STR_1461 :{SMALLFONT}{BLACK}uzavřená trať ve tvaru 'O' STR_1462 :Svah je pro vlečení příliš strmí -STR_1463 :Hostů -STR_1464 :Šroubovice vzhůru (small) -STR_1465 :Šroubovice vzhůru (large) -STR_1466 :Šroubovice dolů (small) -STR_1467 :Šroubovice dolů (large) +STR_1463 :Návštěvníků +STR_1464 :Šroubovice vzhůru (malá) +STR_1465 :Šroubovice vzhůru (velká) +STR_1466 :Šroubovice dolů (malá) +STR_1467 :Šroubovice dolů (velká) STR_1468 :Personál STR_1469 :Dráha musí začínat a končit stanicí STR_1470 :Stanice není dost dlouhá STR_1471 :{WINDOW_COLOUR_2}Rychlost: -STR_1472 :{SMALLFONT}{BLACK}Speed of this ride -STR_1473 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1474 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}Not yet available -STR_1475 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1476 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}Not yet available -STR_1477 :{WINDOW_COLOUR_2}Intensity rating: {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) -STR_1478 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1479 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}Not yet available +STR_1472 :{SMALLFONT}{BLACK}Rychlost této atrakce +STR_1473 :{WINDOW_COLOUR_2}Nadšení: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1474 :{WINDOW_COLOUR_2}Nadšení: {BLACK}Zatím neznámé +STR_1475 :{WINDOW_COLOUR_2}Intenzita: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1476 :{WINDOW_COLOUR_2}Intenzita: {BLACK}Zatím neznámá +STR_1477 :{WINDOW_COLOUR_2}Intenzita: {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) +STR_1478 :{WINDOW_COLOUR_2}Nevolnost: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1479 :{WINDOW_COLOUR_2}Nevolnost: {BLACK}Zatím neznámá STR_1480 :{SMALLFONT}{OPENQUOTES}Nemohu si dovolit {STRINGID}{ENDQUOTES} STR_1481 :{SMALLFONT}{OPENQUOTES}Utratil jsem všechny své peníze{ENDQUOTES} -STR_1482 :{SMALLFONT}{OPENQUOTES}Je my špatně{ENDQUOTES} -STR_1483 :{SMALLFONT}{OPENQUOTES}Je my hrozně špatně{ENDQUOTES} -STR_1484 :{SMALLFONT}{OPENQUOTES}I want to go on something more thrilling than {STRINGID}{ENDQUOTES} +STR_1482 :{SMALLFONT}{OPENQUOTES}Je mi špatně{ENDQUOTES} +STR_1483 :{SMALLFONT}{OPENQUOTES}Je mi hrozně špatně{ENDQUOTES} +STR_1484 :{SMALLFONT}{OPENQUOTES}Chci na něco víc adrenalinového, než {STRINGID}{ENDQUOTES} STR_1485 :{SMALLFONT}{OPENQUOTES}{STRINGID} na mě vypadá moc intenzivně{ENDQUOTES} -STR_1486 :{SMALLFONT}{OPENQUOTES}I haven't finished my {STRINGID} yet{ENDQUOTES} -STR_1487 :{SMALLFONT}{OPENQUOTES}Jen ze sledování {STRINGID} se my dělá zle{ENDQUOTES} +STR_1486 :{SMALLFONT}{OPENQUOTES}Ještě jsem nevypil/nedojedl {STRINGID}{ENDQUOTES} +STR_1487 :{SMALLFONT}{OPENQUOTES}Jen ze pohledu na {STRINGID} se mi dělá zle{ENDQUOTES} STR_1488 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za vstup na {STRINGID}{ENDQUOTES} STR_1489 :{SMALLFONT}{OPENQUOTES}Chci jít domů{ENDQUOTES} -STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} is really good value{ENDQUOTES} +STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} se opravdu vyplatí{ENDQUOTES} STR_1491 :{SMALLFONT}{OPENQUOTES}Už mám {STRINGID}{ENDQUOTES} STR_1492 :{SMALLFONT}{OPENQUOTES}Nemohu si dovolit {STRINGID}{ENDQUOTES} -STR_1493 :{SMALLFONT}{OPENQUOTES}Nejdem hladový{ENDQUOTES} +STR_1493 :{SMALLFONT}{OPENQUOTES}Nemám hlad{ENDQUOTES} STR_1494 :{SMALLFONT}{OPENQUOTES}Nemám žízeň{ENDQUOTES} STR_1495 :{SMALLFONT}{OPENQUOTES}Pomóc! Topím se!{ENDQUOTES} STR_1496 :{SMALLFONT}{OPENQUOTES}Ztratil jsem se!{ENDQUOTES} STR_1497 :{SMALLFONT}{OPENQUOTES}Na {STRINGID} to bylo super{ENDQUOTES} -STR_1498 :{SMALLFONT}{OPENQUOTES}4ekám v řadě na {STRINGID} už věky{ENDQUOTES} +STR_1498 :{SMALLFONT}{OPENQUOTES}Čekám v řadě na {STRINGID} už věky{ENDQUOTES} STR_1499 :{SMALLFONT}{OPENQUOTES}Jsem unavený{ENDQUOTES} STR_1500 :{SMALLFONT}{OPENQUOTES}Mám hlad{ENDQUOTES} -STR_1501 :{SMALLFONT}{OPENQUOTES}Jsem žíznivý{ENDQUOTES} +STR_1501 :{SMALLFONT}{OPENQUOTES}Mám žízeň{ENDQUOTES} STR_1502 :{SMALLFONT}{OPENQUOTES}Potřebuji jít na toaletu{ENDQUOTES} STR_1503 :{SMALLFONT}{OPENQUOTES}Nemůžu najít {STRINGID}{ENDQUOTES} -STR_1504 :{SMALLFONT}{OPENQUOTES}I'm not paying that much to use {STRINGID}{ENDQUOTES} -STR_1505 :{SMALLFONT}{OPENQUOTES}I'm not going on {STRINGID} while it's raining{ENDQUOTES} +STR_1504 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc, jen abych mohl na {STRINGID}{ENDQUOTES} +STR_1505 :{SMALLFONT}{OPENQUOTES}Nepůjdu na {STRINGID} když prší{ENDQUOTES} STR_1506 :{SMALLFONT}{OPENQUOTES}Je tu hrozný nepořádek{ENDQUOTES} STR_1507 :{SMALLFONT}{OPENQUOTES}Nemůžu najít východ z praku{ENDQUOTES} -STR_1508 :{SMALLFONT}{OPENQUOTES}I want to get off {STRINGID}{ENDQUOTES} -STR_1509 :{SMALLFONT}{OPENQUOTES}I want to get out of {STRINGID}{ENDQUOTES} -STR_1510 :{SMALLFONT}{OPENQUOTES}I'm not going on {STRINGID} - It isn't safe{ENDQUOTES} -STR_1511 :{SMALLFONT}{OPENQUOTES}This path is disgusting{ENDQUOTES} +STR_1508 :{SMALLFONT}{OPENQUOTES}Chci pryč z {STRINGID}{ENDQUOTES} +STR_1509 :{SMALLFONT}{OPENQUOTES}Chci se dostat pryč z {STRINGID}{ENDQUOTES} +STR_1510 :{SMALLFONT}{OPENQUOTES}Nepůjdu na {STRINGID} - není to bezpečné{ENDQUOTES} +STR_1511 :{SMALLFONT}{OPENQUOTES}Tahle cesta je odporná{ENDQUOTES} STR_1512 :{SMALLFONT}{OPENQUOTES}Je to tady hrozně přelidněné{ENDQUOTES} -STR_1513 :{SMALLFONT}{OPENQUOTES}The vandalism here is really bad{ENDQUOTES} -STR_1514 :{SMALLFONT}{OPENQUOTES}Krásné prostředí!{ENDQUOTES} -STR_1515 :{SMALLFONT}{OPENQUOTES}This park is really clean and tidy{ENDQUOTES} -STR_1516 :{SMALLFONT}{OPENQUOTES}The jumping fountains are great{ENDQUOTES} -STR_1517 :{SMALLFONT}{OPENQUOTES}The music is nice here{ENDQUOTES} -STR_1518 :{SMALLFONT}{OPENQUOTES}This balloon from {STRINGID} is really good value{ENDQUOTES} -STR_1519 :{SMALLFONT}{OPENQUOTES}This cuddly toy from {STRINGID} is really good value{ENDQUOTES} -STR_1520 :{SMALLFONT}{OPENQUOTES}This park map from {STRINGID} is really good value{ENDQUOTES} -STR_1521 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1522 :{SMALLFONT}{OPENQUOTES}This umbrella from {STRINGID} is really good value{ENDQUOTES} -STR_1523 :{SMALLFONT}{OPENQUOTES}This drink from {STRINGID} is really good value{ENDQUOTES} -STR_1524 :{SMALLFONT}{OPENQUOTES}This burger from {STRINGID} is really good value{ENDQUOTES} -STR_1525 :{SMALLFONT}{OPENQUOTES}These chips from {STRINGID} are really good value{ENDQUOTES} -STR_1526 :{SMALLFONT}{OPENQUOTES}This ice cream from {STRINGID} is really good value{ENDQUOTES} -STR_1527 :{SMALLFONT}{OPENQUOTES}This candyfloss from {STRINGID} is really good value{ENDQUOTES} +STR_1513 :{SMALLFONT}{OPENQUOTES}Je tu spousta vandalů{ENDQUOTES} +STR_1514 :{SMALLFONT}{OPENQUOTES}Krásné kulisy!{ENDQUOTES} +STR_1515 :{SMALLFONT}{OPENQUOTES}Tenhle park je opravdu čistý{ENDQUOTES} +STR_1516 :{SMALLFONT}{OPENQUOTES}Ty fontány jsou opravdu pěkné{ENDQUOTES} +STR_1517 :{SMALLFONT}{OPENQUOTES}Hraje tu hezká hudba{ENDQUOTES} +STR_1518 :{SMALLFONT}{OPENQUOTES}Tenhle balónek z {STRINGID} je skutečně výhodný{ENDQUOTES} +STR_1519 :{SMALLFONT}{OPENQUOTES}Tenhle plyšák z {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1520 :{SMALLFONT}{OPENQUOTES}Tahle mapa parku z {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1521 :{SMALLFONT}{OPENQUOTES}This fotka z atrakce {STRINGID} se orpavdu vyplatí{ENDQUOTES} +STR_1522 :{SMALLFONT}{OPENQUOTES}Tenhle deštník z {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1523 :{SMALLFONT}{OPENQUOTES}Tohle pití od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1524 :{SMALLFONT}{OPENQUOTES}Tenhle burgr od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1525 :{SMALLFONT}{OPENQUOTES}Tyhle hranolky od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1526 :{SMALLFONT}{OPENQUOTES}Ta zmrzilna od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1527 :{SMALLFONT}{OPENQUOTES}Tahle cukrová vata od {STRINGID} se opravdu vyplatí{ENDQUOTES} STR_1528 : STR_1529 : STR_1530 : -STR_1531 :{SMALLFONT}{OPENQUOTES}This pizza from {STRINGID} is really good value{ENDQUOTES} +STR_1531 :{SMALLFONT}{OPENQUOTES}Tenhle kus pizzy od {STRINGID} se opravdu vyplatí{ENDQUOTES} STR_1532 : -STR_1533 :{SMALLFONT}{OPENQUOTES}This popcorn from {STRINGID} is really good value{ENDQUOTES} -STR_1534 :{SMALLFONT}{OPENQUOTES}This hot dog from {STRINGID} is really good value{ENDQUOTES} -STR_1535 :{SMALLFONT}{OPENQUOTES}This tentacle from {STRINGID} is really good value{ENDQUOTES} -STR_1536 :{SMALLFONT}{OPENQUOTES}This hat from {STRINGID} is really good value{ENDQUOTES} -STR_1537 :{SMALLFONT}{OPENQUOTES}This toffee apple from {STRINGID} is really good value{ENDQUOTES} -STR_1538 :{SMALLFONT}{OPENQUOTES}This T-shirt from {STRINGID} is really good value{ENDQUOTES} -STR_1539 :{SMALLFONT}{OPENQUOTES}This doughnut from {STRINGID} is really good value{ENDQUOTES} -STR_1540 :{SMALLFONT}{OPENQUOTES}This coffee from {STRINGID} is really good value{ENDQUOTES} +STR_1533 :{SMALLFONT}{OPENQUOTES}Tenhle popcorn od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1534 :{SMALLFONT}{OPENQUOTES}Tenhle párek v rohlíku od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1535 :{SMALLFONT}{OPENQUOTES}Tohle chapadlo od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1536 :{SMALLFONT}{OPENQUOTES}Tahle čepice hat z {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1537 :{SMALLFONT}{OPENQUOTES}Tohle jablko v županu od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1538 :{SMALLFONT}{OPENQUOTES}Tohle tričko od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1539 :{SMALLFONT}{OPENQUOTES}Tenhle koblížek od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1540 :{SMALLFONT}{OPENQUOTES}Tohle kafe od {STRINGID} se opravdu vyplatí{ENDQUOTES} STR_1541 : -STR_1542 :{SMALLFONT}{OPENQUOTES}This fried chicken from {STRINGID} is really good value{ENDQUOTES} -STR_1543 :{SMALLFONT}{OPENQUOTES}This lemonade from {STRINGID} is really good value{ENDQUOTES} +STR_1542 :{SMALLFONT}{OPENQUOTES}Tohle smažené kuře od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1543 :{SMALLFONT}{OPENQUOTES}Tahle limonáda od {STRINGID} se opravdu vyplatí{ENDQUOTES} STR_1544 : STR_1545 : STR_1546 : @@ -1553,60 +1554,60 @@ STR_1547 : STR_1548 : STR_1549 : STR_1550 :{SMALLFONT}{OPENQUOTES}Wow!{ENDQUOTES} -STR_1551 :{SMALLFONT}{OPENQUOTES}I have the strangest feeling someone is watching me{ENDQUOTES} -STR_1552 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a balloon from {STRINGID}{ENDQUOTES} -STR_1553 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a cuddly toy from {STRINGID}{ENDQUOTES} -STR_1554 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a park map from {STRINGID}{ENDQUOTES} -STR_1555 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1556 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za an umbrella from {STRINGID}{ENDQUOTES} -STR_1557 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a drink from {STRINGID}{ENDQUOTES} -STR_1558 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a burger from {STRINGID}{ENDQUOTES} -STR_1559 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za chips from {STRINGID}{ENDQUOTES} -STR_1560 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za an ice cream from {STRINGID}{ENDQUOTES} -STR_1561 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za candyfloss from {STRINGID}{ENDQUOTES} +STR_1551 :{SMALLFONT}{OPENQUOTES}Mám takový divný pocit, jako by mě někdo pozoroval{ENDQUOTES} +STR_1552 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za balónek od {STRINGID}{ENDQUOTES} +STR_1553 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za plyšáka od {STRINGID}{ENDQUOTES} +STR_1554 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za mapu parku z {STRINGID}{ENDQUOTES} +STR_1555 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za fotku z atrakce {STRINGID}{ENDQUOTES} +STR_1556 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za deštník z {STRINGID}{ENDQUOTES} +STR_1557 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za pití od {STRINGID}{ENDQUOTES} +STR_1558 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za burgr od {STRINGID}{ENDQUOTES} +STR_1559 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za hranolky od {STRINGID}{ENDQUOTES} +STR_1560 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za zmrzlinu od {STRINGID}{ENDQUOTES} +STR_1561 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za cukrovou vatu od {STRINGID}{ENDQUOTES} STR_1562 : STR_1563 : STR_1564 : -STR_1565 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za pizza from {STRINGID}{ENDQUOTES} +STR_1565 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za kus pizzy od {STRINGID}{ENDQUOTES} STR_1566 : -STR_1567 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za popcorn from {STRINGID}{ENDQUOTES} -STR_1568 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a hot dog from {STRINGID}{ENDQUOTES} -STR_1569 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za tentacle from {STRINGID}{ENDQUOTES} -STR_1570 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a hat from {STRINGID}{ENDQUOTES} -STR_1571 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a toffee apple from {STRINGID}{ENDQUOTES} -STR_1572 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a T-shirt from {STRINGID}{ENDQUOTES} -STR_1573 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a doughnut from {STRINGID}{ENDQUOTES} -STR_1574 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za coffee from {STRINGID}{ENDQUOTES} +STR_1567 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za popcorn od {STRINGID}{ENDQUOTES} +STR_1568 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za párek v rohlíku od {STRINGID}{ENDQUOTES} +STR_1569 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za chapadlo od {STRINGID}{ENDQUOTES} +STR_1570 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za čepici z {STRINGID}{ENDQUOTES} +STR_1571 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za jabloku v županu od {STRINGID}{ENDQUOTES} +STR_1572 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za tričko z {STRINGID}{ENDQUOTES} +STR_1573 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za koblížek od {STRINGID}{ENDQUOTES} +STR_1574 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za kafe od {STRINGID}{ENDQUOTES} STR_1575 : -STR_1576 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za fried chicken from {STRINGID}{ENDQUOTES} -STR_1577 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za lemonade from {STRINGID}{ENDQUOTES} +STR_1576 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za smažené kuře od {STRINGID}{ENDQUOTES} +STR_1577 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za limonádu od {STRINGID}{ENDQUOTES} STR_1578 : STR_1579 : STR_1580 : STR_1581 : STR_1582 : STR_1583 : -STR_1584 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1585 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1586 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1587 :{SMALLFONT}{OPENQUOTES}This pretzel from {STRINGID} is really good value{ENDQUOTES} -STR_1588 :{SMALLFONT}{OPENQUOTES}This hot chocolate from {STRINGID} is really good value{ENDQUOTES} -STR_1589 :{SMALLFONT}{OPENQUOTES}This iced tea from {STRINGID} is really good value{ENDQUOTES} -STR_1590 :{SMALLFONT}{OPENQUOTES}This funnel cake from {STRINGID} is really good value{ENDQUOTES} -STR_1591 :{SMALLFONT}{OPENQUOTES}These sunglasses from {STRINGID} are really good value{ENDQUOTES} -STR_1592 :{SMALLFONT}{OPENQUOTES}These beef noodles from {STRINGID} are really good value{ENDQUOTES} -STR_1593 :{SMALLFONT}{OPENQUOTES}These fried rice noodles from {STRINGID} are really good value{ENDQUOTES} -STR_1594 :{SMALLFONT}{OPENQUOTES}This wonton soup from {STRINGID} is really good value{ENDQUOTES} -STR_1595 :{SMALLFONT}{OPENQUOTES}This meatball soup from {STRINGID} is really good value{ENDQUOTES} -STR_1596 :{SMALLFONT}{OPENQUOTES}This fruit juice from {STRINGID} is really good value{ENDQUOTES} -STR_1597 :{SMALLFONT}{OPENQUOTES}This soybean milk from {STRINGID} is really good value{ENDQUOTES} -STR_1598 :{SMALLFONT}{OPENQUOTES}This sujongkwa from {STRINGID} is really good value{ENDQUOTES} -STR_1599 :{SMALLFONT}{OPENQUOTES}This sub sandwich from {STRINGID} is really good value{ENDQUOTES} -STR_1600 :{SMALLFONT}{OPENQUOTES}This cookie from {STRINGID} is really good value{ENDQUOTES} +STR_1584 :{SMALLFONT}{OPENQUOTES}Tahle fotka z atrakce {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1585 :{SMALLFONT}{OPENQUOTES}Tahle fotka z atrakce {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1586 :{SMALLFONT}{OPENQUOTES}Tahle fotka z atrakce {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1587 :{SMALLFONT}{OPENQUOTES}Tenhle preclík od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1588 :{SMALLFONT}{OPENQUOTES}Tahle horká čokoláda od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1589 :{SMALLFONT}{OPENQUOTES}Tenhle ledový čaj od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1590 :{SMALLFONT}{OPENQUOTES}Tahle palačinka od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1591 :{SMALLFONT}{OPENQUOTES}Tyhle sluneční brýle z {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1592 :{SMALLFONT}{OPENQUOTES}Tahle nudlová polívka od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1593 :{SMALLFONT}{OPENQUOTES}Tyhle smažené nudle od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1594 :{SMALLFONT}{OPENQUOTES}Tahle čínská knedlíčková polévka od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1595 :{SMALLFONT}{OPENQUOTES}Tahle knedlíčková polévka od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1596 :{SMALLFONT}{OPENQUOTES}Tenhle ovocný džus od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1597 :{SMALLFONT}{OPENQUOTES}Tohle sojové mléko od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1598 :{SMALLFONT}{OPENQUOTES}Tahle suzungkwa od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1599 :{SMALLFONT}{OPENQUOTES}Tenhle sendvič od {STRINGID} se opravdu vyplatí{ENDQUOTES} +STR_1600 :{SMALLFONT}{OPENQUOTES}Tahle sušenka od {STRINGID} se opravdu vyplatí{ENDQUOTES} STR_1601 : STR_1602 : STR_1603 : -STR_1604 :{SMALLFONT}{OPENQUOTES}This roast sausage from {STRINGID} are really good value{ENDQUOTES} +STR_1604 :{SMALLFONT}{OPENQUOTES}This grilovaná klobása od {STRINGID} se opravdu vyplatí{ENDQUOTES} STR_1605 : STR_1606 : STR_1607 : @@ -1618,27 +1619,27 @@ STR_1612 : STR_1613 : STR_1614 : STR_1615 : -STR_1616 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za on-ride photo from {STRINGID}{ENDQUOTES} -STR_1617 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1618 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1619 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a pretzel from {STRINGID}{ENDQUOTES} -STR_1620 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za hot chocolate from {STRINGID}{ENDQUOTES} -STR_1621 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za iced tea from {STRINGID}{ENDQUOTES} -STR_1622 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a funnel cake from {STRINGID}{ENDQUOTES} -STR_1623 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za sunglasses from {STRINGID}{ENDQUOTES} -STR_1624 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za beef noodles from {STRINGID}{ENDQUOTES} -STR_1625 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za fried rice noodles from {STRINGID}{ENDQUOTES} -STR_1626 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za wonton soup from {STRINGID}{ENDQUOTES} -STR_1627 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za for meatball soup from {STRINGID}{ENDQUOTES} -STR_1628 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za fruit juice from {STRINGID}{ENDQUOTES} -STR_1629 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za soybean milk from {STRINGID}{ENDQUOTES} -STR_1630 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za for sujongkwa from {STRINGID}{ENDQUOTES} -STR_1631 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a sub sandwich from {STRINGID}{ENDQUOTES} -STR_1632 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a cookie from {STRINGID}{ENDQUOTES} +STR_1616 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za fotku z {STRINGID}{ENDQUOTES} +STR_1617 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za fotku z {STRINGID}{ENDQUOTES} +STR_1618 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za fotku z {STRINGID}{ENDQUOTES} +STR_1619 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za preclík od {STRINGID}{ENDQUOTES} +STR_1620 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za horkou čokoládu od {STRINGID}{ENDQUOTES} +STR_1621 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za ledový čaj od {STRINGID}{ENDQUOTES} +STR_1622 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za palačinku od {STRINGID}{ENDQUOTES} +STR_1623 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za slunečná brýle od {STRINGID}{ENDQUOTES} +STR_1624 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za nudlovou polévku od {STRINGID}{ENDQUOTES} +STR_1625 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za smažené nudle od {STRINGID}{ENDQUOTES} +STR_1626 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za čínskou knedlíčkovou polívku od {STRINGID}{ENDQUOTES} +STR_1627 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za knedlíčkovou polívku od {STRINGID}{ENDQUOTES} +STR_1628 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za ovocný džus od {STRINGID}{ENDQUOTES} +STR_1629 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za sojové mléko od {STRINGID}{ENDQUOTES} +STR_1630 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za suzungkwu od {STRINGID}{ENDQUOTES} +STR_1631 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za sendvič od {STRINGID}{ENDQUOTES} +STR_1632 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za sušenku od {STRINGID}{ENDQUOTES} STR_1633 : STR_1634 : STR_1635 : -STR_1636 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a roast sausage from {STRINGID}{ENDQUOTES} +STR_1636 :{SMALLFONT}{OPENQUOTES}Nezaplatím tak moc za a roast sausage od {STRINGID}{ENDQUOTES} STR_1637 : STR_1638 : STR_1639 : @@ -1651,15 +1652,15 @@ STR_1645 : STR_1646 : STR_1647 : STR_1648 :{SMALLFONT}{OPENQUOTES}Pomóc! Polož mě dolů!{ENDQUOTES} -STR_1649 :{SMALLFONT}{OPENQUOTES}Dochází my hotovost!{ENDQUOTES} -STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! A new ride being built!{ENDQUOTES} -STR_1651 :{SMALLFONT}{OPENQUOTES}Nice ride! But not as good as the Phoenix...{ENDQUOTES} -STR_1652 :{SMALLFONT}{OPENQUOTES}I'm so excited - It's an Intamin ride!{ENDQUOTES} -STR_1653 :{SMALLFONT}{OPENQUOTES}...and here we are on {STRINGID}!{ENDQUOTES} -STR_1654 :{WINDOW_COLOUR_2}Recent thoughts: -STR_1655 :{SMALLFONT}{BLACK}Construct footpath on land -STR_1656 :{SMALLFONT}{BLACK}Construct bridge or tunnel footpath -STR_1657 :{WINDOW_COLOUR_2}Preferred ride +STR_1649 :{SMALLFONT}{OPENQUOTES}Dochází mi hotovost!{ENDQUOTES} +STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! Tady se staví nová atrakce!{ENDQUOTES} +STR_1651 :{SMALLFONT}{OPENQUOTES}Dobrá atrakce! Ale ne tak dobrá, jako Fénix...{ENDQUOTES} +STR_1652 :{SMALLFONT}{OPENQUOTES}Tolik se těším! - It's an Intamin ride!{ENDQUOTES} +STR_1653 :{SMALLFONT}{OPENQUOTES}...a teď jsme na {STRINGID}!{ENDQUOTES} +STR_1654 :{WINDOW_COLOUR_2}Poslední myšlenky: +STR_1655 :{SMALLFONT}{BLACK}Stavět cestu na povrchu +STR_1656 :{SMALLFONT}{BLACK}Stavět most nebo tunel +STR_1657 :{WINDOW_COLOUR_2}Oblíbená atrakce STR_1658 :{WINDOW_COLOUR_2}intenzita: {BLACK}méně než {COMMA16} STR_1659 :{WINDOW_COLOUR_2}intenzita: {BLACK}mezi {COMMA16} a {COMMA16} STR_1660 :{WINDOW_COLOUR_2}intenzita: {BLACK}víc než {COMMA16} @@ -1669,327 +1670,327 @@ STR_1663 :{WINDOW_COLOUR_2}Nevolnost: STR_1664 :{WINDOW_COLOUR_2}Energie: STR_1665 :{WINDOW_COLOUR_2}Hlad: STR_1666 :{WINDOW_COLOUR_2}Žízeň: -STR_1667 :{WINDOW_COLOUR_2}Toalety: +STR_1667 :{WINDOW_COLOUR_2}Toaleta: STR_1668 :{WINDOW_COLOUR_2}Uspokojení: {BLACK}neznámé STR_1669 :{WINDOW_COLOUR_2}Uspokojení: {BLACK}{COMMA16}% -STR_1670 :{WINDOW_COLOUR_2}Hostů celkem: {BLACK}{COMMA32} +STR_1670 :{WINDOW_COLOUR_2}Návštěvníků celkem: {BLACK}{COMMA32} STR_1671 :{WINDOW_COLOUR_2}Výdělek celkem: {BLACK}{CURRENCY2DP} -STR_1672 :Brakes -STR_1673 :Spinning Control Toggle Track -STR_1674 :Brake speed +STR_1672 :Brzdy +STR_1673 :Přepnutí točení trati +STR_1674 :Rychlost brzd STR_1675 :{POP16}{VELOCITY} -STR_1676 :{SMALLFONT}{BLACK}Set speed limit for brakes +STR_1676 :{SMALLFONT}{BLACK}Nastavit rychlostní omezení brzd STR_1677 :{WINDOW_COLOUR_2}Popularita: {BLACK}Neznámá STR_1678 :{WINDOW_COLOUR_2}Popularita: {BLACK}{COMMA16}% -STR_1679 :Helix up (left) -STR_1680 :Helix up (right) -STR_1681 :Helix down (left) -STR_1682 :Helix down (right) -STR_1683 :Base size 2 x 2 -STR_1684 :Base size 4 x 4 -STR_1685 :Base size 2 x 4 -STR_1686 :Base size 5 x 1 -STR_1687 :Water splash -STR_1688 :Base size 4 x 1 -STR_1689 :Block brakes +STR_1679 :Spirála nahoru (levá) +STR_1680 :Spirála nahoru (pravá) +STR_1681 :Spirála dolů (levá) +STR_1682 :Spirála dolů (pravá) +STR_1683 :Velikost podstavy 2 x 2 +STR_1684 :Velikost podstavy 4 x 4 +STR_1685 :Velikost podstavy 2 x 4 +STR_1686 :Velikost podstavy 5 x 1 +STR_1687 :Průjezd vodou +STR_1688 :Velikost podstavy 4 x 1 +STR_1689 :Brzdící blok 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_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_1701 :Hire new Mechanic -STR_1702 :Hire new Security Guard -STR_1703 :Hire new Entertainer -STR_1704 :Can't hire new staff... -STR_1705 :{SMALLFONT}{BLACK}Sack this staff member -STR_1706 :{SMALLFONT}{BLACK}Move this person to a new location -STR_1707 :Too many staff in game -STR_1708 :{SMALLFONT}{BLACK}Set patrol area for this staff member -STR_1709 :Sack staff -STR_1710 :Yes -STR_1711 :{WINDOW_COLOUR_1}Are you sure you want to sack {STRINGID}? -STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Sweep footpaths -STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Water gardens -STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Empty litter bins -STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Mow grass -STR_1716 :Invalid name for park -STR_1717 :Can't rename park... -STR_1718 :Park Name -STR_1719 :Enter name for park: -STR_1720 :{SMALLFONT}{BLACK}Name park -STR_1721 :Park closed -STR_1722 :Park open -STR_1723 :Can't open park... -STR_1724 :Can't close park... -STR_1725 :Can't buy land... -STR_1726 :Land not for sale! -STR_1727 :Construction rights not for sale! -STR_1728 :Can't buy construction rights here... -STR_1729 :Land not owned by park! -STR_1730 :{RED}Closed - - +STR_1691 :{WINDOW_COLOUR_2} Cena: {BLACK}{CURRENCY} +STR_1692 :{WINDOW_COLOUR_2} Cena: {BLACK}již od {CURRENCY} +STR_1693 :{SMALLFONT}{BLACK}Návštěvníci +STR_1694 :{SMALLFONT}{BLACK}Personál +STR_1695 :{SMALLFONT}{BLACK}Příjmy a výdaje +STR_1696 :{SMALLFONT}{BLACK}Informace o návštěvnících +STR_1697 :Toto nelze umístit do front +STR_1698 :Toto lze umístit pouze do front +STR_1699 :Příliš mnoho lidí ve hře +STR_1700 :Zaměstnat nového údržbáře +STR_1701 :Zaměstnat nového mechanika +STR_1702 :Zaměstnat nového hlídače +STR_1703 :Zaměstnat nového maskota +STR_1704 :Nelze přijímat nové zaměstnance... +STR_1705 :{SMALLFONT}{BLACK}Propustit tohoto zaměstnance +STR_1706 :{SMALLFONT}{BLACK}Přesunout tuto osobu na jiné místo +STR_1707 :Příliš mnoho zaměstnanců ve hře +STR_1708 :{SMALLFONT}{BLACK}Nastavit oblast pochůzky +STR_1709 :Propustit zaměstnance +STR_1710 :Ano +STR_1711 :{WINDOW_COLOUR_1}Opravdu propustit {STRINGID}? +STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Zametání cest +STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Zalévání květin +STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Vysypávání košů +STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Sekání trávy +STR_1716 :Neplatné jméno parku +STR_1717 :Nejde přejmenovat park... +STR_1718 :Název parku +STR_1719 :Zadejte nové jméno parku: +STR_1720 :{SMALLFONT}{BLACK}Přejmenovat park +STR_1721 :Park je zavřený +STR_1722 :Park je otevřený +STR_1723 :Park nelze otevřít... +STR_1724 :Park nelze zavřít... +STR_1725 :Pozemek nelze zakoupit... +STR_1726 :Pozemek není na prodej! +STR_1727 :Stavební práva nejsou na prodej! +STR_1728 :Tyto stavební práva nelze zakoupit... +STR_1729 :Pozemek není ve vlastnictví parku! +STR_1730 :{RED}Zavřeno - - STR_1731 :{WHITE}{STRINGID} - - -STR_1732 :Build -STR_1733 :Mode -STR_1734 :{WINDOW_COLOUR_2}Number of laps: -STR_1735 :{SMALLFONT}{BLACK}Number of laps of circuit +STR_1732 :Stavět +STR_1733 :Mód +STR_1734 :{WINDOW_COLOUR_2}Počet kol: +STR_1735 :{SMALLFONT}{BLACK}Počet kol okruhu STR_1736 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1737 :{COMMA16} -STR_1738 :Can't change number of laps... -STR_1739 :Race won by guest {INT32} -STR_1740 :Race won by {STRINGID} -STR_1741 :Not yet constructed ! -STR_1742 :{WINDOW_COLOUR_2}Max. people on ride: -STR_1743 :{SMALLFONT}{BLACK}Maximum number of people allowed on this ride at one time +STR_1738 :Nelze změnit počet kol... +STR_1739 :Závod vyhrál návštěvník {INT32} +STR_1740 :Závod vyhrál návštěvník {STRINGID} +STR_1741 :Zatím není postaveno! +STR_1742 :{WINDOW_COLOUR_2}Max. návětěvníků na atrakci +STR_1743 :{SMALLFONT}{BLACK}Maximální povolený počet návětěvníků současně na atrakci STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1745 :{COMMA16} -STR_1746 :Can't change this... -STR_1747 :{WINDOW_COLOUR_2}Time limit: -STR_1748 :{SMALLFONT}{BLACK}Time limit for ride +STR_1746 :Tohle nelze změnit... +STR_1747 :{WINDOW_COLOUR_2}Časový limit: +STR_1748 :{SMALLFONT}{BLACK}Časový limit atrakce STR_1749 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{DURATION} 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_1756 :{WINDOW_COLOUR_2}Admission price: -STR_1757 :{WINDOW_COLOUR_2}Reliability: {MOVE_X}{255}{BLACK}{COMMA16}% -STR_1758 :{SMALLFONT}{BLACK}Build mode -STR_1759 :{SMALLFONT}{BLACK}Move mode -STR_1760 :{SMALLFONT}{BLACK}Fill-in mode -STR_1761 :{SMALLFONT}{BLACK}Build maze in this direction -STR_1762 :Waterfalls -STR_1763 :Rapids -STR_1764 :Log Bumps -STR_1765 :On-ride photo section -STR_1766 :Reverser turntable -STR_1767 :Spinning tunnel -STR_1768 :Can't change number of swings... -STR_1769 :{WINDOW_COLOUR_2}Number of swings: -STR_1770 :{SMALLFONT}{BLACK}Number of complete swings +STR_1751 :Časový limit atrakce nelze změnit... +STR_1752 :{SMALLFONT}{BLACK}Zobrazit seznam návštěvníků v parku +STR_1753 :{SMALLFONT}{BLACK}Zobrazit sumarizovaný seznam návštěvníků v parku +STR_1754 :{BLACK}{COMMA16} návštěvníků +STR_1755 :{BLACK}{COMMA16} návštěvník +STR_1756 :{WINDOW_COLOUR_2}Cena vstupu do parku: +STR_1757 :{WINDOW_COLOUR_2}Spolehlivost: {MOVE_X}{255}{BLACK}{COMMA16}% +STR_1758 :{SMALLFONT}{BLACK}Mód stavby +STR_1759 :{SMALLFONT}{BLACK}Mód přesunu +STR_1760 :{SMALLFONT}{BLACK}Mód výplně +STR_1761 :{SMALLFONT}{BLACK}Stavět bludiště v tomto směru +STR_1762 :Vodopády +STR_1763 :Peřeje +STR_1764 :Nárazy +STR_1765 :Fotobuňka +STR_1766 :Otáčející blok +STR_1767 :Točící se tunel +STR_1768 :Nelze změnit počet zhoupnutí... +STR_1769 :{WINDOW_COLOUR_2}Počet zhoupnutí: +STR_1770 :{SMALLFONT}{BLACK}Počet zhoupnutí STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1772 :{COMMA16} -STR_1773 :Only one on-ride photo section allowed per ride -STR_1774 :Only one cable lift hill allowed per ride +STR_1773 :Je povolena jen jedna fotobuňka na atrakci +STR_1774 :Je povolen pouze jeden výtah na atrakci STR_1775 :Off STR_1776 :On -STR_1777 :{WINDOW_COLOUR_2}Music +STR_1777 :{WINDOW_COLOUR_2}Hudba atrakcí STR_1778 :{STRINGID} - - -STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Panda costume -STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tiger costume -STR_1781 :{INLINE_SPRITE}{00}{20}{00}{00} Elephant costume -STR_1782 :{INLINE_SPRITE}{01}{20}{00}{00} Roman costume -STR_1783 :{INLINE_SPRITE}{02}{20}{00}{00} Gorilla costume -STR_1784 :{INLINE_SPRITE}{03}{20}{00}{00} Snowman costume -STR_1785 :{INLINE_SPRITE}{04}{20}{00}{00} Knight costume -STR_1786 :{INLINE_SPRITE}{05}{20}{00}{00} Astronaut costume -STR_1787 :{INLINE_SPRITE}{06}{20}{00}{00} Bandit costume -STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Sheriff costume -STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Pirate costume -STR_1790 :{SMALLFONT}{BLACK}Select uniform colour for this type of staff -STR_1791 :{WINDOW_COLOUR_2}Uniform colour: -STR_1792 :Responding to {STRINGID} breakdown call -STR_1793 :Heading to {STRINGID} for an inspection -STR_1794 :Fixing {STRINGID} -STR_1795 :Answering radio call -STR_1796 :Has broken down and requires fixing -STR_1797 :This option cannot be changed for this ride -STR_1798 :Whirlpool +STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Panda +STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tigr +STR_1781 :{INLINE_SPRITE}{00}{20}{00}{00} Slon +STR_1782 :{INLINE_SPRITE}{01}{20}{00}{00} Říman +STR_1783 :{INLINE_SPRITE}{02}{20}{00}{00} Gorila +STR_1784 :{INLINE_SPRITE}{03}{20}{00}{00} Sněhulák +STR_1785 :{INLINE_SPRITE}{04}{20}{00}{00} Rytíř +STR_1786 :{INLINE_SPRITE}{05}{20}{00}{00} Skafandr +STR_1787 :{INLINE_SPRITE}{06}{20}{00}{00} Bandita +STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Šerif +STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Pirát +STR_1790 :{SMALLFONT}{BLACK}Vybrat barvu uniformy těchto zaměstnanců +STR_1791 :{WINDOW_COLOUR_2}Barva uniformy: +STR_1792 :Reaguje na poruchu {STRINGID} +STR_1793 :Jde provést inspekci {STRINGID} +STR_1794 :Opravuje {STRINGID} +STR_1795 :Odpovídá po telefonu +STR_1796 :Atrakce se rozbila a vyžaduje opravu +STR_1797 :Tuto možnost nelze u této atrakce měnit +STR_1798 :Vír STR_1799 :{POP16}{POP16}{POP16}{POP16}{POP16}{CURRENCY2DP} -STR_1800 :Safety cut-out -STR_1801 :Restraints stuck closed -STR_1802 :Restraints stuck open -STR_1803 :Doors stuck closed -STR_1804 :Doors stuck open -STR_1805 :Vehicle malfunction -STR_1806 :Brakes failure -STR_1807 :Control failure -STR_1808 :{WINDOW_COLOUR_2}Last breakdown: {BLACK}{STRINGID} -STR_1809 :{WINDOW_COLOUR_2}Current breakdown: {OUTLINE}{RED}{STRINGID} -STR_1810 :{WINDOW_COLOUR_2}Carrying: -STR_1811 :Can't build this here... +STR_1800 :Bezpečnostní zastavneí +STR_1801 :Zaseknuté pásy +STR_1802 :Nejdou zapnout pásy +STR_1803 :Nejdou otevřít dveře +STR_1804 :Nejdou zabřít dveře +STR_1805 :Porucha vozidla +STR_1806 :Porucha brzd +STR_1807 :Porucha ovládání +STR_1808 :{WINDOW_COLOUR_2}Poslední porucha: {BLACK}{STRINGID} +STR_1809 :{WINDOW_COLOUR_2}Současná porucha: {OUTLINE}{RED}{STRINGID} +STR_1810 :{WINDOW_COLOUR_2}Návštěvník nese: +STR_1811 :Tohle zde nelze postavit... STR_1812 :{SMALLFONT}{BLACK}{STRINGID} -STR_1813 :Miscellaneous Objects -STR_1814 :Actions -STR_1815 :Thoughts -STR_1816 :{SMALLFONT}{BLACK}Select information type to show in guest list +STR_1813 :Ostatní objekty +STR_1814 :Dle aktivity +STR_1815 :Dle myšlenek +STR_1816 :{SMALLFONT}{BLACK}Vyberte informaci k zobrazení v seznamu návštěvníků STR_1817 :({COMMA16}) -STR_1818 :{WINDOW_COLOUR_2}All guests -STR_1819 :{WINDOW_COLOUR_2}All guests (summarised) -STR_1820 :{WINDOW_COLOUR_2}Guests {STRINGID} -STR_1821 :{WINDOW_COLOUR_2}Guests thinking {STRINGID} -STR_1822 :{WINDOW_COLOUR_2}Guests thinking about {POP16}{STRINGID} -STR_1823 :{SMALLFONT}{BLACK}Show guests' thoughts about this ride/attraction -STR_1824 :{SMALLFONT}{BLACK}Show guests on this ride/attraction -STR_1825 :{SMALLFONT}{BLACK}Show guests queuing for this ride/attraction +STR_1818 :{WINDOW_COLOUR_2}Všichni návštěvníci +STR_1819 :{WINDOW_COLOUR_2}Všichni návštěvníci (sumarizace) +STR_1820 :{WINDOW_COLOUR_2}Návštěvníci {STRINGID} +STR_1821 :{WINDOW_COLOUR_2}Návštěvníci myslící si {STRINGID} +STR_1822 :{WINDOW_COLOUR_2}Návštěvníci myslící na {POP16}{STRINGID} +STR_1823 :{SMALLFONT}{BLACK}Zobrazit myšlěnky návštěvníků o této atrakci +STR_1824 :{SMALLFONT}{BLACK}Zobrazit návštěvníky na této atrakci +STR_1825 :{SMALLFONT}{BLACK}Zobrazit návštěvníky, kteří stojí frontu na tuto atrakci STR_1826 :Stav STR_1827 :Popularita STR_1828 :Spokojenost STR_1829 :Výdělečnost -STR_1830 :Délka řady +STR_1830 :Délka fronty STR_1831 :Doba čekání -STR_1832 :Reliability -STR_1833 :Přerušní provozu -STR_1834 :Guests favourite +STR_1832 :Spolehlivost +STR_1833 :Mimo provoz +STR_1834 :Oblíbenost STR_1835 :Popularita: Neznámá STR_1836 :Popularita: {COMMA16}% STR_1837 :Spokojenost: Neznámá STR_1838 :Spokojenost: {COMMA16}% -STR_1839 :Reliability: {COMMA16}% -STR_1840 :Přerušní provozu: {COMMA16}% -STR_1841 :Výdělečnost: {CURRENCY2DP} per hour -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_1839 :Spolehlivost: {COMMA16}% +STR_1840 :Mimo provoz: {COMMA16}% +STR_1841 :Výdělečnost: {CURRENCY2DP} za hodinu +STR_1842 :Nejoblíbenější: {COMMA16} návštěvníka +STR_1843 :Nejoblíbenější: {COMMA16} návštěvníků +STR_1844 :{SMALLFONT}{BLACK}Vyberte informaci k zobrazení v seznamu atrakcí 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_1849 :{WINDOW_COLOUR_2}Play music -STR_1850 :{SMALLFONT}{BLACK}Vyber jaká hudba se bude hrát +STR_1846 :{COMMA16} návštěvníků +STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} návštěvníků +STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16} návštěvníků +STR_1849 :{WINDOW_COLOUR_2}Hrát hudbu +STR_1850 :{SMALLFONT}{BLACK}Vyberte, jaká hudba se bude hrát STR_1851 :{WINDOW_COLOUR_2}Cena provozu: {BLACK}{CURRENCY2DP} za hodinu -STR_1852 :{WINDOW_COLOUR_2}Cena provozu: {BLACK}Unknown +STR_1852 :{WINDOW_COLOUR_2}Cena provozu: {BLACK}Neznámá STR_1853 :{WINDOW_COLOUR_2}Postaveno: {BLACK}Letos -STR_1854 :{WINDOW_COLOUR_2}Postaveno: {BLACK}Minulí rok +STR_1854 :{WINDOW_COLOUR_2}Postaveno: {BLACK}Minulý rok STR_1855 :{WINDOW_COLOUR_2}Postaveno: {BLACK}Před {COMMA16} lety STR_1856 :{WINDOW_COLOUR_2}Zisk za prodaný předmět: {BLACK}{CURRENCY2DP} STR_1857 :{WINDOW_COLOUR_2}Ztráta na prodaný předmět: {BLACK}{CURRENCY2DP} -STR_1858 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY2DP} per month -STR_1859 :Uklízeč -STR_1860 :Technik -STR_1861 :Hlídač -STR_1862 :Bavič -STR_1863 :Uklízeč -STR_1864 :Technik -STR_1865 :Hlídač -STR_1866 :Bavič +STR_1858 :{WINDOW_COLOUR_2}Náklady: {BLACK}{CURRENCY2DP} měsíčně +STR_1859 :údržbářů +STR_1860 :mechaniků +STR_1861 :hlídačů +STR_1862 :maskotů +STR_1863 :údržbář +STR_1864 :mechanik +STR_1865 :hlídač +STR_1866 :maskot STR_1867 :{BLACK}{COMMA16} {STRINGID} -STR_1868 :Can't change number of rotations... -STR_1869 :{WINDOW_COLOUR_2}Number of rotations: -STR_1870 :{SMALLFONT}{BLACK}Number of complete rotations +STR_1868 :Nelze změnit počet otoček... +STR_1869 :{WINDOW_COLOUR_2}Počet otoček: +STR_1870 :{SMALLFONT}{BLACK}Počet celých otoček STR_1871 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1872 :{COMMA16} -STR_1873 :{WINDOW_COLOUR_2}Income: {BLACK}{CURRENCY2DP} per hour -STR_1874 :{WINDOW_COLOUR_2}Profit: {BLACK}{CURRENCY2DP} per hour +STR_1873 :{WINDOW_COLOUR_2}Příjem: {BLACK}{CURRENCY2DP} za hodinu +STR_1874 :{WINDOW_COLOUR_2}Zisk: {BLACK}{CURRENCY2DP} za hodinu 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_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}% -STR_1890 :{SMALLFONT}{BLACK}Select how often a mechanic should check this ride -STR_1891 :No {STRINGID} in park yet! +STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Inspekce atrakcí +STR_1877 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{252}{19}{00}{00}Opravy atrakcí +STR_1878 :{WINDOW_COLOUR_2}Inspekce: +STR_1879 :Každých 10 minut +STR_1880 :Každých 20 minut +STR_1881 :Každých 30 minut +STR_1882 :Každých 45 minut +STR_1883 :Každou hodinu +STR_1884 :Každé dvě hodiny +STR_1885 :Nikdy +STR_1886 :Probíhá inspekce {STRINGID} +STR_1887 :{WINDOW_COLOUR_2}Doba od poslední inspekce: {BLACK}{COMMA16} minut +STR_1888 :{WINDOW_COLOUR_2}Doba od poslední inspekce: {BLACK}více než 4 hodiny +STR_1889 :{WINDOW_COLOUR_2}Mimo provoz: {MOVE_X}{255}{BLACK}{COMMA16}% +STR_1890 :{SMALLFONT}{BLACK}Vyberte, jak často by měl mechanik provést inspekci +STR_1891 :V parku není řádný {STRINGID}! # The following two strings were used to display an error when the disc was missing. # This has been replaced in OpenRCT2. STR_1892 : STR_1893 : -STR_1894 :{WINDOW_COLOUR_2}{STRINGID} sold: {BLACK}{COMMA32} +STR_1894 :{WINDOW_COLOUR_2}{STRINGID} prodáno: {BLACK}{COMMA32} STR_1895 :{SMALLFONT}{BLACK}Postavit novou atrakci -STR_1896 :{WINDOW_COLOUR_2}Expenditure/Income -STR_1897 :{WINDOW_COLOUR_2}Ride construction -STR_1898 :{WINDOW_COLOUR_2}Ride running costs -STR_1899 :{WINDOW_COLOUR_2}Land purchase -STR_1900 :{WINDOW_COLOUR_2}Landscaping -STR_1901 :{WINDOW_COLOUR_2}Park entrance tickets -STR_1902 :{WINDOW_COLOUR_2}Ride tickets -STR_1903 :{WINDOW_COLOUR_2}Shop sales -STR_1904 :{WINDOW_COLOUR_2}Shop stock -STR_1905 :{WINDOW_COLOUR_2}Food/drink sales -STR_1906 :{WINDOW_COLOUR_2}Food/drink stock -STR_1907 :{WINDOW_COLOUR_2}Staff wages +STR_1896 :{WINDOW_COLOUR_2}Příjmy a výdaje +STR_1897 :{WINDOW_COLOUR_2}Stavby atrakcí +STR_1898 :{WINDOW_COLOUR_2}Úržba atrakcí +STR_1899 :{WINDOW_COLOUR_2}Nákupy pozemků +STR_1900 :{WINDOW_COLOUR_2}Úpravy terénu +STR_1901 :{WINDOW_COLOUR_2}Vstupenky do parku +STR_1902 :{WINDOW_COLOUR_2}Vstupenky na atrakce +STR_1903 :{WINDOW_COLOUR_2}Prodeje obchodů +STR_1904 :{WINDOW_COLOUR_2}Nákupy zboží do obchodů +STR_1905 :{WINDOW_COLOUR_2}Prodeje jídla a pití +STR_1906 :{WINDOW_COLOUR_2}Nákupy jídla a pití +STR_1907 :{WINDOW_COLOUR_2}Platy zaměstnanů STR_1908 :{WINDOW_COLOUR_2}Marketing -STR_1909 :{WINDOW_COLOUR_2}Research -STR_1910 :{WINDOW_COLOUR_2}Loan interest -STR_1911 :{BLACK} at {COMMA16}% per year +STR_1909 :{WINDOW_COLOUR_2}Výzkum +STR_1910 :{WINDOW_COLOUR_2}Úrok z půjčky +STR_1911 :{BLACK} s {COMMA16}% ročním úrokem STR_1912 :{MONTH} STR_1913 :{BLACK}+{CURRENCY2DP} STR_1914 :{BLACK}{CURRENCY2DP} STR_1915 :{RED}{CURRENCY2DP} -STR_1916 :{WINDOW_COLOUR_2}Loan: +STR_1916 :{WINDOW_COLOUR_2}Půjčka: STR_1917 :{POP16}{POP16}{POP16}{CURRENCY} -STR_1918 :Can't borrow any more money! -STR_1919 :Not enough cash available! -STR_1920 :Can't pay back loan! -STR_1921 :{SMALLFONT}{BLACK}Start a new game -STR_1922 :{SMALLFONT}{BLACK}Continue playing a saved game -STR_1923 :{SMALLFONT}{BLACK}Show tutorial -STR_1924 :{SMALLFONT}{BLACK}Exit -STR_1925 :Can't place person here... +STR_1918 :Není možné si půjčit více peněz! +STR_1919 :Nedostatek hotovosti! +STR_1920 :Nelze splatit půjčku! +STR_1921 :{SMALLFONT}{BLACK}Začít novou hru +STR_1922 :{SMALLFONT}{BLACK}Nahrát uloženou hru +STR_1923 :{SMALLFONT}{BLACK}Zobrazit tutoriál +STR_1924 :{SMALLFONT}{BLACK}Ukončit hru +STR_1925 :Sem tuto osobu nelze umístit... STR_1926 :{SMALLFONT} -STR_1927 :{YELLOW}{STRINGID} has broken down -STR_1928 :{RED}{STRINGID} has crashed! -STR_1929 :{RED}{STRINGID} still hasn't been fixed{NEWLINE}Check where your mechanics are and consider organizing them better -STR_1930 :{SMALLFONT}{BLACK}Turn on/off tracking information for this guest - (If tracking is on, guest's movements will be reported in the message area) -STR_1931 :{STRINGID} has joined the queue line for {STRINGID} -STR_1932 :{STRINGID} is on {STRINGID} -STR_1933 :{STRINGID} is in {STRINGID} -STR_1934 :{STRINGID} has left {STRINGID} -STR_1935 :{STRINGID} has left the park -STR_1936 :{STRINGID} has bought {STRINGID} -STR_1937 :{SMALLFONT}{BLACK}Show information about the subject of this message -STR_1938 :{SMALLFONT}{BLACK}Show view of guest -STR_1939 :{SMALLFONT}{BLACK}Show view of staff member -STR_1940 :{SMALLFONT}{BLACK}Show happiness, energy, hunger etc. for this guest -STR_1941 :{SMALLFONT}{BLACK}Show which rides this guest has been on -STR_1942 :{SMALLFONT}{BLACK}Show financial information about this guest -STR_1943 :{SMALLFONT}{BLACK}Show guest's recent thoughts -STR_1944 :{SMALLFONT}{BLACK}Show items guest is carrying -STR_1945 :{SMALLFONT}{BLACK}Show orders and options for this staff member -STR_1946 :{SMALLFONT}{BLACK}Select costume for this entertainer -STR_1947 :{SMALLFONT}{BLACK}Show areas patrolled by selected staff type, and locate the nearest staff member -STR_1948 :{SMALLFONT}{BLACK}Hire a new staff member of the selected type -STR_1949 :Financial Summary -STR_1950 :Financial Graph -STR_1951 :Park Value Graph -STR_1952 :Profit Graph +STR_1927 :{YELLOW}{STRINGID} má poruchu +STR_1928 :{RED}{STRINGID} havaroval! +STR_1929 :{RED}{STRINGID} má stále poruchu!{NEWLINE}Zkontrolujte, kde jsou vaši mechanici a zkuste je lépe organizovat +STR_1930 :{SMALLFONT}{BLACK}Přepnout sledování tohoto návštěvníka - (Pokud je sledování zapnuté, pohyby návštěvníka budou nahlašovány do zpráv) +STR_1931 :{STRINGID} je ve frontě na {STRINGID} +STR_1932 :{STRINGID} je na {STRINGID} +STR_1933 :{STRINGID} je v {STRINGID} +STR_1934 :{STRINGID} opusil(a) {STRINGID} +STR_1935 :{STRINGID} opusil(a) park +STR_1936 :{STRINGID} si koupil(a) {STRINGID} +STR_1937 :{SMALLFONT}{BLACK}Zobrazit informace o předmětu zprávy +STR_1938 :{SMALLFONT}{BLACK}Zobrazit pohled na návštěvníka +STR_1939 :{SMALLFONT}{BLACK}Zobrazit pohled na zaměstnance +STR_1940 :{SMALLFONT}{BLACK}Zobrazit náladu, energii, hlad atd. tohoto návštěvníka +STR_1941 :{SMALLFONT}{BLACK}Zobrazit atrakce, které návštěvník navštívil +STR_1942 :{SMALLFONT}{BLACK}Zobrazit informace o financích návštěvníka +STR_1943 :{SMALLFONT}{BLACK}Zobrazit poslední myšlenky návštěvníka +STR_1944 :{SMALLFONT}{BLACK}Zobrazit věci, které návštěvník nese +STR_1945 :{SMALLFONT}{BLACK}Zobrazit rozkazy a nastavení zaměstnance +STR_1946 :{SMALLFONT}{BLACK}Vybrat kostým maskota +STR_1947 :{SMALLFONT}{BLACK}Zobrazit oblasti pochůzek vybraného typu personálu a najít nejbližšího +STR_1948 :{SMALLFONT}{BLACK}Přijmout nového zaměstnance +STR_1949 :Přehled financí +STR_1950 :Graf financí +STR_1951 :Graf hodnoty parku +STR_1952 :Graf zisku STR_1953 :Marketing -STR_1954 :Research Funding -STR_1955 :{WINDOW_COLOUR_2}Number of circuits: -STR_1956 :{SMALLFONT}{BLACK}Number of circuits of track per ride +STR_1954 :Financování vývoje +STR_1955 :{WINDOW_COLOUR_2}Počet kolegeček: +STR_1956 :{SMALLFONT}{BLACK}Počet kolegeček za jednu jízdu STR_1957 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1958 :{COMMA16} -STR_1959 :Can't change number of circuits... -STR_1960 :{WINDOW_COLOUR_2}Balloon price: -STR_1961 :{WINDOW_COLOUR_2}Cuddly Toy price: -STR_1962 :{WINDOW_COLOUR_2}Park Map price: -STR_1963 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_1964 :{WINDOW_COLOUR_2}Umbrella price: -STR_1965 :{WINDOW_COLOUR_2}Drink price: -STR_1966 :{WINDOW_COLOUR_2}Burger price: -STR_1967 :{WINDOW_COLOUR_2}Chips price: -STR_1968 :{WINDOW_COLOUR_2}Ice Cream price: -STR_1969 :{WINDOW_COLOUR_2}Candyfloss price: +STR_1959 :Počet kolegeček nelze změnit... +STR_1960 :{WINDOW_COLOUR_2}Cena balónku: +STR_1961 :{WINDOW_COLOUR_2}Cena plyšáka: +STR_1962 :{WINDOW_COLOUR_2}Cena mapy parku: +STR_1963 :{WINDOW_COLOUR_2}Cena fotky z atrakce: +STR_1964 :{WINDOW_COLOUR_2}Cena deštníku: +STR_1965 :{WINDOW_COLOUR_2}Cena pití: +STR_1966 :{WINDOW_COLOUR_2}Cena burgru: +STR_1967 :{WINDOW_COLOUR_2}Cena hranolek: +STR_1968 :{WINDOW_COLOUR_2}Cena zmrzliny: +STR_1969 :{WINDOW_COLOUR_2}Cena cukrové vaty: STR_1970 :{WINDOW_COLOUR_2} STR_1971 :{WINDOW_COLOUR_2} STR_1972 :{WINDOW_COLOUR_2} -STR_1973 :{WINDOW_COLOUR_2}Pizza price: +STR_1973 :{WINDOW_COLOUR_2}Cena za kus pizzy: STR_1974 :{WINDOW_COLOUR_2} -STR_1975 :{WINDOW_COLOUR_2}Popcorn price: -STR_1976 :{WINDOW_COLOUR_2}Hot Dog price: -STR_1977 :{WINDOW_COLOUR_2}Tentacle price: -STR_1978 :{WINDOW_COLOUR_2}Hat price: -STR_1979 :{WINDOW_COLOUR_2}Toffee Apple price: -STR_1980 :{WINDOW_COLOUR_2}T-Shirt price: -STR_1981 :{WINDOW_COLOUR_2}Doughnut price: -STR_1982 :{WINDOW_COLOUR_2}Coffee price: +STR_1975 :{WINDOW_COLOUR_2}Cena popcornu: +STR_1976 :{WINDOW_COLOUR_2}Cena párku v rohlíku: +STR_1977 :{WINDOW_COLOUR_2}Cena chapadla: +STR_1978 :{WINDOW_COLOUR_2}Cena čepice: +STR_1979 :{WINDOW_COLOUR_2}Cena jablka v županu: +STR_1980 :{WINDOW_COLOUR_2}Cena trička: +STR_1981 :{WINDOW_COLOUR_2}Cena koblížku: +STR_1982 :{WINDOW_COLOUR_2}Cena kávy: STR_1983 :{WINDOW_COLOUR_2} -STR_1984 :{WINDOW_COLOUR_2}Fried Chicken price: -STR_1985 :{WINDOW_COLOUR_2}Lemonade price: +STR_1984 :{WINDOW_COLOUR_2}Cena smaženého kuřete: +STR_1985 :{WINDOW_COLOUR_2}Cena limonády: STR_1986 :{WINDOW_COLOUR_2} STR_1987 :{WINDOW_COLOUR_2} STR_1988 :Balónek @@ -1999,536 +2000,536 @@ STR_1991 :Fotka z atrakce STR_1992 :Deštník STR_1993 :Pití STR_1994 :Burger -STR_1995 :Lupínky +STR_1995 :Hranolky STR_1996 :Zmrzlina STR_1997 :Cukrová vata STR_1998 :Prázdná plechovka STR_1999 :Odpadky -STR_2000 :Prázdná obal od burgeru +STR_2000 :Prázdný obal od burgeru STR_2001 :Pizza -STR_2002 :Poukaz +STR_2002 :Kupon STR_2003 :Popcorn -STR_2004 :Hot Dog -STR_2005 :Tentacle +STR_2004 :Párek v rohlíku +STR_2005 :Chapadlo STR_2006 :Čepice -STR_2007 :Karamelové jablko +STR_2007 :Jablko v županu STR_2008 :Tričko -STR_2009 :Kobliha +STR_2009 :Koblížek STR_2010 :Káva -STR_2011 :Prázdná kelímek -STR_2012 :Smažené Kuře +STR_2011 :Prázdný kelímek +STR_2012 :Smažené kuře STR_2013 :Limonáda STR_2014 :Prázdná krabička STR_2015 :Prázdná láhev STR_2016 :Balónky STR_2017 :Plyšové hračky STR_2018 :Mapy -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_2028 :Empty Burger Boxes -STR_2029 :Pizzas -STR_2030 :Vouchers +STR_2019 :Fotky za atrakcí +STR_2020 :Deštníky +STR_2021 :Nápoje +STR_2022 :Burgry +STR_2023 :Hranolky +STR_2024 :Zmrzliny +STR_2025 :Cukrové vaty +STR_2026 :Prázdné plechovky +STR_2027 :Odpad +STR_2028 :Prázdné krabice od burgrů +STR_2029 :Pizzy +STR_2030 :Kupony STR_2031 :Popcorn -STR_2032 :Hot Dogs -STR_2033 :Tentacles -STR_2034 :Hats -STR_2035 :Toffee Apples -STR_2036 :T-Shirts -STR_2037 :Doughnuts -STR_2038 :Coffees -STR_2039 :Empty Cups -STR_2040 :Fried Chicken -STR_2041 :Lemonade -STR_2042 :Empty Boxes -STR_2043 :Empty Bottles -STR_2044 :a Balloon -STR_2045 :a Cuddly Toy -STR_2046 :a Park Map -STR_2047 :an On-Ride Photo -STR_2048 :an Umbrella -STR_2049 :a Drink -STR_2050 :a Burger -STR_2051 :some Chips -STR_2052 :an Ice Cream -STR_2053 :some Candyfloss -STR_2054 :an Empty Can -STR_2055 :some Rubbish -STR_2056 :an Empty Burger Box -STR_2057 :a Pizza -STR_2058 :a Voucher -STR_2059 :some Popcorn -STR_2060 :a Hot Dog -STR_2061 :a Tentacle -STR_2062 :a Hat -STR_2063 :a Toffee Apple -STR_2064 :a T-Shirt -STR_2065 :a Doughnut -STR_2066 :a Coffee -STR_2067 :an Empty Cup -STR_2068 :some Fried Chicken -STR_2069 :some Lemonade -STR_2070 :an Empty Box -STR_2071 :an Empty Bottle -STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Balloon -STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Cuddly Toy -STR_2074 :Map of {STRINGID} -STR_2075 :On-Ride Photo of {STRINGID} -STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Umbrella -STR_2077 :Drink +STR_2032 :Párky v rohlíku +STR_2033 :Chapadla +STR_2034 :Čepice +STR_2035 :Jablka v županu +STR_2036 :Trička +STR_2037 :Koblížky +STR_2038 :Kávy +STR_2039 :Prázdné kelímky +STR_2040 :Smažená kuřata +STR_2041 :Limonády +STR_2042 :Prázdné krabičky +STR_2043 :Prýzdné láhve +STR_2044 :balónek +STR_2045 :plyšák +STR_2046 :mapa +STR_2047 :fotka z atrakce +STR_2048 :deštník +STR_2049 :pití +STR_2050 :burger +STR_2051 :hranolky +STR_2052 :zmrzlina +STR_2053 :cukrová vata +STR_2054 :prázdná plechovka +STR_2055 :odpadky +STR_2056 :prázdná krabice od burgru +STR_2057 :kus pizzy +STR_2058 :kupon +STR_2059 :popcorn +STR_2060 :párek v rohlíku +STR_2061 :chapadlo +STR_2062 :čepice +STR_2063 :jablko v županu +STR_2064 :tričko +STR_2065 :koblížek +STR_2066 :káva +STR_2067 :prázdný kelímek +STR_2068 :smažené kuře +STR_2069 :limonáda +STR_2070 :prázdná krabička +STR_2071 :prázdná lahev +STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} balónek +STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} plyšák +STR_2074 :Mapa {STRINGID} +STR_2075 :Fotka z {STRINGID} +STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} deštník +STR_2077 :Pití STR_2078 :Burger -STR_2079 :Chips -STR_2080 :Ice Cream -STR_2081 :Candyfloss -STR_2082 :Empty Can -STR_2083 :Rubbish -STR_2084 :Empty Burger Box +STR_2079 :Hranolky +STR_2080 :Zmrzlina +STR_2081 :Cukrová vata +STR_2082 :Prázdná plechovka +STR_2083 :Odpadky +STR_2084 :Prázdná krabice od burgru STR_2085 :Pizza -STR_2086 :Voucher for {STRINGID} +STR_2086 :Kupon na {STRINGID} STR_2087 :Popcorn -STR_2088 :Hot Dog -STR_2089 :Tentacle -STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Hat -STR_2091 :Toffee Apple -STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} T-Shirt -STR_2093 :Doughnut -STR_2094 :Coffee -STR_2095 :Empty Cup -STR_2096 :Fried Chicken -STR_2097 :Lemonade -STR_2098 :Empty Box -STR_2099 :Empty Bottle -STR_2100 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2101 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2102 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2103 :{WINDOW_COLOUR_2}Pretzel price: -STR_2104 :{WINDOW_COLOUR_2}Hot Chocolate price: -STR_2105 :{WINDOW_COLOUR_2}Iced Tea price: -STR_2106 :{WINDOW_COLOUR_2}Funnel Cake price: -STR_2107 :{WINDOW_COLOUR_2}Sunglasses price: -STR_2108 :{WINDOW_COLOUR_2}Beef Noodles price: -STR_2109 :{WINDOW_COLOUR_2}Fried Rice Noodles price: -STR_2110 :{WINDOW_COLOUR_2}Wonton Soup price: -STR_2111 :{WINDOW_COLOUR_2}Meatball Soup price: -STR_2112 :{WINDOW_COLOUR_2}Fruit Juice price: -STR_2113 :{WINDOW_COLOUR_2}Soybean Milk price: -STR_2114 :{WINDOW_COLOUR_2}Sujongkwa price: -STR_2115 :{WINDOW_COLOUR_2}Sub Sandwich price: -STR_2116 :{WINDOW_COLOUR_2}Cookie price: +STR_2088 :Párek v rohlíku +STR_2089 :Chapadlo +STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} čepice +STR_2091 :Jablko v županu +STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} tričko +STR_2093 :Koblížek +STR_2094 :Káva +STR_2095 :Prázný kelímek +STR_2096 :Smažené kuře +STR_2097 :Limonáda +STR_2098 :Prázdná krabička +STR_2099 :Prázdná láhev +STR_2100 :{WINDOW_COLOUR_2}Cena fotky z atrakce: +STR_2101 :{WINDOW_COLOUR_2}Cena fotky z atrakce: +STR_2102 :{WINDOW_COLOUR_2}Cena fotky z atrakce: +STR_2103 :{WINDOW_COLOUR_2}Cena preclíku: +STR_2104 :{WINDOW_COLOUR_2}Cena horké čokolády: +STR_2105 :{WINDOW_COLOUR_2}Cena ledového čaje: +STR_2106 :{WINDOW_COLOUR_2}Cena palačinky: +STR_2107 :{WINDOW_COLOUR_2}Cena slunečních brýlí: +STR_2108 :{WINDOW_COLOUR_2}Cena nudlové polévky: +STR_2109 :{WINDOW_COLOUR_2}Cena smažených nudlí: +STR_2110 :{WINDOW_COLOUR_2}Cena čín.knedlíčkové polévky: +STR_2111 :{WINDOW_COLOUR_2}Cena knedlíčkové polévky: +STR_2112 :{WINDOW_COLOUR_2}Cena ovocného džusu: +STR_2113 :{WINDOW_COLOUR_2}Cena sojového mléka: +STR_2114 :{WINDOW_COLOUR_2}Cena suzungkwa: +STR_2115 :{WINDOW_COLOUR_2}Cena sendviče: +STR_2116 :{WINDOW_COLOUR_2}Cena sušenky: STR_2117 :{WINDOW_COLOUR_2} STR_2118 :{WINDOW_COLOUR_2} STR_2119 :{WINDOW_COLOUR_2} -STR_2120 :{WINDOW_COLOUR_2}Roast Sausage price: +STR_2120 :{WINDOW_COLOUR_2}Cena grilované klobásy: STR_2121 :{WINDOW_COLOUR_2} -STR_2122 :On-Ride Photo -STR_2123 :On-Ride Photo -STR_2124 :On-Ride Photo -STR_2125 :Pretzel -STR_2126 :Hot Chocolate -STR_2127 :Iced Tea -STR_2128 :Funnel Cake -STR_2129 :Sunglasses -STR_2130 :Beef Noodles -STR_2131 :Fried Rice Noodles -STR_2132 :Wonton Soup -STR_2133 :Meatball Soup -STR_2134 :Fruit Juice -STR_2135 :Soybean Milk -STR_2136 :Sujongkwa -STR_2137 :Sub Sandwich -STR_2138 :Cookie -STR_2139 :Empty Bowl -STR_2140 :Empty Drink Carton -STR_2141 :Empty Juice Cup -STR_2142 :Roast Sausage -STR_2143 :Empty Bowl -STR_2144 :On-Ride Photos -STR_2145 :On-Ride Photos -STR_2146 :On-Ride Photos -STR_2147 :Pretzels -STR_2148 :Hot Chocolates -STR_2149 :Iced Teas -STR_2150 :Funnel Cakes -STR_2151 :Sunglasses -STR_2152 :Beef Noodles -STR_2153 :Fried Rice Noodles -STR_2154 :Wonton Soups -STR_2155 :Meatball Soups -STR_2156 :Fruit Juices -STR_2157 :Soybean Milks -STR_2158 :Sujongkwa -STR_2159 :Sub Sandwiches -STR_2160 :Cookies -STR_2161 :Empty Bowls -STR_2162 :Empty Drink Cartons -STR_2163 :Empty Juice cups -STR_2164 :Roast Sausages -STR_2165 :Empty Bowls -STR_2166 :an On-Ride Photo -STR_2167 :an On-Ride Photo -STR_2168 :an On-Ride Photo -STR_2169 :a Pretzel -STR_2170 :a Hot Chocolate -STR_2171 :an Iced Tea -STR_2172 :a Funnel Cake -STR_2173 :a pair of Sunglasses -STR_2174 :some Beef Noodles -STR_2175 :some Fried Rice Noodles -STR_2176 :some Wonton Soup -STR_2177 :some Meatball Soup -STR_2178 :a Fruit Juice -STR_2179 :some Soybean Milk -STR_2180 :some Sujongkwa -STR_2181 :a Sub Sandwich -STR_2182 :a Cookie -STR_2183 :an Empty Bowl -STR_2184 :an Empty Drink Carton -STR_2185 :an Empty Juice Cup -STR_2186 :a Roast Sausage -STR_2187 :an Empty Bowl -STR_2188 :On-Ride Photo of {STRINGID} -STR_2189 :On-Ride Photo of {STRINGID} -STR_2190 :On-Ride Photo of {STRINGID} -STR_2191 :Pretzel -STR_2192 :Hot Chocolate -STR_2193 :Iced Tea -STR_2194 :Funnel Cake -STR_2195 :Sunglasses -STR_2196 :Beef Noodles -STR_2197 :Fried Rice Noodles -STR_2198 :Wonton Soup -STR_2199 :Meatball Soup -STR_2200 :Fruit Juice -STR_2201 :Soybean Milk -STR_2202 :Sujongkwa -STR_2203 :Sub Sandwich -STR_2204 :Cookie -STR_2205 :Empty Bowl -STR_2206 :Empty Drink Carton -STR_2207 :Empty Juice Cup -STR_2208 :Roast Sausage -STR_2209 :Empty Bowl -STR_2210 :{SMALLFONT}{BLACK}Show list of handymen in park -STR_2211 :{SMALLFONT}{BLACK}Show list of mechanics in park -STR_2212 :{SMALLFONT}{BLACK}Show list of security guards in park -STR_2213 :{SMALLFONT}{BLACK}Show list of entertainers in park -STR_2214 :Construction not possible while game is paused! +STR_2122 :Fotka z atrakce +STR_2123 :Fotka z atrakce +STR_2124 :Fotka z atrakce +STR_2125 :Preclík +STR_2126 :Horká čokoláda +STR_2127 :Ledový čaj +STR_2128 :Palačinka +STR_2129 :Sluneční brýle +STR_2130 :Nudlová polévka +STR_2131 :Smažené nudle +STR_2132 :Čínská knedlíčková polévka +STR_2133 :Knedlíčková polévka +STR_2134 :Ovocný džus +STR_2135 :Sojové mléko +STR_2136 :Suzungkwa +STR_2137 :Sendvič +STR_2138 :Sušenka +STR_2139 :Prázdná miska +STR_2140 :Prázdné pitíčko +STR_2141 :Prázdný obal od džusu +STR_2142 :Grilovaná klobása +STR_2143 :Prázdná miska +STR_2144 :Fotky z atrakcí +STR_2145 :Fotky z atrakcí +STR_2146 :Fotky z atrakcí +STR_2147 :Preclíky +STR_2148 :Horké čokolády +STR_2149 :Ledové čaje +STR_2150 :Palačinky +STR_2151 :Sluneční brýle +STR_2152 :Nudlové polévky +STR_2153 :Smažené nudle +STR_2154 :Čínské knedlíčkové polévky +STR_2155 :Knedlíčkové polévky +STR_2156 :Ovocné džusy +STR_2157 :Sojová mléka +STR_2158 :Suzungkwy +STR_2159 :Sendviče +STR_2160 :Sušenky +STR_2161 :Prázdné misky +STR_2162 :Prázdná pitíčka +STR_2163 :Prázdné obaly od džusů +STR_2164 :Grilované klobásy +STR_2165 :Prázdné misky +STR_2166 :fotky z atrakcí +STR_2167 :fotky z atrakcí +STR_2168 :fotky z atrakcí +STR_2169 :preclík +STR_2170 :horká čokoláda +STR_2171 :ledový čaj +STR_2172 :palačinka +STR_2173 :sluneční brýle +STR_2174 :nudlová polévka +STR_2175 :smažené nudle +STR_2176 :čínská knedlíčková polévka +STR_2177 :knedlíčková polévka +STR_2178 :ovocný džus +STR_2179 :sojové mléko +STR_2180 :suzungkwa +STR_2181 :sendvič +STR_2182 :sušenka +STR_2183 :prázdná miska +STR_2184 :prázné pitíčko +STR_2185 :prázdný obal od džusu +STR_2186 :grilovaná klobása +STR_2187 :prázdná miska +STR_2188 :Fotka z {STRINGID} +STR_2189 :Fotka z {STRINGID} +STR_2190 :Fotka z {STRINGID} +STR_2191 :Preclík +STR_2192 :Horká čokoláda +STR_2193 :Ledový čaj +STR_2194 :Palačinka +STR_2195 :Sluneční brýle +STR_2196 :Nudlová polévka +STR_2197 :Smažené nudle +STR_2198 :Čínská knedlíčková polévka +STR_2199 :Knedlíčková polévka +STR_2200 :Ovocný džus +STR_2201 :Sojové mléko +STR_2202 :Suzungkwa +STR_2203 :Sendvič +STR_2204 :Sušenka +STR_2205 :Prázdná miska +STR_2206 :Prázné pitíčko +STR_2207 :Prázdný obal od džusu +STR_2208 :Grilovaná klobása +STR_2209 :Prázdná miska +STR_2210 :{SMALLFONT}{BLACK}Zobrazit seznam údržbářů +STR_2211 :{SMALLFONT}{BLACK}Zobrazit seznam mechaniků +STR_2212 :{SMALLFONT}{BLACK}Zobrazit seznam hlídačů +STR_2213 :{SMALLFONT}{BLACK}Zobrazit seznam maskotů +STR_2214 :Nelze stavět při pozastavené hře! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F -STR_2218 :{RED}{STRINGID} on {STRINGID} hasn't returned to the {STRINGID} yet!{NEWLINE}Check whether it is stuck or has stalled -STR_2219 :{RED}{COMMA16} people have died in an accident on {STRINGID} -STR_2220 :{WINDOW_COLOUR_2}Park Rating: {BLACK}{COMMA16} -STR_2221 :{SMALLFONT}{BLACK}Park Rating: {COMMA16} +STR_2218 :{RED}{STRINGID} na {STRINGID} se stále nevrátil do {STRINGID}!{NEWLINE}Zkontrolujte, jestli se nezasekl nebo nezastavil +STR_2219 :{RED}{COMMA16} lidí zemřelo při nehodě na {STRINGID} +STR_2220 :{WINDOW_COLOUR_2}Hodnocení parku: {BLACK}{COMMA16} +STR_2221 :{SMALLFONT}{BLACK}Hodnocení parku: {COMMA16} STR_2222 :{SMALLFONT}{BLACK}{STRINGID} -STR_2223 :{WINDOW_COLOUR_2}Guests in park: {BLACK}{COMMA16} -STR_2224 :{WINDOW_COLOUR_2}Cash: {BLACK}{CURRENCY2DP} -STR_2225 :{WINDOW_COLOUR_2}Cash: {RED}{CURRENCY2DP} -STR_2226 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} -STR_2227 :{WINDOW_COLOUR_2}Company value: {BLACK}{CURRENCY} -STR_2228 :{WINDOW_COLOUR_2}Last month's profit from food/drink and{NEWLINE}merchandise sales: {BLACK}{CURRENCY} -STR_2229 :Slope up to vertical -STR_2230 :Vertical track -STR_2231 :Holding brake for drop -STR_2232 :Cable lift hill -STR_2233 :{SMALLFONT}{BLACK}Park information -STR_2234 :Recent Messages +STR_2223 :{WINDOW_COLOUR_2}Návštěvníci v parku: {BLACK}{COMMA16} +STR_2224 :{WINDOW_COLOUR_2}Hotovost: {BLACK}{CURRENCY2DP} +STR_2225 :{WINDOW_COLOUR_2}Hotovost: {RED}{CURRENCY2DP} +STR_2226 :{WINDOW_COLOUR_2}Hodnota parku: {BLACK}{CURRENCY} +STR_2227 :{WINDOW_COLOUR_2}Hodnota společnosti: {BLACK}{CURRENCY} +STR_2228 :{WINDOW_COLOUR_2}Výnos za poslední měsíc z prodeje{NEWLINE}jídla, pití a suvenýrů: {BLACK}{CURRENCY} +STR_2229 :Sklon až do vertikální polohy +STR_2230 :Svislá trať +STR_2231 :Držení brzd pro pád +STR_2232 :Řtězový výtah +STR_2233 :{SMALLFONT}{BLACK}Informace o zábavním parku +STR_2234 :Poslední zprávy STR_2235 :{SMALLFONT}{STRINGID} {STRINGID} -STR_2236 :Ledna -STR_2237 :Únorna -STR_2238 :Březena -STR_2239 :Dubna -STR_2240 :Května -STR_2241 :Června -STR_2242 :Červenece -STR_2243 :Srpena -STR_2244 :Září -STR_2245 :Říjena -STR_2246 :Listopadu -STR_2247 :Prosinece -STR_2248 :Can't demolish ride/attraction... -STR_2249 :{BABYBLUE}New ride/attraction now available:{NEWLINE}{STRINGID} -STR_2250 :{BABYBLUE}New scenery/themeing now available:{NEWLINE}{STRINGID} -STR_2251 :Can only be built on paths! -STR_2252 :Can only be built across paths! -STR_2253 :Transport Rides -STR_2254 :Gentle Rides -STR_2255 :Roller Coasters -STR_2256 :Thrill Rides -STR_2257 :Water Rides -STR_2258 :Shops & Stalls -STR_2259 :Scenery & Themeing -STR_2260 :No funding -STR_2261 :Minimum funding -STR_2262 :Normal funding -STR_2263 :Maximum funding -STR_2264 :Research funding -STR_2265 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY} per month -STR_2266 :Research priorities -STR_2267 :Currently in development -STR_2268 :Last development -STR_2269 :{WINDOW_COLOUR_2}Type: {BLACK}{STRINGID} -STR_2270 :{WINDOW_COLOUR_2}Progress: {BLACK}{STRINGID} -STR_2271 :{WINDOW_COLOUR_2}Expected: {BLACK}{STRINGID} -STR_2272 :{WINDOW_COLOUR_2}Ride/attraction:{NEWLINE}{BLACK}{STRINGID} -STR_2273 :{WINDOW_COLOUR_2}Scenery/themeing:{NEWLINE}{BLACK}{STRINGID} -STR_2274 :{SMALLFONT}{BLACK}Show details of this invention or development -STR_2275 :{SMALLFONT}{BLACK}Show funding and options for research & development -STR_2276 :{SMALLFONT}{BLACK}Show research & development status -STR_2277 :Unknown -STR_2278 :Transport Ride -STR_2279 :Gentle Ride -STR_2280 :Roller Coaster -STR_2281 :Thrill Ride -STR_2282 :Water Ride -STR_2283 :Shop/Stall -STR_2284 :Scenery/Themeing -STR_2285 :Initial research -STR_2286 :Designing -STR_2287 :Completing design -STR_2288 :Unknown +STR_2236 :leden +STR_2237 :únor +STR_2238 :březen +STR_2239 :duben +STR_2240 :květen +STR_2241 :červen +STR_2242 :červenec +STR_2243 :srpen +STR_2244 :září +STR_2245 :říjen +STR_2246 :listopad +STR_2247 :prosinec +STR_2248 :Nelze zbourat atrakci... +STR_2249 :{BABYBLUE}Dostupný nový obchod, stánek nebo atrakce:{NEWLINE}{STRINGID} +STR_2250 :{BABYBLUE}Dostupná nová kulisa:{NEWLINE}{STRINGID} +STR_2251 :Toto lze postavit pouze na cestách! +STR_2252 :Toto lze postavit pouze napříč cestám! +STR_2253 :Atrakce pro přepravu +STR_2254 :Mírné atrakce +STR_2255 :Horské dráhy +STR_2256 :Adrenalinové atrakce +STR_2257 :Vodní atrakce +STR_2258 :Obchody a stánky +STR_2259 :Kulisy +STR_2260 :Žádné financování +STR_2261 :Minimální financování +STR_2262 :Normální financování +STR_2263 :Maximální financování +STR_2264 :Financování vývoje +STR_2265 :{WINDOW_COLOUR_2}Náklady: {BLACK}{CURRENCY} měsíčně +STR_2266 :Priority výzkumu +STR_2267 :Právě ve výzkumu +STR_2268 :Naposledy vyvinuto +STR_2269 :{WINDOW_COLOUR_2}Typ: {BLACK}{STRINGID} +STR_2270 :{WINDOW_COLOUR_2}Postup: {BLACK}{STRINGID} +STR_2271 :{WINDOW_COLOUR_2}Předpokládané dokončení: {BLACK}{STRINGID} +STR_2272 :{WINDOW_COLOUR_2}Atrakce:{NEWLINE}{BLACK}{STRINGID} +STR_2273 :{WINDOW_COLOUR_2}Kulisa:{NEWLINE}{BLACK}{STRINGID} +STR_2274 :{SMALLFONT}{BLACK}Zobrazit detaily výzkumu/zlepšení +STR_2275 :{SMALLFONT}{BLACK}Zobrazit financování a možnosti výzkumu +STR_2276 :{SMALLFONT}{BLACK}Zobrazit stav výzkumu a vývoje +STR_2277 :Neznámý +STR_2278 :Atrakce pro přepravu +STR_2279 :Mírná atrakce +STR_2280 :Horská dráha +STR_2281 :Adrenalinová atrakce +STR_2282 :Vodní atrakce +STR_2283 :Obchod/Stánek +STR_2284 :Kulisa +STR_2285 :Počáteční výzkum +STR_2286 :Navrhování +STR_2287 :Dokončování návrhu +STR_2288 :Neznámé STR_2289 :{STRINGID} {STRINGID} STR_2290 :{SMALLFONT}{BLACK}{STRINGID} {STRINGID} -STR_2291 :Select scenario for new game -STR_2292 :{WINDOW_COLOUR_2}Rides been on: -STR_2293 :{BLACK} Nothing -STR_2294 :{SMALLFONT}{BLACK}Change base land style -STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land -STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} paid to enter park -STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} ride -STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} rides -STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} item of food -STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} items of food -STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drink -STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drinks -STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenir -STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenirs -STR_2305 :Track design files -STR_2306 :Save track design -STR_2307 :Select {STRINGID} design -STR_2308 :{STRINGID} Track Designs -STR_2309 :Install New Track Design -STR_2310 :Build custom design -STR_2311 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} (approx.) -STR_2312 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} (approx.) -STR_2313 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} (approx.) -STR_2314 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID} -STR_2315 :{WINDOW_COLOUR_2}Cost: {BLACK}around {CURRENCY} -STR_2316 :{WINDOW_COLOUR_2}Space required: {BLACK}{COMMA16} x {COMMA16} blocks +STR_2291 :Vyberte scénář pro novou hru +STR_2292 :{WINDOW_COLOUR_2}Atrakce byly na: +STR_2293 :{BLACK} Nic +STR_2294 :{SMALLFONT}{BLACK}Změnit vzhled země +STR_2295 :{SMALLFONT}{BLACK}Změnit vzhled boků mapy +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno pro vstup do parku +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} atrakci +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} atrakce +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} jídlo +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} jídlo +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} pití +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} pití +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} suvenýr +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} utraceno za {BLACK}{COMMA16} suvenýry +STR_2305 :Soubory tratě +STR_2306 :Uložit návrh trati +STR_2307 :Vyberte návrh {STRINGID} +STR_2308 :Návrhy trati {STRINGID} +STR_2309 :Nainstalvoat nový návrh trati +STR_2310 :Vytvořit vlastní návrh +STR_2311 :{WINDOW_COLOUR_2}Nadšení: asi {BLACK}{COMMA2DP32} +STR_2312 :{WINDOW_COLOUR_2}Intenzita: asi {BLACK}{COMMA2DP32} +STR_2313 :{WINDOW_COLOUR_2}Nevolnost: asi {BLACK}{COMMA2DP32} +STR_2314 :{WINDOW_COLOUR_2}Délka jízdy: {BLACK}{STRINGID} +STR_2315 :{WINDOW_COLOUR_2}Cena: {BLACK}okolo {CURRENCY} +STR_2316 :{WINDOW_COLOUR_2}Vyžadovaný prostor: {BLACK}{COMMA16} x {COMMA16} dlaždic STR_2317 : STR_2318 : STR_2319 : STR_2320 : -STR_2321 :{WINDOW_COLOUR_2}Number of rides/attractions: {BLACK}{COMMA16} -STR_2322 :{WINDOW_COLOUR_2}Staff: {BLACK}{COMMA16} -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_2321 :{WINDOW_COLOUR_2}Celkem atrakcí: {BLACK}{COMMA16} +STR_2322 :{WINDOW_COLOUR_2}Personál: {BLACK}{COMMA16} +STR_2323 :{WINDOW_COLOUR_2}Velikost parku: {BLACK}{COMMA32}m{SQUARED} +STR_2324 :{WINDOW_COLOUR_2}Velikost parku: {BLACK}{COMMA32}čtverečních stop +STR_2325 :{SMALLFONT}{BLACK}Přikoupit k parku pozemky +STR_2326 :{SMALLFONT}{BLACK}Zakoupit stavební práva dovolující stavbu nad, nebo pod zemí za hranicí parku +STR_2327 :Nastavení STR_2328 :{WINDOW_COLOUR_2}Měna: STR_2329 :{WINDOW_COLOUR_2}Délka a rychlost: STR_2330 :{WINDOW_COLOUR_2}Teplota: STR_2331 :{WINDOW_COLOUR_2}Výškové značky: STR_2332 :Jednotky -STR_2333 :Sound -STR_2334 :Libry ({POUND}) -STR_2335 :Dolary ($) -STR_2336 :Franky (F) +STR_2333 :Efekty +STR_2334 :Libra ({POUND}) +STR_2335 :Dolar ($) +STR_2336 :Frank (F) STR_2337 :Marka (DM) -STR_2338 :Yeny ({YEN}) +STR_2338 :Yen ({YEN}) STR_2339 :Pesos (Pts) STR_2340 :Lira (L) -STR_2341 :Guldeny (fl.) -STR_2342 :Koruny (Kč) -STR_2343 :Euroa ({EURO}) +STR_2341 :Gulden (fl.) +STR_2342 :Švédská koruna (kr) +STR_2343 :Euro ({EURO}) STR_2344 :Imperiální STR_2345 :Metrické -STR_2346 :Display -STR_2347 :{RED}{STRINGID} has drowned! -STR_2348 :{SMALLFONT}{BLACK}Show statistics for this staff member -STR_2349 :{WINDOW_COLOUR_2}Wages: {BLACK}{CURRENCY} per month -STR_2350 :{WINDOW_COLOUR_2}Employed: {BLACK}{MONTHYEAR} -STR_2351 :{WINDOW_COLOUR_2}Lawns mown: {BLACK}{COMMA16} -STR_2352 :{WINDOW_COLOUR_2}Gardens watered: {BLACK}{COMMA16} -STR_2353 :{WINDOW_COLOUR_2}Litter swept: {BLACK}{COMMA16} -STR_2354 :{WINDOW_COLOUR_2}Bins emptied: {BLACK}{COMMA16} -STR_2355 :{WINDOW_COLOUR_2}Rides fixed: {BLACK}{COMMA16} -STR_2356 :{WINDOW_COLOUR_2}Rides inspected: {BLACK}{COMMA16} -STR_2357 :House -STR_2358 :Units -STR_2359 :Real Values -STR_2360 :{WINDOW_COLOUR_2}Display Resolution: -STR_2361 :Landscape Smoothing -STR_2362 :{SMALLFONT}{BLACK}Toggle landscape tile edge smoothing on/off -STR_2363 :Gridlines on Landscape -STR_2364 :{SMALLFONT}{BLACK}Toggle gridlines on landscape on/off -STR_2365 :The bank refuses to increase your loan! +STR_2346 :Zobrazení +STR_2347 :{RED}{STRINGID} se utopil! +STR_2348 :{SMALLFONT}{BLACK}Zobrazit statistiku zaměstnance +STR_2349 :{WINDOW_COLOUR_2}Plat: {BLACK}{CURRENCY} měsíčně +STR_2350 :{WINDOW_COLOUR_2}Zaměstnán od: {BLACK}{MONTHYEAR} +STR_2351 :{WINDOW_COLOUR_2}Posekáno dlaždic trávy: {BLACK}{COMMA16} +STR_2352 :{WINDOW_COLOUR_2}Zalito květin: {BLACK}{COMMA16} +STR_2353 :{WINDOW_COLOUR_2}Zameteno odpadků: {BLACK}{COMMA16} +STR_2354 :{WINDOW_COLOUR_2}Vysypáno košů: {BLACK}{COMMA16} +STR_2355 :{WINDOW_COLOUR_2}Opraveno atrakcí: {BLACK}{COMMA16} +STR_2356 :{WINDOW_COLOUR_2}Provedeno inspekcí: {BLACK}{COMMA16} +STR_2357 :Dům +STR_2358 :Jednotky +STR_2359 :Reálné hodnoty +STR_2360 :Rozlišení displeje: +STR_2361 :Vyhlazování krajiny +STR_2362 :{SMALLFONT}{BLACK}Přepíná vyhlazování hran krajiny +STR_2363 :Vykreslit mřížku na krajině +STR_2364 :{SMALLFONT}{BLACK}Přepíná zobrazení mřížky na krajině +STR_2365 :Banka vám odmítá dát větší půjčku! STR_2366 :Celsius ({DEGREE}C) STR_2367 :Fahrenheit ({DEGREE}F) -STR_2368 :None -STR_2369 :Low -STR_2370 :Average -STR_2371 :High -STR_2372 :Low -STR_2373 :Medium -STR_2374 :High -STR_2375 :Very high -STR_2376 :Extreme -STR_2377 :Ultra-Extreme -STR_2378 :{SMALLFONT}{BLACK}Adjust smaller area of land -STR_2379 :{SMALLFONT}{BLACK}Adjust larger area of land -STR_2380 :{SMALLFONT}{BLACK}Adjust smaller area of water -STR_2381 :{SMALLFONT}{BLACK}Adjust larger area of water -STR_2382 :Land -STR_2383 :Water -STR_2384 :{WINDOW_COLOUR_2}Tvůj úkol: +STR_2368 :nic +STR_2369 :málo +STR_2370 :průměr +STR_2371 :hodně +STR_2372 :málo +STR_2373 :střední +STR_2374 :vysoké +STR_2375 :velmi vysoké +STR_2376 :extrém +STR_2377 :ultra-Extrém +STR_2378 :{SMALLFONT}{BLACK}Upravit menší oblast krajiny +STR_2379 :{SMALLFONT}{BLACK}Upravit větší oblast krajiny +STR_2380 :{SMALLFONT}{BLACK}Upravit menší vodní plochu +STR_2381 :{SMALLFONT}{BLACK}Upravit větší vodní plochu +STR_2382 :Země +STR_2383 :Vodní plochy +STR_2384 :{WINDOW_COLOUR_2}Cíl scénáře: STR_2385 :{BLACK}žádný -STR_2386 :{BLACK}Mít v parku alespoň {COMMA16} hostů na konci {MONTHYEAR}, s hodnocením parku alespoň 600 +STR_2386 :{BLACK}Mít v parku alespoň {COMMA16} návštěvníků na konci {MONTHYEAR}, s hodnocením parku alespoň 600 STR_2387 :{BLACK}Dosáhnout hodnoty parku alespoň {POP16}{POP16}{CURRENCY} na konci {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} -STR_2388 :{BLACK}Bav se! -STR_2389 :{BLACK}Build the best {STRINGID} you can! -STR_2390 :{BLACK}Mýt v parku 10 druhů kolotoču v provozu, každy s hodnotou zábavnosti alespoň 6.00 -STR_2391 :{BLACK}Mít v parku alespoň {COMMA16} hostů a zároveň nesmíš nikdy nechat hodnocení parku spadnout pod 700! +STR_2388 :{BLACK}Příjemnou zábavu! +STR_2389 :{BLACK}Postav ten nejlepší {STRINGID}! +STR_2390 :{BLACK}Mít v parku 10 druhů kolotočů v provozu, každý s hodnotou zábavnosti alespoň 6.00 +STR_2391 :{BLACK}Mít v parku alespoň {COMMA16} návštěvníků a zároveň nikdy nenechat hodnocení parku spadnout pod 700! STR_2392 :{BLACK}Dosáhnout měsíčního příjmu z lístků na atrakce alespoň {POP16}{POP16}{CURRENCY} -STR_2393 :{BLACK}{BLACK}Mýt v parku 10 druhů kolotoču v provozu, každy s hodnotou zábavnosti alespoň 7.00 a délkou alespoň {LENGHT} -STR_2394 :{BLACK}To finish building all 5 of the partially built roller coasters in this park, designing them to achieve excitement ratings of at least {POP16}{POP16}{COMMA2DP32} each +STR_2393 :{BLACK}{BLACK}Mít v parku 10 druhů kolotoču v provozu, každý s hodnotou zábavnosti alespoň 7.00 a délkou alespoň {LENGHT} +STR_2394 :{BLACK}Dokončit všech 5 rozestavěných horských drah tak, aby každá dosahovala hodnocení vzrušení alespoň {POP16}{POP16}{COMMA2DP32} STR_2395 :{BLACK}Vrátit půjčku a dosáhnout hodnoty parku alspoň {POP16}{POP16}{CURRENCY} -STR_2396 :{BLACK}To achieve a monthly profit from food, drink and merchandise sales of at least {POP16}{POP16}{CURRENCY} +STR_2396 :{BLACK}Dosáhnout měsíčního zisku z jídla, pití a suvenýrů alespoň {POP16}{POP16}{CURRENCY} STR_2397 :Nic -STR_2398 :Počet hostů v daný čas +STR_2398 :Počet návštěvníků v daný čas STR_2399 :Hodnotu praku v dané datum STR_2400 :Volná zábava STR_2401 :Postav nejlepší atrakci co dokážeš STR_2402 :Postavit 10 kolotočů -STR_2403 :Počet hostů v parku +STR_2403 :Počet návštěvníků v parku STR_2404 :Měsíční příjem z STR_2405 :Postavit 10 drah zadané délky STR_2406 :Dokončit stavbu 5 kolotočů -STR_2407 :Repay loan and achieve a given park value -STR_2408 :Monthly profit from food/merchandise -STR_2409 :{WINDOW_COLOUR_2}Marketing campaigns in operation -STR_2410 :{BLACK}None -STR_2411 :{WINDOW_COLOUR_2}Marketing campaigns available -STR_2412 :{SMALLFONT}{BLACK}Start this marketing campaign -STR_2413 :{BLACK}({CURRENCY2DP} per week) -STR_2414 :(Not Selected) -STR_2415 :{WINDOW_COLOUR_2}Ride: -STR_2416 :{WINDOW_COLOUR_2}Item: -STR_2417 :{WINDOW_COLOUR_2}Length of time: -STR_2418 :Free entry to {STRINGID} -STR_2419 :Free ride on {STRINGID} -STR_2420 :Half-price entry to {STRINGID} -STR_2421 :Free {STRINGID} -STR_2422 :Advertising campaign for {STRINGID} -STR_2423 :Advertising campaign for {STRINGID} -STR_2424 :{WINDOW_COLOUR_2}Vouchers for free entry to the park -STR_2425 :{WINDOW_COLOUR_2}Vouchers for free rides on a particular ride -STR_2426 :{WINDOW_COLOUR_2}Vouchers for half-price entry to the park -STR_2427 :{WINDOW_COLOUR_2}Vouchers for free food or drink -STR_2428 :{WINDOW_COLOUR_2}Advertising campaign for the park -STR_2429 :{WINDOW_COLOUR_2}Advertising campaign for a particular ride -STR_2430 :{BLACK}Vouchers for free entry to {STRINGID} -STR_2431 :{BLACK}Vouchers for free ride on {STRINGID} -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_2407 :Vrátit půjčku a dosáhnout dané hodnoty parku +STR_2408 :Měsíční zisk z prodeje jídla a suvenýrů +STR_2409 :{WINDOW_COLOUR_2}Probíhající reklamní kampaně +STR_2410 :{BLACK}Žádné +STR_2411 :{WINDOW_COLOUR_2}Dostupné reklamní kampaně +STR_2412 :{SMALLFONT}{BLACK}Zahájit tuto reklamní kampaň +STR_2413 :{BLACK}({CURRENCY2DP} týdně) +STR_2414 :(nezvoleno) +STR_2415 :{WINDOW_COLOUR_2}Atrakce: +STR_2416 :{WINDOW_COLOUR_2}Položka: +STR_2417 :{WINDOW_COLOUR_2}Časové období: +STR_2418 :Volný vstup do {STRINGID} +STR_2419 :Volné vstupenky na {STRINGID} +STR_2420 :Vstupenky za polovic na {STRINGID} +STR_2421 :{STRINGID} zdarma +STR_2422 :Reklamní kampaň pro {STRINGID} +STR_2423 :Reklamní kampaň pro {STRINGID} +STR_2424 :{WINDOW_COLOUR_2}Kupony na volný vstup do parku +STR_2425 :{WINDOW_COLOUR_2}Kupony na volné jízdy dané atrakce +STR_2426 :{WINDOW_COLOUR_2}Kupony na vstup do parku za polovic +STR_2427 :{WINDOW_COLOUR_2}Kupony na jídlo nebo pití zdarma +STR_2428 :{WINDOW_COLOUR_2}Reklamní kampaň pro park +STR_2429 :{WINDOW_COLOUR_2}Reklamní kampaň pro danou atrakci +STR_2430 :{BLACK}Kupony na volný vstup do {STRINGID} +STR_2431 :{BLACK}Kupony na volné jízdy {STRINGID} +STR_2432 :{BLACK}Kupony na vstup za polovic do {STRINGID} +STR_2433 :{BLACK}Kupony na {STRINGID} zdarma +STR_2434 :{BLACK}Reklamní kampaň pro {STRINGID} +STR_2435 :{BLACK}Reklamní kampaň pro {STRINGID} +STR_2436 :1 týden STR_2437 : STR_2438 : STR_2439 : STR_2440 : STR_2441 : STR_2442 : -STR_2443 :{WINDOW_COLOUR_2}Cost per week: {BLACK}{CURRENCY2DP} -STR_2444 :{WINDOW_COLOUR_2}Total cost: {BLACK}{CURRENCY2DP} -STR_2445 :Start this marketing campaign -STR_2446 :{YELLOW}Your marketing campaign for free entry to the park has finished -STR_2447 :{YELLOW}Your marketing campaign for free rides on {STRINGID} has finished -STR_2448 :{YELLOW}Your marketing campaign for half-price entry to the park has finished -STR_2449 :{YELLOW}Your marketing campaign for free {STRINGID} has finished -STR_2450 :{YELLOW}Your advertising campaign for the park has finished -STR_2451 :{YELLOW}Your advertising campaign for {STRINGID} has finished -STR_2452 :{WINDOW_COLOUR_2}Cash (less loan): {BLACK}{CURRENCY2DP} -STR_2453 :{WINDOW_COLOUR_2}Cash (less loan): {RED}{CURRENCY2DP} +STR_2443 :{WINDOW_COLOUR_2}Náklady týdně: {BLACK}{CURRENCY2DP} +STR_2444 :{WINDOW_COLOUR_2}Celkové náklady: {BLACK}{CURRENCY2DP} +STR_2445 :Zahájit reklamní kampaň +STR_2446 :{YELLOW}Reklamní kampaň s kupony pro volný vstup do parku skončila +STR_2447 :{YELLOW}Reklamní kampaň s kupony pro volné jízdy na {STRINGID} skončila +STR_2448 :{YELLOW}Reklamní kampaň s kupony na vstup do parku za polovic skončila +STR_2449 :{YELLOW}Reklamní kampaň s kupony na {STRINGID} zdarma skončila +STR_2450 :{YELLOW}Reklamní kampaň pro park skončila +STR_2451 :{YELLOW}Reklamní kampaň pro {STRINGID} skončila +STR_2452 :{WINDOW_COLOUR_2}Hotovost (bez půjčky): {BLACK}{CURRENCY2DP} +STR_2453 :{WINDOW_COLOUR_2}Hotovost (bez půjčky): {RED}{CURRENCY2DP} STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - STR_2455 :{SMALLFONT}{BLACK}+{CURRENCY2DP} - STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} - -STR_2457 :{SMALLFONT}{BLACK}Show financial accounts -STR_2458 :{SMALLFONT}{BLACK}Show graph of cash (less loan) over time -STR_2459 :{SMALLFONT}{BLACK}Show graph of park value over time -STR_2460 :{SMALLFONT}{BLACK}Show graph of weekly profit -STR_2461 :{SMALLFONT}{BLACK}Show marketing campaigns -STR_2462 :{SMALLFONT}{BLACK}Show view of park entrance -STR_2463 :{SMALLFONT}{BLACK}Show graph of park ratings over time -STR_2464 :{SMALLFONT}{BLACK}Show graph of guest numbers over time -STR_2465 :{SMALLFONT}{BLACK}Show park entrance price and information -STR_2466 :{SMALLFONT}{BLACK}Show park statistics -STR_2467 :{SMALLFONT}{BLACK}Show objectives for this game -STR_2468 :{SMALLFONT}{BLACK}Show recent awards this park has received -STR_2469 :{SMALLFONT}{BLACK}Select level of research & development -STR_2470 :{SMALLFONT}{BLACK}Research new transport rides -STR_2471 :{SMALLFONT}{BLACK}Research new gentle rides -STR_2472 :{SMALLFONT}{BLACK}Research new roller coasters -STR_2473 :{SMALLFONT}{BLACK}Research new thrill rides -STR_2474 :{SMALLFONT}{BLACK}Research new water rides -STR_2475 :{SMALLFONT}{BLACK}Research new shops and stalls -STR_2476 :{SMALLFONT}{BLACK}Research new scenery and themeing -STR_2477 :{SMALLFONT}{BLACK}Select operating mode for this ride/attraction -STR_2478 :{SMALLFONT}{BLACK}Show graph of velocity against time -STR_2479 :{SMALLFONT}{BLACK}Show graph of altitude against time -STR_2480 :{SMALLFONT}{BLACK}Show graph of vertical acceleration against time -STR_2481 :{SMALLFONT}{BLACK}Show graph of lateral acceleration against time -STR_2482 :{SMALLFONT}{BLACK}Profit: {CURRENCY} per week, Park Value: {CURRENCY} -STR_2483 :{WINDOW_COLOUR_2}Weekly profit: {BLACK}+{CURRENCY2DP} -STR_2484 :{WINDOW_COLOUR_2}Weekly profit: {RED}{CURRENCY2DP} -STR_2485 :Controls -STR_2486 :General -STR_2487 :Show 'real' names of guests -STR_2488 :{SMALLFONT}{BLACK}Toggle between showing 'real' names of guests and guest numbers -STR_2489 :Shortcut keys... -STR_2490 :Keyboard shortcuts -STR_2491 :Reset keys -STR_2492 :{SMALLFONT}{BLACK}Set all keyboard shortcuts back to default settings -STR_2493 :Close top-most window -STR_2494 :Close all floating windows -STR_2495 :Cancel construction mode -STR_2496 :Pause game -STR_2497 :Zoom view out -STR_2498 :Zoom view in -STR_2499 :Rotate view clockwise -STR_2500 :Rotate construction object -STR_2501 :Underground view toggle -STR_2502 :Remove base land toggle -STR_2503 :Remove vertical land toggle -STR_2504 :See-through rides toggle -STR_2505 :See-through scenery toggle -STR_2506 :Invisible supports toggle -STR_2507 :Invisible people toggle -STR_2508 :Height marks on land toggle -STR_2509 :Height marks on ride tracks toggle -STR_2510 :Height marks on paths toggle -STR_2511 :Adjust land -STR_2512 :Adjust water -STR_2513 :Build scenery -STR_2514 :Build paths -STR_2515 :Build new ride -STR_2516 :Show financial information -STR_2517 :Show research information -STR_2518 :Show rides list -STR_2519 :Show park information -STR_2520 :Show guest list -STR_2521 :Show staff list -STR_2522 :Show recent messages -STR_2523 :Show map -STR_2524 :Screenshot +STR_2457 :{SMALLFONT}{BLACK}Zobrazit účet +STR_2458 :{SMALLFONT}{BLACK}Zobrazit graf hotovosti +STR_2459 :{SMALLFONT}{BLACK}Zobrazit graf hodnoty parku +STR_2460 :{SMALLFONT}{BLACK}Zobrazit graf týdenního zisku +STR_2461 :{SMALLFONT}{BLACK}Zobrazit reklamní kampaně +STR_2462 :{SMALLFONT}{BLACK}Pohled na vstup do parku +STR_2463 :{SMALLFONT}{BLACK}Zobrazit graf hodnocení parku +STR_2464 :{SMALLFONT}{BLACK}Zobrazit graf návštěvnosti +STR_2465 :{SMALLFONT}{BLACK}Zobrazit cenu vstupu do parku +STR_2466 :{SMALLFONT}{BLACK}Zobrazit statistiky parku +STR_2467 :{SMALLFONT}{BLACK}Zobrazit cíle hry +STR_2468 :{SMALLFONT}{BLACK}Zobrazit nejnovější ocenění, která park získal +STR_2469 :{SMALLFONT}{BLACK}Vyberte úroveň financování vývoje +STR_2470 :{SMALLFONT}{BLACK}Vyvíjet nové atrakce pro přepravu +STR_2471 :{SMALLFONT}{BLACK}Vyvíjet nové mírné atrakce +STR_2472 :{SMALLFONT}{BLACK}Vyvíjet nové horské dráhy +STR_2473 :{SMALLFONT}{BLACK}Vyvíjet nové adrenalinové atrakce +STR_2474 :{SMALLFONT}{BLACK}Vyvíjet nové vodní atrakce +STR_2475 :{SMALLFONT}{BLACK}Vyvíjet nové obchody a stánky +STR_2476 :{SMALLFONT}{BLACK}Vyvíjet nové kulisy +STR_2477 :{SMALLFONT}{BLACK}Vyberte mód provozu atrakce +STR_2478 :{SMALLFONT}{BLACK}Zobrazit graf rychlosti +STR_2479 :{SMALLFONT}{BLACK}Zobrazit graf vyvýšení +STR_2480 :{SMALLFONT}{BLACK}Zobrazit graf vertikálního zrychlení +STR_2481 :{SMALLFONT}{BLACK}Zobrazit graf laterálního zrychlení +STR_2482 :{SMALLFONT}{BLACK}Zisk: {CURRENCY} týdně, hodnota parku: {CURRENCY} +STR_2483 :{WINDOW_COLOUR_2}Týdení zisk: {BLACK}+{CURRENCY2DP} +STR_2484 :{WINDOW_COLOUR_2}Týdení zisk: {RED}{CURRENCY2DP} +STR_2485 :Ovládání +STR_2486 :Obecné +STR_2487 :Zobrazit "skutečná" jména návštěvníků +STR_2488 :{SMALLFONT}{BLACK}Přepíná mezi zobrazením "skutečného" jména a čísla návštěvníka +STR_2489 :Klávesové zkratky... +STR_2490 :Klávesové zkratky +STR_2491 :Obnovit původní nastavení +STR_2492 :{SMALLFONT}{BLACK}Nastaví všechny klávesové zkratky na jejich výchzí hodnoty +STR_2493 :Zavřít okno na vrchu +STR_2494 :Zavřít všechny plovoucí okna +STR_2495 :Zrušit mód stavění +STR_2496 :Pozastavit hru +STR_2497 :Oddálit pohled +STR_2498 :Přiblížit pohled +STR_2499 :Otočit pohled podle směru hod. ruč. +STR_2500 :Otočit stavební objekt +STR_2501 :Přepnout podzemní pohled +STR_2502 :Přepnout zobrazení povrchu země +STR_2503 :Přepnout zobrazení boků mapy +STR_2504 :Přepnout průhledné atrakce +STR_2505 :Přepnout průhledné kulisy +STR_2506 :Přepnout průhledné podpěry +STR_2507 :Přepnout neviditelné návštěvníky +STR_2508 :Přepnout výškové popisky krajiny +STR_2509 :Přepnout výškové popisky atrakcí +STR_2510 :Přepnout výškové popisky cest +STR_2511 :Úpravy terénu +STR_2512 :Úpravy vodních ploch +STR_2513 :Stavět kulisy +STR_2514 :Stavět cesty +STR_2515 :Stavět nové atrakce +STR_2516 :Zobrazit informace o financích +STR_2517 :Zobrazit informace o výzkumu +STR_2518 :Zobrazit seznam atrakcí +STR_2519 :Zobrazit informace o parku +STR_2520 :Zobrazit seznam návštěvníků +STR_2521 :Zobrazit seznam personálu +STR_2522 :Zobrazit poslední zprávy +STR_2523 :Zobrazit mapu +STR_2524 :Snímek obrazovky ### The following need to be reordered to match SDL_keycode layout. STR_2525 :??? STR_2526 :??? @@ -2685,37 +2686,37 @@ STR_2676 :??? STR_2677 :??? STR_2678 :??? STR_2679 :??? -STR_2680 :All research complete -STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} +STR_2680 :Všechen výzkum byl dokončen +STR_2681 :{MEDIUMFONT}{BLACK}Přidat {CURRENCY} hotovosti STR_2682 : STR_2683 : -STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive -STR_2685 :Simplex Noise Parameters -STR_2686 :{WINDOW_COLOUR_2}Low: -STR_2687 :{WINDOW_COLOUR_2}High: -STR_2688 :{WINDOW_COLOUR_2}Base Frequency: -STR_2689 :{WINDOW_COLOUR_2}Octaves: -STR_2690 :Map Generation -STR_2691 :{WINDOW_COLOUR_2}Base height: -STR_2692 :{WINDOW_COLOUR_2}Water level: -STR_2693 :{WINDOW_COLOUR_2}Terrain: -STR_2694 :Generate -STR_2695 :Random terrain -STR_2696 :Place trees +STR_2684 :{SMALLFONT}{BLACK}Dorazí velká skupina návštěvníků +STR_2685 :Parametry simplex noise +STR_2686 :{WINDOW_COLOUR_2}Hloubky: +STR_2687 :{WINDOW_COLOUR_2}Výšky: +STR_2688 :{WINDOW_COLOUR_2}Základní frekvence: +STR_2689 :{WINDOW_COLOUR_2}Oktávy: +STR_2690 :Generování mapy +STR_2691 :{WINDOW_COLOUR_2}Výška povrchu: +STR_2692 :{WINDOW_COLOUR_2}Výška vodní hladiny: +STR_2693 :{WINDOW_COLOUR_2}Terén: +STR_2694 :Generovat +STR_2695 :Náhodný terén +STR_2696 :Umístit stromy STR_2697 :??? STR_2698 :??? STR_2699 :??? -STR_2700 :Autosave frequency: -STR_2701 :Every minute -STR_2702 :Every 5 minutes -STR_2703 :Every 15 minutes -STR_2704 :Every 30 minutes -STR_2705 :Every hour -STR_2706 :Never -STR_2707 :Use system dialog window -STR_2708 :{WINDOW_COLOUR_1}Are you sure you want to overwrite {STRINGID}? -STR_2709 :Overwrite -STR_2710 :Type the name of the file. +STR_2700 :Frekvence auto ukládání: +STR_2701 :každou minutu +STR_2702 :každých 5 minut +STR_2703 :každých 15 minut +STR_2704 :každých 30 minut +STR_2705 :každou hodinu +STR_2706 :nikdy +STR_2707 :použít systémový dialog +STR_2708 :{WINDOW_COLOUR_1}Opravdu chcete přepsat {STRINGID}? +STR_2709 :Přepsat +STR_2710 :Napište název souboru. STR_2711 :; STR_2712 := STR_2713 :, @@ -2725,152 +2726,152 @@ STR_2716 :/ STR_2717 :' STR_2718 :(up) STR_2719 :(new file) -STR_2720 :{UINT16}sec -STR_2721 :{UINT16}secs -STR_2722 :{UINT16}min:{UINT16}sec -STR_2723 :{UINT16}min:{UINT16}secs -STR_2724 :{UINT16}mins:{UINT16}sec -STR_2725 :{UINT16}mins:{UINT16}secs +STR_2720 :{UINT16}s +STR_2721 :{UINT16}s +STR_2722 :{UINT16}min:{UINT16}s +STR_2723 :{UINT16}min:{UINT16}s +STR_2724 :{UINT16}min:{UINT16}s +STR_2725 :{UINT16}min:{UINT16}s STR_2726 :{UINT16}min -STR_2727 :{UINT16}mins -STR_2728 :{UINT16}hour:{UINT16}min -STR_2729 :{UINT16}hour:{UINT16}mins -STR_2730 :{UINT16}hours:{UINT16}min -STR_2731 :{UINT16}hours:{UINT16}mins -STR_2732 :{COMMA16}ft -STR_2733 :{COMMA16}m -STR_2734 :{COMMA16}mph -STR_2735 :{COMMA16}km/h -STR_2736 :{MONTH}, Year {COMMA16} -STR_2737 :{STRINGID} {MONTH}, Year {COMMA16} -STR_2738 :Title screen music: -STR_2739 :None +STR_2727 :{UINT16}min +STR_2728 :{UINT16}hod:{UINT16}min +STR_2729 :{UINT16}hod:{UINT16}min +STR_2730 :{UINT16}hod:{UINT16}min +STR_2731 :{UINT16}hod:{UINT16}min +STR_2732 :{COMMA16} stop +STR_2733 :{COMMA16} metrů +STR_2734 :{COMMA16} mílí za hodinu +STR_2735 :{COMMA16} km/h +STR_2736 :{MONTH}, rok {COMMA16} +STR_2737 :{STRINGID} {MONTH}, rok {COMMA16} +STR_2738 :Hudba úvodní obrazovky: +STR_2739 :Žádná 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_2742 :css50.dat nenalezen +STR_2743 :Nakopírujte data\css17.dat z vaší instalace RCT1 do to data\css50.dat ve vaší instalaci RCT2. STR_2744 :[ STR_2745 :\ STR_2746 :] STR_2747 :{ENDQUOTES} STR_2748 :Bar -STR_2749 :My new scenario +STR_2749 :Můj nový scénář # New strings used in the cheats window previously these were ??? -STR_2750 :Move all items to top -STR_2751 :Move all items to bottom -STR_2752 :Clear grass -STR_2753 :Mowed grass -STR_2754 :Water plants -STR_2755 :Fix vandalism -STR_2756 :Remove litter -STR_2757 :Force Sun -STR_2758 :Force Thunder -STR_2759 :Zero Clearance +STR_2750 :Posunout všechny položky nahoru +STR_2751 :Posunout všechny položky dolů +STR_2752 :Vyčistit trávu +STR_2753 :Posekat trávu +STR_2754 :Zalít květiny +STR_2755 :Opravit vandalismy +STR_2756 :Odebrat odpadky +STR_2757 : +STR_2758 : +STR_2759 :Povolit křížení staveb STR_2760 :+{CURRENCY} STR_2761 : STR_2762 : STR_2763 :??? STR_2764 : -STR_2765 :Large Tram -STR_2766 :Win scenario -STR_2767 :Freeze Climate -STR_2768 :Unfreeze Climate -STR_2769 :Open Park -STR_2770 :Close Park -STR_2771 :Slower Gamespeed -STR_2772 :Faster Gamespeed -STR_2773 :Windowed -STR_2774 :Fullscreen -STR_2775 :Fullscreen (desktop) -STR_2776 :Language: +STR_2765 :Plná tramvaj +STR_2766 :Vyhrát scénář +STR_2767 :Zákaz změny klimatu +STR_2768 :Povolení změny klimatu +STR_2769 :Otevřít park +STR_2770 :Zavřít park +STR_2771 :Pomalejší hra +STR_2772 :Rychlejší hra +STR_2773 :V okně +STR_2774 :Celá obrazovka +STR_2775 :Celá obrazovka (okno bez okrajů) +STR_2776 :Jazyk: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} -STR_2779 :Viewport #{COMMA16} -STR_2780 :Extra viewport +STR_2779 :Pohled #{COMMA16} +STR_2780 :Extra pohled # End of new strings STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} STR_2782 :SHIFT + STR_2783 :CTRL + -STR_2784 :Change keyboard shortcut -STR_2785 :{WINDOW_COLOUR_2}Press new shortcut key for:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} -STR_2786 :{SMALLFONT}{BLACK}Click on shortcut description to select new key -STR_2787 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} -STR_2788 :{WINDOW_COLOUR_2}Congratulations !{NEWLINE}{BLACK}You achieved your objective with a company value of {CURRENCY} ! -STR_2789 :{WINDOW_COLOUR_2}You have failed your objective ! -STR_2790 :Enter name into scenario chart -STR_2791 :Enter name -STR_2792 :Please enter your name for the scenario chart: -STR_2793 :{SMALLFONT}(Completed by {STRINGID}) -STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY} -STR_2795 :Sort -STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed -STR_2797 :Scroll view when pointer at screen edge -STR_2798 :{SMALLFONT}{BLACK}Select whether to scroll the view when the mouse pointer is at the screen edge -STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments -STR_2800 :{WINDOW_COLOUR_2}Total admissions: {BLACK}{COMMA32} -STR_2801 :{WINDOW_COLOUR_2}Income from admissions: {BLACK}{CURRENCY2DP} -STR_2802 :Map -STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map -STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map -STR_2805 :{SMALLFONT}{BLACK}Show map of park -STR_2806 :{RED}Guests are complaining about the disgusting state of the paths in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2807 :{RED}Guests are complaining about the amount of litter in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2808 :{RED}Guests are complaining about the vandalism in your park{NEWLINE}Check where your security guards are and consider organising them better -STR_2809 :{RED}Guests are hungry and can't find anywhere to buy food -STR_2810 :{RED}Guests are thirsty and can't find anywhere to buy drinks -STR_2811 :{RED}Guests are complaining because they can't find the toilets in your park -STR_2812 :{RED}Guests are getting lost or stuck{NEWLINE}Check whether the layout of your footpaths needs improving to help the guests find their way around -STR_2813 :{RED}Your park entrance fee is too high!{NEWLINE}Reduce your entrance fee or improve the value of the park to attract more guests -STR_2814 :{WINDOW_COLOUR_2}Most untidy park award -STR_2815 :{WINDOW_COLOUR_2}Tidiest park award -STR_2816 :{WINDOW_COLOUR_2}Award for the park with the best roller coasters -STR_2817 :{WINDOW_COLOUR_2}Best value park award -STR_2818 :{WINDOW_COLOUR_2}Most beautiful park award -STR_2819 :{WINDOW_COLOUR_2}Worst value park award -STR_2820 :{WINDOW_COLOUR_2}Safest park award -STR_2821 :{WINDOW_COLOUR_2}Best staff award -STR_2822 :{WINDOW_COLOUR_2}Best park food award -STR_2823 :{WINDOW_COLOUR_2}Worst park food award -STR_2824 :{WINDOW_COLOUR_2}Best park toilets award -STR_2825 :{WINDOW_COLOUR_2}Most disappointing park award -STR_2826 :{WINDOW_COLOUR_2}Best water rides award -STR_2827 :{WINDOW_COLOUR_2}Best custom-designed rides award -STR_2828 :{WINDOW_COLOUR_2}Most dazzling ride colour schemes award -STR_2829 :{WINDOW_COLOUR_2}Most confusing park layout award -STR_2830 :{WINDOW_COLOUR_2}Best gentle ride award -STR_2831 :{TOPAZ}Your park has received an award for being 'The most untidy park in the country'! -STR_2832 :{TOPAZ}Your park has received an award for being 'The tidiest park in the country'! -STR_2833 :{TOPAZ}Your park has received an award for being 'The park with the best roller coasters'! -STR_2834 :{TOPAZ}Your park has received an award for being 'The best value park in the country'! -STR_2835 :{TOPAZ}Your park has received an award for being 'The most beautiful park in the country'! -STR_2836 :{TOPAZ}Your park has received an award for being 'The worst value park in the country'! -STR_2837 :{TOPAZ}Your park has received an award for being 'The safest park in the country'! -STR_2838 :{TOPAZ}Your park has received an award for being 'The park with the best staff'! -STR_2839 :{TOPAZ}Your park has received an award for being 'The park with the best food in the country'! -STR_2840 :{TOPAZ}Your park has received an award for being 'The park with the worst food in the country'! -STR_2841 :{TOPAZ}Your park has received an award for being 'The park with the best toilet facilities in the country'! -STR_2842 :{TOPAZ}Your park has received an award for being 'The most disappointing park in the country'! -STR_2843 :{TOPAZ}Your park has received an award for being 'The park with the best water rides in the country'! -STR_2844 :{TOPAZ}Your park has received an award for being 'The park with the best custom-designed rides'! -STR_2845 :{TOPAZ}Your park has received an award for being 'The park with the most dazzling choice of colour schemes'! -STR_2846 :{TOPAZ}Your park has received an award for being 'The park with the most confusing layout'! -STR_2847 :{TOPAZ}Your park has received an award for being 'The park with the best gentle rides'! -STR_2848 :{WINDOW_COLOUR_2}No recent awards -STR_2849 :New scenario installed successfully -STR_2850 :New track design installed successfully -STR_2851 :Scenario already installed -STR_2852 :Track design already installed -STR_2853 :Forbidden by the local authority! -STR_2854 :{RED}Guests can't get to the entrance of {STRINGID} !{NEWLINE}Construct a path to the entrance -STR_2855 :{RED}{STRINGID} has no path leading from its exit !{NEWLINE}Construct a path from the ride exit +STR_2784 :Změnit klávesovou zkratku +STR_2785 :{WINDOW_COLOUR_2}Stiskněte novou klávesovou zkratku pro:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2786 :{SMALLFONT}{BLACK}Klikněte na popis klávesové zkratky pro výběr nastavení zkratky +STR_2787 :{WINDOW_COLOUR_2}Hodnota parku: {BLACK}{CURRENCY} +STR_2788 :{WINDOW_COLOUR_2}Gratulujeme!{NEWLINE}{BLACK}Bylo dosaženo cíle scénáře s hodnotou společnosti {CURRENCY}! +STR_2789 :{WINDOW_COLOUR_2}Nepodařilo se dosáhnout cíle scénáře! +STR_2790 :Zadejte jméno do žebříčku scénáře +STR_2791 :Zadejte jméno +STR_2792 :Zadejte prosím vaše jméno do žebříčku scénáře: +STR_2793 :{SMALLFONT}(Dosáhl: {STRINGID}) +STR_2794 :{WINDOW_COLOUR_2}Dosáhl: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2}s hodnotou společnosti: {BLACK}{CURRENCY} +STR_2795 :Seřadit +STR_2796 :{SMALLFONT}{BLACK}Seřadit seznam podle zobrazené informace +STR_2797 :Posouvat pohled při najetí myší k okraji +STR_2798 :{SMALLFONT}{BLACK}Vyberte, zda posouvat pohled když ukazatel myši narazí na hranu displeje +STR_2799 :{SMALLFONT}{BLACK}Zobrazit a upravit přiřazení controlu +STR_2800 :{WINDOW_COLOUR_2}Celkem vstupů: {BLACK}{COMMA32} +STR_2801 :{WINDOW_COLOUR_2}Příjem ze vstupů: {BLACK}{CURRENCY2DP} +STR_2802 :Mapa +STR_2803 :{SMALLFONT}{BLACK}Zobrazit tyto návštěvníky zvýrazněné na mapě +STR_2804 :{SMALLFONT}{BLACK}Zobrazit tento personál zvýrazněné na mapě +STR_2805 :{SMALLFONT}{BLACK}Zobazit mapu parku +STR_2806 :{RED}Návštěvníci si stěžují na odporné cesty v parku{NEWLINE}Zkontrolujte, kde jsou vaši údržbáři a zkuste je lépe organizovat +STR_2807 :{RED}Návštěvníci si stěžují na velké množství odpadků na zemi v parku{NEWLINE}Zkontrolujte, kde jsou vaši údržbáři a zkuste je lépe organizovat +STR_2808 :{RED}Návštěvníci si stěžují na vandaly v parku{NEWLINE}Zkontrolujte, kde jsou vaši hlídači a zkuste je lépe organizovat +STR_2809 :{RED}Návštěvníci mají hlad, ale nemohou najít žádné stánky s jídlem +STR_2810 :{RED}Návštěvníci mají žízeň, ale nemohou najít žádné stánky s pitím +STR_2811 :{RED}Návštěvníci si stěžují, protože nemohou najít v parku toalety +STR_2812 :{RED}Návštěvníci se v parku ztrácí{NEWLINE}Zkontrolujte strukturu cest a zkuste je lépe rozvrhnout +STR_2813 :{RED}Cena za vstup do parku je velmi vysoká!{NEWLINE}Snižtě cenu vstupu do parku, nebo zvyště hodnocení parku pro přilákání nových návštěvníků +STR_2814 :{WINDOW_COLOUR_2}Nejšpinavější park v zemi +STR_2815 :{WINDOW_COLOUR_2}Nejčistší park v zemi +STR_2816 :{WINDOW_COLOUR_2}Park s nejlepšími horskými drahami +STR_2817 :{WINDOW_COLOUR_2}Nejvýhodnější park v zemi +STR_2818 :{WINDOW_COLOUR_2}Nejkrásnější park v zemi +STR_2819 :{WINDOW_COLOUR_2}Nejméně výhodný park v zemi +STR_2820 :{WINDOW_COLOUR_2}Nejbezpečnější park v zemi +STR_2821 :{WINDOW_COLOUR_2}Park s nejlepším personálem +STR_2822 :{WINDOW_COLOUR_2}Park s nejlepším jídlem v zemi +STR_2823 :{WINDOW_COLOUR_2}Park s nejhorším jídlem v zemi +STR_2824 :{WINDOW_COLOUR_2}Park s nejlepšími toaletami v zemi +STR_2825 :{WINDOW_COLOUR_2}Park, který nejvíce zklamal +STR_2826 :{WINDOW_COLOUR_2}Park s nejlepšími vodními atrakcemi +STR_2827 :{WINDOW_COLOUR_2}Park s nejlépe samostatně navrženými atrakcemi +STR_2828 :{WINDOW_COLOUR_2}Ocenění za nejoslnivější barevné kombinace atrakcí +STR_2829 :{WINDOW_COLOUR_2}Nejzmateněji navržený park +STR_2830 :{WINDOW_COLOUR_2}Park s nejlepšími mírnými atrakcemi +STR_2831 :{TOPAZ}Váš park obdržel ocenění "Nejšpinavější park v zemi"! +STR_2832 :{TOPAZ}Váš park obdržel ocenění "Nejčistší park v zemi"! +STR_2833 :{TOPAZ}Váš park obdržel ocenění "Park s nejlepšími horskými drahami"! +STR_2834 :{TOPAZ}Váš park obdržel ocenění "Nejvýhodnější park v zemi"! +STR_2835 :{TOPAZ}Váš park obdržel ocenění "Nejkrásnější park v zemi"! +STR_2836 :{TOPAZ}Váš park obdržel ocenění "Nejméně výhodný park v zemi"! +STR_2837 :{TOPAZ}Váš park obdržel ocenění "Nejbezpečnější park v zemi"! +STR_2838 :{TOPAZ}Váš park obdržel ocenění "Park s nejlepším personálem"! +STR_2839 :{TOPAZ}Váš park obdržel ocenění "Park s nejlepším jídlem v zemi"! +STR_2840 :{TOPAZ}Váš park obdržel ocenění "Park s nejhorším jídlem v zemi"! +STR_2841 :{TOPAZ}Váš park obdržel ocenění "Park s nejlepšími toaletami v zemi"! +STR_2842 :{TOPAZ}Váš park obdržel ocenění "Park, který nejvíce zklamal"! +STR_2843 :{TOPAZ}Váš park obdržel ocenění "Park s nejlepšími vodními atrakcemi"! +STR_2844 :{TOPAZ}Váš park obdržel ocenění "Park s nejlépe samostatně navrženými atrakcemi"! +STR_2845 :{TOPAZ}Váš park obdržel ocenění "Ocenění za nejoslnivější barevné kombinace atrakcí"! +STR_2846 :{TOPAZ}Váš park obdržel ocenění "Nejzmateněji navržený park"! +STR_2847 :{TOPAZ}Váš park obdržel ocenění "Park s nejlepšími mírnými atrakcemi"! +STR_2848 :{WINDOW_COLOUR_2}Za poslední dobu žádné ocenění +STR_2849 :Nový scénář úspěšně nainstalován +STR_2850 :Nový návrh tratě úspěšně nainstalován +STR_2851 :Scénář už je nainstalovaný +STR_2852 :Návrh trati už je nainstalován +STR_2853 :Zakázáno místní správnou! +STR_2854 :{RED}Návštěvníci nemohou najít vstup do {STRINGID} !{NEWLINE}Postavte cestu k vstupu +STR_2855 :{RED}{STRINGID} nemá postavenou vestu z východu!{NEWLINE}Postavte cestu z východu atrakce STR_2856 :{WINDOW_COLOUR_2}Tutorial -STR_2857 :{WINDOW_COLOUR_2}(Press a key or mouse button to take control) -STR_2858 :Can't start marketing campaign... -STR_2859 :Another instance of OpenRCT2 is already running -STR_2860 :Infogrames Interactive credits... -STR_2861 :{WINDOW_COLOUR_2}Licensed to Infogrames Interactive Inc. -STR_2862 :Music acknowledgements... -STR_2863 :Music acknowledgements +STR_2857 :{WINDOW_COLOUR_2}(Stiskněte klávesu, nebo klikněte pro převzetí kontroly) +STR_2858 :Nelze zahájit reklamní kampań... +STR_2859 :OpenRCT2 už běží +STR_2860 :Infogrames Interactive poděkování... +STR_2861 :{WINDOW_COLOUR_2}Licencováno Infogrames Interactive Inc. +STR_2862 :Poděkování za hudbu... +STR_2863 :Poděkování za hudbu STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) non copyright STR_2865 :{WINDOW_COLOUR_2}Heyken's Serenade: (J.Heyken) British Standard Music Coy; GEMA, BRITICO STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Composer unknown) Copyright Control @@ -2978,31 +2979,31 @@ STR_2967 : STR_2968 : STR_2969 : STR_2970 : -STR_2971 :Main colour scheme -STR_2972 :Alternative colour scheme 1 -STR_2973 :Alternative colour scheme 2 -STR_2974 :Alternative colour scheme 3 -STR_2975 :{SMALLFONT}{BLACK}Select which colour scheme to change, or paint ride with -STR_2976 :{SMALLFONT}{BLACK}Paint an individual area of this ride using the selected colour scheme -STR_2977 :Staff member name -STR_2978 :Enter new name for this member of staff: -STR_2979 :Can't name staff member... -STR_2980 :Too many banners in game -STR_2981 :{RED}No entry - - -STR_2982 :Banner text -STR_2983 :Enter new text for this banner: -STR_2984 :Can't set new text for banner... -STR_2985 :Banner -STR_2986 :{SMALLFONT}{BLACK}Change text on banner -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_2992 :Sign text -STR_2993 :Enter new text for this sign: -STR_2994 :{SMALLFONT}{BLACK}Change text on sign -STR_2995 :{SMALLFONT}{BLACK}Demolish this sign +STR_2971 :Primární barevná kombinace +STR_2972 :Alternativní barevná kombinace 1 +STR_2973 :Alternativní barevná kombinace 2 +STR_2974 :Alternativní barevná kombinace 3 +STR_2975 :{SMALLFONT}{BLACK}Vyberte barevnou kombinaci, kterou chcete změnit, nebo aplikovat +STR_2976 :{SMALLFONT}{BLACK}Obarvit část atrakce vybranou barevnou kombinací +STR_2977 :Přejmenovat zaměstnance +STR_2978 :Zadejte nové jméno tohoto zaměstnance: +STR_2979 :Nelze přejmenovat zaměstnance... +STR_2980 :Příliš mnoho banerů ve hře +STR_2981 :{RED}Zákaz vstupu - - +STR_2982 :Text baneru +STR_2983 :Zadejte nový text baneru: +STR_2984 :Nelze změnit text baneru... +STR_2985 :Baner +STR_2986 :{SMALLFONT}{BLACK}Změnit text baneru +STR_2987 :{SMALLFONT}{BLACK}Nastavit tento baner jako "zákaz vstupu" pro návštěvníky +STR_2988 :{SMALLFONT}{BLACK}Zrušit baner +STR_2989 :{SMALLFONT}{BLACK}Vybrat hlavní barvu +STR_2990 :{SMALLFONT}{BLACK}Vybrat barvu textu +STR_2991 :Cedule +STR_2992 :Text cedule +STR_2993 :Zadejte nový text cedule: +STR_2994 :{SMALLFONT}{BLACK}Změnit text na ceduli +STR_2995 :{SMALLFONT}{BLACK}Zrušit ceduli STR_2996 :{BLACK}ABC STR_2997 :{GREY}ABC STR_2998 :{WHITE}ABC @@ -3017,151 +3018,151 @@ STR_3006 :{PALEGOLD}ABC STR_3007 :{LIGHTPINK}ABC STR_3008 :{PEARLAQUA}ABC STR_3009 :{PALESILVER}ABC -STR_3010 :Unable to load file... -STR_3011 :File contains invalid data -STR_3012 :Dodgems beat style -STR_3013 :Fairground organ style -STR_3014 :Roman fanfare style -STR_3015 :Oriental style -STR_3016 :Martian style -STR_3017 :Jungle drums style -STR_3018 :Egyptian style -STR_3019 :Toyland style +STR_3010 :Nepodařilo se načíst soubor... +STR_3011 :Soubor obsahuje neplatná data +STR_3012 :Autodrom +STR_3013 :Tržnice +STR_3014 :Římská fanfára +STR_3015 :Orient +STR_3016 :Marťan +STR_3017 :Jungle bubny +STR_3018 :Egypt +STR_3019 :Země hraček STR_3020 : -STR_3021 :Space style -STR_3022 :Horror style -STR_3023 :Techno style -STR_3024 :Gentle style -STR_3025 :Summer style -STR_3026 :Water style -STR_3027 :Wild west style -STR_3028 :Jurassic style -STR_3029 :Rock style -STR_3030 :Ragtime style -STR_3031 :Fantasy style -STR_3032 :Rock style 2 -STR_3033 :Ice style -STR_3034 :Snow style -STR_3035 :Custom music 1 -STR_3036 :Custom music 2 -STR_3037 :Medieval style -STR_3038 :Urban style -STR_3039 :Organ style -STR_3040 :Mechanical style -STR_3041 :Modern style -STR_3042 :Pirates style -STR_3043 :Rock style 3 -STR_3044 :Candy style -STR_3045 :{SMALLFONT}{BLACK}Select style of music to play -STR_3046 :This ride cannot be modified -STR_3047 :Local authority forbids demolition or modifications to this ride -STR_3048 :Marketing campaigns forbidden by local authority -STR_3049 :Golf hole A -STR_3050 :Golf hole B -STR_3051 :Golf hole C -STR_3052 :Golf hole D -STR_3053 :Golf hole E -STR_3054 :Loading... -STR_3055 :White -STR_3056 :Translucent -STR_3057 :{WINDOW_COLOUR_2}Construction Marker: -STR_3058 :Brick walls -STR_3059 :Hedges -STR_3060 :Ice blocks -STR_3061 :Wooden fences -STR_3062 :{SMALLFONT}{BLACK}Standard roller coaster track -STR_3063 :{SMALLFONT}{BLACK}Water channel (track submerged) -STR_3064 :Beginner Parks -STR_3065 :Challenging Parks -STR_3066 :Expert Parks -STR_3067 :{OPENQUOTES}Real{ENDQUOTES} Parks -STR_3068 :Other Parks -STR_3069 :Top Section -STR_3070 :Slope to Level -STR_3071 :{WINDOW_COLOUR_2}Same price throughout park -STR_3072 :{SMALLFONT}{BLACK}Select whether this price is used throughout the entire park -STR_3073 :{RED}WARNING: Your park rating has dropped below 700 !{NEWLINE}If you haven't raised the park rating in 4 weeks, your park will be closed down -STR_3074 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have 3 weeks to raise the park rating -STR_3075 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have only 2 weeks to raise the park rating, or your park will be closed down -STR_3076 :{RED}FINAL WARNING: Your park rating is still below 700 !{NEWLINE}In just 7 days your park will be closed down unless you can raise the rating -STR_3077 :{RED}CLOSURE NOTICE: Your park has been closed down ! -STR_3078 :Plain entrance -STR_3079 :Wooden entrance -STR_3080 :Canvas tent entrance -STR_3081 :Castle entrance (grey) -STR_3082 :Castle entrance (brown) -STR_3083 :Jungle entrance -STR_3084 :Log cabin entrance -STR_3085 :Classical/Roman entrance -STR_3086 :Abstract entrance -STR_3087 :Snow/Ice entrance -STR_3088 :Pagoda entrance -STR_3089 :Space entrance -STR_3090 :{SMALLFONT}{BLACK}Select style of entrance, exit, and station -STR_3091 :You are not allowed to remove this section! -STR_3092 :You are not allowed to move or modify the station for this ride! -STR_3093 :{WINDOW_COLOUR_2}Favourite: {BLACK}{STRINGID} +STR_3021 :Vesmír +STR_3022 :Horor +STR_3023 :Techno +STR_3024 :Mírná hudna +STR_3025 :Letní hudba +STR_3026 :Vodní +STR_3027 :Divoký západ +STR_3028 :Jurský styl +STR_3029 :Rock +STR_3030 :Ragtime +STR_3031 :Fantasy +STR_3032 :Rock 2 +STR_3033 :Led +STR_3034 :Sníh +STR_3035 :Vlastní hudba 1 +STR_3036 :Vlastní hudba 2 +STR_3037 :Středověk +STR_3038 :Urban +STR_3039 :Varhany +STR_3040 :Mechanika +STR_3041 :Moderní +STR_3042 :Piráti +STR_3043 :Rock 3 +STR_3044 :Sladkosti +STR_3045 :{SMALLFONT}{BLACK}Vyberte styl muziky, která bude hrát +STR_3046 :Tuto atrakci nelze upravovat +STR_3047 :Místní správa zakazuje úpravy a zrušení této atrakce +STR_3048 :Reklamní kampaně zakázány místní správou +STR_3049 :Jamka A +STR_3050 :Jamka B +STR_3051 :Jamka C +STR_3052 :Jamka D +STR_3053 :Jamka E +STR_3054 :Načítání... +STR_3055 :Bílá +STR_3056 :Průhledná +STR_3057 :{WINDOW_COLOUR_2}Barva návrhu výstavby: +STR_3058 :Cihlová zeď +STR_3059 :Živý plot +STR_3060 :Kusy ledu +STR_3061 :Dřevený plot +STR_3062 :{SMALLFONT}{BLACK}Standardní trať horské dráhy +STR_3063 :{SMALLFONT}{BLACK}Vodní kanál (trať potopena) +STR_3064 :Začátečnické parky +STR_3065 :Středně obtížné parky +STR_3066 :Parky pro experty +STR_3067 :{OPENQUOTES}Skutečné{ENDQUOTES} parky +STR_3068 :Ostatní parky +STR_3069 :Top výběr +STR_3070 :Přechod sklonu do roviny +STR_3071 :{WINDOW_COLOUR_2}Stejná cena všude v parku +STR_3072 :{SMALLFONT}{BLACK}Nastaví stejnou cenu všude v parku +STR_3073 :{RED}POZOR: Hodnocení parku kleslo pod 700!{NEWLINE}Pokud hodnocení nestoupne do 4 týdnů, park bude uzavřen +STR_3074 :{RED}POZOR: Hodnocení parku je stále nižší, než 700!{NEWLINE}Máte 3 týdny na zvýšení hodnocení parku +STR_3075 :{RED}POZOR: Hodnocení parku je stále nižší, než 700!{NEWLINE}Máte už jen 2 týdny na zvýšení hodnocení parku, nebo bude park uzavřen +STR_3076 :{RED}POSLEDNÍ VAROVÁNÍ: Hodnocení parku je stále nižší, než 700!{NEWLINE}Za pouhých 7 dní dojde k uzavření parku, pokud do té doby nezvýšíte hodnocení +STR_3077 :{RED}OZNÁMENÍ O UZAVŘENÍ: Zábavní park byl uzavřen! +STR_3078 :Obyčejný +STR_3079 :Dřevěný +STR_3080 :Plátěný stan +STR_3081 :Hradní věž (šedá) +STR_3082 :Hradní věž (hnědá) +STR_3083 :Jungle +STR_3084 :Dřevěná chata +STR_3085 :Klasika/Římský styl +STR_3086 :Abstraktní +STR_3087 :Sníh/led +STR_3088 :Pagoda +STR_3089 :Vesmír +STR_3090 :{SMALLFONT}{BLACK}Vyberte styl vchodu, východu a stanice +STR_3091 :Není dovoleno odebrat tuto stanici +STR_3092 :Není dovoleno přesouvat nebo modifikovat tuto stanici +STR_3093 :{WINDOW_COLOUR_2}Nejoblíbenější: {BLACK}{STRINGID} STR_3094 :N/A -STR_3095 :{WINDOW_COLOUR_2}Lift hill chain speed: +STR_3095 :{WINDOW_COLOUR_2}Rychlost řetězového výtahu: STR_3096 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} -STR_3097 :{SMALLFONT}{BLACK}Select lift hill chain speed -STR_3098 :Can't change lift hill speed... -STR_3099 :{SMALLFONT}{BLACK}Select colour -STR_3100 :{SMALLFONT}{BLACK}Select second colour -STR_3101 :{SMALLFONT}{BLACK}Select third colour -STR_3102 :{SMALLFONT}{BLACK}Re-paint coloured scenery on landscape -STR_3103 :Can't re-paint this... -STR_3104 :{SMALLFONT}{BLACK}List rides -STR_3105 :{SMALLFONT}{BLACK}List shops and stalls -STR_3106 :{SMALLFONT}{BLACK}List information kiosks and other guest facilities -STR_3107 :Close -STR_3108 :Test -STR_3109 :Open -STR_3110 :{WINDOW_COLOUR_2}Block Sections: {BLACK}{COMMA16} -STR_3111 :{SMALLFONT}{BLACK}Click on design to build it -STR_3112 :{SMALLFONT}{BLACK}Click on design to rename or delete it -STR_3113 :Select a different design -STR_3114 :{SMALLFONT}{BLACK}Go back to design selection window -STR_3115 :{SMALLFONT}{BLACK}Save track design -STR_3116 :{SMALLFONT}{BLACK}Save track design (Not possible until ride has been tested and statistics have been generated) -STR_3117 :{BLACK}Calling mechanic... -STR_3118 :{BLACK}{STRINGID} is heading for the ride -STR_3119 :{BLACK}{STRINGID} is fixing the ride -STR_3120 :{SMALLFONT}{BLACK}Locate nearest available mechanic, or mechanic fixing ride -STR_3121 :Unable to locate mechanic, or all nearby mechanics are busy -STR_3122 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guest -STR_3123 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guests -STR_3124 :Broken {STRINGID} -STR_3125 :{WINDOW_COLOUR_2}Excitement Factor: {BLACK}+{COMMA16}% -STR_3126 :{WINDOW_COLOUR_2}Intensity Factor: {BLACK}+{COMMA16}% -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_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) -STR_3135 :{RED}(Vehicle design unavailable - Ride performance may be affected) -STR_3136 :Warning: This design will be built with an alternative vehicle type and may not perform as expected -STR_3137 :Select Nearby Scenery -STR_3138 :Reset Selection -STR_3139 :Cable lift unable to work in this operating mode -STR_3140 :Cable lift hill must start immediately after station -STR_3141 :Multi-circuit per ride not possible with cable lift hill -STR_3142 :{WINDOW_COLOUR_2}Capacity: {BLACK}{STRINGID} -STR_3143 :{SMALLFONT}{BLACK}Show people on map -STR_3144 :{SMALLFONT}{BLACK}Show rides and stalls on map -STR_3145 :{SMALLFONT}{BLACK}Scroll {STRINGID} left -STR_3146 :{SMALLFONT}{BLACK}Scroll {STRINGID} right -STR_3147 :{SMALLFONT}{BLACK}Scroll {STRINGID} left fast -STR_3148 :{SMALLFONT}{BLACK}Scroll {STRINGID} right fast -STR_3149 :{SMALLFONT}{BLACK}Scroll {STRINGID} left/right -STR_3150 :{SMALLFONT}{BLACK}Scroll {STRINGID} up -STR_3151 :{SMALLFONT}{BLACK}Scroll {STRINGID} down -STR_3152 :{SMALLFONT}{BLACK}Scroll {STRINGID} up fast -STR_3153 :{SMALLFONT}{BLACK}Scroll {STRINGID} down fast -STR_3154 :{SMALLFONT}{BLACK}Scroll {STRINGID} up/down +STR_3097 :{SMALLFONT}{BLACK}Vyberte rychlost řetězového výtahu +STR_3098 :Rychlost řetězového výtahu nelze změnit... +STR_3099 :{SMALLFONT}{BLACK}Vyberte barvu +STR_3100 :{SMALLFONT}{BLACK}Vyberte sekundární barvu +STR_3101 :{SMALLFONT}{BLACK}Vyberte terciální barvu +STR_3102 :{SMALLFONT}{BLACK}Přebarvit kulisy v krajině +STR_3103 :Nelze přemalovat... +STR_3104 :{SMALLFONT}{BLACK}Seznam atrakcí +STR_3105 :{SMALLFONT}{BLACK}Seznam obchodů a stánků +STR_3106 :{SMALLFONT}{BLACK}Seznam kiosků a jiných zařízení +STR_3107 :Zavřít +STR_3108 :Testovat +STR_3109 :Otevřít +STR_3110 :{WINDOW_COLOUR_2}Block sekces: {BLACK}{COMMA16} +STR_3111 :{SMALLFONT}{BLACK}Pro postavení klikněte na návrh +STR_3112 :{SMALLFONT}{BLACK}Pro přejmenování nebo smazaní klikněte na návrh +STR_3113 :Vybrat jiný návrh +STR_3114 :{SMALLFONT}{BLACK}Jít zpět do okna výběru návrhů +STR_3115 :{SMALLFONT}{BLACK}Uložit návrh trati +STR_3116 :{SMALLFONT}{BLACK}Uložit návrh trati (Možné pouze po otestování trati a naměření hodnot) +STR_3117 :{BLACK}Volá se mechanik... +STR_3118 :{BLACK}{STRINGID} jde k atrakci +STR_3119 :{BLACK}{STRINGID} opravuje atrakci +STR_3120 :{SMALLFONT}{BLACK}Najít nejbližsího dostupného mechanika, nebo mechanika, který tuto atrakci právě opravuje +STR_3121 :Nepodařilo se najít dostupného mechanika +STR_3122 :{WINDOW_COLOUR_2}Oblíbená atrakce {BLACK}{COMMA16} návštěvníka +STR_3123 :{WINDOW_COLOUR_2}Oblíbená atrakce {BLACK}{COMMA16} návštěvníků +STR_3124 :Porucha na {STRINGID} +STR_3125 :{WINDOW_COLOUR_2}Faktor nadšení: {BLACK}+{COMMA16}% +STR_3126 :{WINDOW_COLOUR_2}Faktor intenzity: {BLACK}+{COMMA16}% +STR_3127 :{WINDOW_COLOUR_2}Faktor nevolnosti: {BLACK}+{COMMA16}% +STR_3128 :Uložit návrh trati +STR_3129 :Uložit návrh trati s kulisami +STR_3130 :Uložit +STR_3131 :Zrušit +STR_3132 :{BLACK}Klikněte na kulisy, které chcete uložit společně s tratí... +STR_3133 :Toto nelze postavit na trati se sklonem +STR_3134 :{RED}(Návrh obsahuje kulisy, které nejsou dostupné) +STR_3135 :{RED}(Návrh vozů nedostupný - může ovlivnit výkon atrakce) +STR_3136 :Varování: Tento návrh bude postaven s alternativními vozy, které se mohou chovat jinak, než zamýšleno +STR_3137 :Vyberte okolní kulisy +STR_3138 :Zrušit výběr +STR_3139 :Řetězový výtah nefunguje v tomto provozním módu +STR_3140 :Řetězový výtah musí začít hned za stanicí +STR_3141 :Více koleček za jízdu není přípustné současně s řetězovým výtahem +STR_3142 :{WINDOW_COLOUR_2}Kapacita: {BLACK}{STRINGID} +STR_3143 :{SMALLFONT}{BLACK}Zobrazit návštěvníky na mapě +STR_3144 :{SMALLFONT}{BLACK}Zobrazit atrakce a stánky na mapě +STR_3145 :{SMALLFONT}{BLACK}Posunout {STRINGID} vlevo +STR_3146 :{SMALLFONT}{BLACK}Posunout {STRINGID} vpravo +STR_3147 :{SMALLFONT}{BLACK}Posunout {STRINGID} rychle vlevo +STR_3148 :{SMALLFONT}{BLACK}Posunout {STRINGID} rychle vpravo +STR_3149 :{SMALLFONT}{BLACK}Posunout {STRINGID} vlevo/vpravo +STR_3150 :{SMALLFONT}{BLACK}Posunout {STRINGID} nahoru +STR_3151 :{SMALLFONT}{BLACK}Posunout {STRINGID} dolů +STR_3152 :{SMALLFONT}{BLACK}Posunout {STRINGID} nahoru rychle +STR_3153 :{SMALLFONT}{BLACK}Posunout {STRINGID} dolů rychle +STR_3154 :{SMALLFONT}{BLACK}Posunout {STRINGID} nahoru/dolů STR_3155 : STR_3156 : STR_3157 :map @@ -3169,235 +3170,235 @@ STR_3158 :graph STR_3159 :list STR_3160 : STR_3161 : -STR_3162 :Unable to allocate enough memory -STR_3163 :Installing new data: -STR_3164 :{BLACK}{COMMA16} selected (maximum {COMMA16}) +STR_3162 :Nepodařilo se alokovat dostatek paměti +STR_3163 :Instaluji nová data: +STR_3164 :{BLACK}{COMMA16} vybráno (maximum {COMMA16}) STR_3165 : STR_3166 :{BLACK}(ID: -STR_3167 :{WINDOW_COLOUR_2}Includes: {BLACK}{COMMA16} objects +STR_3167 :{WINDOW_COLOUR_2}Včetně: {BLACK}{COMMA16} objektů STR_3168 :{WINDOW_COLOUR_2}Text: {BLACK}{STRINGID} -STR_3169 :Data for the following object not found: -STR_3170 :Not enough space for graphics -STR_3171 :Too many objects of this type selected -STR_3172 :The following object must be selected first: {STRING} -STR_3173 :This object is currently in use -STR_3174 :This object is required by another object -STR_3175 :This object is always required -STR_3176 :Unable to select this object -STR_3177 :Unable to de-select this object -STR_3178 :At least one path object must be selected -STR_3179 :At least one ride vehicle/attraction object must be selected -STR_3180 :Invalid selection of objects -STR_3181 :Object Selection - {STRINGID} -STR_3182 :Park entrance type must be selected -STR_3183 :Water type must be selected -STR_3184 :Ride Vehicles/Attractions -STR_3185 :Small Scenery -STR_3186 :Large Scenery -STR_3187 :Walls/Fences -STR_3188 :Path Signs -STR_3189 :Footpaths -STR_3190 :Path Extras -STR_3191 :Scenery Groups -STR_3192 :Park Entrance -STR_3193 :Water -STR_3194 :Scenario Description -STR_3195 :Invention List -STR_3196 :{WINDOW_COLOUR_2}Research Group: {BLACK}{STRINGID} -STR_3197 :{WINDOW_COLOUR_2}Items pre-invented at start of game: -STR_3198 :{WINDOW_COLOUR_2}Items to invent during game: -STR_3199 :Random Shuffle -STR_3200 :{SMALLFONT}{BLACK}Randomly shuffle the list of items to invent during the game -STR_3201 :Object Selection -STR_3202 :Landscape Editor -STR_3203 :Invention List Set Up -STR_3204 :Options Selection -STR_3205 :Objective Selection -STR_3206 :Save Scenario -STR_3207 :Roller Coaster Designer -STR_3208 :Track Designs Manager -STR_3209 :Back to Previous Step: -STR_3210 :Forward to Next Step: -STR_3211 :{WINDOW_COLOUR_2}Map size: +STR_3169 :Nebyly nalezeny data pro následující objekt: +STR_3170 :Nedostatek místa pro grafiku +STR_3171 :Vybráno příliš mnoho objektů tohoto typu +STR_3172 :Napřed musí být vybrán tento objekt: {STRING} +STR_3173 :Tento objekt se momentálně používá +STR_3174 :Tento objekt je vyžadován jiným objektem +STR_3175 :Tento objekt je vždy vyžadován +STR_3176 :Nelze vybrat objekt +STR_3177 :Nelze zrušit výběr objektu +STR_3178 :Alespoň jeden objekt cesty musí být vybrán +STR_3179 :Alespoň jeden objekt atrakce musí být vybrán +STR_3180 :Neplatný výběr objektů +STR_3181 :Výběr objektu - {STRINGID} +STR_3182 :Vstup do parku musí být vybraný +STR_3183 :Typ vodních ploch musí být vybraný +STR_3184 :Vozy/atrakce +STR_3185 :Malé kulisy +STR_3186 :Velké kulisy +STR_3187 :Stěny/ploty +STR_3188 :Cedule u cest +STR_3189 :Cesty +STR_3190 :Doplňky cest +STR_3191 :Skupiny kulis +STR_3192 :Vstup do parku +STR_3193 :Voda +STR_3194 :Popis scénáře +STR_3195 :Seznam výzkumů +STR_3196 :{WINDOW_COLOUR_2}Skupina výzkumu: {BLACK}{STRINGID} +STR_3197 :{WINDOW_COLOUR_2}Položky vyzkoumané před začátem hry: +STR_3198 :{WINDOW_COLOUR_2}Položky k vyzkoumání během hry: +STR_3199 :Náhodně zamíchat +STR_3200 :{SMALLFONT}{BLACK}Náhodně zamíchá seznam položek k vyzkoumání během hry +STR_3201 :Výběr objektů +STR_3202 :Editor krajiny +STR_3203 :Nastavení seznamu výkumu +STR_3204 :Výběr nastavení +STR_3205 :Výběr cílů +STR_3206 :Uložit scénář +STR_3207 :Návrh horské dráhy +STR_3208 :Správa návrhů tratí +STR_3209 :Zpět k předchozímu kroku: +STR_3210 :Jít na následující krok: +STR_3211 :{WINDOW_COLOUR_2}Velikost mapy: STR_3212 :{POP16}{COMMA16} x {PUSH16}{COMMA16} -STR_3213 :Can't decrease map size any further -STR_3214 :Can't increase map size any further -STR_3215 :Too close to edge of map -STR_3216 :{SMALLFONT}{BLACK}Select park-owned land etc. -STR_3217 :Land Owned -STR_3218 :Construction Rights Owned -STR_3219 :Land For Sale -STR_3220 :Construction Rights For Sale -STR_3221 :{SMALLFONT}{BLACK}Set land to be owned by the park -STR_3222 :{SMALLFONT}{BLACK}Set construction rights only to be owned by the park -STR_3223 :{SMALLFONT}{BLACK}Set land to be available to purchase by the park -STR_3224 :{SMALLFONT}{BLACK}Set construction rights to be available to purchase by the park -STR_3225 :{SMALLFONT}{BLACK}Toggle on/off building a random cluster of objects around the selected position -STR_3226 :{SMALLFONT}{BLACK}Build park entrance -STR_3227 :Too many park entrances! -STR_3228 :{SMALLFONT}{BLACK}Set starting positions for people -STR_3229 :Block Brakes cannot be used directly after station -STR_3230 :Block Brakes cannot be used directly after each other -STR_3231 :Block Brakes cannot be used directly after the top of this lift hill -STR_3232 :Options - Financial -STR_3233 :Options - Guests -STR_3234 :Options - Park -STR_3235 :{SMALLFONT}{BLACK}Show financial options -STR_3236 :{SMALLFONT}{BLACK}Show guest options -STR_3237 :{SMALLFONT}{BLACK}Show park options -STR_3238 :No Money -STR_3239 :{SMALLFONT}{BLACK}Make this park a 'no money' park with no financial restrictions -STR_3240 :{WINDOW_COLOUR_2}Initial cash: -STR_3241 :{WINDOW_COLOUR_2}Initial loan: -STR_3242 :{WINDOW_COLOUR_2}Maximum loan size: -STR_3243 :{WINDOW_COLOUR_2}Annual interest rate: -STR_3244 :Forbid marketing campaigns -STR_3245 :{SMALLFONT}{BLACK}Forbid advertising, promotional schemes, and other marketing campaigns +STR_3213 :Mapu nelze více zmenšit +STR_3214 :Mapu nelze více zvětšit +STR_3215 :Příliš blízko u kraje mapy +STR_3216 :{SMALLFONT}{BLACK}Výběr pozemků parku atd. +STR_3217 :Vlastněné pozemky +STR_3218 :Zakoupená stavební práva +STR_3219 :Pozemky na prodej +STR_3220 :Stavební práva na prodej +STR_3221 :{SMALLFONT}{BLACK}Nastavit pozemky vlastněné parkem +STR_3222 :{SMALLFONT}{BLACK}Nastavit stavební práva vlastněná parkem +STR_3223 :{SMALLFONT}{BLACK}Nastavit pozemky možné dokoupit k parku +STR_3224 :{SMALLFONT}{BLACK}Nastavit stavební práva možná k dokoupení parkem +STR_3225 :{SMALLFONT}{BLACK}Přepnout stavění skupiny náhodných objektů okolo vybrané pozice +STR_3226 :{SMALLFONT}{BLACK}Postavit vstup do parku +STR_3227 :Příliš mnoho vstupů do parku +STR_3228 :{SMALLFONT}{BLACK}Nastavit počáteční pozice návštěvníků +STR_3229 :Brzdící bloky nelze použít hned za stanicí +STR_3230 :Brzdící bloky nelze použít v řadě za sebou +STR_3231 :Brzdící bloky nelze použít hned za řetězovým výtahem +STR_3232 :Nastavení - Finance +STR_3233 :Nastavení - Návštěvníci +STR_3234 :Nastavení - Park +STR_3235 :{SMALLFONT}{BLACK}Zobrazit nastavení financí +STR_3236 :{SMALLFONT}{BLACK}Zobrazit nastavení návštěvníků +STR_3237 :{SMALLFONT}{BLACK}Zobrazit nastavení parku +STR_3238 :Bez peněz +STR_3239 :{SMALLFONT}{BLACK}Nebrat ohled na peníze - bez finančních omezení +STR_3240 :{WINDOW_COLOUR_2}Počátační kapitál: +STR_3241 :{WINDOW_COLOUR_2}Počáteční půjčka: +STR_3242 :{WINDOW_COLOUR_2}Maximální půjčka: +STR_3243 :{WINDOW_COLOUR_2}Každoroční úrok: +STR_3244 :Zákaz reklamních kampaní +STR_3245 :{SMALLFONT}{BLACK}Zákaz reklamy, kuponů a ostatních marketingových kampaní STR_3246 :{WINDOW_COLOUR_2}{CURRENCY} STR_3247 :{WINDOW_COLOUR_2}{COMMA16}% -STR_3248 :Can't increase initial cash any further! -STR_3249 :Can't reduce initial cash any further! -STR_3250 :Can't increase initial loan any further! -STR_3251 :Can't reduce initial loan any further! -STR_3252 :Can't increase maximum loan size any further! -STR_3253 :Can't reduce maximum loan size any further! -STR_3254 :Can't increase interest rate any further! -STR_3255 :Can't reduce interest rate any further! -STR_3256 :Guests prefer less intense rides -STR_3257 :{SMALLFONT}{BLACK}Select whether guests should generally prefer less intense rides only -STR_3258 :Guests prefer more intense rides -STR_3259 :{SMALLFONT}{BLACK}Select whether guests should generally prefer more intense rides only -STR_3260 :{WINDOW_COLOUR_2}Cash per guest (average): -STR_3261 :{WINDOW_COLOUR_2}Guests initial happiness: -STR_3262 :{WINDOW_COLOUR_2}Guests initial hunger: -STR_3263 :{WINDOW_COLOUR_2}Guests initial thirst: -STR_3264 :Can't increase this any further! -STR_3265 :Can't reduce this any further! -STR_3266 :{SMALLFONT}{BLACK}Select how this park charges for entrance and rides -STR_3267 :Forbid tree removal -STR_3268 :{SMALLFONT}{BLACK}Forbid tall trees being removed -STR_3269 :Forbid landscape changes -STR_3270 :{SMALLFONT}{BLACK}Forbid any changes to the landscape -STR_3271 :Forbid high construction -STR_3272 :{SMALLFONT}{BLACK}Forbid any tall construction -STR_3273 :Park rating higher difficult level -STR_3274 :{SMALLFONT}{BLACK}Make the park rating value more challenging -STR_3275 :Guest generation higher difficult level -STR_3276 :{SMALLFONT}{BLACK}Make it more difficult to attract guests to the park -STR_3277 :{WINDOW_COLOUR_2}Cost to buy land: -STR_3278 :{WINDOW_COLOUR_2}Cost to buy construction rights: -STR_3279 :Free park entry / Pay per ride -STR_3280 :Pay to enter park / Free rides -STR_3281 :{WINDOW_COLOUR_2}Entry price: -STR_3282 :{SMALLFONT}{BLACK}Select objective and park name -STR_3283 :{SMALLFONT}{BLACK}Select rides to be preserved -STR_3284 :Objective Selection -STR_3285 :Preserved Rides -STR_3286 :{SMALLFONT}{BLACK}Select objective for this scenario -STR_3287 :{WINDOW_COLOUR_2}Objective: -STR_3288 :{SMALLFONT}{BLACK}Select climate -STR_3289 :{WINDOW_COLOUR_2}Climate: -STR_3290 :Cool and wet -STR_3291 :Warm -STR_3292 :Hot and dry -STR_3293 :Cold -STR_3294 :Change... -STR_3295 :{SMALLFONT}{BLACK}Change name of park -STR_3296 :{SMALLFONT}{BLACK}Change name of scenario -STR_3297 :{SMALLFONT}{BLACK}Change detail notes about park / scenario -STR_3298 :{WINDOW_COLOUR_2}Park Name: {BLACK}{STRINGID} -STR_3299 :{WINDOW_COLOUR_2}Park/Scenario Details: -STR_3300 :{WINDOW_COLOUR_2}Scenario Name: {BLACK}{STRINGID} -STR_3301 :{WINDOW_COLOUR_2}Objective Date: +STR_3248 :Nelze zvýšit základní kapitál! +STR_3249 :Nelze snížit základní kapitál! +STR_3250 :Nelze zvýšit základní půjčku! +STR_3251 :Nelze snížit základní půjčku! +STR_3252 :Nelze zvýšit maximální půjčku! +STR_3253 :Nelze snížit maximální půjčku! +STR_3254 :Nelze zvýšit úrok půjčky! +STR_3255 :Nelze snížit úrok půjčky! +STR_3256 :Návštěvníci preferují mírnější atrakce +STR_3257 :{SMALLFONT}{BLACK}Vyberte, zda návštěvníci mají obecně preferovat jen mírnější atrakce +STR_3258 :Návštěvníci preferují divočejší atrakce +STR_3259 :{SMALLFONT}{BLACK}Vyberte, zda návštěvníci mají obecně preferovat jen divočejší atrakce +STR_3260 :{WINDOW_COLOUR_2}Průměrná hotovost návštěvníků: +STR_3261 :{WINDOW_COLOUR_2}Počáteční nálada návštěvníků: +STR_3262 :{WINDOW_COLOUR_2}Počáteční hlad návštěvníků: +STR_3263 :{WINDOW_COLOUR_2}Počáteční žízeň návštěvníků: +STR_3264 :Toto nastavení již nelze více zvýšit! +STR_3265 :Toto nastavení již nelze více snížit! +STR_3266 :{SMALLFONT}{BLACK}Vyberte systém zpoplatnění parku +STR_3267 :Zákaz kácení stromů +STR_3268 :{SMALLFONT}{BLACK}Vysoké stromy nelze odstranit +STR_3269 :Zakázat změny terénu +STR_3270 :{SMALLFONT}{BLACK}Krajina nesmí být nijak upravována +STR_3271 :Zakázat výškové stavby +STR_3272 :{SMALLFONT}{BLACK}Zákaz jakýchkoliv vysokých konstrukcí +STR_3273 :Těžsí zisk hodnocení parku +STR_3274 :{SMALLFONT}{BLACK}Těžší získat dobré hodnocení parku +STR_3275 :Těžsí lákání zákazníků +STR_3276 :{SMALLFONT}{BLACK}Těžší nalákání zákazníků do parku +STR_3277 :{WINDOW_COLOUR_2}Cena zakoupení pozemku: +STR_3278 :{WINDOW_COLOUR_2}Cena zakoupení staveních práv: +STR_3279 :Vstup zdarma / placené atrakce +STR_3280 :Placený vstup / atrakce zdarma +STR_3281 :{WINDOW_COLOUR_2}Cena za vstup: +STR_3282 :{SMALLFONT}{BLACK}Vyberte cíl a název parku +STR_3283 :{SMALLFONT}{BLACK}Vyberte atrakce, které zůstanou zachovány +STR_3284 :Výběr cílů +STR_3285 :Zachované atrakce +STR_3286 :{SMALLFONT}{BLACK}Vývěr cíle scénáře +STR_3287 :{WINDOW_COLOUR_2}Cíl: +STR_3288 :{SMALLFONT}{BLACK}Výběr klimatu +STR_3289 :{WINDOW_COLOUR_2}Klima: +STR_3290 :Chladno a mokro +STR_3291 :Teplo +STR_3292 :Horko a sucho +STR_3293 :Chladno +STR_3294 :Změnit... +STR_3295 :{SMALLFONT}{BLACK}Změnit název parku +STR_3296 :{SMALLFONT}{BLACK}Změnit název scénáře +STR_3297 :{SMALLFONT}{BLACK}Změnit podrobnosti parku/scénáře +STR_3298 :{WINDOW_COLOUR_2}Název parku: {BLACK}{STRINGID} +STR_3299 :{WINDOW_COLOUR_2}Detaily parku/scénáře: +STR_3300 :{WINDOW_COLOUR_2}Název scénáře: {BLACK}{STRINGID} +STR_3301 :{WINDOW_COLOUR_2}Datum cíle: STR_3302 :{WINDOW_COLOUR_2}{MONTHYEAR} -STR_3303 :{WINDOW_COLOUR_2}Number of guests: -STR_3304 :{WINDOW_COLOUR_2}Park value: -STR_3305 :{WINDOW_COLOUR_2}Monthly income: -STR_3306 :{WINDOW_COLOUR_2}Monthly profit: -STR_3307 :{WINDOW_COLOUR_2}Minimum length: -STR_3308 :{WINDOW_COLOUR_2}Excitement rating: +STR_3303 :{WINDOW_COLOUR_2}Počet návštěvníků: +STR_3304 :{WINDOW_COLOUR_2}Hodnota parku: +STR_3305 :{WINDOW_COLOUR_2}Měsíční příjem: +STR_3306 :{WINDOW_COLOUR_2}Měsíční zisk: +STR_3307 :{WINDOW_COLOUR_2}Minimální délka: +STR_3308 :{WINDOW_COLOUR_2}Nadšení: STR_3309 :{WINDOW_COLOUR_2}{COMMA16} STR_3310 :{WINDOW_COLOUR_2}{LENGTH} STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} -STR_3312 :{WINDOW_COLOUR_2}Rides/attractions under a preservation order: -STR_3313 :Scenario Name -STR_3314 :Enter name for scenario: -STR_3315 :Park/Scenario Details -STR_3316 :Enter description of this scenario: -STR_3317 :No details yet -STR_3318 :{SMALLFONT}{BLACK}Select which group this scenario appears in -STR_3319 :{WINDOW_COLOUR_2}Scenario Group: -STR_3320 :Unable to save scenario file... -STR_3321 :New objects installed successfully -STR_3322 :{WINDOW_COLOUR_2}Objective: {BLACK}{STRINGID} -STR_3323 :Missing object data, ID: -STR_3324 :Requires Add-On Pack: -STR_3325 :Requires an Add-On Pack -STR_3326 :{WINDOW_COLOUR_2}(no image) -STR_3327 :Starting positions for people not set -STR_3328 :Can't advance to next editor stage... -STR_3329 :Park entrance not yet built -STR_3330 :Park must own some land -STR_3331 :Path from park entrance to map edge either not complete or too complex - Path must be single-width with as few junctions and corners as possible -STR_3332 :Park entrance is the wrong way round or has no path leading to the map edge -STR_3333 :Export plug-in objects with saved games -STR_3334 :{SMALLFONT}{BLACK}Select whether to save any additional plug-in object data required (add-in data not supplied with the main product) in saved game or scenario files, allowing them to be loaded by someone who doesn't have the additional object data -STR_3335 :Roller Coaster Designer - Select Ride Types & Vehicles -STR_3336 :Track Designs Manager - Select Ride Type +STR_3312 :{WINDOW_COLOUR_2}Atrakce, které je nutno zachovat: +STR_3313 :Název scénáře +STR_3314 :Zadejte název scénáře: +STR_3315 :Detaily parku/scénáře +STR_3316 :Zadejte popis scénáře: +STR_3317 :Zatím bez detailů +STR_3318 :{SMALLFONT}{BLACK}Vyberte skupinu scénářů +STR_3319 :{WINDOW_COLOUR_2}Skupina scénářů: +STR_3320 :Nepodařilo se uložit scénář... +STR_3321 :Nové objekty byly úspěšně nainstalovány +STR_3322 :{WINDOW_COLOUR_2}Cíl scénáře: {BLACK}{STRINGID} +STR_3323 :Chybějící data objektu, ID: +STR_3324 :Vyžaduje Add-On Pack: {STRINGID} +STR_3325 :Vyžaduje Add-On Pack +STR_3326 :{WINDOW_COLOUR_2}(bez obrázku) +STR_3327 :Nenastavena počáteční pozice návštěvníků +STR_3328 :Nelze přejít k dalšímu kroku... +STR_3329 :Není postaven vstup do parku +STR_3330 :Park nevlastní žádné pozemky +STR_3331 :Cesta od vstupu do parku k hraně mapy není kompletní, nebo je příliš složitá - Cesta musí být široká jednu dlaždici a mít co nejméně zatáček a křižovatek +STR_3332 :Vstup do parku je špatně otočený, nebo z něj nevede cesta k hraně mapy +STR_3333 :Exportovat plug-in objekty s uložením hry +STR_3334 :{SMALLFONT}{BLACK}Vyberte, zda ukládat data plug-in objektů (add-in data nejsou dodána s hlavním produktem) do souborů uložených her a scénářů, což dovolí jejích načítání na těmi, kdo nemají tyto dodatečná data objektů. +STR_3335 :Návrh horské dráhy - Vyberte typ atrake a vozů +STR_3336 :Správa návrhu trati - Vyberte typ trati STR_3337 : -STR_3338 :{BLACK}Custom-designed layout -STR_3339 :{BLACK}{COMMA16} design available, or custom-designed layout -STR_3340 :{BLACK}{COMMA16} designs available, or custom-designed layout -STR_3341 :{SMALLFONT}{BLACK}Game tools -STR_3342 :Scenario Editor -STR_3343 :Convert Saved Game to Scenario -STR_3344 :Roller Coaster Designer -STR_3345 :Track Designs Manager -STR_3346 :Can't save track design... -STR_3347 :Ride is too large, contains too many elements, or scenery is too spread out -STR_3348 :Rename -STR_3349 :Delete -STR_3350 :Track design name -STR_3351 :Enter new name for this track design: -STR_3352 :Can't rename track design... -STR_3353 :New name contains invalid characters -STR_3354 :Another file exists with this name, or file is write-protected -STR_3355 :File is write-protected or locked -STR_3356 :Delete File -STR_3357 :{WINDOW_COLOUR_2}Are you sure you want to permanently delete {STRINGID} ? -STR_3358 :Can't delete track design... -STR_3359 :{BLACK}No track designs of this type -STR_3360 :Warning! -STR_3361 :Too many track designs of this type - Some will not be listed. +STR_3338 :{BLACK}Vlastnoručně navržné +STR_3339 :{BLACK}{COMMA16} návrh dostupný, nebo vlastnoručně narvržený +STR_3340 :{BLACK}{COMMA16} návrhy dostupné, nebo vlastnoručně narvrženy +STR_3341 :{SMALLFONT}{BLACK}Herní nástroje +STR_3342 :Editor scénáře +STR_3343 :Konvertovat uloženou hru na scénář +STR_3344 :Návrh horské dráhy +STR_3345 :Správa návrhu trati +STR_3346 :Nelze uložit návrh trati... +STR_3347 :Trať je příliš velká, obsahuje příliš mnoho prvků, nebo příliš rozsáhlé kulisy +STR_3348 :Přejmenovat +STR_3349 :Odstranit +STR_3350 :Název návrhu trati +STR_3351 :Zadejte jméno návrhu tratě: +STR_3352 :Nelze přejmenovat návrh tratě... +STR_3353 :Nový název obsahuje neplatné znaky +STR_3354 :Existuje soubor se stejným jménem, nebo je soubor jen pro čtení +STR_3355 :Soubor je jen pro čtení, nebo zamčený +STR_3356 :Smazat soubor +STR_3357 :{WINDOW_COLOUR_2}Opravdu chcete nevratně odstranit {STRINGID} ? +STR_3358 :Nelze odstranit návrh trati... +STR_3359 :{BLACK}Žádné návrhy tratí tohoto typu +STR_3360 :Pozor! +STR_3361 :Příliš mnoho návrhů tratí tohoto typu - některé nejsou zobrazeny. STR_3362 : STR_3363 : -STR_3364 :Advanced -STR_3365 :{SMALLFONT}{BLACK}Allow selection of individual items of scenery in addition to scenery groups -STR_3366 :{BLACK}= Ride -STR_3367 :{BLACK}= Food Stall -STR_3368 :{BLACK}= Drink Stall -STR_3369 :{BLACK}= Souvenir Stall -STR_3370 :{BLACK}= Info. Kiosk -STR_3371 :{BLACK}= First Aid -STR_3372 :{BLACK}= Cash Machine -STR_3373 :{BLACK}= Toilet -STR_3374 :Warning: Too many objects selected! -STR_3375 :Not all objects in this scenery group could be selected -STR_3376 :Install new track design... -STR_3377 :{SMALLFONT}{BLACK}Install a new track design file -STR_3378 :Install -STR_3379 :Cancel -STR_3380 :Unable to install this track design... -STR_3381 :File is not compatible or contains invalid data -STR_3382 :File copy failed -STR_3383 :Select new name for track design -STR_3384 :An existing track design already has this name - Please select a new name for this design: -STR_3385 :Beginners Tutorial -STR_3386 :Custom Rides Tutorial -STR_3387 :Roller Coaster Building Tutorial -STR_3388 :Unable to switch to selected mode -STR_3389 :Unable to select additional item of scenery... -STR_3390 :Too many items selected +STR_3364 :Pokročilé +STR_3365 :{SMALLFONT}{BLACK}Povolit výběr jednotlvých kulis společně se skupinami kulis +STR_3366 :{BLACK}= Atrakce +STR_3367 :{BLACK}= Stánek s jídlem +STR_3368 :{BLACK}= Stánek s pitím +STR_3369 :{BLACK}= Stánek se suvenýry +STR_3370 :{BLACK}= Kiosek +STR_3371 :{BLACK}= První pomoc +STR_3372 :{BLACK}= Bankomat +STR_3373 :{BLACK}= Toaleta +STR_3374 :Pozor: Vybráno příliš mnoho objektů! +STR_3375 :Ne všechny objekty této skupiny kulis mohou být vybrány +STR_3376 :Instalace nového návrhu trati... +STR_3377 :{SMALLFONT}{BLACK}Instalace nového souboru s návrhem trati +STR_3378 :Instalovat +STR_3379 :Zrušit +STR_3380 :Nelze nainstalovat tento návrh trati... +STR_3381 :Soubor není kompatibilní, nebo obsahuje neplatná data +STR_3382 :Kopírování souboru selhalo +STR_3383 :Vyberte nový název návrhu trati +STR_3384 :Existuje návrh trati se stejným názvem - vyberte prosím jiný název: +STR_3385 :Tutoriál pro začátečníky +STR_3386 :Tutoriál pro vlastní tratě +STR_3387 :Tutoriál pro stavbu horských drah +STR_3388 :Nepodařilo se přepnout do vybraného módu +STR_3389 :Nepodařilo se vybrat dodatečné kulisy... +STR_3390 :Vybráno příliš mnoho položek # Start of tutorial strings. Not used at the moment, so not necessary to translate. STR_3391 :{SMALLFONT}{BLACK}Here is our park - Let's have a quick look around... STR_3392 :{SMALLFONT}{BLACK}Holding down the RIGHT mouse button and moving the mouse is the quickest way to move the view... @@ -3416,8 +3417,8 @@ STR_3404 :{SMALLFONT}{BLACK}Oh - The park is still closed! Right - Let's open STR_3405 :{SMALLFONT}{BLACK}While we're waiting for our first guests, let's build some scenery... STR_3406 :{SMALLFONT}{BLACK}Here's our empty park. We're going to build a simple custom-designed ride... STR_3407 :{SMALLFONT}{BLACK}First we need to choose a starting position... -STR_3408 :{SMALLFONT}{BLACK}The section of track we've just built is a 'station platform', to allow guests to get on and off the ride... -STR_3409 :{SMALLFONT}{BLACK}We'll extend the platform a bit by adding a couple more station platform sections... +STR_3408 :{SMALLFONT}{BLACK}The sekce of track we've just built is a 'station platform', to allow guests to get on and off the ride... +STR_3409 :{SMALLFONT}{BLACK}We'll extend the platform a bit by adding a couple more station platform sekces... STR_3410 :{SMALLFONT}{BLACK}The icons at the top of the construction window let you choose different track pieces to add... STR_3411 :{SMALLFONT}{BLACK}We'll select a left-hand curve... STR_3412 :{SMALLFONT}{BLACK}The curve hasn't been built yet, but the white ghost image shows where it will be built. Clicking the large 'build this' icon actually builds the track... @@ -3446,389 +3447,389 @@ STR_3434 :{SMALLFONT}{BLACK}Let's test the ride and see if it works! STR_3435 :{SMALLFONT}{BLACK}Great - It worked! Let's add the footpaths and let guests onto our new roller coaster... STR_3436 :{SMALLFONT}{BLACK}While waiting for our first riders, we could customise the ride a bit... # End of tutorial strings -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_3437 :{SMALLFONT}{BLACK}Odebrat velkou oblast kulis z krajiny +STR_3438 :Odsud nelze odebrat všechny kulisy... +STR_3439 :Odebrat kulisy STR_3440 :Strana 1 STR_3441 :Strana 2 STR_3442 :Strana 3 STR_3443 :Strana 4 STR_3444 :Strana 5 -STR_3445 :Set Patrol Area -STR_3446 :Cancel Patrol Area +STR_3445 :Nastavit oblast obchůzky +STR_3446 :Zrušit oblast obchůzky # New strings, cleaner -STR_5120 :Finances -STR_5121 :Research -STR_5122 :Select rides by track type (like in RCT1) -STR_5123 :Renew rides +STR_5120 :Finance +STR_5121 :Výzkum +STR_5122 :Výběr atrakcí podle typu (jako v RCT1) +STR_5123 :Obnovit atrakce STR_5124 : -STR_5125 :All destructable -STR_5126 :Random title music -STR_5127 :{SMALLFONT}{BLACK}Disable land elevation -STR_5128 :Selection size -STR_5129 :Enter selection size between {COMMA16} and {COMMA16} -STR_5130 :Map size -STR_5131 :Enter map size between {COMMA16} and {COMMA16} -STR_5132 :Fix all rides -STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights -STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights -STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights -STR_5136 :Land rights -STR_5137 :Allow lift hill and launch speeds{NEWLINE}up to {VELOCITY} +STR_5125 :Vše lze zbourat +STR_5126 :Náhodná hudba +STR_5127 :{SMALLFONT}{BLACK}Měnit vzhled země namísto změny výšky terénu +STR_5128 :Velikost výběru +STR_5129 :Zadejte velikost výběru mezi {COMMA16} a {COMMA16} +STR_5130 :Velikost mapy +STR_5131 :Zadete velikost mapy mezi {COMMA16} a {COMMA16} +STR_5132 :Opravit všechny atrakce +STR_5133 :{SMALLFONT}{BLACK}Změnit menší oblast pozemkových práv +STR_5134 :{SMALLFONT}{BLACK}Změnit větší oblast pozemkových práv +STR_5135 :{SMALLFONT}{BLACK}Koupit pozemková a konstrukční práva +STR_5136 :Pozemková práva +STR_5137 :Povolit rychlost výrahů drah až do {VELOCITY} STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} -STR_5140 :Disable brakes failure -STR_5141 :Disable all breakdowns +STR_5140 :Vypnout poruchy brzd +STR_5141 :Vypnout rozbíjení atrakcí STR_5142 :Normální rychlost -STR_5143 :Quick Speed -STR_5144 :Fast Speed -STR_5145 :Turbo Speed -STR_5146 :Hyper Speed -STR_5147 :Cheats -STR_5148 :{SMALLFONT}{BLACK}Change the game speed -STR_5149 :{SMALLFONT}{BLACK}Show cheat options -STR_5150 :Enable debugging tools -STR_5151 :, -STR_5152 :. -STR_5153 :Edit Themes... -STR_5154 :Hardware display -STR_5155 :Allow testing of unfinished tracks -STR_5156 :{SMALLFONT}{BLACK}Allows testing of most ride types even when the track is unfinished, does not apply to block sectioned modes -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_5161 :Date Format: -STR_5162 :Day/Month/Year -STR_5163 :Month/Day/Year -STR_5164 :Twitch Channel name -STR_5165 :Name peeps after followers -STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers -STR_5167 :Track follower peeps -STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers -STR_5169 :Name peeps after people in Twitch chat -STR_5170 :{SMALLFONT}{BLACK}Will name peeps after people in Twitch chat -STR_5171 :Track chat peeps -STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants -STR_5173 :Pull Twitch chat as news -STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications -STR_5175 :Input the name of your Twitch channel -STR_5176 :Enable Twitch integration -STR_5177 :Fullscreen mode: -STR_5178 :{SMALLFONT}{BLACK}Show financial cheats -STR_5179 :{SMALLFONT}{BLACK}Show guest cheats -STR_5180 :{SMALLFONT}{BLACK}Show park cheats -STR_5181 :{SMALLFONT}{BLACK}Show ride cheats +STR_5143 :Vyšší rychlost +STR_5144 :Vysoká rychlost +STR_5145 :Turbo rychlost +STR_5146 :Hyper rychlost +STR_5147 :Cheaty +STR_5148 :{SMALLFONT}{BLACK}Změnit rychlost hry +STR_5149 :{SMALLFONT}{BLACK}Zobrazit možnosti cheatů +STR_5150 :Zapnout debug nástroje +STR_5151 : +STR_5152 :, +STR_5153 :Upravit motivy... +STR_5154 :Hardwarové zobrazování +STR_5155 :Povolit testování nedostavěných atrakcí +STR_5156 :{SMALLFONT}{BLACK}Povolí testování většiny typů atrakcí, i přesto, že atrakce není dostavěna. Netýká se block sekceed modes +STR_5157 :Odemknout všechny ceny +STR_5158 :Odejiít do menu +STR_5159 :Vypnout OpenRCT2 +STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, Rok {POP16}{COMMA16} +STR_5161 :Formát data: +STR_5162 :Den/Měsíc/Rok +STR_5163 :Měsíc/Den/Rok +STR_5164 :Název Twitch kanálu +STR_5165 :Pojmenovávat návstěvníky podle foldolníů +STR_5166 :{SMALLFONT}{BLACK}Pojmenovávat návstěvníky podle foldolníů Twitch kanálu +STR_5167 :Sledovat návštěvníky-foldolníy +STR_5168 :{SMALLFONT}{BLACK}Zapne sledování návštěvníků, pojmenovaných po Twitch foldolníech +STR_5169 :Pojmenovávat návštěvníky podle lidí v Twitch chatu +STR_5170 :{SMALLFONT}{BLACK}Bude pojmenovávat návštěvníky podle lidí v Twitch chatu +STR_5171 :Sledovat návštěvníky z chatu +STR_5172 :{SMALLFONT}{BLACK}Zapne sledování návštěvníků, pojmenovaných po lidech v Twitch chatu +STR_5173 :Použít Twitch chat jako zprávy +STR_5174 :{SMALLFONT}{BLACK}Bude používat zprávy z Twitch chatu, začínající !news pro herní notifikace +STR_5175 :Zadejte název vašeho Twitch kanálu +STR_5176 :Povolit Twitch integraci +STR_5177 :Režim zobrazení: +STR_5178 :{SMALLFONT}{BLACK}Zobrazit cheaty financí +STR_5179 :{SMALLFONT}{BLACK}Zobrazit cheaty návštěvníků +STR_5180 :{SMALLFONT}{BLACK}Zorabzit cheaty parku +STR_5181 :{SMALLFONT}{BLACK}Zobrazit cheaty atrakcí STR_5182 :{INT32} -STR_5183 :Base height -STR_5184 :Enter base height between {COMMA16} and {COMMA16} -STR_5185 :Water level -STR_5186 :Enter water level between {COMMA16} and {COMMA16} -STR_5187 :Finances -STR_5188 :New Campaign +STR_5183 :Základní výška +STR_5184 :Zadejte základní výšku v rozmezí od {COMMA16} do {COMMA16} +STR_5185 :Úroveň vody +STR_5186 :Zadejte úroveň vody v rozmezí od {COMMA16} do {COMMA16} +STR_5187 :Finance +STR_5188 :Nová reklamní kampaň STR_5189 :Výzkum STR_5190 :Mapa -STR_5191 :Viewport +STR_5191 :Pohled STR_5192 :Poslední novinky STR_5193 :Pozemky STR_5194 :Voda STR_5195 :Vyčistit scénář STR_5196 :Pozemková práva -STR_5197 :Scenery -STR_5198 :Cesta -STR_5199 :Ride Construction -STR_5200 :Track Design Place -STR_5201 :New Ride -STR_5202 :Track Design Selection +STR_5197 :Kulisy +STR_5198 :Cesty +STR_5199 :Stavba atrakcí +STR_5200 :Umístění návrhu trati +STR_5201 :Nová atrakce +STR_5202 :Výběr návrhu trati STR_5203 :Atrakce STR_5204 :Seznam atrakcí -STR_5205 :Host -STR_5206 :Seznam hostů -STR_5207 :Zaměstnanci -STR_5208 :seznam zaměstnanců -STR_5209 :Banner -STR_5210 :Object Selection -STR_5211 :Invention List -STR_5212 :Scenario Options -STR_5213 :Objective Options -STR_5214 :Map Generation -STR_5215 :Track Design Manager -STR_5216 :Track Design Manager List -STR_5217 :Cheats -STR_5218 :Themes +STR_5205 :Návštěvník +STR_5206 :Seznam návštěvníků +STR_5207 :Personál +STR_5208 :Seznam personálu +STR_5209 :Baner +STR_5210 :Výběr objektu +STR_5211 :Seznam vynálezů +STR_5212 :Nastavení sénáře +STR_5213 :Nastavení cílů +STR_5214 :Vytváření mapy +STR_5215 :Správce návrhů tratí +STR_5216 :Správce seznamu návrhů tratí +STR_5217 :Cheaty +STR_5218 :Motivy STR_5219 :Nastavení STR_5220 :Klávesové zkratky STR_5221 :Změnit klávesové zkratky STR_5222 :Načíst/uložit -STR_5223 :Save Prompt -STR_5224 :Demolish Ride Prompt -STR_5225 :Fire Staff Prompt -STR_5226 :Track Delete Prompt -STR_5227 :Save Overwrite Prompt +STR_5223 :Výzva k uložení +STR_5224 :Výzva k odstranění atrakce +STR_5225 :Výzva k vyhazovu personálu +STR_5226 :Výzva k odstranění trati +STR_5227 :Výzva k přepisu uložené hry STR_5228 :{SMALLFONT}{BLACK}Hlavní UI STR_5229 :{SMALLFONT}{BLACK}Park STR_5230 :{SMALLFONT}{BLACK}Nástroje -STR_5231 :{SMALLFONT}{BLACK}Rides and Peeps +STR_5231 :{SMALLFONT}{BLACK}Atrakce a návštěvníci STR_5232 :{SMALLFONT}{BLACK}Editory STR_5233 :{SMALLFONT}{BLACK}Ostatní -STR_5234 :{SMALLFONT}{BLACK}Prompts +STR_5234 :{SMALLFONT}{BLACK}Výzvy STR_5235 :{SMALLFONT}{BLACK}Nastavení STR_5236 :Okno: STR_5237 :Paleta: -STR_5238 :Current Theme: +STR_5238 :Aktuální motiv: STR_5239 :Duplikovat -STR_5240 :Enter a name for the theme -STR_5241 :Can't change this theme -STR_5242 :Theme name already exists -STR_5243 :Invalid characters used -STR_5244 :Themes -STR_5245 :Top Toolbar -STR_5246 :Bottom Toolbar -STR_5247 :Track Editor Bottom Toolbar -STR_5248 :Scenario Editor Bottom Toolbar -STR_5249 :Title Menu Buttons -STR_5250 :Title Exit Button -STR_5251 :Title Options Button -STR_5252 :Title Scenario Selection -STR_5253 :Park Information -STR_5254 :Create -STR_5255 :{SMALLFONT}{BLACK}Create a new title sequence from scratch -STR_5256 :Create a new theme to make changes to -STR_5257 :{SMALLFONT}{BLACK}Create a new theme based on the current one -STR_5258 :{SMALLFONT}{BLACK}Delete the current theme -STR_5259 :{SMALLFONT}{BLACK}Rename the current theme -STR_5260 :Giant Screenshot -STR_5261 :Filter +STR_5240 :Zadejte jméno pro tento motiv +STR_5241 :Tento motiv nelze změnit +STR_5242 :Jméno motivu již existuje +STR_5243 :Použity neplatné znaky +STR_5244 :Motivy +STR_5245 :Vrchní nástrojová lišta +STR_5246 :Dolní nástrojová lišta +STR_5247 :Dolní nástrojová lišta editoru tratě +STR_5248 :Dolní nástrojová lišta editoru scénářů +STR_5249 :Tlačítka titulního menu +STR_5250 :Tlačítko titulního menu pro odchod +STR_5251 :Tlačítko titulního menu pro nastavení +STR_5252 :Tlačítko titulního menu pro výběr scénáře +STR_5253 :Informace o zábavním parku +STR_5254 :Vytvořit +STR_5255 :{SMALLFONT}{BLACK}Vytvořit novou herní sekvenci +STR_5256 :Vytvořit nový motiv +STR_5257 :{SMALLFONT}{BLACK}Vytvořit nový motiv na základě současného +STR_5258 :{SMALLFONT}{BLACK}Odstranit současný motiv +STR_5259 :{SMALLFONT}{BLACK}Přejmenovat současný motiv +STR_5260 :Snímek celého parku +STR_5261 :Filtr STR_5262 :Wacky Worlds STR_5263 :Time Twister -STR_5264 :Custom -STR_5265 :{SMALLFONT}{BLACK}Select which content sources are visible -STR_5266 :{SMALLFONT}{BLACK}Display -STR_5267 :{SMALLFONT}{BLACK}Culture and Units -STR_5268 :{SMALLFONT}{BLACK}Audio -STR_5269 :{SMALLFONT}{BLACK}Controls and interface -STR_5270 :{SMALLFONT}{BLACK}Miscellaneous +STR_5264 :Vlastní +STR_5265 :{SMALLFONT}{BLACK}Vyberte viditelné zdroje obsahu +STR_5266 :{SMALLFONT}{BLACK}Zobrazení +STR_5267 :{SMALLFONT}{BLACK}Lokalizace +STR_5268 :{SMALLFONT}{BLACK}Zvuk +STR_5269 :{SMALLFONT}{BLACK}Ovládání +STR_5270 :{SMALLFONT}{BLACK}Ostatní STR_5271 :{SMALLFONT}{BLACK}Twitch -STR_5272 :{SMALLFONT}{BLACK}Small Scenery -STR_5273 :{SMALLFONT}{BLACK}Large Scenery -STR_5274 :{SMALLFONT}{BLACK}Footpath -STR_5275 :Search for Objects -STR_5276 :Enter the name of an object to search for -STR_5277 :Clear -STR_5278 :Sandbox mode -STR_5279 :Sandbox mode off -STR_5280 :{SMALLFONT}{BLACK}Allow editing land ownership settings through the Map window and other options that are normally restricted to the Scenario Editor -STR_5281 :{SMALLFONT}{BLACK}Features -STR_5282 :RCT1 Ride Open/Close Lights -STR_5283 :RCT1 Park Open/Close Lights -STR_5284 :RCT1 Scenario Selection Font -STR_5285 :EXPLODE!!! -STR_5286 :{SMALLFONT}{BLACK}Makes some guests explode -STR_5287 :Ride is already broken down -STR_5288 :Ride is closed -STR_5289 :No breakdowns available for this ride -STR_5290 :Fix ride -STR_5291 :Can't force breakdown -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_5272 :{SMALLFONT}{BLACK}Drobné kulisy +STR_5273 :{SMALLFONT}{BLACK}Velké kulisy +STR_5274 :{SMALLFONT}{BLACK}Cesty +STR_5275 :Hledat objekty +STR_5276 :Zadejte jméno objektu, který hledáte +STR_5277 :Vyčistit +STR_5278 :Sandbox mód +STR_5279 :Sandbox mód vypnutý +STR_5280 :{SMALLFONT}{BLACK}Povolit pomocí okna s mapou úpravy nastavení práv pozemků dalších možností, která jsou jinak možná jen v editoru scénáře +STR_5281 :{SMALLFONT}{BLACK}Funkce +STR_5282 :RCT1 světla atrakcí otevřeno/zavřeno +STR_5283 :RCT1 světla parku otevřeno/zavřeno +STR_5284 :RCT1 výber fontu scénáře +STR_5285 :VÝBUCH!!! +STR_5286 :{SMALLFONT}{BLACK}Vyhodit několik návštěvníků do povětří +STR_5287 :Atrakce už má poruchu +STR_5288 :Atrakce je zavřená +STR_5289 :Tato atrakce nemůže mít poruchy +STR_5290 :Opravit atrakci +STR_5291 :Nelze vynutit poruchu atrakce +STR_5292 :{SMALLFONT}{BLACK}Vynutit poruchu atrakce +STR_5293 :{SMALLFONT}{BLACK}Zavřít atrakci +STR_5294 :{SMALLFONT}{BLACK}Otestovat atrakci +STR_5295 :{SMALLFONT}{BLACK}Otevřít atrakci +STR_5296 :{SMALLFONT}{BLACK}Zavřít zábavní park +STR_5297 :{SMALLFONT}{BLACK}Otevřít zábavní park STR_5298 :{RED}{STRINGID} STR_5299 :{LIGHTPINK}{STRINGID} -STR_5300 :{SMALLFONT}{BLACK}Quick fire staff -STR_5301 :{MEDIUMFONT}{BLACK}Clear your loan -STR_5302 :Clear loan -STR_5303 :Allow building in pause mode -STR_5304 :Title Sequence: +STR_5300 :{SMALLFONT}{BLACK}Propustit zaměstnance +STR_5301 :{MEDIUMFONT}{BLACK}Vyrovnání dluhů +STR_5302 :Vyrovnat dluh +STR_5303 :Povolit stavění, když je hra pozastavená +STR_5304 :Herní sekvence: 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 :Random -STR_5311 :{SMALLFONT}{BLACK}Debug tools -STR_5312 :Show console -STR_5313 :Show tile inspector -STR_5314 :Tile inspector -STR_5315 :Grass -STR_5316 :Sand -STR_5317 :Dirt -STR_5318 :Rock -STR_5319 :Martian -STR_5320 :Checkerboard -STR_5321 :Grass clumps -STR_5322 :Ice -STR_5323 :Grid (red) -STR_5324 :Grid (yellow) -STR_5325 :Grid (blue) -STR_5326 :Grid (green) -STR_5327 :Sand (dark) -STR_5328 :Sand (light) -STR_5329 :Checkerboard (inverted) -STR_5330 :Underground view -STR_5331 :Rock -STR_5332 :Wood (red) -STR_5333 :Wood (black) -STR_5334 :Ice -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_5341 :Flags -STR_5342 :Choose a map tile -STR_5343 :Automatically place staff -STR_5344 :Changelog -STR_5345 :Financial cheats -STR_5346 :Guest cheats -STR_5347 :Park cheats -STR_5348 :Ride cheats -STR_5349 :{SMALLFONT}{BLACK}All Rides +STR_5310 :Náhoda +STR_5311 :{SMALLFONT}{BLACK}Debug nástroje +STR_5312 :Zobrazit konzoli +STR_5313 :Zobrazit průzkumníka dlaždic +STR_5314 :Průzkumník dlaždic +STR_5315 :Tráva +STR_5316 :Písek +STR_5317 :Hlína +STR_5318 :Kámen +STR_5319 :Marťan +STR_5320 :Šachovnice +STR_5321 :Drny +STR_5322 :Led +STR_5323 :Mřížka (červená) +STR_5324 :Mřížka (žlutá) +STR_5325 :Mřížka (modrá) +STR_5326 :Mřížka (zelená) +STR_5327 :Písek (tmavý) +STR_5328 :Písek (světlý) +STR_5329 :Šachovnice (obrácená) +STR_5330 :Podzemní pohled +STR_5331 :Kámen +STR_5332 :Dřevo (červené) +STR_5333 :Dřevo (černé) +STR_5334 :Led +STR_5335 :Vstup na atrakci +STR_5336 :Východ z atrakce +STR_5337 :Vstup do zábavního parku +STR_5338 :Typ prvku +STR_5339 :Výška povrchu +STR_5340 :Výška objektu +STR_5341 :Vlajky +STR_5342 :Výběr dlaždice +STR_5343 :Automaticky umisťovat personál +STR_5344 :Seznam změn +STR_5345 :Cheaty financí +STR_5346 :Cheaty návštěvníků +STR_5347 :Cheaty parku +STR_5348 :Cheaty atrakcí +STR_5349 :{SMALLFONT}{BLACK}Všechny atrakce STR_5350 :Max STR_5351 :Min -STR_5352 :{BLACK}Happiness: -STR_5353 :{BLACK}Energy: -STR_5354 :{BLACK}Hunger: -STR_5355 :{BLACK}Thirst: -STR_5356 :{BLACK}Nausea: -STR_5357 :{BLACK}Nausea tolerance: -STR_5358 :{BLACK}Bathroom: -STR_5359 :Remove guests -STR_5360 :{SMALLFONT}{BLACK}Removes all guests from the map -STR_5361 :Give all guests: -STR_5362 :{BLACK}Set all guests' preferred ride intensity to: -STR_5363 :More than 1 -STR_5364 :Less than 15 -STR_5365 :{BLACK}Staff speed: -STR_5366 :Normal -STR_5367 :Fast -STR_5368 :Reset crash status -STR_5369 :Park parameters... -STR_5370 :{SMALLFONT}{BLACK}Click this button to modify park{NEWLINE}parameters like restrictions,{NEWLINE}guest generation and money. -STR_5371 :Object Selection -STR_5372 :Invert right mouse dragging -STR_5373 :Name {STRINGID} -STR_5374 :Date {STRINGID} +STR_5352 :{BLACK}Nadšení: +STR_5353 :{BLACK}Energie: +STR_5354 :{BLACK}Hlad: +STR_5355 :{BLACK}Žízeň: +STR_5356 :{BLACK}Nevolnost: +STR_5357 :{BLACK}Tolerance nevolnosti: +STR_5358 :{BLACK}Toaleta: +STR_5359 :Vyhnat návštěvníky +STR_5360 :{SMALLFONT}{BLACK}Vyžene všechny návštěvníky z mapy +STR_5361 :Rozdat všem návštěvníkům: +STR_5362 :{BLACK}Nastav preferovanou intenzitu návštěvníků na: +STR_5363 :Více než 1 +STR_5364 :Méně než 15 +STR_5365 :{BLACK}Rychlost personálu: +STR_5366 :Normální +STR_5367 :Vysoká +STR_5368 :Vymazat havárii +STR_5369 :Parametry parku... +STR_5370 :{SMALLFONT}{BLACK}Klikněte na toto tlačítko pro {NEWLINE}úpravy parametrů jako omezení parku,{NEWLINE} generování návštěvníků a peněz. +STR_5371 :Výběr objektu +STR_5372 :Obrátit směr posouvání pohledu pravým tlačítkem +STR_5373 :Název {STRINGID} +STR_5374 :Datum {STRINGID} STR_5375 :{UP} STR_5376 :{DOWN} -STR_5377 :{SMALLFONT}{BLACK}Saves -STR_5378 :{SMALLFONT}{BLACK}Script -STR_5379 :{SMALLFONT}{BLACK}Skip to next wait command -STR_5380 :{SMALLFONT}{BLACK}Start playing title sequence -STR_5381 :{SMALLFONT}{BLACK}Stop playing title sequence -STR_5382 :{SMALLFONT}{BLACK}Restart title sequence -STR_5383 :{SMALLFONT}{BLACK}Create a new title sequence based on the current one -STR_5384 :{SMALLFONT}{BLACK}Delete the current title sequence -STR_5385 :{SMALLFONT}{BLACK}Rename the current title sequence -STR_5386 :{SMALLFONT}{BLACK}Insert a new command -STR_5387 :{SMALLFONT}{BLACK}Edit the selected command -STR_5388 :{SMALLFONT}{BLACK}Delete the selected command -STR_5389 :{SMALLFONT}{BLACK}Skip to the selected command in the title sequence -STR_5390 :{SMALLFONT}{BLACK}Move the selected command down -STR_5391 :{SMALLFONT}{BLACK}Move the selected command up -STR_5392 :{SMALLFONT}{BLACK}Add a save to the title sequence -STR_5393 :{SMALLFONT}{BLACK}Remove the selected save from the title sequence -STR_5394 :{SMALLFONT}{BLACK}Rename the selected save -STR_5395 :{SMALLFONT}{BLACK}Load the selected save in game -STR_5396 :{SMALLFONT}{BLACK}Reload the title sequence if changes have been made to it outside of the game -STR_5397 :Can only be used on the title screen -STR_5398 :Cannot edit title sequence while it's playing -STR_5399 :Press the stop button to continue editing -STR_5400 :Can't change this title sequence -STR_5401 :Create a new title sequence to make changes to -STR_5402 :Failed to load title sequence -STR_5403 :There may be no Load or Wait command or a save may be invalid -STR_5404 :Name already exists -STR_5405 :Enter a name for the save -STR_5406 :Enter a name for the title sequence -STR_5407 :Add -STR_5408 :Remove -STR_5409 :Insert -STR_5410 :Edit -STR_5411 :Reload -STR_5412 :Skip to -STR_5413 :Load -STR_5414 :Load{MOVE_X}{87}Six Flags Magic Mountain.SC6 -STR_5415 :Load{MOVE_X}{87}{STRING} -STR_5416 :Load{MOVE_X}{87}No save selected -STR_5417 :Location -STR_5418 :Location{MOVE_X}{87}{COMMA16} {COMMA16} -STR_5419 :Rotate -STR_5420 :Rotate{MOVE_X}{87}{COMMA16} -STR_5421 :Zoom -STR_5422 :Zoom{MOVE_X}{87}{COMMA16} -STR_5423 :Wait -STR_5424 :Wait{MOVE_X}{87}{COMMA16} +STR_5377 :{SMALLFONT}{BLACK}Uložené hry +STR_5378 :{SMALLFONT}{BLACK}Skripty +STR_5379 :{SMALLFONT}{BLACK}Přeskočit na následující příkaz "Čekat" +STR_5380 :{SMALLFONT}{BLACK}Spustit herní sekvenci +STR_5381 :{SMALLFONT}{BLACK}Zastavit herní sekvenci +STR_5382 :{SMALLFONT}{BLACK}Restartovat herní sekvenci +STR_5383 :{SMALLFONT}{BLACK}Vytvořit stejnou novou herní sekvenci +STR_5384 :{SMALLFONT}{BLACK}Odebrat herní sekvenci +STR_5385 :{SMALLFONT}{BLACK}Přejmenovat herní sekvenci +STR_5386 :{SMALLFONT}{BLACK}Vložit nový příkaz +STR_5387 :{SMALLFONT}{BLACK}Upravit vybraný příkaz +STR_5388 :{SMALLFONT}{BLACK}Odebrat vybraný příkaz +STR_5389 :{SMALLFONT}{BLACK}Přeskočit na následující příkaz v sekvenci +STR_5390 :{SMALLFONT}{BLACK}Přesunout příkaz níže +STR_5391 :{SMALLFONT}{BLACK}Přesunout příkaz výše +STR_5392 :{SMALLFONT}{BLACK}Přidat uloženou hru do sekvence +STR_5393 :{SMALLFONT}{BLACK}Odebrat uloženou hru ze sekvence +STR_5394 :{SMALLFONT}{BLACK}Přejmenovat uloženou hru +STR_5395 :{SMALLFONT}{BLACK}Načíst vybranou uloženou hru +STR_5396 :{SMALLFONT}{BLACK}Znovu načíst herní sekvenci, pokud byla upravována mimo hru +STR_5397 :Může být použito pouze na titulní obrazovce +STR_5398 :Nelze upravovat herní sekvenci, když právě hraje +STR_5399 :Stiskněte tlačítko "stop" pro pokračování v úpravách +STR_5400 :Tuto herní sekvenci nelze měnit +STR_5401 :Vytvořit novou herní sekvenci +STR_5402 :Nepodařilo se načíst herní sekvenci +STR_5403 :Patrně chybí příkaz Načti, Čekej, nebo je uložená hra neplatná +STR_5404 :Název již existuje +STR_5405 :Zadejte název pro uloženou hru +STR_5406 :Zadejte název herní sekvence +STR_5407 :Přidat +STR_5408 :Odebrat +STR_5409 :Vložit +STR_5410 :Upravit +STR_5411 :Znovu načíst +STR_5412 :Přeskočit na +STR_5413 :Načíst +STR_5414 :Načíst{MOVE_X}{87}Six Flags Magic Mountain.SC6 +STR_5415 :Načíst{MOVE_X}{87}{STRING} +STR_5416 :Načíst{MOVE_X}{87}No save selected +STR_5417 :Umístění +STR_5418 :Umístění{MOVE_X}{87}{COMMA16} {COMMA16} +STR_5419 :Otočit +STR_5420 :Otočit{MOVE_X}{87}{COMMA16} +STR_5421 :Přiblížit +STR_5422 :Přiblížit{MOVE_X}{87}{COMMA16} +STR_5423 :Čekat +STR_5424 :Čekat{MOVE_X}{87}{COMMA16} STR_5425 :Restart -STR_5426 :End -STR_5427 :Coordinates: -STR_5428 :Anticlockwise rotations: -STR_5429 :Zoom level: -STR_5430 :Seconds to wait: -STR_5431 :Save to load: -STR_5432 :Command: -STR_5433 :Title Sequences -STR_5434 :Command Editor -STR_5435 :Rename save -STR_5436 :Edit Title Sequences... -STR_5437 :No save selected -STR_5438 :Can't make changes while command editor is open -STR_5439 :A wait command with at least 4 seconds is required with a restart command -STR_5440 :Minimise fullscreen on focus loss -STR_5441 :{SMALLFONT}{BLACK}Identifies rides by track type,{NEWLINE}so vehicles can be changed{NEWLINE}afterwards, like in RCT1. -STR_5442 :Force park rating: -STR_5443 :Speed{MOVE_X}{87}{STRINGID} -STR_5444 :Speed: -STR_5445 :Speed -STR_5446 :Get -STR_5447 :Type {STRINGID} -STR_5448 :Ride / Vehicle {STRINGID} -STR_5449 :Reduce game speed -STR_5450 :Increase game speed -STR_5451 :Open cheats window -STR_5452 :Toggle visibility of toolbars -STR_5453 :Select another ride -STR_5454 :Uncap FPS -STR_5455 :Enable sandbox mode -STR_5456 :Disable clearance checks -STR_5457 :Disable support limits -STR_5458 :Rotate clockwise -STR_5459 :Rotate anti-clockwise -STR_5460 :Rotate view anti-clockwise -STR_5461 :Set guests' parameters +STR_5426 :Konec +STR_5427 :Souřadnice: +STR_5428 :Počet otočení proti směru hod.ruč.: +STR_5429 :Úroveň přiblížení: +STR_5430 :Délka čekání (v sekundách): +STR_5431 :Uložená hra k načtení: +STR_5432 :Příkaz: +STR_5433 :Herní sekvence +STR_5434 :Editor příkazů +STR_5435 :Přejmenovat uloženou hru +STR_5436 :Upravit herní sekvence... +STR_5437 :Nevybrána žádná ulžoená hra +STR_5438 :Nelze vytvářet změny, když je otevřený editor příkazů +STR_5439 :Příkaz "Čekat" alespoň 4 vteřiny je vyžadován společně s příkazem "Restart" +STR_5440 :Minimalizovat celoobrazovkový režim při přepnutí ze hry +STR_5441 :{SMALLFONT}{BLACK}Identifikovat atrakce podle typu,{NEWLINE}potom lze později měnit vozy,{NEWLINE}tak jako v RCT1. +STR_5442 :Hodnocení parku: +STR_5443 :Rychlost{MOVE_X}{87}{STRINGID} +STR_5444 :Rychlost: +STR_5445 :Rychlost +STR_5446 :Získat +STR_5447 :Typ {STRINGID} +STR_5448 :Atrakce/vůz {STRINGID} +STR_5449 :Snížit rychlost hry +STR_5450 :Zvýšit rychlost hry +STR_5451 :Otevřít cheaty +STR_5452 :Skrýt/zobrazit lištu s nástroji +STR_5453 :Vybrat jinou atrakci +STR_5454 :Neomezovat FPS +STR_5455 :Zapnout sandbox mód +STR_5456 :Vypnout kontroly křížení +STR_5457 :Vypnout limity podpěr +STR_5458 :Otočit po směru hod. ruč. +STR_5459 :Otočit proti směru hod. ruč. +STR_5460 :Otočit pohled proti směru hod. ruč. +STR_5461 :Nastavit parametry návštěvníka STR_5462 :{CURRENCY} -STR_5463 :Goal: Have fun! -STR_5464 :General -STR_5465 :Climate -STR_5466 :Staff +STR_5463 :Cíl: Příjemná zábava! +STR_5464 :Obecné +STR_5465 :Klima +STR_5466 :Personál STR_5467 :ALT + -STR_5468 :Recent messages -STR_5469 :Scroll map up -STR_5470 :Scroll map left -STR_5471 :Scroll map down -STR_5472 :Scroll map right -STR_5473 :Cycle day / night -STR_5474 :Display text on banners in upper case -STR_5475 :{COMMA16} weeks +STR_5468 :Poslední zprávy +STR_5469 :Posunou mapu nahoru +STR_5470 :Posunou mapu vlevo +STR_5471 :Posunou mapu dolů +STR_5472 :Posunou mapu vpravo +STR_5473 :Cyklus dne a noci +STR_5474 :Zobrazit text na banerech v kapitálkách +STR_5475 :{COMMA16} týdnů STR_5476 :Hardware -STR_5477 :Map rendering -STR_5478 :Controls -STR_5479 :Toolbar -STR_5480 :Show toolbar buttons for: -STR_5481 :Themes -STR_5482 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}1 minute -STR_5483 :{BLACK}({COMMA16} weeks remaining) -STR_5484 :{BLACK}({COMMA16} week remaining) +STR_5477 :Vykreslování mapy +STR_5478 :Ovládání +STR_5479 :Panel nástrojů +STR_5480 :Zobrazit tlačítka pro: +STR_5481 :Motivy +STR_5482 :{WINDOW_COLOUR_2}Doba od poslední inspekce: {BLACK}1 minuta +STR_5483 :{BLACK}(zbývá {COMMA16} týdnů) +STR_5484 :{BLACK}(zbývá {COMMA16} týden) STR_5485 :{SMALLFONT}{STRING} STR_5486 :{BLACK}{COMMA16} -STR_5487 :{SMALLFONT}{BLACK}Show recent messages -STR_5488 :No entrance (OpenRCT2 only!) -STR_5489 :{SMALLFONT}{BLACK}Show only tracked guests -STR_5490 :Disable audio on focus loss +STR_5487 :{SMALLFONT}{BLACK}Zobrazit poslední zprávy +STR_5488 :Bez vstupu (pouze pro OpenRCT2!) +STR_5489 :{SMALLFONT}{BLACK}Zobrazit pouze sledované návštěvníky +STR_5490 :Vypnout zvuk při přepnutí ze hry STR_5491 :Seznam vynálezů STR_5492 :Nastavení scénáře STR_5493 :Poslat zprávu @@ -3836,24 +3837,24 @@ STR_5494 : STR_5495 :Seznam hráčů STR_5496 :Hráč: STR_5497 :Ping: -STR_5498 :Seznam Serverů +STR_5498 :Seznam serverů STR_5499 :Jméno hráče: -STR_5500 :Přidat Server -STR_5501 :Spustit Server +STR_5500 :Přidat server +STR_5501 :Spustit server STR_5502 :Hra více hráčů -STR_5503 :Enter hostname or IP address: -STR_5504 :{SMALLFONT}{BLACK}Show multiplayer status +STR_5503 :Zadejte hostname, nebo IP adresu: +STR_5504 :{SMALLFONT}{BLACK}Zobrazit stav hry více hráčů STR_5505 :Nelze se připojit k serveru. -STR_5506 :Hosté ingnorují intensitu -STR_5507 :Handymen mow grass by default -STR_5508 :APovolit nahrávat soubory s chybným kontrolním součtem -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_5506 :Návštěvníci ingnorují intenzitu atrakcí +STR_5507 :Údržbáři nyní sekají trávu ve výchozím nastavení +STR_5508 :Povolit nahrávání souborů s chybným kontrolním součtem +STR_5509 :{SMALLFONT}{BLACK}Povolí nahrávání scénářů s neplatným kontrolním součtem - například scénáře demoverze, nebo poškozené uložené hry. +STR_5510 :Výchozí zvukové zařízení STR_5511 :(UNKNOWN) STR_5512 :Uložit hru jako STR_5513 :(Rychle) uložit hru STR_5514 :Vypnout vandalismus -STR_5515 :{SMALLFONT}{BLACK}Zastaví vandalismus naštvaných hostů +STR_5515 :{SMALLFONT}{BLACK}Zastaví vandalismus naštvaných návštěvníků STR_5516 :{SMALLFONT}{BLACK}Černá STR_5517 :{SMALLFONT}{BLACK}Šedá STR_5518 :{SMALLFONT}{BLACK}Bílá @@ -3886,24 +3887,24 @@ STR_5544 :{SMALLFONT}{BLACK}Jasně červená STR_5545 :{SMALLFONT}{BLACK}Temně růžová STR_5546 :{SMALLFONT}{BLACK}Jasně růžová STR_5547 :{SMALLFONT}{BLACK}Světle -STR_5548 :Show all operating modes +STR_5548 :Zobrazit všechny módy provozu STR_5549 :Rok/Měsíc/Den STR_5550 :{POP16}{POP16}Rok {COMMA16}, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} STR_5551 :Rok/Den/Měsíc STR_5552 :{POP16}{POP16}Rok {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 +STR_5553 :Pozastavit hru při otevření Steamu +STR_5554 :{SMALLFONT}{BLACK}Zapnout nástroj pro kopce +STR_5555 :Zobrazovat vozidla i jiných typů atrakcí STR_5556 :Vyhodit hráče STR_5557 :Zůstat připojen při desynchronizaci (Hra více hráčů) STR_5558 :Změna tohoto nastavení vyžaduje restart -STR_5559 :10 min. inspections -STR_5560 :{SMALLFONT}{BLACK}Sets the inspection time to 'Every 10 minutes' on all rides +STR_5559 :10 minutové inspekce +STR_5560 :{SMALLFONT}{BLACK}Nastaví interval inspekcí 'Každých 10 minut' pro všechny atrakce STR_5561 :Nahrání souborů jazyka selhalo STR_5562 :POZOR! -STR_5563 :This feature is currently unstable, take extra caution. -STR_5564 :Insert Corrupt Element -STR_5565 :{SMALLFONT}{BLACK}Inserts a corrupt map element at top of tile. This will hide any element above the corrupt element. +STR_5563 :Tato funkce není stabilní, postupujte opatrně. +STR_5564 :Vložit neplatný prvek +STR_5565 :{SMALLFONT}{BLACK}Vloží neplatný prvek mapy na vrchol dlaždice, a tím zakryje všechny ostatní prvky STR_5566 :Heslo: STR_5567 :Propagovat STR_5568 :Vyžadovat heslo @@ -3915,15 +3916,7138 @@ STR_5573 :Odstranit z oblíbených STR_5574 :Jméno serveru: STR_5575 :Hráčů maximálně: STR_5576 :Port: -STR_5577 :Jiho-Korejský Won (W) -STR_5578 :Ruský Rubl (R) +STR_5577 :Jihokorejský won (W) +STR_5578 :Ruský rubl (R) +STR_5579 :Koeficient velikosti okna: +STR_5580 :Česká koruna (Kč) +STR_5581 :Zobrazit FPS +STR_5582 :Zachytávat kurzor myši v okně +STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} +STR_5584 :SI +STR_5585 :{SMALLFONT}{BLACK}Odemkne limity atrakcí, například {VELOCITY} stoupání +STR_5586 :Automaticky otevírat obchody a stánky +STR_5587 :{SMALLFONT}{BLACK}Po zapnutí budou nově postavené stánky a obchody automaticky otevírány +STR_5588 :{SMALLFONT}{BLACK}Hrát s jinými hráči +STR_5589 :Nastavení upozornění +STR_5590 :Ocenění zábavního parku +STR_5591 :Reklamní kampaň skončila +STR_5592 :Varování zábavního parku +STR_5593 :Varování hodnocení parku +STR_5594 :Atrakce se rozbila +STR_5595 :Atrakce havarovala +STR_5596 :Varování atrakcí +STR_5597 :Vyzkoumané atrakce / kulisy +STR_5598 :Varování návštěvníků +STR_5599 :Návštěvník se ztratil +STR_5600 :Návštěvník opustil zábavní park +STR_5601 :Návštěvník čeká ve frontě na atrakci +STR_5602 :Návštěvník je na atrakci +STR_5603 :Návštěvník opustil atrakci +STR_5604 :Návštěvník si zakoupil položku +STR_5605 :Návštěvník použil zařízení +STR_5606 :Návštěvník zemřel +STR_5607 :{SMALLFONT}{BLACK}Vynuceně odebrat vybraný prvek mapy. +STR_5608 :BH +STR_5609 :CH +STR_5610 :{SMALLFONT}{BLACK}Odebere vybraný prvek mapy. Odebrání je vynucené, nestojí/nevrací tedy hotovost. Používejte opratrně. +STR_5611 :G +STR_5612 :{SMALLFONT}{BLACK}Vlajka pro ghost-element +STR_5613 :B +STR_5614 :{SMALLFONT}{BLACK}Vlajka pro rozbitý prvek +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}Vlajka pro poslední element dlaždice +STR_5617 :{SMALLFONT}{BLACK}Posunout vybraný prvek nahoru +STR_5618 :{SMALLFONT}{BLACK}Posunout vybraný prvek dolů +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}Reálné{ENDQUOTES} parky +STR_5626 :Ostatní parky +STR_5627 :Seskupit scénáře podle: +STR_5628 :Původní hry +STR_5629 :Obtížnosti +STR_5630 :Zapnout odemykání scénářů +STR_5631 :Originální DLC parky +STR_5632 :Postav si vlastní... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Utracená hotovost: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Spuštěné příkazy: {BLACK}{COMMA16} +STR_5637 :Toto nelze provést... +STR_5638 :Přístup zamítnut +STR_5639 :{SMALLFONT}{BLACK}Zobrazit seznam hráčů +STR_5640 :{SMALLFONT}{BLACK}Spravovat skupiny +STR_5641 :Výchozí skupina: +STR_5642 :Skupina: +STR_5643 :Přidat skupinu +STR_5644 :Odebrat skupinu +STR_5645 :Chat +STR_5646 :Terénní úravy +STR_5647 :Pozastavení hry +STR_5648 :Nastavit úroveň vody +STR_5649 :Vytvořit atrakci +STR_5650 :Odstranit atrakci +STR_5651 :Postavit atrakci +STR_5652 :Vlastnosti atrakce +STR_5653 :Kulisa +STR_5654 :Cesta +STR_5655 :Návštěvník +STR_5656 :Zaměstnanec +STR_5657 :Vlastnísti parku +STR_5658 :Financování parku +STR_5659 :Vyhodit hráče +STR_5660 :Upravit skupiny +STR_5661 :Nastavit skupinu hráče +STR_5662 :N/A +STR_5663 :Vyčistit krajinu +STR_5664 :Cheaty +STR_5665 :Přepínat skupinové stavění kulis +STR_5701 :{WINDOW_COLOUR_2}Poslední akce: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Najít hráčovu poslední akci +STR_5703 :Nelze vyhodit zakladatele hry +STR_5704 :Poslední akce: +STR_5705 :Nelze nastavit tuto skupinu +STR_5706 :Nelze odebrat skupinu, ke které hráč patří +STR_5707 :Tato skupina nemůže být upravena +STR_5708 :Nelze odebrat skupinu, ke které patří zakladatel hry +STR_5709 :Přejmenovat skupinu +STR_5710 :Název skupiny +STR_5711 :Zadejte nový název skupiny: +STR_5712 :Nelze upravit oprávnění, které nemáte +STR_5713 :Vyhodit hráče +STR_5714 :Zobrazit nastavení +STR_5715 :Nová hra +STR_5716 :Není povoleno ve hře více hráčů +# For identifying client network version in server list window +STR_5717 :Verze síťové hry: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Verze síťové hry: {STRING} +STR_5719 :Slunečno +STR_5720 :Polojasno +STR_5721 :Zataženo +STR_5722 :Přeháňky +STR_5723 :Déšť +STR_5724 :Bouřka +STR_5725 :{BLACK}Vynutit počasí: +STR_5726 :{SMALLFONT}{BLACK}Nastaví momentální počasí v parku +STR_5727 :Metoda škálování +STR_5728 :Vyžaduje hardwarové zobrazování +STR_5729 :{SMALLFONT}{BLACK}Vyžaduje hardwarové zobrazování +STR_5730 :Nejbližší sousedi +STR_5731 :Lineární +STR_5732 :Anizotropní +STR_5733 :U celočíselného škálování používat NS metodu +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Vykreslování +STR_5735 :Stav připojení +STR_5736 :Hráč +STR_5737 :Zavřeno, {COMMA16} návštěvník zůstal na atrakci +STR_5738 :Zavřeno, {COMMA16} návštěvníků zůstalo na atrakci +STR_5739 :{WINDOW_COLOUR_2}Návštěvníci na atrakci: {BLACK}{COMMA16} +STR_5740 :Nekonečné marketingové kampaně +STR_5741 :{SMALLFONT}{BLACK}Reklamní marketingové kampaně nikdy neskončí +STR_5742 :Autentizace ... +STR_5743 :Připojování ... +STR_5744 :Hledání adresy serveru ... +STR_5745 :Detekována desynchronizace se serverem +STR_5746 :Odpojeno +STR_5747 :Odpojeno: {STRING} +STR_5748 :Vyhozen +STR_5749 :Vypadněte z tohoto serveru! +STR_5750 :Spojení ukončeno +STR_5751 :Žádná data +STR_5752 :{OUTLINE}Hráč {RED}{STRING} se odpojil +STR_5753 :{OUTLINE}Hráč {RED}{STRING} se odpojil ({STRING}) +STR_5754 :Neplatné jméno hráče +STR_5755 :Nesprávná verze hry +STR_5756 :Špatné heslo +STR_5757 :Server je plný +STR_5758 :{OUTLINE}{GREEN}Hráč {STRING} se připojil do hry +STR_5759 :Stahování mapy ... ({INT32} / {INT32}) +STR_5760 :Hongkongský dolar (HK$) +STR_5761 :Tchajwanský dolar (NT$) +STR_5762 :Čínský jüan (CN{YEN}) +STR_5763 :Všechny soubory +STR_5764 :Neplatný typ atrakce +STR_5765 :Nelze upravovat atrakce neplatného typu +STR_5766 : +STR_5767 :Příjem +STR_5768 :Celkem zákazníků +STR_5769 :Celkový zisk +STR_5770 :Zákazníků za hodinu +STR_5771 :Cena údržby +STR_5772 :Stáří +STR_5773 :Celkem zákazníků: {COMMA32} +STR_5774 :Celkový zisk: {CURRENCY2DP} +STR_5775 :Zákazníci: {COMMA32} za hodinu +STR_5776 :Postaveno: letos +STR_5777 :Postaveno: minulý rok +STR_5778 :Postaveno: před {COMMA16} lety +STR_5779 :Příjem: {CURRENCY2DP} za hodinu +STR_5780 :Cena údržby: {CURRENCY2DP} za hodinu +STR_5781 :Cena údržby: neznámá +STR_5782 :Úspěšně připojeno. Chatujte stisknutím klávesy '{STRING}'. +STR_5783 :{WINDOW_COLOUR_2}Neodemčený scénář +STR_5784 :{BLACK}Pro odemčení tohoto scénáře dokončete předcházející scénáře +STR_5785 :Nelze přejmenovat skupinu... +STR_5786 :Neplatný název skupiny. +STR_5787 :{COMMA32} hráčů online +STR_5788 :Výchozí interval inspekcí: +STR_5789 :Vypnout blesky během bouřky +STR_5790 :{SMALLFONT}{BLACK}Přepíná ceny ve stylu RCT1{NEWLINE}(např. cenu vstupu i atrakce) +STR_5791 :{SMALLFONT}{BLACK}Nastaví spolehlivost všech atrakcí na 100% a rok jejich postavení na "letos" +STR_5792 :{SMALLFONT}{BLACK}Opraví všechny rozbité atrakce +STR_5793 :{SMALLFONT}{BLACK}Vymaže historii havárií atrakce{NEWLINE}(návštěvníci si přestanou stěžovat na bezpečnost) +STR_5794 :{SMALLFONT}{BLACK}V některých scénářích není možné{NEWLINE}provádět úpravy předem postavených atrakcí.{NEWLINE}Tento cheat zruší toto omezení +STR_5795 :{SMALLFONT}{BLACK}Návštěvníci navštěvují všechny atrakce,{NEWLINE}i když mají velmi vysokou intenzitu +STR_5796 :{SMALLFONT}{BLACK}Vynutí otevření nebo zavření parku +STR_5797 :{SMALLFONT}{BLACK}Zakáže změny počasí{NEWLINE}(v parku bude odteď pořád stejně) +STR_5798 :{SMALLFONT}{BLACK}Povolí stavění, když je hra zapauzována +STR_5799 :{SMALLFONT}{BLACK}Zakáže havárie atrakcí způsobené poruchou brzd +STR_5800 :{SMALLFONT}{BLACK}Atrakce nebudou mít poruchy -##################### -# Rides/attractions # -##################### -#WW +############################################################################### +## RCT2 Objects +############################################################################### +[AML1] +STR_NAME :Americké parní vlaky +STR_DESC :Miniaturní replika parní lokomotivy s tendrem táhne dřevěné vagóny s plátěnými střechami +STR_CPTY :6 míst v každém vagónu + +[CLIFT1] +STR_NAME :Kryté sedačkové lanovky +STR_DESC :Lanovka se sedačkami se střechou +STR_CPTY :2 místa na jedné sedačce + +[CLIFT2] +STR_NAME :Sedačkové lanovky +STR_DESC :Lanovka se sedačkami +STR_CPTY :2 místa na jedné sedačce + +[LIFT1] +STR_NAME :Výtahy +STR_DESC :Návštěvníci jezdí ve výtahu nahoru nebo dolů, aby se dostali z jednoho patra do druhého +STR_CPTY :16 návštěvníků + +[MONO1] +STR_NAME :Aerodynamické jednokolejné vlaky +STR_DESC :Velkokapacitní jodnokolejné vlaky s aerodynamickou přídí a zádí +STR_CPTY :5 nebo 10 míst v každém vagónu + +[MONO2] +STR_NAME :Malé jednokolejné vozy +STR_DESC :Malé jednokolejné vozy bez dveří +STR_CPTY :4 místa v každém voze + +[MONO3] +STR_NAME :Retro jednokolejné vlaky +STR_DESC :Retro jednokolejné vlaky bez oken +STR_CPTY :4 místa v každém voze + +[NRL] +STR_NAME :Parní vlaky +STR_DESC :Miniaturní replika parní lokomotivy s tendrem táhne dřevěné vagóny +STR_CPTY :6 míst v každém vagónu + +[NRL2] +STR_NAME :Parní vlaky s krytými vozy +STR_DESC :Miniaturní replika parní lokomotivy s tendrem táhne dřevěné vagóny s plátěnými střechami +STR_CPTY :6 míst v každém vagónu + +[SMONO] +STR_NAME :Zavěšené jednokolejné vlaky +STR_DESC :Velkokapacitní jodnokolejné vlaky +STR_CPTY :8 míst v každém vozu + +[TRAM1] +STR_NAME :Tramvaje +STR_DESC :Retro repliky tramvají +STR_CPTY :10 míst v každém vozu + +[4X4] +STR_NAME :Monster Trucks +STR_DESC :Obří auta s pohonem 4x4, které jsou schopna vyjíždět velmi strmé svahy +STR_CPTY :2 místa v každém vozu + +[CHBUILD] +STR_NAME :Křívý dům +STR_DESC :Budova s pokřivenými místnostmi a nakloněnými chodbami, které dezorientují návštěvníky +STR_CPTY :5 návštěvníků + +[CIRCUS1] +STR_NAME :Cirkus +STR_DESC :Zvířecí představení uvnitř velkého stanu +STR_CPTY :30 návštěvníků + +[CTCAR] +STR_NAME :Autodráha +STR_DESC :Malá autíčka jezdí po postavené dráze +STR_CPTY :2 místa v každém vozu + +[DODG1] +STR_NAME :Autodrom +STR_DESC :Autodrom s lektrickými autíčky +STR_CPTY :1 místo v každém voze + +[FSAUC] +STR_NAME :Létající talíře +STR_DESC :Autodrom se vznášedly +STR_CPTY :1 místo v každém voze + +[FWH1] +STR_NAME :Ruské kolo +STR_DESC :Velké otáčející se kolo s otevřenými sedadly +STR_CPTY :32 návštěvníků + +[GOLF1] +STR_NAME :Mini Golf +STR_DESC :Příjemná hra miniaturního golfu +STR_CPTY : + +[GTC] +STR_NAME :Vlak duchů +STR_DESC :Vozy ve tvaru příšer jezdí po vícepatrovém okruhu okolo strašidelných kulis a speciálních efektů +STR_CPTY :2 místa v každém vozu + +[HELICAR] +STR_NAME :Mini vrtulníky +STR_DESC :Po ocelové kolejnici jezdí miniaturní helikoptéry, ovládané šlapáním návštěvníků +STR_CPTY :2 místa v každém vozu + +[HHBUILD] +STR_NAME :Dům hrůzy +STR_DESC :Velká stará budova se stašidelnými chodbami a děsivými pokoji +STR_CPTY :15 návštěvníků + +[HMAZE] +STR_NAME :Bludiště +STR_DESC :Bludiště je postavené z 2 metrů vysokého živého plotu, nebo zdí. Návštěvníci v něm bloudí, dokud nenaleznou východ +STR_CPTY : + +[HMCAR] +STR_NAME :Strašidelná jízda velkým domem +STR_DESC :Vozy jezdí po vícepatrovém okruhu okolo strašidelných kulis a speciálních efektů +STR_CPTY :2 místa v každém vozu + +[HSKELT] +STR_NAME :Točitá skluzavka +STR_DESC :Dřevěná budova se schodištěm uvnitř a venkovní točitou skluzavkou, na které se jezdí s podložkami +STR_CPTY : + +[MGR1] +STR_NAME :Kolotoč +STR_DESC :Klasický kolotoč s vyřezávanými koníky +STR_CPTY :16 návštěvníků + +[MONBK] +STR_NAME :Jednokolejná jízdní kola +STR_DESC :Po ocelové kolejnici jezdí speciální jízdní kola, ovládané šlapáním návštěvníků +STR_CPTY :1 místo na každém kole + +[OBS1] +STR_NAME :Pozorovací věž +STR_DESC :Otáčející se pozorovací kabina, která postupně vyjíždí na vysokou věž +STR_CPTY :20 návštěvníků + +[OBS2] +STR_NAME :Dvoupatrová pozorovací věž +STR_DESC :Otáčející se dvoupatrová pozorovací věž, která postupně vyjíždí na vysokou věž +STR_CPTY :32 návštěvníků + +[RCR] +STR_NAME :Závodní auta +STR_DESC :Vozy ve tvaru závodních aut +STR_CPTY :1 místo v každém voze + +[SPCAR] +STR_NAME :Sportovní auta +STR_DESC :Vozy ve tvaru sportovních aut +STR_CPTY :2 místa v každém vozu + +[SRINGS] +STR_NAME :Vesmírné kruhy +STR_DESC :Tři v sobě zasazené rotující kruhy dají návštěvníkům možnost volného pohybu ve všech třech rozměrech +STR_CPTY :1 místo v každém kruhu + +[SUBMAR] +STR_NAME :Jízda ponorkou +STR_DESC :Návštěvníci vyrazí na podvodní jízdu v ponorce +STR_CPTY :4 návštěvníci v každé ponorce + +[TRUCK1] +STR_NAME :Pickupy +STR_DESC :Vozy ve tvaru nákladních aut (pickupů) +STR_CPTY :1 místo v každém voze + +[VCR] +STR_NAME :Veteráni +STR_DESC :Vozy ve tvaru veteránů jezdí po postavené dráze +STR_CPTY :2 místa v každém vozu + +[AMT1] +STR_NAME :Dulní horská dráha +STR_DESC :Horská dráha ve stylu dulních vlaků jezdí po ocelové horské dráze maskované jako staré koleje +STR_CPTY :2 nebo 4 místa v každém voze + +[ARRSW1] +STR_NAME :Zavěšené houpající se vozy +STR_DESC :Zavěšená horská dráha z volné zavěšených vozů, které se naklání při jízdě do zatáček +STR_CPTY :4 místa v každém voze + +[ARRSW2] +STR_NAME :Zavěšené houpající se aeroplány +STR_DESC :Zavěšená horská dráha z volné zavěšených vozů ve tvaru aeroplánu, které se naklání při jízdě do zatáček +STR_CPTY :4 místa v každém voze + +[ARRT1] +STR_NAME :Vývrtková horská dráha +STR_DESC :Malá ocelová horská dráha, na které vozy jezdí skrze lopinky a jezdí ve vývrtce +STR_CPTY :4 místa v každém voze + +[ARRT2] +STR_NAME :Hyper horská dráha +STR_DESC :Vysoká horská dráha s dlouhými pády, velkou rychlostí a pohodlnými vlaky, kde se jezdí s opěrkou v klíně +STR_CPTY :6 míst v každém voze + +[ARRX] +STR_NAME :Vícerozměrná horská dráha +STR_DESC :Vozy se sedadly schopny otáčet návštěvníky vzhůru nohama +STR_CPTY :4 místa v každém voze + +[BATFL] +STR_NAME :Houpající se vozy +STR_DESC :Málé houpající se vozy zavěšené na kolejnici +STR_CPTY :2 místa v každém vozu + +[BMAIR] +STR_NAME :Létající horská dráha +STR_DESC :Návštěvníci sedí v pohodlných sedadlech pod tratí cestující skrze propletenou dráhu, poskytující pocit letu +STR_CPTY :4 místa v každém voze + +[BMFL] +STR_NAME :Horská dráha bez podlahy +STR_DESC :Široká horská dráha bez podlahy poskytují návštěvníkům pocit volného vzduchu během jízdy skrze propletenou dráhu +STR_CPTY :4 místa v každém voze + +[BMRB] +STR_NAME :Hyperzakroucená dráha (široké vozy) +STR_DESC :Široké 4-místné vozy s vystouplým sezením a jednoduchou opěrkou v klíně +STR_CPTY :4 místa v každém voze + +[BMSD] +STR_NAME :Zakroucená horská dráha +STR_DESC :Široká ocelová horská dráha, na které vozy jedou po hladkých kolejnících skrze propletenou dráhu +STR_CPTY :4 místa v každém voze + +[BMSU] +STR_NAME :Horská dráha "na stojáka" +STR_DESC :Návětěvníci jedou ve stoje v širokých vozech se speciálně navrženým držením po propletené dráze s pády +STR_CPTY :4 místa v každém voze + +[BMVD] +STR_NAME :Horská dráha s volným pádem +STR_DESC :Extra-široké vozy letí dolů po zcela kolmé dráze a poskytují tím pocit volného pádu +STR_CPTY :4 místa v každém voze + +[BOB1] +STR_NAME :Horská bobová dráha +STR_DESC :Návštěvníci jedou po propletené bobové dráze +STR_CPTY :2 místa v každém vozu + +[GOLTR] +STR_NAME :Hyperzakroucená dráha +STR_DESC :Prostorné vozy trains s jednoduchou opěrkou v klíně +STR_CPTY :6 míst v každém voze + +[INTBOB] +STR_NAME :Létající zatáčky +STR_DESC :Návštěvníci jedou po propletené bobové dráze +STR_CPTY :6 míst v každém voze + +[INTINV] +STR_NAME :Horská dráha ve tvaru "U" +STR_DESC :Vozy vyrazí vstříc jednomu konci trati, poté prosviští pozpátku stanicí a vyletí až na druhý konec trati +STR_CPTY :4 místa v každém voze + +[INTST] +STR_NAME :Giga dráha +STR_DESC :Gigantická horská dráha schopna volných pádů a kopců přes 90 metrů dlouhých +STR_CPTY :4 místa v každém voze + +[IVMC1] +STR_NAME :Ostrá zavěšená horská dráha +STR_DESC :Vozy jsou zavěšeny na kolejnicích s ostrými zatáčkami a ostrými pády +STR_CPTY :4 místa v každém voze + +[JSTAR1] +STR_NAME :Tobogánová horská dráha +STR_DESC :Horská dráha ve stylu tobogánu s vozy se sedačkami za sebou +STR_CPTY :4 místa v každém voze + +[MFT] +STR_NAME :Horská dráha s malými vozy +STR_DESC :Horská dráha s dvoumístnými vozy bez předků +STR_CPTY :2 místa v každém vozu + +[NEMT] +STR_NAME :Zavěšená horská dráha +STR_DESC :Vozy jsou zavěšeny na kolejnicích se zatáčkami, pády a lopinky +STR_CPTY :4 místa v každém voze + +[PMT1] +STR_NAME :Důlní jízda +STR_DESC :Horská dráha s vozy ve stylu důlních vagónů, které jedou po hladkých kolejnících skrze propletenou dráhu +STR_CPTY :2 nebo 4 místa v každém voze + +[PREMT1] +STR_NAME :Horská dráha s elektromotorem +STR_DESC :Horská dráha s vozy poháněnými elektromotorem, které sviští skrze propletenou dráhu +STR_CPTY :4 místa v každém voze + +[PTCT1] +STR_NAME :Dřevěná horská dráha +STR_DESC :Dřevěná horská dráha s vozy s polstrovanými sedadly a opěrkou v klína +STR_CPTY :4 místa v každém voze + +[PTCT2] +STR_NAME :Dřevěná horská dráha (6 sedadel) +STR_DESC :Dřevěná horská dráha s vozy s polstrovanými sedadly a opěrkou v klína +STR_CPTY :6 míst v každém voze + +[PTCT2R] +STR_NAME :Dřevěná horská dráha (6 sedadel, pozpátku) +STR_DESC :Dřevěná horská dráha s vozy s polstrovanými sedadly a opěrkou v klína, na které se jezdí pozpátku +STR_CPTY :6 míst v každém voze + +[RCKC] +STR_NAME :Raketová auta +STR_DESC :Horská dráha s vozy vypadjícími jako rakety +STR_CPTY :4 místa v každém voze + +[REVCAR] +STR_NAME :Otáčivá horská dráha +STR_DESC :Po dřevěné dráze jedou vozy, které se ve speciálních místech se otočí a jedou pozpátku +STR_CPTY :6 míst v každém voze + +[REVF1] +STR_NAME :Volný pád pozpátku +STR_DESC :Velká dráha s vozem pro volný pád pozpátku +STR_CPTY :8 návštěvníků + +[SBOX] +STR_NAME :Závodní dřevěné vozy +STR_DESC :Návštěvníci jezdí v dřevených závodních vozech po jednokolejné horské dráze +STR_CPTY :4 místa v každém voze + +[SCHT1] +STR_NAME :Horská dráha +STR_DESC :Horská dráha s lopinky, po které jezdí vozy s opěrkou v klíně +STR_CPTY :4 místa v každém voze + +[SFRIC1] +STR_NAME :Horská dráha s bočním uchycením +STR_DESC :Po dráze jezdí vozy, které mají kola horizontálně uložená pod podlahou a opírají se jimi o stěny dráhy +STR_CPTY :4 místa v každém voze + +[SKYTR] +STR_NAME :Mini zavěšená létající horská dráha +STR_DESC :Návštěvníci jedou na jednokolejné trati vleže hlavou dolů, zavěšeni ve speciálním voze, který se v zatáčkách houpe +STR_CPTY :1 místo v každém voze + +[SLCFO] +STR_NAME :Obrácená zavěšená horská dráha +STR_DESC :Návštěvníci sedí po dvou zavěšení pod tratí a vidí dopředu nebo dozadu podle toho, jak zrovna jedou skrze lopinky a ostré zatáčky +STR_CPTY :4 místa v každém voze + +[SLCT] +STR_NAME :Malá zavěšená horská dráha +STR_DESC :Návštěvníci sedí po dvou zavěšení pod tratí a jedou skrze lopinky a ostré zatáčky +STR_CPTY :2 místa v každém vozu + +[SMC1] +STR_NAME :Myší vozy +STR_DESC :Vozy ve tvaru myší +STR_CPTY :4 místa v každém voze + +[SMC2] +STR_NAME :Dulní vozy +STR_DESC :Vozy ve tvaru dřevěných dulních vagónů +STR_CPTY :4 místa v každém voze + +[SPDRCR] +STR_NAME :Spiralní horská dráha +STR_DESC :Malá ocelová horská dráha se spirálovitým profilem a vozy se sedadly za sebou +STR_CPTY :6 míst v každém voze + +[STEEP1] +STR_NAME :Dostihy +STR_DESC :Vozy ve tvaru koní vozí návštěvníky po jednokolejné trati +STR_CPTY :2 místa na každém koni + +[STEEP2] +STR_NAME :Závody motorek +STR_DESC :Vozy ve tvaru motorek vozí návštěvníky po jednokolejné trati +STR_CPTY :2 místa na každé motorce + +[THCAR] +STR_NAME :Svislá dráha na stlačený vzduch +STR_DESC :Po mocném startu na stlačený vzduch se vozy rozjedou po svislé dráze, přes vrchol a svisle dolů zpět do stanice +STR_CPTY :2 místa v každém vozu + +[TOGST] +STR_NAME :Horská dráha "na stojáka" +STR_DESC :Návětěvníci jedou po horské dráze ve stoje +STR_CPTY :4 místa v každém voze + +[UTCAR] +STR_NAME :Zatočené vozy +STR_DESC :Horská dráha, která se točí dokola tak, že návštěvníci jsou pořád na stejném místě. +STR_CPTY :4 místa v každém voze + +[UTCARR] +STR_NAME :Zatočené vozy (pozpátku) +STR_DESC :Horská dráha, která se točí dokola tak, že návštěvníci jsou pořád na stejném místě. +STR_CPTY :4 místa v každém voze + +[VEKDV] +STR_NAME :Zavěšená svislá dráha +STR_DESC :Návštěvníci sedí ve vozrech zavěšených pod tratí, jedou pozpátku nahoru po svislé dráze, padají dolů a jezdí skrze lopinky s ostrými zatáčkami +STR_CPTY :4 místa v každém voze + +[VEKST] +STR_NAME :Horská dráha "na ležáka" +STR_DESC :Návštěvníci jedou v leže zavěšeni do speciálního držení, ve kterém na břiše projedou trať s ostrými zatáčkami +STR_CPTY :4 místa v každém voze + +[VEKVAMP] +STR_NAME :Houpající se vozy bez podlahy +STR_DESC :Zavěšená horská dráha připomínající sedačkovou lanovku, houpající se v zatáčkách +STR_CPTY :2 místa v každém vozu + +[VREEL] +STR_NAME :Virginský moták +STR_DESC :Kulaté vozy se točí během jízdy po cik-cak dřevěné trati +STR_CPTY :4 místa v každém voze + +[WCATC] +STR_NAME :Automobilové vozy +STR_DESC :Horská dráha s vozy, které připomínají automobily +STR_CPTY :4 místa v každém voze + +[WMMINE] +STR_NAME :Dřevěná divoká dulní jízda +STR_DESC :Malinké dulí vozy jedou po cik-cak dřevěné trati a silně se naklání v ostrých zatáčkách a drsných pádech +STR_CPTY :2 místa v každém vozu + +[WMOUSE] +STR_NAME :Dřevěná divoká myš +STR_DESC :Malé vozy ve tvaru myší jedou po dřevěné trati a silně se naklání v ostrých zatáčkách a drsných pádech +STR_CPTY :2 místa v každém vozu + +[WMSPIN] +STR_NAME :Točící se divoká myš +STR_DESC :Vozy ve tvaru myší jedou po dřevěné trati a pro dezorientaci návštěvníků se točí, zatímco se naklání v ostrých zatáčkách a drsných pádech +STR_CPTY :4 místa v každém voze + +[ZLDB] +STR_NAME :Beruščiny vozy +STR_DESC :Horská dráha s vozy ve tvaru malých berušek +STR_CPTY :2 místa v každém vozu + +[ZLOG] +STR_NAME :Kládové vozy +STR_DESC :Horská dráha s vozy ve tvaru klád +STR_CPTY :2 místa v každém vozu + +[C3D] +STR_NAME :3D Kino +STR_DESC :Kin promítající 3D filmy uvnitř duté kulovité konstrukce +STR_CPTY :20 návštěvníků + +[ENTERP] +STR_NAME :Loď Enterprise +STR_DESC :Otáčející se kolo se zavěšenými kabinami, které se napřed roztočí a pak se zvedne na pomocné podpěře +STR_CPTY :16 návštěvníků + +[GDROP1] +STR_NAME :Roto-pád +STR_DESC :Kruh sedadel je za pomalé rotace vytažen navrchol vysoké věže, spuštěn volným pádem k zemi a opatrně zastaven pomocí magnetických brzd +STR_CPTY :16 návštěvníků + +[KART1] +STR_NAME :Motokáry +STR_DESC :Benzínové ovladatelné motokáry +STR_CPTY :1 místo v každém voze + +[MCARPET1] +STR_NAME :Kouzelný koberec +STR_DESC :Velký vůz připomínající koberec se pohybuje krouživými pohyby hýbe nahoru a dolů za pomoci 4 ramen +STR_CPTY :12 návštěvníků + +[SIMPOD] +STR_NAME :Simulátor pohybu +STR_DESC :Návštěvníci sledují film uvnitř simulátoru pohybu, zatímco se simulátorem hýbe hydraulika +STR_CPTY :8 návštěvníků + +[SSC1] +STR_NAME :Volný pád +STR_DESC :Vůz pro volný pád je pneumaticky vystřeleno vzhůru po vysoké ocelové věži a následně volně padá k zemi +STR_CPTY :8 návštěvníků + +[SWSH1] +STR_NAME :Piratská loď +STR_DESC :Velká houpající se pirátská loď +STR_CPTY :16 návštěvníků + +[SWSH2] +STR_NAME :Houpající se obrácená loď +STR_DESC :Loď je připevněna na porpěru, která se chová jako protizávaží a otáčí se o 360 stupňů +STR_CPTY :12 návštěvníků + +[TOPSP1] +STR_NAME :Top Spin +STR_DESC :Návštěvníci sedí v gondole zavěšené na podpěrách, otáčející se dopředu a dozadu vzhůru nohama +STR_CPTY :8 návštěvníků + +[TWIST1] +STR_NAME :Twist +STR_DESC :Návštěvníci sedí po dvou v jedné ze tří kabin, které kolem sebe rotují +STR_CPTY :18 návštěvníků + +[TWIST2] +STR_NAME :Sněhové kalíšky +STR_DESC :Návštěvníci sedí po dvou v kalíšcích, které se otáčejí okolo sněhuláka uprostřed +STR_CPTY :18 návštěvníků + +[BBOAT] +STR_NAME :Malé čluny +STR_DESC :Malé čluny s motorovým pohonem ovládaným návštěvníky +STR_CPTY :2 místa v každé lodi + +[CBOAT] +STR_NAME :Kánoe +STR_DESC :Dlouhé kánoe, u kterých musí návštěvníci pádlovat +STR_CPTY :2 místa v každé lodi + +[CSTBOAT] +STR_NAME :Lodě horské dráhy +STR_DESC :Lodě ve tvaru vozů horské dráhy +STR_CPTY :6 míst v každé lodi + +[DING1] +STR_NAME :Nafukovací čluny +STR_DESC :Návštěvníci jedou v nafukovacích člunech po tobogánu +STR_CPTY :2 místa v každé lodi + +[JSKI] +STR_NAME :Vodní lyže +STR_DESC :Návštěvníci jezdí na vodních lyžích +STR_CPTY :1 místo na každých lyžích + +[LFB1] +STR_NAME :Divoká řeka +STR_DESC :Lodě ve tvaru klád se plaví po vodním kanálu a cákají. Nikdo nezůstane suchý +STR_CPTY :4 místa v každé lodi + +[RAPBOAT] +STR_NAME :Divoká voda +STR_DESC :Kulaté lodě se plaví po meandrech na vodním kanále a sjíždějí pěnící peřeje +STR_CPTY :8 míst v každé lodi + +[RBOAT] +STR_NAME :Veslice +STR_DESC :Veslice, u kterých musí návštěvníci veslovat +STR_CPTY :2 místa v každé lodi + +[RFTBOAT] +STR_NAME :Říční rafty +STR_DESC :Rafty se plaví po meandrech na vodním kanále +STR_CPTY :4 místa na každém raftu + +[SPBOAT] +STR_NAME :Cákající lodě +STR_DESC :Velkokapacitní lodě se plaví po vodním kanále, poháněny do pásem do strmých úseků, zrychlují sjíždením svahů a namočí návštěvníky pořádným šplouchnutím +STR_CPTY :16 míst na každé lodi + +[SWANS] +STR_NAME :Labutě +STR_DESC :Lodě ve tvaru labutí, ovládáné šlapaním návštěvníků +STR_CPTY :4 místa na každém raftu + +[TRIKE] +STR_NAME :Vodní tricykly +STR_DESC :Šlapadla ve tvaru tricyklů s velkými plovoucími koly +STR_CPTY :2 místa na každém kole + +[ATM1] +STR_NAME :Bankomat +STR_DESC :Bankomat pro návštěvníky, kterým by došla hotovost + +[BALLN] +STR_NAME :Stánek s balónky +STR_DESC :Stánek se suvenýry - balónky, plněnými héliem + +[BNOODLES] +STR_NAME :Stánek s hovězími nudlemi +STR_DESC :Stánek prodávající čínské hovězí nudle + +[BURGB] +STR_NAME :Stánek s burgery +STR_DESC :Stánek ve tvaru burgeru podávající burgery + +[CHCKS] +STR_NAME :Stánek se smaženým kuřetem +STR_DESC :Stánek prodávající kyblíky smaženého kuřete + +[CHKNUG] +STR_NAME :Stánek s kuřecími nugety +STR_DESC :Stánek prodávající kuřecí nugety + +[CHPSH] +STR_NAME :Stánek s hranolkami +STR_DESC :Stánek prodávající hranolky + +[CHPSH2] +STR_NAME :Stánek s hranolkami +STR_DESC :Stánek prodávající hranolky + +[CINDR] +STR_NAME :Stánek s suzungkwa +STR_DESC :Stánek prodávající suzungkwa + +[CNDYF] +STR_NAME :Stánek s cukrovou vatou +STR_DESC :Stánek prodávající cukrovou vatu + +[COFFS] +STR_NAME :Stánek s kávou +STR_DESC :Hezky vypadající stánek prodávající kávu + +[COOKST] +STR_NAME :Stánek se sušenkami +STR_DESC :Stánek prodávající gigantické sušenky + +[DOUGH] +STR_NAME :Stánek s koblížky +STR_DESC :Stánek prodávající americké koblížky + +[DRNKS] +STR_NAME :Stánek s pitím +STR_DESC :Stánek ve tvaru plechovky prodávající perlivé nápoje + +[FAID1] +STR_NAME :První pomoc +STR_DESC :Místo pro návštěvníky, kterým by se udělalo nevolno, které napomáhá brzkému uzdravení + +[FRNOOD] +STR_NAME :Stánek se smaženými nudlemi +STR_DESC :Stánek prodávající čínské rýžové smažené nudle + +[FUNCAKE] +STR_NAME :Stánek s palačinkami +STR_DESC :Stánek prodávající palačinky + +[HATST] +STR_NAME :Stánek s čepicemi +STR_DESC :Stánek se suvenýry - pěnovými čepicemi + +[HCHOC] +STR_NAME :Stánek s horkou čokoládou +STR_DESC :Stánek prodávající horkou čokoládu + +[HOTDS] +STR_NAME :Stánek s párky v rohlíku +STR_DESC :Stánek prodávající párky v rohlíku + +[ICECR1] +STR_NAME :Stánek s nanuky +STR_DESC :Stánek prodávající různé druhy nanuků + +[ICECR2] +STR_NAME :Stánek se zmrzlinou +STR_DESC :Stánek prodávající kornouty zmrzliny + +[ICETST] +STR_NAME :Stánek s ledovým čajem +STR_DESC :Stánek prodávající různé druhy ledového čaje + +[INFOK] +STR_NAME :Kiosek +STR_DESC :Stínek s informacemi o parku, prodávající mapy a deštníky + +[LEMST] +STR_NAME :Stánek s limonádou +STR_DESC :Stánek prodávající osvěžující citronádu + +[MBSOUP] +STR_NAME :Stánek s polévkou +STR_DESC :Stánek prodávající čínskou knedlíčkovou polévku + +[PIZZS] +STR_NAME :Stánek s pizzou +STR_DESC :Stánek prodávající kusy pizzy + +[POPCS] +STR_NAME :Stánek s popcornem +STR_DESC :Stánek prodávající obrovské kelímky popcornu + +[PRETST] +STR_NAME :Stánek s preclíky +STR_DESC :Stánek prodávající křupavé preclíky + +[RSAUS] +STR_NAME :Stánek s klobásami +STR_DESC :Stánek prodávající grilované klobásy + +[SOUVS] +STR_NAME :Stánek se suvenýry +STR_DESC :Stánek prodávající seuvenýry - plyšáky a deštníky + +[SOYBEAN] +STR_NAME :Stánek s mlékem +STR_DESC :Stánek prodávající kelímky sojového mléka + +[SQDST] +STR_NAME :Stánek s plody moře +STR_DESC :Stánek prodávající smažená chapadla + +[STARFRDR] +STR_NAME :Stánek s džusy +STR_DESC :Stánek prodávající ovocné nápoje + +[SUBSTL] +STR_NAME :Stánek se sendviči +STR_DESC :Stánek prodávající čerstvé sendviče + +[SUNGST] +STR_NAME :Stánek s brýlemi +STR_DESC :Stánek prodávající mnoho různých druhů slunečních brýlí + +[TLT1] +STR_NAME :Toalety +STR_DESC :Toalety, usazené v betonové zástavbě + +[TLT2] +STR_NAME :Toalety +STR_DESC :Toilets, usazené v dřevěné zástavbě + +[TOFFS] +STR_NAME :Stánek s jablky v županu +STR_DESC :Stánek prodávající jablka v županu na tyčce + +[TSHRT] +STR_NAME :Stánek s tričky +STR_DESC :Stánek se suvenýry - tričky + +[WONTON] +STR_NAME :Stánek s čínskou polévkou +STR_DESC :Stánek prodávající čínskou knedlíčkovou polévku + +[ALLSORT1] +STR_NAME :Cukroví + +[ALLSORT2] +STR_NAME :Cukroví + +[BADSHUT] +STR_NAME :Pérák + +[BADSHUT2] +STR_NAME :Pérák + +[BALL1] +STR_NAME :Americký fotbal + +[BALL2] +STR_NAME :Americký fotbal + +[BALL3] +STR_NAME :Fotbal + +[BALL4] +STR_NAME :Tenisový míček + +[BEANST1] +STR_NAME :Obrovský stonek + +[BEANST2] +STR_NAME :Obrovský stonek + +[BRBASE] +STR_NAME :Základní blok + +[BRBASE2] +STR_NAME :Základní blok + +[BRBASE3] +STR_NAME :Základní blok + +[BRCRRF1] +STR_NAME :Zatočená střecha + +[BRCRRF2] +STR_NAME :Zatočená střecha + +[CARROT] +STR_NAME :Obrovská mrkev + +[CHBBASE] +STR_NAME :Blok šachovnice + +[CHEST1] +STR_NAME :Truhla s pokladem + +[CHEST2] +STR_NAME :Truhla s pokladem + +[CHOCROOF] +STR_NAME :Tabulka čokolády + +[CNBALLS] +STR_NAME :Kanónové koule + +[CNDYRK1] +STR_NAME :Sladká tyčinka + +[COLAGUM] +STR_NAME :Gumové cukrovinky + +[CORROOF] +STR_NAME :Kovová střecha + +[CORROOF2] +STR_NAME :Kovová stěna + +[CWBCRV32] +STR_NAME :Zatočená stěna + +[CWBCRV33] +STR_NAME :Zatočený blok + +[CWFCRV32] +STR_NAME :Zatočená stěna + +[CWFCRV33] +STR_NAME :Zatočený blok + +[Tráva1] +STR_NAME :Obrovská kapradina + +[GGRS1] +STR_NAME :Obrovská tráva + +[HANG1] +STR_NAME :Gilotina + +[HELMET1] +STR_NAME :Helma na americký fotbal + +[ICECUBE] +STR_NAME :Koskta ledu + +[IGROOF] +STR_NAME :Střecha iglů + +[JBEAN1] +STR_NAME :Lentilka + +[JELBAB1] +STR_NAME :Želatinový medvídci + +[JELDROP1] +STR_NAME :Ovocné bonbony + +[JELDROP2] +STR_NAME :Ovocné bonbony + +[JNGROOF1] +STR_NAME :Střecha + +[LOLLY1] +STR_NAME :Lízátko + +[MALLOW1] +STR_NAME :Maršmeloun + +[MALLOW2] +STR_NAME :Maršmeloun + +[MINROOF1] +STR_NAME :Střecha + +[MINT1] +STR_NAME :Máta + +[MMENT1] +STR_NAME :Ornament + +[MMENT2] +STR_NAME :Ornament + +[MMENT3] +STR_NAME :Ornament + +[PAGROOF1] +STR_NAME :Střecha + +[PIPE32] +STR_NAME :Část trubky + +[PIPE32J] +STR_NAME :Část trubky + +[PIPE8] +STR_NAME :Část trubky + +[PIRFLAG] +STR_NAME :Pirátská vlajka + +[PIRROOF1] +STR_NAME :Střecha + +[PIRROOF2] +STR_NAME :Střecha + +[PRCAN] +STR_NAME :Kanón + +[ROMROOF1] +STR_NAME :Střecha + +[ROMROOF2] +STR_NAME :Sloup + +[ROOF1] +STR_NAME :Střecha + +[ROOF10] +STR_NAME :Střecha + +[ROOF11] +STR_NAME :Střecha + +[ROOF12] +STR_NAME :Střecha + +[ROOF13] +STR_NAME :Střecha + +[ROOF14] +STR_NAME :Střecha + +[ROOF2] +STR_NAME :Střecha + +[ROOF3] +STR_NAME :Střecha + +[ROOF4] +STR_NAME :Střecha + +[ROOF5] +STR_NAME :Střecha + +[ROOF6] +STR_NAME :Střecha + +[ROOF7] +STR_NAME :Střecha + +[ROOF8] +STR_NAME :Střecha + +[ROOF9] +STR_NAME :Střecha + +[SKTBASE] +STR_NAME :Blok + +[SKTBASET] +STR_NAME :Blok + +[SKTDW] +STR_NAME :Stěna + +[SKTDW2] +STR_NAME :Stěna + +[SMSKULL] +STR_NAME :Lebka + +[SPCROOF1] +STR_NAME :Střecha + +[STBASE] +STR_NAME :Ocelový blok + +[STLBASET] +STR_NAME :Ocelový blok + +[STLDW] +STR_NAME :Ocelová stěna + +[STLDW2] +STR_NAME :Ocelová stěna + +[SUMRF] +STR_NAME :Střecha + +[SUPPLEG1] +STR_NAME :Tyč + +[SUPPLEG2] +STR_NAME :Tyč + +[SUPPW1] +STR_NAME :Podpěra + +[SUPPW2] +STR_NAME :Podpěra + +[SUPPW3] +STR_NAME :Podpěra + +[TAC] +STR_NAME :Cypřiš + +[TAL] +STR_NAME :Strom ve tvaru aligátora + +[TAP] +STR_NAME :Borovice + +[TAS] +STR_NAME :Osika + +[TAS1] +STR_NAME :Strom sladkostí + +[TAS2] +STR_NAME :Strom sladkostí + +[TAS3] +STR_NAME :Strom sladkostí + +[TAS4] +STR_NAME :Cukroví + +[TB1] +STR_NAME :Bílý střelec + +[TB2] +STR_NAME :Černý střelec + +[TBC] +STR_NAME :Kaktus + +[TBN] +STR_NAME :Kost + +[TBN1] +STR_NAME :Kosti + +[TBP] +STR_NAME :Topol + +[TBR] +STR_NAME :Rákos + +[TBR1] +STR_NAME :Barel + +[TBR2] +STR_NAME :Barel + +[TBR3] +STR_NAME :Barel + +[TBR4] +STR_NAME :Barel + +[TBW] +STR_NAME :Rozbité kolo + +[TCB] +STR_NAME :Strom ve tvaru kyje + +[TCC] +STR_NAME :Cedr + +[TCD] +STR_NAME :Kotel + +[TCE] +STR_NAME :Jilm + +[TCF] +STR_NAME :Jedle + +[TCFS] +STR_NAME :Zasněžená Jedle + +[TCJ] +STR_NAME :Jalovec + +[TCL] +STR_NAME :Libanonský cedr + +[TCN] +STR_NAME :Kanón + +[TCO] +STR_NAME :Dub + +[TCRP] +STR_NAME :Borovice + +[TCT] +STR_NAME :Zelný strom + +[TCT1] +STR_NAME :Hradní věž + +[TCT2] +STR_NAME :Hradní věž + +[TCY] +STR_NAME :Tis + +[TDM] +STR_NAME :Strom ve tvaru diamantu + +[TDN4] +STR_NAME :Dinosaurus + +[TDN5] +STR_NAME :Dinosaurus + +[TDT1] +STR_NAME :Uschlý strom + +[TDT2] +STR_NAME :Uschlý strom + +[TDT3] +STR_NAME :Uschlý strom + +[TEEPEE1] +STR_NAME :Týpí + +[TEL] +STR_NAME :Modřín + +[TEN] +STR_NAME :Kleopatřina jehla + +[TEP] +STR_NAME :Egyptský sloup + +[TERB] +STR_NAME :Kamenný blok + +[TERS] +STR_NAME :Rozbitá socha + +[TES1] +STR_NAME :Egyptská socha + +[TF1] +STR_NAME :Ovocný strom + +[TF2] +STR_NAME :Ovocný strom + +[TGC1] +STR_NAME :Socha + +[TGC2] +STR_NAME :Socha + +[TGG] +STR_NAME :Gong + +[TGHC] +STR_NAME :Hinoki cypřiš + +[TGHC2] +STR_NAME :Maďarský cypřiš + +[TGS] +STR_NAME :Socha žirafy + +[TGS1] +STR_NAME :Náhrobek + +[TGS2] +STR_NAME :Náhrobek + +[TGS3] +STR_NAME :Náhrobek + +[TGS4] +STR_NAME :Náhrobek + +[TH1] +STR_NAME :Palma + +[TH2] +STR_NAME :Palma + +[THL] +STR_NAME :Dřezovec trojtrnný + +[THRS] +STR_NAME :Socha jezdce + +[THT] +STR_NAME :Strom ve tvaru srdce + +[TIC] +STR_NAME :Cedr + +[TIG] +STR_NAME :Iglů + +[TITC] +STR_NAME :Italský cypřiš + +[TJB1] +STR_NAME :Křoví + +[TJB2] +STR_NAME :Křoví + +[TJB3] +STR_NAME :Křoví + +[TJB4] +STR_NAME :Křoví + +[TJF] +STR_NAME :Květina + +[TJP1] +STR_NAME :Rostlina + +[TJP2] +STR_NAME :Rostlina + +[TJT1] +STR_NAME :Strom + +[TJT2] +STR_NAME :Strom + +[TJT3] +STR_NAME :Strom + +[TJT4] +STR_NAME :Strom + +[TJT5] +STR_NAME :Strom + +[TJT6] +STR_NAME :Strom + +[TK1] +STR_NAME :Bílý kůň + +[TK2] +STR_NAME :Černý kůň + +[TK3] +STR_NAME :Bílý král + +[TK4] +STR_NAME :Černý král + +[TL0] +STR_NAME :Strom + +[TL1] +STR_NAME :Strom + +[TL2] +STR_NAME :Strom + +[TL3] +STR_NAME :Strom + +[TLC] +STR_NAME :Lawsonův cypřiš + +[TLP] +STR_NAME :Lombardský topol + +[TLY] +STR_NAME :Lilie + +[TM0] +STR_NAME :Strom + +[TM1] +STR_NAME :Strom + +[TM2] +STR_NAME :Strom + +[TM3] +STR_NAME :Strom + +[TMBJ] +STR_NAME :Modrý jalovec + +[TMC] +STR_NAME :Montereyův cypřiš + +[TMG] +STR_NAME :Mongolský strom + +[TMJ] +STR_NAME :Odpad + +[TML] +STR_NAME :Polena + +[TMM1] +STR_NAME :Velký náhrobek + +[TMM2] +STR_NAME :Velký náhrobek + +[TMM3] +STR_NAME :Velký náhrobek + +[TMO1] +STR_NAME :Marťanský objekt + +[TMO2] +STR_NAME :Marťanský objekt + +[TMO3] +STR_NAME :Marťanský objekt + +[TMO4] +STR_NAME :Marťanský objekt + +[TMO5] +STR_NAME :Marťanský objekt + +[TMP] +STR_NAME :Blahočet chilský + +[TMS1] +STR_NAME :Muchomůrka + +[TMW] +STR_NAME :Kola + +[TMZP] +STR_NAME :Borovice Montezumova + +[TNS] +STR_NAME :Smrk ztepilý + +[TNSS] +STR_NAME :Zasněžený smrk ztepilý + +[TNTROOF1] +STR_NAME :Plátěná střecha + +[TOH1] +STR_NAME :Dům + +[TOH2] +STR_NAME :Dům + +[TOH3] +STR_NAME :Budova + +[TORN1] +STR_NAME :Ornamentální strom + +[TORN2] +STR_NAME :Ornamentální strom + +[TOS] +STR_NAME :Socha + +[TOT1] +STR_NAME :Strom + +[TOT2] +STR_NAME :Strom + +[TOT3] +STR_NAME :Strom + +[TOT4] +STR_NAME :Strom + +[TOTEM1] +STR_NAME :Totem + +[TP1] +STR_NAME :Bílá pěšák + +[TP2] +STR_NAME :Černý pěšák + +[TPM] +STR_NAME :Palma + +[TQ1] +STR_NAME :Bílá královna + +[TQ2] +STR_NAME :Černá královna + +[TR1] +STR_NAME :Bílá věž + +[TR2] +STR_NAME :Černá věž + +[TRC] +STR_NAME :Římský sloup + +[TRF] +STR_NAME :Jedle nádherná + +[TRF2] +STR_NAME :Jedle nádherná + +[TRF3] +STR_NAME :Zasněžená jedle nádherná + +[TRFS] +STR_NAME :Zasněžená jedle nádherná + +[TRMS] +STR_NAME :Římská socha + +[TROPT1] +STR_NAME :Strom + +[TRWS] +STR_NAME :Římská socha + +[TS0] +STR_NAME :Strom + +[TS1] +STR_NAME :Strom + +[TS2] +STR_NAME :Strom + +[TS3] +STR_NAME :Strom + +[TS4] +STR_NAME :Ornamentální strom + +[TS5] +STR_NAME :Ornamentální strom + +[TS6] +STR_NAME :Ornamentální strom + +[TSB] +STR_NAME :Bříza bělokorá + +[TSC] +STR_NAME :Kaktus + +[TSC2] +STR_NAME :Stavba + +[TSCP] +STR_NAME :Vesmírná loď + +[TSD] +STR_NAME :Strom ve tvaru listu + +[TSF1] +STR_NAME :Obrovská vločka + +[TSF2] +STR_NAME :Obrovská vločka + +[TSF3] +STR_NAME :Obrovská vločka + +[TSH] +STR_NAME :Socha koně + +[TSH0] +STR_NAME :Křoví + +[TSH1] +STR_NAME :Keř + +[TSH2] +STR_NAME :Křoví + +[TSH3] +STR_NAME :Křoví + +[TSH4] +STR_NAME :Keř + +[TSH5] +STR_NAME :Křoví + +[TSM] +STR_NAME :Sněhulák + +[TSNB] +STR_NAME :Sněhová koule + +[TSNC] +STR_NAME :Dřevostavba + +[TSP] +STR_NAME :Borovice lesní + +[TSP1] +STR_NAME :Strom + +[TSP2] +STR_NAME :Strom + +[TSPH] +STR_NAME :Dům + +[TSQ] +STR_NAME :Squirrel Shaped Tree + +[TST1] +STR_NAME :Muchomůrka + +[TST2] +STR_NAME :Muchomůrka + +[TST3] +STR_NAME :Muchomůrka + +[TST4] +STR_NAME :Muchomůrka + +[TST5] +STR_NAME :Muchomůrka + +[TSTD] +STR_NAME :Socha delfína + +[TT1] +STR_NAME :Římský palác + +[TTG] +STR_NAME :Cíl + +[TUS] +STR_NAME :Socha jednorožce + +[TVL] +STR_NAME :Štědřenec + +[TWH1] +STR_NAME :Dům + +[TWH2] +STR_NAME :Dýňový dům + +[TWN] +STR_NAME :Ořešák královský + +[TWP] +STR_NAME :Topol bílý + +[TWW] +STR_NAME :Vrba + +[WAG1] +STR_NAME :Vagón + +[WAG2] +STR_NAME :Vagón + +[WDBASE] +STR_NAME :Dřevěný blok + +[TDF] +STR_NAME :Fontána delfína + +[TEF] +STR_NAME :Fontána slona + +[TQF] +STR_NAME :Fontána amorka + +[TTF] +STR_NAME :Fontána + +[TWF] +STR_NAME :Geometrická fontána + +[TCK] +STR_NAME :Hodiny + +[TG1] +STR_NAME :Zahrady + +[TG10] +STR_NAME :Zahrady + +[TG11] +STR_NAME :Zahrady + +[TG12] +STR_NAME :Zahrady + +[TG13] +STR_NAME :Zahrady + +[TG14] +STR_NAME :Zahrady + +[TG15] +STR_NAME :Zahrady + +[TG16] +STR_NAME :Zahrady + +[TG17] +STR_NAME :Zahrady + +[TG18] +STR_NAME :Zahrady + +[TG19] +STR_NAME :Zahrady + +[TG2] +STR_NAME :Zahrady + +[TG20] +STR_NAME :Zahrady + +[TG21] +STR_NAME :Zahrady + +[TG3] +STR_NAME :Zahrady + +[TG4] +STR_NAME :Zahrady + +[TG5] +STR_NAME :Zahrady + +[TG6] +STR_NAME :Zahrady + +[TG7] +STR_NAME :Zahrady + +[TG8] +STR_NAME :Zahrady + +[TG9] +STR_NAME :Zahrady + +[BUTTFLY] +STR_NAME :Motýl + +[COG1] +STR_NAME :Ozubené kolo + +[COG1R] +STR_NAME :Ozubené kolo + +[COG1U] +STR_NAME :Ozubené kolo + +[COG1UR] +STR_NAME :Ozubené kolo + +[COG2] +STR_NAME :Malé ozubené kolo + +[COG2R] +STR_NAME :Malé ozubené kolo + +[COG2U] +STR_NAME :Malé ozubené kolo + +[COG2UR] +STR_NAME :Malé ozubené kolo + +[FIRE1] +STR_NAME :Plameny + +[SNAIL] +STR_NAME :Šnek + +[SPIDER1] +STR_NAME :Pavouk + +[TGH1] +STR_NAME :Socha + +[TGH2] +STR_NAME :Socha + +[TSG] +STR_NAME :Bažina + +[TSK] +STR_NAME :Lebka + +[TSMP] +STR_NAME :Dýně + +[WASP] +STR_NAME :Vosa + +[WDIAG] +STR_NAME :Fontána + +[WHORIZ] +STR_NAME :Vodní proud + +[WSPOUT] +STR_NAME :Vodní chrlič + +[GEOROOF1] +STR_NAME :Skleněná střecha + +[GEOROOF2] +STR_NAME :Skleněná střecha + +[TGE1] +STR_NAME :Geometrická socha + +[TGE2] +STR_NAME :Geometrická socha + +[TGE3] +STR_NAME :Geometrická socha + +[TGE4] +STR_NAME :Geometrická socha + +[TGE5] +STR_NAME :Geometrická socha + +[BADRACK] +STR_NAME :Raketa na badminton + +[GENSTORE] +STR_NAME :Obchod se smíšeným zbožím + +[MDSAENT] +STR_NAME :'Medusa' cedule + +[NITROENT] +STR_NAME :'Nitro' cedule + +[SAH] +STR_NAME :Dům + +[SAH2] +STR_NAME :Dům + +[SAH3] +STR_NAME :Činžovní dům + +[SALOON] +STR_NAME :Salón + +[SCLN] +STR_NAME :Kolonáda + +[SCT] +STR_NAME :Stan + +[SDN1] +STR_NAME :Dinosaurus + +[SDN2] +STR_NAME :Dinosaurus + +[SDN3] +STR_NAME :Dinosaurus + +[SGP] +STR_NAME :Obrovská dýně + +[SHS1] +STR_NAME :Řadový dům + +[SHS2] +STR_NAME :Dům + +[SMH1] +STR_NAME :Hornická chatrč + +[SMH2] +STR_NAME :Hornická chatrč + +[SMN1] +STR_NAME :Důlní štola + +[SOB] +STR_NAME :Kancelářský blok + +[SOH1] +STR_NAME :Dům + +[SOH2] +STR_NAME :Dům + +[SOH3] +STR_NAME :Dům + +[SPS] +STR_NAME :Čerpací stanice + +[SSH] +STR_NAME :Vesmírná loď + +[SSK1] +STR_NAME :Koslivec + +[SST] +STR_NAME :Satelit + +[STB1] +STR_NAME :Hradní věž + +[STB2] +STR_NAME :Hradní věž + +[STG1] +STR_NAME :Hradní věž + +[STG2] +STR_NAME :Hradní věž + +[STH] +STR_NAME :Radnice + +[TAVERN] +STR_NAME :Hospoda + +[WWBANK] +STR_NAME :Banka + +[SSIG2] +STR_NAME :3D cedule + +[SSIG3] +STR_NAME :vertikální 3D cedule + +[SSIG4] +STR_NAME :3D cedule + +[SSIG1] +STR_NAME :Posuvná cedule + +[GLTHENT] +STR_NAME :'Goliath' cedule + +[PRSHIP] +STR_NAME :Pirátská loď + +[SCOL] +STR_NAME :Římské koloseum + +[SIP] +STR_NAME :Ledový palác + +[SMB] +STR_NAME :Marťanská stavba + +[SPG] +STR_NAME :Pagoda + +[SPYR] +STR_NAME :Pyramida + +[SSPX] +STR_NAME :Sfinga + +[SSR] +STR_NAME :Vesmírná raketa + +[SVLC] +STR_NAME :Sopka + +[WALLBADM] +STR_NAME :Badmintonová raketa + +[WALLBB16] +STR_NAME :Stěna + +[WALLBB32] +STR_NAME :Stěna + +[WALLBB33] +STR_NAME :Stěna + +[WALLBB34] +STR_NAME :Kamenná stěna + +[WALLBB8] +STR_NAME :Stěna + +[WALLBR16] +STR_NAME :Stěna + +[WALLBR32] +STR_NAME :Stěna + +[WALLBR8] +STR_NAME :Stěna + +[WALLBRWN] +STR_NAME :Okno + +[WALLCB16] +STR_NAME :Stěna + +[WALLCB32] +STR_NAME :Stěna + +[WALLCB8] +STR_NAME :Stěna + +[WALLCBWN] +STR_NAME :Okno + +[WALLCF16] +STR_NAME :Stěna + +[WALLCF32] +STR_NAME :Stěna + +[WALLCF8] +STR_NAME :Stěna + +[WALLCFAR] +STR_NAME :Stěna + +[WALLCFWN] +STR_NAME :Okno + +[WALLCO16] +STR_NAME :Ocelová stěna + +[WALLCW32] +STR_NAME :Stěna + +[WALLCX32] +STR_NAME :Stěna + +[WALLCY32] +STR_NAME :Stěna + +[WALLCZ32] +STR_NAME :Stěna + +[WALLIG16] +STR_NAME :Stěna iglů + +[WALLIG24] +STR_NAME :Stěna iglů + +[WALLJB16] +STR_NAME :Lentilková stěna + +[WALLJN32] +STR_NAME :Stěna + +[WALLLT32] +STR_NAME :Ocelová kosntrukce + +[WALLMM16] +STR_NAME :Zábradlí + +[WALLMM17] +STR_NAME :Zábradlí + +[WALLMN32] +STR_NAME :Stěna + +[WALLNT32] +STR_NAME :Síť na tenis + +[WALLNT33] +STR_NAME :Síť na tenis + +[WALLPG32] +STR_NAME :Stěna + +[WALLPOST] +STR_NAME :Sloup + +[WALLPR32] +STR_NAME :Lanoví + +[WALLPR33] +STR_NAME :Stěna + +[WALLPR34] +STR_NAME :Stěna + +[WALLPR35] +STR_NAME :Stěna + +[WALLRH32] +STR_NAME :Stěna + +[WALLRK32] +STR_NAME :Kamenná stěna + +[WALLRS16] +STR_NAME :Stěna + +[WALLRS32] +STR_NAME :Stěna + +[WALLRS8] +STR_NAME :Stěna + +[WALLSC16] +STR_NAME :Zábradlí + +[WALLSK16] +STR_NAME :Stěna + +[WALLSK32] +STR_NAME :Stěna + +[WALLSP32] +STR_NAME :Stěna + +[WALLST16] +STR_NAME :Ocelová stěna + +[WALLST32] +STR_NAME :Ocelová stěna + +[WALLST8] +STR_NAME :Ocelová stěna + +[WALLSTFN] +STR_NAME :Ocelový plot + +[WALLSTWN] +STR_NAME :Ocelová stěna + +[WALLTN32] +STR_NAME :Tyče + +[WALLTXGT] +STR_NAME :'Texas Giant' cedule + +[WALLU132] +STR_NAME :Stěna + +[WALLU232] +STR_NAME :Stěna + +[WALLWD16] +STR_NAME :Dřevěná stěna + +[WALLWD32] +STR_NAME :Dřevěná stěna + +[WALLWD33] +STR_NAME :Dřevěná stěna + +[WALLWD8] +STR_NAME :Dřevěná stěna + +[WALLWDPS] +STR_NAME :Dřevěný sloup v plotě + +[WBR1] +STR_NAME :Cihlová stěna + +[WBR1A] +STR_NAME :Cihlová stěna + +[WBR2] +STR_NAME :Kamenná stěna + +[WBR2A] +STR_NAME :Kamenná stěna + +[WBR3] +STR_NAME :Kamenná stěna + +[WBRG] +STR_NAME :Cihlová stěna + +[WBW] +STR_NAME :Plot z kostí + +[WC1] +STR_NAME :Hradní stěna + +[WC10] +STR_NAME :Hradní stěna + +[WC11] +STR_NAME :Hradní stěna + +[WC12] +STR_NAME :Hradní stěna + +[WC13] +STR_NAME :Hradní stěna + +[WC14] +STR_NAME :Stěna + +[WC15] +STR_NAME :Stěna + +[WC16] +STR_NAME :Fence + +[WC17] +STR_NAME :Dřevěný plot + +[WC18] +STR_NAME :Dřevěný sloup v plotě + +[WC2] +STR_NAME :Hradní stěna + +[WC3] +STR_NAME :Stěna římských sloupů + +[WC4] +STR_NAME :Hradní stěna + +[WC5] +STR_NAME :Hradní stěna + +[WC6] +STR_NAME :Hradní stěna + +[WC7] +STR_NAME :Hradní stěna + +[WC8] +STR_NAME :Hradní stěna + +[WC9] +STR_NAME :Hradní stěna + +[WCH] +STR_NAME :Živý plot + +[WCHG] +STR_NAME :Živý plot + +[WCW1] +STR_NAME :Stěna z hracích karet + +[WCW2] +STR_NAME :Stěna z hracích karet + +[WEW] +STR_NAME :Egyptská stěna + +[WFW1] +STR_NAME :Dřevěný plot + +[WFWG] +STR_NAME :Dřevěný plot + +[WHG] +STR_NAME :Živý plot + +[WHGG] +STR_NAME :Živý plot + +[WJF] +STR_NAME :Jungle plot + +[WMF] +STR_NAME :Drátěný plot + +[WMFG] +STR_NAME :Drátěný plot + +[WMW] +STR_NAME :Marťanská zeď + +[WMWW] +STR_NAME :Dřevěný plot + +[WPF] +STR_NAME :Plot + +[WPFG] +STR_NAME :Plot + +[WPW1] +STR_NAME :Zeď dřevených sloupů + +[WPW2] +STR_NAME :Zeď dřevených sloupů + +[WPW3] +STR_NAME :Dřevěný plot + +[WRW] +STR_NAME :Římská zeď + +[WRWA] +STR_NAME :Římská zeď + +[WSW] +STR_NAME :Zábradlí + +[WSW1] +STR_NAME :Zábradlí + +[WSW2] +STR_NAME :Zábradlí + +[WSWG] +STR_NAME :Zábradlí + +[WWTW] +STR_NAME :Vysoký dřevěný plot + +[WWTWA] +STR_NAME :Stěna ze dřevěného plotu + +[WALLBRDR] +STR_NAME :Brána + +[WALLCBDR] +STR_NAME :Brána + +[WALLCBPC] +STR_NAME :Padací brána + +[WALLCFDR] +STR_NAME :Brána + +[WALLCFPC] +STR_NAME :Padací brána + +[WALLWF32] +STR_NAME :Vodopád + +[WALLGL16] +STR_NAME :Skleněná stěna + +[WALLGL32] +STR_NAME :Skleněná stěna + +[WALLGL8] +STR_NAME :Skleněná stěna + +[WGW2] +STR_NAME :Skleněná stěna + +[WALLSIGN] +STR_NAME :Posuvná cedule + +[BN1] +STR_NAME :Cedule + +[BN2] +STR_NAME :Cedule v jungle stylu + +[BN3] +STR_NAME :Cedule v klasickém stylu + +[BN4] +STR_NAME :Cedule v egyptském stylu + +[BN5] +STR_NAME :Dřevěná cedule + +[BN6] +STR_NAME :Cedule v jurském stylu + +[BN7] +STR_NAME :Cedule v pagoda stylu + +[BN8] +STR_NAME :Zasněžená cedule + +[BN9] +STR_NAME :Cedule ve vesmírném stylu + +[PATHASH] +STR_NAME :Popelavá cesta + +[PATHCRZY] +STR_NAME :Šílená cesta + +[PATHDIRT] +STR_NAME :Blátivá cesta + +[PATHSPCE] +STR_NAME :Cesta ve vesmírném stylu + +[ROAD] +STR_NAME :Silnice + +[TARMAC] +STR_NAME :Asfaltová cesta + +[TARMACB] +STR_NAME :Hnědá asfaltová cesta + +[TARMACG] +STR_NAME :Zelená asfaltová cesta + +[LAMP1] +STR_NAME :Lampaa + +[LAMP2] +STR_NAME :Lampa + +[LAMP3] +STR_NAME :Lampa + +[LAMP4] +STR_NAME :Lampa + +[LAMPDSY] +STR_NAME :Květinová lampa + +[LAMPPIR] +STR_NAME :Lampa + +[LITTER1] +STR_NAME :Odpadkový koš + +[LITTERMN] +STR_NAME :Odpadkový koš + +[LITTERSP] +STR_NAME :Odpadkový koš + +[LITTERWW] +STR_NAME :Odpadkový koš + +[BENCH1] +STR_NAME :Lavička + +[BENCHLOG] +STR_NAME :Lavička + +[BENCHPL] +STR_NAME :Sedadla + +[BENCHSPC] +STR_NAME :Lavička + +[BENCHSTN] +STR_NAME :Kamenná lavička + +[JUMPFNT1] +STR_NAME :Skákající fontány + +[JUMPSNW1] +STR_NAME :Skákající sněhové koule + +[QTV1] +STR_NAME :TV ve frontě + +[SCGABSTR] +STR_NAME :Abstraktí kulisy + +[SCGCANDY] +STR_NAME :Kulisy obrovského cukroví + +[SCGCLASS] +STR_NAME :Klasické/Římské kulisy + +[SCGEGYPT] +STR_NAME :Egyptské motivy + +[SCGFENCE] +STR_NAME :Ploty a stěny + +[SCGGARDN] +STR_NAME :Zahrady + +[SCGGIANT] +STR_NAME :Kulisy obrovských zahrad + +[SCGHALLO] +STR_NAME :Strašidelné kulisy + +[SCGINDUS] +STR_NAME :Mechanické kulisy + +[SCGJUNGL] +STR_NAME :Jungle kulisy + +[SCGJURAS] +STR_NAME :Jurské kulisy + +[SCGMART] +STR_NAME :Marťanské kulisy + +[SCGMEDIE] +STR_NAME :Středověké kulisy + +[SCGMINE] +STR_NAME :Dulní kulisy + +[SCGORIEN] +STR_NAME :Pagoda kulisy + +[SCGPATHX] +STR_NAME :Cedule a věci na cesty + +[SCGPIRAT] +STR_NAME :Pirátské kulisy + +[SCGSHRUB] +STR_NAME :Keře a ornamenty + +[SCGSIXFL] +STR_NAME :Six Flags kulisy + +[SCGSNOW] +STR_NAME :Ledové a sněhové kulisy + +[SCGSPACE] +STR_NAME :Vesmírné kulisy + +[SCGSPOOK] +STR_NAME :Strašidelné kulisy + +[SCGSPORT] +STR_NAME :Sportovní kulisy + +[SCGTREES] +STR_NAME :Stromy + +[SCGURBAN] +STR_NAME :Urban kulisy + +[SCGWALLS] +STR_NAME :Stěny and střechy + +[SCGWATER] +STR_NAME :Vodní kulisy + +[SCGWOND] +STR_NAME :Kulisy říše divů + +[SCGWWEST] +STR_NAME :Kulisy divokého západu + +[PKEMM] +STR_NAME :Brány pro vstup do parku + +[PKENT1] +STR_NAME :Tradiční brána pro vstup do parku + +[PKESFH] +STR_NAME :Budova vstupu do parku + +[WTRCYAN] +STR_NAME :Obyčejná voda + +[WTRGREEN] +STR_NAME :Jedovatě zelená voda + +[WTRGRN] +STR_NAME :Zelená voda + +[WTRORNG] +STR_NAME :Oranžová voda + +############################################################################### +## Wacky Worlds Objects +############################################################################### +[LONDONBS] +STR_NAME :Tramvaj ve tvaru Londýnského autobusu +STR_DESC :Repliky tramvají +STR_CPTY :10 míst v každém voze + +[MINELIFT] +STR_NAME :Důlní výtah +STR_DESC :Návštěvníci jezdí ve výtahu nahoru nebo dolů, aby se dostali z jednoho patra do druhého +STR_CPTY :16 návštěvníků + +[SANFTRAM] +STR_NAME :Tramvaj ze San Francisca +STR_DESC :Repliky tramvají +STR_CPTY :10 míst v každém voze + +[STEAMTRN] +STR_NAME :Mahárádžova parní lokomotiva +STR_DESC :Miniaturní replika parní lokomotivy s tendrem táhne kryté dřevěné vagóny +STR_CPTY :6 míst v každém vagónu + +[BLACKCAB] +STR_NAME :Autodráha s Londýnskými taxíky +STR_DESC :Vozy ve tvaru Londýnských taxíků jezdí po postavené dráze +STR_CPTY :2 místa v každém voze + +[CRNVBFLY] +STR_NAME :Motýlková autodráha +STR_DESC :Vozy ve tvaru motýlů jezdí po postavené dráze +STR_CPTY :2 místa v každém voze + +[CRNVFROG] +STR_NAME :Žabí autodráha +STR_DESC :Vozy ve tvaru žab jezdí po postavené dráze +STR_CPTY :2 místa v každém voze + +[CRNVLZRD] +STR_NAME :Ještěrčí autodráha +STR_DESC :Vozy ve tvaru ještěrek jezdí po postavené dráze +STR_CPTY :2 místa v každém voze + +[DRAGDODG] +STR_NAME :Čínská dračí hlava +STR_DESC :Autodrom s vozy ve tvaru dračích hlav +STR_CPTY :1 místo v každém voze + +[HIPPORID] +STR_NAME :Hroší jízda +STR_DESC :Návštěvníci vyrazí na podvodní jízdu v ponorce +STR_CPTY :5 míst v každé ponorce + +[HUSKIE] +STR_NAME :Autodráha se saněmi +STR_DESC :Vozy ve tvaru sněžných saní jezdí po postavené dráze +STR_CPTY :2 místa v každém voze + +[KILLWHAL] +STR_NAME :Zabijácká velryba +STR_DESC :Návštěvníci vyrazí na podvodní jízdu v ponorce +STR_CPTY :5 míst v každé ponorce + +[SKIDOO] +STR_NAME :Sněžné vozy +STR_DESC :Autodrom s vozy ve tvaru sněžných vozů +STR_CPTY :1 místo v každém voze + +[ANACONDA] +STR_NAME :Anakonda +STR_DESC :Prostorné vozy s opěrkou v klíně +STR_CPTY :6 míst v každém voze + +[BOMERANG] +STR_NAME :Bumerang +STR_DESC :Po mocném startu na stlačený vzduch se vozy rozjedou po svislé dráze, přes vrchol a svisle dolů zpět do stanice +STR_CPTY :2 místa v každém voze + +[BULLET] +STR_NAME :Šinkansen +STR_DESC :Horská dráha s vozy, které vypadají jako vozy Šinkansenu +STR_CPTY :4 místa v každém voze + +[CADDILAC] +STR_NAME :Limuzínová horská dráha +STR_DESC :Horská dráha s vozy, které vypadají jako limuzíny +STR_CPTY :4 místa v každém voze + [CONDORRD] -STR_NAME :Condor Ride -STR_DESC :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air in Condor-shaped trains -STR_CPTY :4 passengers per car +STR_NAME :Jízda kondorů +STR_DESC :Návštěvníci jedou na jednokolejné trati vleže hlavou dolů, zavěšeni ve speciálním voze, který se v zatáčkách houpe +STR_CPTY :1 místo v každém voze + +[CONGAEEL] +STR_NAME :Jízda mořského úhoře +STR_DESC :Malá ocelová horská dráha, na které vozy připomínající mořské úhoře jezdí skrze lopinky a jezdí ve vývrtce +STR_CPTY :4 místa v každém voze + +[DRAGON] +STR_NAME :Dračí horská dráha +STR_DESC :Horská dráha s vozy ve tvaru draků +STR_CPTY :4 místa v každém voze + +[FOOTBALL] +STR_NAME :Footbalová horská dráha +STR_DESC :Zavěšená horská dráha s vozy připomínající fotbalové míče, které se houpají v zatáčkách +STR_CPTY :4 místa v každém voze + +[GORILLA] +STR_NAME :Gorilí horská dráha +STR_DESC :Zavěšená horská dráha s vozy připomínající gorily, které se houpají v zatáčkách +STR_CPTY :4 místa v každém voze + +[GRATWHTE] +STR_NAME :Žraločí horská dráha +STR_DESC :Prostorné vozy s opěrkou v klíně +STR_CPTY :6 míst v každém voze + +[JAGUARRD] +STR_NAME :Jaguáří horská dráha +STR_DESC :Malá horská dráha, na které vozy po jednom projíždí trať s kroucenými pády +STR_CPTY :4 místa v každém voze + +[KOLARIDE] +STR_NAME :Koalí dráha +STR_DESC :Velká dráha s vozem pro volný pád pozpátku +STR_CPTY :8 návštěvníků + +[LIONRIDE] +STR_NAME :Lví horská dráha +STR_DESC :Malá horská dráha, na které vozy po jednom projíždí trať s kroucenými pády +STR_CPTY :4 místa v každém voze + +[MINECART] +STR_NAME :Jízda dolem +STR_DESC :Dřevěná horská dráha s vozy s polstrovanými sedadly a opěrkou v klíně +STR_CPTY :4 místa v každém voze + +[OSTRICH] +STR_NAME :Pštrosí jízda +STR_DESC :Horská dráha s lopinky, na které se jezdí ve stoje +STR_CPTY :4 místa v každém voze + +[PENGUINB] +STR_NAME :Tučnáčí bobová dráha +STR_DESC :Návštěvníci jedou po propletené bobové dráze +STR_CPTY :2 místa v každém voze + +[POLARBER] +STR_NAME :Horská dráha polárního medvěda +STR_DESC :Návštěvníci sedí po dvou zavěšení pod tratí a vidí dopředu nebo dozadu podle toho, jak zrovna jedou skrze ostré zatáčky +STR_CPTY :4 místa v každém voze + +[RHINORID] +STR_NAME :Rhino Ride +STR_DESC :Malá ocelová horská dráha se spirálovitým profilem a vozy se sedadly za sebou +STR_CPTY :6 míst v každém voze + +[ROCKET] +STR_NAME :Raketová jízda z 50. let +STR_DESC :Vozy vyrazí vstříc jednomu konci trati, poté prosviští pozpátku stanicí a vyletí až na druhý konec trati +STR_CPTY :4 místa v každém voze + +[RSSNCRRD] +STR_NAME :Moskvičová horská dráha +STR_DESC :Horská dráha s Ruskými vozy +STR_CPTY :4 místa v každém voze + +[SEALS] +STR_NAME :Tulení horská dráha +STR_DESC :Malá ocelová horská dráha, na které vozy připomínající tuleně jezdí skrze lopinky a jezdí ve vývrtce +STR_CPTY :4 místa v každém voze + +[SLOTH] +STR_NAME :Lenochodí jízda +STR_DESC :Zavěšená horská dráha s vozy připomínající lenochody, které se houpají v zatáčkách +STR_CPTY :4 místa v každém voze + +[SPUTNIKR] +STR_NAME :Sputnik +STR_DESC :Návštěvníci jedou na jednokolejné trati vleže hlavou dolů, zavěšeni ve speciálním voze, který se v zatáčkách houpe +STR_CPTY :2 místa v každém voze + +[STGCCSTR] +STR_NAME :Dostaníková horská dráha +STR_DESC :Dřevěná horská dráha s vozy s polstrovanými sedadly a opěrkou v klíně +STR_CPTY :4 místa v každém voze + +[SURFBRDC] +STR_NAME :Surfující horská dráha +STR_DESC :Návětěvníci jedou ve stoje v širokých vozech se speciálně navrženým držením po propletené dráze s pády +STR_CPTY :4 místa v každém voze + +[TAXICSTR] +STR_NAME :Taxi horská dráha +STR_DESC :Gigantická ocelová horská dráha schopna volných pádů a kopců přes 90 metrů dlouhých +STR_CPTY :4 místa v každém voze + +[TGVTRAIN] +STR_NAME :TGV horská dráha +STR_DESC :Horská dráha s vozy poháněnými elektromotorem, které sviští skrze propletenou dráhu +STR_CPTY :4 místa v každém voze + +[TIGRTWST] +STR_NAME :Horská dráha bengálských tigrů +STR_DESC :Horská dráha, která se točí dokola tak, že návštěvníci jsou pořád na stejném místě +STR_CPTY :4 místa v každém voze + +[WHICGRUB] +STR_NAME :Červí jízda +STR_DESC :Horská dráha s vozy ve tvaru červů +STR_CPTY :2 místa v každém voze + +[COFFEECU] +STR_NAME :Jízda v šálku kávy +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí okolo kafemlýnku uprostřed +STR_CPTY :18 návštěvníků + +[DIAMONDR] +STR_NAME :Diamontová jízda +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí okolo diamantu uprostřed +STR_CPTY :18 návštěvníků + +[FABERGE] +STR_NAME :Jízda Fabergého vejce +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí okolo Fabergého vejce uprostřed +STR_CPTY :18 návštěvníků + +[FIGHTKIT] +STR_NAME :Jízda papírového draka +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí +STR_CPTY :18 návštěvníků + +[FIRECRAK] +STR_NAME :Jízda rachejtle +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí +STR_CPTY :16 návštěvníků + +[ITALYPOR] +STR_NAME :Italská policejní jízda +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí okolo italských policistů +STR_CPTY :18 návštěvníků + +[JUNKSWNG] +STR_NAME :Čínská loď +STR_DESC :Loď je připevněna na porpěru, která se chová jako protizávaží a otáčí se o 360 stupňů +STR_CPTY :12 návštěvníků + +[CROCFLUM] +STR_NAME :Krokodýlí jízda +STR_DESC :Lodě ve tvaru krokodýlů se plaví po vodním kanálu a cákají. Nikdo nezůstane suchý +STR_CPTY :4 místa na každé lodi + +[DHOWWATR] +STR_NAME :Plachetnice +STR_DESC :Ozdobné plachetnice, u kterých musí návštěvníci pádlovat +STR_CPTY :2 místa na každé lodi + +[DOLPHINR] +STR_NAME :Delfíní jízda +STR_DESC :Lodě ve tvaru delfínů, které mohou návštěvníci ovládat +STR_CPTY :1 místo v každé lodi + +[MANDARIN] +STR_NAME :Čínské kachny +STR_DESC :Lodě ve tvaru labutí, ovládáné šlapaním návštěvníků +STR_CPTY :4 místa na každé lodi + +[MANTARAY] +STR_NAME :Rejnočí jízda +STR_DESC :Velkokapacitní lodě se plaví po vodním kanále, poháněny do pásem do strmých úseků, zrychlují sjíždením svahů a namočí návštěvníky pořádným šplouchnutím +STR_CPTY :16 míst na každé lodi + +[OUTRIGGR] +STR_NAME :Loď s podporami +STR_DESC :Dlouhé kánoe s postranními podporami, u kterých musí návštěvníci pádlovat +STR_CPTY :2 místa v každé lodi + +[TUTLBOAT] +STR_NAME :Želví jízda +STR_DESC :Malé čluny ve tvaru mořských želv s motorovým pohonem ovládaným návštěvníky +STR_CPTY :2 místa v každé lodi + +[1X1ATRE2] +STR_NAME :Vinná réva + +[1X1ATREE] +STR_NAME :Názké křoví + +[1X1BRANG] +STR_NAME :Bumerang + +[1X1DIDGE] +STR_NAME :Didgeridoo + +[1X1EMUXX] +STR_NAME :Emu + +[1X1JUGT2] +STR_NAME :Strom z deštného pralesa 1 + +[1X1JUGT3] +STR_NAME :Strom z deštného pralesa 2 + +[1X1KANGA] +STR_NAME :Klokat + +[1X1TERMM] +STR_NAME :Termitiště + +[ADPANDA] +STR_NAME :Dosplělá panda + +[ANTILOPF] +STR_NAME :Antilopa - samice + +[ANTILOPM] +STR_NAME :Antilopa - samec + +[ANTILOPP] +STR_NAME :Antilopí pár + +[BABPANDA] +STR_NAME :Malá panda + +[BABYELE] +STR_NAME :Malý slon + +[BALLLAN2] +STR_NAME :Čínské lampióny + +[BALLLANT] +STR_NAME :Čínské lampióny + +[BambooBs] +STR_NAME :Bambus + +[BAMBOOPL] +STR_NAME :Sloup z bambusu + +[BSTATUE1] +STR_NAME :Rozbitá socha + +[FSTATUE1] +STR_NAME :Opravená socha + +[JACHTREE] +STR_NAME :Sakura + +[JAPCHBLO] +STR_NAME :Sakura + +[JAPPINTR] +STR_NAME :Borovice Thunbergova + +[JAPSNOTR] +STR_NAME :Kalina řasnatá + +[ORIEGONG] +STR_NAME :Gong + +[PCG] +STR_NAME :Trubka + +[PCO] +STR_NAME :Trubka + +[POSTBOX] +STR_NAME :Britská poštovní schránka + +[PST] +STR_NAME :Trubka + +[PTJ] +STR_NAME :Trubka + +[PTK] +STR_NAME :Trubka + +[PVA] +STR_NAME :Trubka + +[RBRICK01] +STR_NAME :Obrácená červená střecha + +[RBRICK02] +STR_NAME :Rohová červená střecha + +[RBRICK03] +STR_NAME :Krajní červená střecha + +[RBRICK04] +STR_NAME :Plochá rohová červená střecha + +[RBRICK05] +STR_NAME :Červená střecha 2 + +[RBRICK07] +STR_NAME :Červená střecha 3 + +[RBRICK08] +STR_NAME :Červená střecha 1 + +[RCORR01] +STR_NAME :Vlnitá střecha + +[RCORR02] +STR_NAME :Vlnitá střecha + +[RCORR03] +STR_NAME :Vlnitá střecha + +[RCORR04] +STR_NAME :Vlnitá střecha + +[RCORR05] +STR_NAME :Vlnitá střecha + +[RCORR07] +STR_NAME :Vlnitá střecha + +[RCORR08] +STR_NAME :Vlnitá střecha + +[RCORR09] +STR_NAME :Vlnitá střecha + +[RCORR10] +STR_NAME :Vlnitá střecha + +[RCORR11] +STR_NAME :Vlnitá střecha + +[RDRAB05] +STR_NAME :Základna malého minaretu + +[RDRAB06] +STR_NAME :Střední část malého minaretu + +[RDRAB07] +STR_NAME :Základna malé věže + +[RDRAB08] +STR_NAME :Minaret 1 + +[RDRAB09] +STR_NAME :Minaret 2 + +[RDRAB10] +STR_NAME :Minaret 3 + +[RDRAB11] +STR_NAME :Střecha 1 + +[RDRAB12] +STR_NAME :Střecha 2 + +[RDRAB13] +STR_NAME :Střecha 3 + +[RDRAB14] +STR_NAME :Střecha 4 + +[RGEORG01] +STR_NAME :Gregoriánská střecha 7 + +[RGEORG02] +STR_NAME :Gregoriánská střecha 6 + +[RGEORG03] +STR_NAME :Gregoriánská střecha + +[RGEORG04] +STR_NAME :Gregoriánská střecha + +[RGEORG05] +STR_NAME :Gregoriánská střecha + +[RGEORG06] +STR_NAME :Gregoriánská střecha + +[RGEORG07] +STR_NAME :Gregoriánská střecha + +[RGEORG08] +STR_NAME :Georgian stěna přízemí + +[RGEORG09] +STR_NAME :Gregoriánská střecha + +[RGEORG10] +STR_NAME :Gregoriánská střecha + +[RGEORG11] +STR_NAME :Gregoriánská plochá střecha + +[RGEORG12] +STR_NAME :Gregoriánská střecha + +[ROOFICE1] +STR_NAME :Ledová střecha + +[ROOFICE2] +STR_NAME :Ledová střecha + +[ROOFICE3] +STR_NAME :Ledová střecha + +[ROOFICE4] +STR_NAME :Ledová střecha + +[ROOFICE5] +STR_NAME :Ledová střecha + +[ROOFICE6] +STR_NAME :Ledová střecha + +[RKREML01] +STR_NAME :Kremlinský Minaret díl 1 + +[RKREML02] +STR_NAME :Kremlinský Minaret díl 2 + +[RKREML03] +STR_NAME :Kremlinský Minaret díl 3 + +[RKREML04] +STR_NAME :Kremlinská střecha díl 1 + +[RKREML05] +STR_NAME :Kremlinská střecha díl 2 + +[RKREML06] +STR_NAME :Kremlinská věž - střed + +[RKREML07] +STR_NAME :Kremlinská věž - základ + +[RKREML11] +STR_NAME :Kremlinská věž + +[RLOG01] +STR_NAME :Střecha dulní chatrče + +[RLOG02] +STR_NAME :Střecha dulní chatrče + +[RLOG03] +STR_NAME :Stěna dulní chatrče + +[RLOG04] +STR_NAME :Stěna dulní chatrče + +[RLOG05] +STR_NAME :Střecha dulní chatrče + +[RMARBLE1] +STR_NAME :Mramorová střecha + +[RMARBLE2] +STR_NAME :Mramorová střecha + +[RMARBLE3] +STR_NAME :Mramorová střecha + +[RMARBLE4] +STR_NAME :Mramorová střecha + +[RMUD01] +STR_NAME :Zaoblená zeď z bahna + +[RMUD02] +STR_NAME :Zaoblená zeď z bahna + +[RMUD03] +STR_NAME :Zaoblená zeď z bahna + +[RMUD05] +STR_NAME :Střecha z bahna + +[ROOFIG01] +STR_NAME :Stěna iglů + +[ROOFIG02] +STR_NAME :Stěna iglů + +[ROOFIG03] +STR_NAME :Stěna iglů + +[ROOFIG04] +STR_NAME :Stěna iglů + +[ROOFIG06] +STR_NAME :Stěna iglů + +[RSHOGI1] +STR_NAME :Čínská střecha + +[RSHOGI2] +STR_NAME :Čínská střecha + +[RSHOGI3] +STR_NAME :Čínská střecha + +[SMALLGEO] +STR_NAME :Malá geosféra + +[VERTPIPE] +STR_NAME :Ledová trubka + +[ICEBARL1] +STR_NAME :Ledové barely + +[ICEBARL2] +STR_NAME :Ledové barely + +[ICEBARL3] +STR_NAME :Ledové barely + +[PIPEVENT] +STR_NAME :Výdech ledové trubky + +[PIPEBASE] +STR_NAME :Ledová trubka + +[RTUDOR01] +STR_NAME :Tudorská střecha + +[RTUDOR02] +STR_NAME :Tudorská střecha + +[RTUDOR03] +STR_NAME :Tudorská střecha + +[RWDAUB01] +STR_NAME :Hliněná střecha + +[RWDAUB02] +STR_NAME :Hliněná střecha + +[RWDAUB03] +STR_NAME :Hliněná střecha + +[SB1HSPB1] +STR_NAME :Zavěšený most + +[SB1HSPB2] +STR_NAME :Zavěšený most + +[SB1HSPB3] +STR_NAME :Zavěšený most + +[SB2PALM1] +STR_NAME :Veranda + +[SB2SKY01] +STR_NAME :Kamenné schodiště mrakodrapu + +[SBH1TEPE] +STR_NAME :Týpí + +[SBH1WGWH] +STR_NAME :Kolo vagónu + +[SBH2SHLT] +STR_NAME :Pátrací světlo + +[SBH3CAC1] +STR_NAME :Kaktus + +[SBH3CAC2] +STR_NAME :Kaktus + +[SBH3CAC3] +STR_NAME :Kaktus + +[SBH3CSKL] +STR_NAME :Zvířecí lebka + +[SBH3OSCR] +STR_NAME :Ocenění horské dráhy + +[SBH3PLM1] +STR_NAME :Palma + +[SBH3PLM2] +STR_NAME :Palma + +[SBH3PLM3] +STR_NAME :Palma + +[SBH3RT66] +STR_NAME :Silnice 66 + +[SBH4TOTM] +STR_NAME :Totem + +[SBSKYS01] +STR_NAME :Zeď kamenného mrakodrapu + +[SBSKYS02] +STR_NAME :Zeď kamenného mrakodrapu + +[SBSKYS03] +STR_NAME :Výtah mrakodrapu + +[SBSKYS04] +STR_NAME :Výtah mrakodrapu + +[SBSKYS05] +STR_NAME :Kovový set mrakodrapu 1 - konvexní díl + +[SBSKYS06] +STR_NAME :Kovový set mrakodrapu 1 - konkávní díl + +[SBSKYS07] +STR_NAME :Kovový set mrakodrapu 2 - konvexní díl + +[SBSKYS08] +STR_NAME :Kovový set mrakodrapu 2 - konkávní díl + +[SBSKYS09] +STR_NAME :Kovový set mrakodrapu 2 - konkávní díl + +[SBSKYS10] +STR_NAME :Konkávní díl mrakodrapu + +[SBSKYS11] +STR_NAME :Konkávní střecha mrakodrapu + +[SBSKYS12] +STR_NAME :Konvexní střecha mrakodrapu + +[SBSKYS13] +STR_NAME :Konvexní střecha mrakodrapu + +[SBSKYS14] +STR_NAME :Střecha mrakodrapu + +[SBSKYS15] +STR_NAME :Střecha mrakodrapu + +[SBSKYS16] +STR_NAME :Střecha mrakodrapu + +[SBSKYS17] +STR_NAME :Střecha mrakodrapu + +[SBSKYS18] +STR_NAME :Střecha mrakodrapu + +[SBWIND01] +STR_NAME :Roh větrem ošlehané stěny + +[SBWIND02] +STR_NAME :Roh větrem ošlehané střechy + +[SBWIND03] +STR_NAME :Roh větrem ošlehané stěny + +[SBWIND04] +STR_NAME :Konvexní roh větrem ošlehané stěny + +[SBWIND05] +STR_NAME :Konvexní roh větrem ošlehané střechy + +[SBWIND06] +STR_NAME :Konvexní roh větrem ošlehané stěny + +[SBWIND07] +STR_NAME :Základna větrem ošlehaného kamene + +[SBWIND08] +STR_NAME :Základna větrem ošlehaného kamene + +[SBWIND09] +STR_NAME :Střední část větrem ošlehaného kamene + +[SBWIND10] +STR_NAME :Střední část větrem ošlehaného kamene + +[SBWIND11] +STR_NAME :Střední část větrem ošlehaného kamene + +[SBWIND12] +STR_NAME :Střední část větrem ošlehaného kamene + +[SBWIND13] +STR_NAME :Vršek větrem ošlehaného kamene + +[SBWIND14] +STR_NAME :Vršek větrem ošlehaného kamene + +[SBWIND15] +STR_NAME :Střecha větrem ošlehaného kamene + +[SBWIND16] +STR_NAME :Střecha větrem ošlehaného kamene + +[SBWIND17] +STR_NAME :Střecha větrem ošlehaného kamene + +[SBWIND18] +STR_NAME :Podlaha větrem ošlehaného kamene + +[SBWIND19] +STR_NAME :Podlaha větrem ošlehaného kamene + +[SBWIND20] +STR_NAME :Stěna větrem ošlehaného kamene + +[SBWIND21] +STR_NAME :Stěna větrem ošlehaného kamene + +[SBWPLM01] +STR_NAME :Vršek chaty + +[SBWPLM02] +STR_NAME :Veranda u chaty + +[SBWPLM03] +STR_NAME :Vršek chaty + +[SBWPLM04] +STR_NAME :Vršek chaty + +[SBWPLM05] +STR_NAME :Vršek chaty + +[SBWPLM06] +STR_NAME :Stěna chaty + +[SBWPLM07] +STR_NAME :Stěna chaty + +[SBWPLM08] +STR_NAME :Stěna chaty + +[TALLLAN1] +STR_NAME :Vysoká lucena + +[TALLLAN2] +STR_NAME :Vysoká lucena + +[TERRARMY] +STR_NAME :Terakotová armáda + +[TJBLOCK1] +STR_NAME :Mahárádžův palác + +[TJBLOCK2] +STR_NAME :Mahárádžův palác + +[TJBLOCK3] +STR_NAME :Mahárádžův palác + +[TNT1] +STR_NAME :Dynamit + +[TNT2] +STR_NAME :Barel dynamitu + +[TNT3] +STR_NAME :Rozbuška + +[TNT4] +STR_NAME :Krabicke dynamitu + +[TRCKPRT1] +STR_NAME :Diamantový košík + +[TRCKPRT2] +STR_NAME :Prázdný košík + +[TRCKPRT3] +STR_NAME :Diamantový sloup + +[TRCKPRT4] +STR_NAME :Povoz + +[TRCKPRT5] +STR_NAME :Zatáčka na trati + +[TRCKPRT6] +STR_NAME :Rozbitá trať + +[TRCKPRT7] +STR_NAME :Konec tratě + +[TRCKPRT8] +STR_NAME :Rozpůlení tratě + +[TRCKPRT9] +STR_NAME :Rovná trať + +[UKPHONE] +STR_NAME :Britská telefoní budka + +[WABORG01] +STR_NAME :Umění domorodců + +[WABORG02] +STR_NAME :Umění domorodců + +[WABORG03] +STR_NAME :Umění domorodců + +[WABORG04] +STR_NAME :Umění domorodců + +[WABORG05] +STR_NAME :Umění domorodců + +[WABORG06] +STR_NAME :Umění domorodců + +[WABORG07] +STR_NAME :Umění domorodců + +[WABORG08] +STR_NAME :Umění domorodců + +[WAZTEC01] +STR_NAME :Střecha chrámu + +[WAZTEC02] +STR_NAME :Střecha chrámu + +[WAZTEC03] +STR_NAME :Stěna chrámu + +[WAZTEC04] +STR_NAME :Stěna chrámu + +[WAZTEC05] +STR_NAME :Stěna chrámu + +[WAZTEC06] +STR_NAME :Stěna chrámu + +[WAZTEC07] +STR_NAME :Stěna chrámu + +[WAZTEC08] +STR_NAME :Stěna chrámu + +[WAZTEC09] +STR_NAME :Stěna chrámu + +[WAZTEC10] +STR_NAME :Stěna chrámu + +[WAZTEC11] +STR_NAME :Rohová stěna chrámu + +[WAZTEC12] +STR_NAME :Rohová stěna chrámu + +[WAZTEC13] +STR_NAME :Stěna chrámu + +[WAZTEC14] +STR_NAME :Stěna chrámu + +[WAZTEC15] +STR_NAME :Střecha chrámu + +[WAZTEC16] +STR_NAME :Střecha chrámu + +[WAZTEC17] +STR_NAME :Střecha chrámu + +[WAZTEC18] +STR_NAME :Střecha chrámu + +[WAZTEC19] +STR_NAME :Střecha chrámu + +[WAZTEC20] +STR_NAME :Chrámové schody + +[WAZTEC21] +STR_NAME :Chrámové schody + +[WAZTEC22] +STR_NAME :Stěna chrámu + +[WAZTEC23] +STR_NAME :Stěna chrámu + +[WAZTEC24] +STR_NAME :Stěna chrámu + +[WAZTEC25] +STR_NAME :Stěna chrámu + +[WAZTEC26] +STR_NAME :Rohová stěna chrámu + +[WAZTEC27] +STR_NAME :Rohová stěna chrámu + +[WCUZCO01] +STR_NAME :Monumentální stěna + +[WCUZCO02] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO03] +STR_NAME :Monumentální stěna + +[WCUZCO04] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO05] +STR_NAME :Monumentální stěna + +[WCUZCO06] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO07] +STR_NAME :Monumentální stěna + +[WCUZCO08] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO09] +STR_NAME :Monumentální stěna + +[WCUZCO10] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO11] +STR_NAME :Monumentální stěna + +[WCUZCO12] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO13] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO14] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO15] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO16] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO17] +STR_NAME :Monumentální stěna + +[WCUZCO18] +STR_NAME :Rozbitá monumentální stěna + +[WCUZCO19] +STR_NAME :Monumentální schodiště + +[WCUZCO20] +STR_NAME :Monumentální schodiště + +[WCUZCO21] +STR_NAME :Monumentální rohová stěna + +[WCUZCO22] +STR_NAME :Monumentální rohová stěna + +[WCUZCO23] +STR_NAME :Monumentální rohová stěna + +[WCUZCO24] +STR_NAME :Monumentální rohová stěna + +[WCUZCO25] +STR_NAME :Monumentální schodiště + +[WCUZCO26] +STR_NAME :Monumentální schodiště + +[WCUZCO27] +STR_NAME :Monumentální stěna + +[WCUZCO28] +STR_NAME :Rozbitá monumentální stěna + +[WDRAB09] +STR_NAME :Khaki set - část 1 + +[WDRAB10] +STR_NAME :Khaki stěna - část 9 + +[WDRAB11] +STR_NAME :Khaki stěna - část 10 + +[WDRAB12] +STR_NAME :Khaki stěna - část 11 + +[WDRAB13] +STR_NAME :Khaki stěna - část 2 + +[WGEORG07] +STR_NAME :Gregoriánská přízemní stěna - část 4 + +[WGEORG08] +STR_NAME :Gregoriánská přízemní stěna - část 5 + +[WGEORG09] +STR_NAME :Gregoriánská přízemní stěna - část 6 + +[WGEORG10] +STR_NAME :Gregoriánská stěna - část 4 + +[WGEORG11] +STR_NAME :Gregoriánská stěna - část 5 + +[WGEORG12] +STR_NAME :Gregoriánská stěna - část 6 + +[WKREML01] +STR_NAME :Kremlinská stěna - část 1 + +[WKREML02] +STR_NAME :Kremlinská stěna - část 2 + +[WKREML03] +STR_NAME :Kremlinská stěna - část 1 + +[WKREML04] +STR_NAME :Kremlinská stěna - část 2 + +[WKREML05] +STR_NAME :Kremlinská stěna - část 3 + +[WKREML06] +STR_NAME :Kremlinská stěna - část 4 + +[WMAYAN01] +STR_NAME :Stěna Ztraceného města + +[WMAYAN02] +STR_NAME :Střecha Ztraceného města + +[WMAYAN03] +STR_NAME :Stěna Ztraceného města + +[WMAYAN04] +STR_NAME :Stěna Ztraceného města + +[WMAYAN05] +STR_NAME :Stěna Ztraceného města + +[WMAYAN06] +STR_NAME :Stěna Ztraceného města + +[WMAYAN07] +STR_NAME :Stěna Ztraceného města + +[WMAYAN08] +STR_NAME :Stěna Ztraceného města + +[WMAYAN09] +STR_NAME :Stěna Ztraceného města + +[WMAYAN10] +STR_NAME :Stěna Ztraceného města + +[WMAYAN11] +STR_NAME :Stěna Ztraceného města + +[WMAYAN12] +STR_NAME :Schodiště Ztraceného města + +[WMAYAN13] +STR_NAME :Schodiště Ztraceného města + +[WMAYAN14] +STR_NAME :Schodiště Ztraceného města + +[WMAYAN15] +STR_NAME :Schodiště Ztraceného města + +[WMAYAN16] +STR_NAME :Schodiště Ztraceného města + +[WMAYAN17] +STR_NAME :Sloup Ztraceného města + +[WMAYAN18] +STR_NAME :Sloup Ztraceného města + +[WMAYAN20] +STR_NAME :Stěna Ztraceného města + +[WMAYAN21] +STR_NAME :Střecha Ztraceného města + +[WMAYAN22] +STR_NAME :Střecha Ztraceného města + +[WMAYAN23] +STR_NAME :Rohová štěna Ztraceného města + +[WMAYAN24] +STR_NAME :Rohová štěna Ztraceného města + +[WMAYAN25] +STR_NAME :Rohová štěna Ztraceného města + +[WMAYAN26] +STR_NAME :Rohová štěna Ztraceného města + +[WNAUTI01] +STR_NAME :Mořská střecha + +[WNAUTI02] +STR_NAME :Mořská střecha + +[WNAUTI03] +STR_NAME :Mořská střecha + +[WNAUTI04] +STR_NAME :Mořská střecha + +[WNAUTI05] +STR_NAME :Mořská střecha + +[WTUDOR12] +STR_NAME :Tudorská stěna - část 4 + +[WTUDOR13] +STR_NAME :Tudorská stěna + +[WTUDOR14] +STR_NAME :Tudorská přízemní stěna - část 1 + +[WTUDOR15] +STR_NAME :Tudorská přízemní stěna - část 2 + +[WTUDOR16] +STR_NAME :Tudorská přízemní stěna - část 3 + +[WTUDOR17] +STR_NAME :Tudorská přízemní stěna - část 4 + +[WTUDOR18] +STR_NAME :Tudorská přízemní stěna - část 5 + +[CAMPFANI] +STR_NAME :Animatovaný táborák + +[CONVEYR1] +STR_NAME :Roh dopravího pásu + +[CONVEYR2] +STR_NAME :Dopravní pás + +[CONVEYR3] +STR_NAME :Konec dopravního pásu + +[CONVEYR4] +STR_NAME :Dopravní pás + +[CONVEYR5] +STR_NAME :Roh dopravního pásu + +[FISHHOLE] +STR_NAME :Rybí díra + +[FLAMNGO1] +STR_NAME :Plameňák + +[FLAMNGO2] +STR_NAME :Plameňák + +[FLAMNGO3] +STR_NAME :Plameňák + +[FOUNTARC] +STR_NAME :Australská fontána + +[FOUNTROW] +STR_NAME :Australská fontána + +[G1DANCER] +STR_NAME :Mardi Gras tanečnice + +[G2DANCER] +STR_NAME :Mardi Gras tanečnice + +[INUIT] +STR_NAME :Eskymák + +[INUIT2] +STR_NAME :Eskymák + +[INFLAG01] +STR_NAME :Indická hedvábná vlajka + +[INFLAG02] +STR_NAME :Indická hedvábná vlajka + +[INFLAG03] +STR_NAME :Indická hedvábná vlajka + +[INFLAG04] +STR_NAME :Indická hedvábná vlajka + +[INFLAG05] +STR_NAME :Indická hedvábná vlajka + +[JPFLAG01] +STR_NAME :Japonská hedvábná vlajka + +[JPFLAG02] +STR_NAME :Japonská hedvábná vlajka + +[JPFLAG03] +STR_NAME :Japonská hedvábná vlajka + +[JPFLAG04] +STR_NAME :Japonská hedvábná vlajka + +[JPFLAG05] +STR_NAME :Japonská hedvábná vlajka + +[JPFLAG06] +STR_NAME :Japonská hedvábná vlajka + +[OILPUMP] +STR_NAME :Ropné čerpadlo + +[SBALLOON] +STR_NAME :Animované balónky + +[WCUZFOUN] +STR_NAME :Monumentální fontána + +[WROPECOR] +STR_NAME :Mořský roh střechy + +[WROPESWA] +STR_NAME :Mořské střešní zábradlí + +[1X2ABR01] +STR_NAME :Domorodecká obyčejná dlaždice + +[1X2ABR02] +STR_NAME :Domorodecké umění + +[1X2ABR03] +STR_NAME :Domorodecké umění + +[1X2AZT01] +STR_NAME :Stěna chrámu s hlavou + +[1X2AZT02] +STR_NAME :Rozbitá stěna chrímu s hlavou + +[1X2LGCHM] +STR_NAME :Dulní chatrč s postranním komínem + +[AFRCLION] +STR_NAME :Lev + +[AFRRHINO] +STR_NAME :Nosorožec + +[ATRACTOR] +STR_NAME :Traktor + +[AFRZEBRA] +STR_NAME :Zebra + +[1X4BRG01] +STR_NAME :Zavěšený most + +[1X4BRG02] +STR_NAME :Zavěšený most + +[1X4BRG03] +STR_NAME :Zavěšený most + +[1X4BRG04] +STR_NAME :Zavěšený most + +[1X4BRG05] +STR_NAME :Zavěšený most + +[3X3ATRE1] +STR_NAME :Jungle strom 2 + +[3X3MANTR] +STR_NAME :Mangrove + +[50ROCKET] +STR_NAME :Raketa z 50. let + +[BamboRf1] +STR_NAME :Bambusová střecha + +[BAMBORF2] +STR_NAME :Bambusová střecha + +[BamboRf3] +STR_NAME :Bambusová střecha + +[BIGGEOSP] +STR_NAME :Velká geosféra + +[CIRCUS] +STR_NAME :Cirkus + +[COWBOY01] +STR_NAME :Kovboj 1 + +[COWBOY02] +STR_NAME :Kovboj 2 + +[DAMTOWER] +STR_NAME :Přehradní věž + +[EIFFEL] +STR_NAME :Eiffelova věž + +[FATBUDDA] +STR_NAME :Buddha + +[GIRAFFE1] +STR_NAME :Žirafa 1 + +[GIRAFFE2] +STR_NAME :Žirafa 2 + +[GOLDBUDA] +STR_NAME :Zlatý Buddha + +[HIPPO01] +STR_NAME :Hroch 1 + +[HIPPO02] +STR_NAME :Hroch 2 + +[IndickáST] +STR_NAME :Indián + +[LARGEJU1] +STR_NAME :Velký strom deštného pralesa + +[LINCOLNS] +STR_NAME :Socha Washingtona + +[RDRAB01] +STR_NAME :Velká věž + +[RDRAB02] +STR_NAME :Velká věž + +[RDRAB03] +STR_NAME :Velká věž + +[RDRAB04] +STR_NAME :Velká věž + +[REDWOOD] +STR_NAME :Sequoioideae + +[RKREML08] +STR_NAME :Kremlinská věž + +[RKREML09] +STR_NAME :Kremlinská věž + +[RKREML10] +STR_NAME :Kremlinská věž + +[RTUDOR05] +STR_NAME :Tudorská střecha + +[RTUDOR06] +STR_NAME :Tudorská střecha + +[SHIVA] +STR_NAME :Shiva + +[SOFLIBRT] +STR_NAME :Socha svobody + +[SPUTNIK] +STR_NAME :Sputnik + +[TAJMCBSE] +STR_NAME :Mahárádžův palác - věž + +[TAJMCOLM] +STR_NAME :Mahárádžův palác - věž + +[TAJMCTOP] +STR_NAME :Mahárádžův palác - věž + +[1X2GLAMA] +STR_NAME :Zlatá lama + +[3X3ALTRE] +STR_NAME :Strom z jungle s leopardy + +[3X3ATRE2] +STR_NAME :Strom z jungle + +[3X3ATRE3] +STR_NAME :Strom z jungle s lijánami + +[3X3EUCAL] +STR_NAME :Eukalyptus + +[3X3HMSEN] +STR_NAME :HMS Endeavour + +[ADULTELE] +STR_NAME :Dospělý slon + +[ATOMIUM] +STR_NAME :Atomium + +[BIGBEN] +STR_NAME :Big Ben a parlament + +[BIGDISH] +STR_NAME :Satelit + +[CDRAGON] +STR_NAME :Čínský drak + +[EASERLND] +STR_NAME :Socha Velikonočního ostrova + +[EVILSAM] +STR_NAME :Ďábelský samurai + +[GDSTAUE1] +STR_NAME :Zlatá socha 1 + +[GDSTAUE2] +STR_NAME :Zlatá socha 2 + +[GEISHA] +STR_NAME :Gejša + +[GOODSAM] +STR_NAME :Hodný samurai + +[GWOCTUR1] +STR_NAME :Velká čínská zeď - věž + +[GWOCTUR2] +STR_NAME :Velká čínská zeď - věž + +[HELIPAD] +STR_NAME :Heliport + +[ICEFOR01] +STR_NAME :Ledová kreace + +[ICEFOR02] +STR_NAME :Ledová kreace + +[MBSKYR01] +STR_NAME :Střecha mrakodrapu + +[MBSKYR02] +STR_NAME :Vrcholek mrakodrapu + +[OVRGRWNT] +STR_NAME :Starý přerostlý strom + +[POGODAL] +STR_NAME :Pagoda + +[PAGODAM] +STR_NAME :Pagoda + +[PAGODAS] +STR_NAME :Pagoda + +[PAGODATW] +STR_NAME :Pagoda - věž + +[RADAR] +STR_NAME :Radar + +[SPACEORB] +STR_NAME :Vesmírné objekty + +[SUNKEN] +STR_NAME :Potopená loď + +[TAJMDOME] +STR_NAME :Mahárádžův palác + +[WINDMILL] +STR_NAME :Větrný mlýn + +[TMARCH1] +STR_NAME :Mahárádžův palác - věžička + +[TMARCH2] +STR_NAME :Mahárádžův palác - věžička + +[W2CORR01] +STR_NAME :Vlnitá zeď + +[W2CORR02] +STR_NAME :Vlnitá zeď + +[W2CORR03] +STR_NAME :Vlnitá zeď + +[W2CORR04] +STR_NAME :Vlnitá zeď + +[W2CORR05] +STR_NAME :Vlnitá zeď + +[W2CORR06] +STR_NAME :Vlnitá zeď + +[W2CORR07] +STR_NAME :Vlnitá zeď + +[W2CORR08] +STR_NAME :Vlnitá zeď + +[W3CORR01] +STR_NAME :Vlnitá zeď + +[W3CORR02] +STR_NAME :Vlnitá zeď + +[W3CORR03] +STR_NAME :Vlnitá zeď + +[W3CORR04] +STR_NAME :Vlnitá zeď + +[W3CORR05] +STR_NAME :Vlnitá zeď + +[W3CORR06] +STR_NAME :Vlnitá zeď + +[W3CORR07] +STR_NAME :Vlnitá zeď + +[W3CORR08] +STR_NAME :Vlnitá zeď + +[WALLNA01] +STR_NAME :Mořská zeď + +[WALLNA02] +STR_NAME :Mořská zeď + +[WALLNA03] +STR_NAME :Mořská zeď + +[WALLNA04] +STR_NAME :Mořská zeď + +[WALLNA05] +STR_NAME :Mořská zeď + +[WALLNA06] +STR_NAME :Mořská zeď + +[WALLNA07] +STR_NAME :Mořská zeď + +[WALLNA08] +STR_NAME :Mořská zeď + +[WALLNA09] +STR_NAME :Mořská zeď + +[WALLNA10] +STR_NAME :Mořská zeď + +[WALLNA11] +STR_NAME :Mořská zeď + +[WALLNA12] +STR_NAME :Mořská zeď + +[WALLNA13] +STR_NAME :Mořská zeď + +[WALLNA14] +STR_NAME :Mořská zeď + +[WWDAUB01] +STR_NAME :Hliněná zeď + +[WWDAUB02] +STR_NAME :Hliněná zeď + +[WWDAUB03] +STR_NAME :Hliněná zeď + +[WWDAUB04] +STR_NAME :Hliněná zeď + +[WWDAUB05] +STR_NAME :Hliněná zeď + +[WWDAUB06] +STR_NAME :Hliněná zeď + +[WWDAUB07] +STR_NAME :Hliněná zeď + +[WBambo01] +STR_NAME :Bambusová zeď + +[WBambo02] +STR_NAME :Bambusová zeď + +[WBambo03] +STR_NAME :Bambusová zeď + +[WBAMBO04] +STR_NAME :Bambusová zeď + +[WBambo05] +STR_NAME :Bambusová zeď + +[WBambo11] +STR_NAME :Bambusová zeď + +[WBambo12] +STR_NAME :Bambusová zeď + +[WBambo13] +STR_NAME :Bambusová zeď + +[WBambo14] +STR_NAME :Bambusová zeď + +[WBambo15] +STR_NAME :Bambusová zeď + +[WBambo21] +STR_NAME :Bambusová zeď + +[WBRICK01] +STR_NAME :Zeď z červených cihel 1 + +[WBRICK02] +STR_NAME :Zeď z červených cihel 2 + +[WBRICK03] +STR_NAME :Zeď z červených cihel 3 + +[WBRICK04] +STR_NAME :Zeď z červených cihel 4 + +[WBRICK05] +STR_NAME :Zeď z červených cihel 5 + +[WBRICK08] +STR_NAME :Zeď z červených cihel 8 + +[WBRICK11] +STR_NAME :Zeď z červených cihel 11 + +[WBRICK12] +STR_NAME :Zeď z červených cihel 12 + +[WBRICK13] +STR_NAME :Zeď z červených cihel 13 + +[WCORR01] +STR_NAME :Vlnitá zeď + +[WCORR02] +STR_NAME :Vlnitá zeď + +[WCORR03] +STR_NAME :Vlnitá zeď + +[WCORR04] +STR_NAME :Vlnitá zeď + +[WCORR05] +STR_NAME :Vlnitá zeď + +[WCORR06] +STR_NAME :Vlnitá zeď + +[WCORR07] +STR_NAME :Vlnitá zeď + +[WCORR08] +STR_NAME :Vlnitá zeď + +[WCORR09] +STR_NAME :Vlnitá zeď + +[WCORR10] +STR_NAME :Vlnitá zeď + +[WCORR11] +STR_NAME :Vlnitá zeď + +[WCORR12] +STR_NAME :Vlnitá zeď + +[WCORR13] +STR_NAME :Vlnitá zeď + +[WCORR14] +STR_NAME :Vlnitá zeď + +[WCORR15] +STR_NAME :Vlnitá zeď + +[WCORR16] +STR_NAME :Vlnitá zeď + +[WDRAB01] +STR_NAME :Khaki stěna - část 1 + +[WDRAB02] +STR_NAME :Khaki stěna - část 2 + +[WDRAB03] +STR_NAME :Khaki stěna - část 3 + +[WDRAB04] +STR_NAME :Khaki stěna - část 4 + +[WDRAB05] +STR_NAME :Khaki stěna - část 5 + +[WDRAB06] +STR_NAME :Khaki stěna - část 6 + +[WDRAB07] +STR_NAME :Khaki stěna - část 7 + +[WDRAB08] +STR_NAME :Khaki stěna - část 8 + +[WGEORG01] +STR_NAME :Gregoriánská stěna - část 1 + +[WGEORG02] +STR_NAME :Gregoriánská přízemní stěna - část 1 + +[WGEORG03] +STR_NAME :Gregoriánská stěna - část 2 + +[WGEORG04] +STR_NAME :Gregoriánská přízemní stěna - část 2 + +[WGEORG05] +STR_NAME :Gregoriánská stěna - část 3 + +[WGEORG06] +STR_NAME :Gregoriánská přízemní stěna - část 3 + +[WGWOC1] +STR_NAME :Velká čínská zeď + +[WGWOC2] +STR_NAME :Velká čínská zeď + +[WGWOC3] +STR_NAME :Velká čínská zeď + +[WALLICE1] +STR_NAME :Ledová stěna + +[WALLICE2] +STR_NAME :Ledová stěna + +[WALLICE3] +STR_NAME :Ledová stěna + +[WALLICE4] +STR_NAME :Ledová stěna + +[WALLICE5] +STR_NAME :Ledová stěna + +[WALLICE6] +STR_NAME :Ledová stěna + +[WALLICE7] +STR_NAME :Ledová stěna + +[WALLICE8] +STR_NAME :Ledová stěna + +[WALLICE9] +STR_NAME :Ledová stěna + +[WALLIC10] +STR_NAME :Ledová stěna + +[WIGLOO1] +STR_NAME :Stěna iglů + +[WIGLOO2] +STR_NAME :Stěna iglů + +[WKREML07] +STR_NAME :Kremlinská stěna - část 5 + +[WKREML08] +STR_NAME :Kremlinská stěna - část 6 + +[WKREML09] +STR_NAME :Kremlinská stěna - část 7 + +[WKREML10] +STR_NAME :Kremlinská stěna - část 8 + +[WLOG01] +STR_NAME :Stěna dulní chatrče + +[WLOG02] +STR_NAME :Stěna dulní chatrče + +[WLOG03] +STR_NAME :Stěna dulní chatrče + +[WLOG04] +STR_NAME :Stěna dulní chatrče + +[WLOG05] +STR_NAME :Stěna dulní chatrče + +[WLOG06] +STR_NAME :Stěna dulní chatrče + +[WMARBLE1] +STR_NAME :Ornamentální mramorová zeď + +[WMARBLE2] +STR_NAME :Ornamentální mramorová zeď + +[WMARBLE3] +STR_NAME :Ornamentální mramorová zeď + +[WMARBLE4] +STR_NAME :Ornamentální mramorová zeď + +[WMARBLE5] +STR_NAME :Ornamentální mramorová zeď + +[WMARBLE6] +STR_NAME :Ornamentální mramorová zeď + +[WMARBPL1] +STR_NAME :Obyčejná mramorová zeď + +[WMARBPL2] +STR_NAME :Obyčejná mramorová zeď + +[WMARBPL3] +STR_NAME :Obyčejná mramorová zeď + +[WMARBPL4] +STR_NAME :Obyčejná mramorová zeď + +[WMARBPL5] +STR_NAME :Obyčejná mramorová zeď + +[WMARBPL6] +STR_NAME :Obyčejná mramorová zeď + +[WMARBPL7] +STR_NAME :Obyčejná mramorová zeď + +[WMUD01] +STR_NAME :Stěna z bahna + +[WMUD02] +STR_NAME :Stěna z bahna + +[WMUD03] +STR_NAME :Stěna z bahna + +[WMUD04] +STR_NAME :Stěna z bahna + +[WMUD05] +STR_NAME :Stěna z bahna + +[WMUD06] +STR_NAME :Stěna z bahna + +[WMUD07] +STR_NAME :Stěna z bahna + +[WMUD08] +STR_NAME :Stěna z bahna + +[WPALM01] +STR_NAME :Stěna chaty + +[WPALM02] +STR_NAME :Stěna chaty + +[WPALM03] +STR_NAME :Stěna chaty + +[WPALM04] +STR_NAME :Stěna chaty + +[WPALM05] +STR_NAME :Stěna chaty + +[WSHOGI01] +STR_NAME :Čínská zeď + +[WSHOGI02] +STR_NAME :Čínská zeď + +[WSHOGI03] +STR_NAME :Čínská zeď + +[WSHOGI04] +STR_NAME :Čínská zeď + +[WSHOGI05] +STR_NAME :Čínská zeď + +[WSHOGI06] +STR_NAME :Čínská zeď + +[WSHOGI07] +STR_NAME :Čínská zeď + +[WSHOGI08] +STR_NAME :Čínská zeď + +[WSHOGI09] +STR_NAME :Čínská zeď + +[WSHOGI10] +STR_NAME :Čínská zeď + +[WSHOGI11] +STR_NAME :Čínská zeď + +[WSHOGI12] +STR_NAME :Čínská zeď + +[WSHOGI13] +STR_NAME :Čínská zeď + +[WSHOGI14] +STR_NAME :Čínská zeď + +[WSHOGI15] +STR_NAME :Čínská zeď + +[WSHOGI16] +STR_NAME :Čínská zeď + +[WSHOGI17] +STR_NAME :Čínská zeď + +[WSKYSC01] +STR_NAME :Kovový set mrakodrapu 1 - stěna + +[WSKYSC02] +STR_NAME :Kovový set mrakodrapu 2 - stěna + +[WSKYSC03] +STR_NAME :Kovový set mrakodrapu 1 - stěna + +[WSKYSC04] +STR_NAME :Kovový výtah mrakodrapu + +[WSKYSC05] +STR_NAME :Kovový výtah mrakodrapu + +[WSKYSC06] +STR_NAME :Kovový mrakodrap - výtah + +[WSKYSC07] +STR_NAME :Kovový mrakodrap - výtah + +[WSKYSC08] +STR_NAME :Kovový mrakodrap - stěna + +[WSKYSC09] +STR_NAME :Kovový mrakodrap - stěna + +[WSKYSC10] +STR_NAME :Kamenný mrakodrap - stěna + +[WSKYSC11] +STR_NAME :Kamenný mrakodrap - stěna + +[WSKYSC12] +STR_NAME :Kamenný mrakodrap - stěna + +[WTUDOR01] +STR_NAME :Tudorská přízemní stěna - část 1 + +[WTUDOR02] +STR_NAME :Tudorská přízemní stěna - část 2 + +[WTUDOR03] +STR_NAME :Tudorská přízemní stěna - část 3 + +[WTUDOR04] +STR_NAME :Tudorská přízemní stěna - část 4 + +[WTUDOR05] +STR_NAME :Tudorská přízemní stěna - část 5 + +[WTUDOR06] +STR_NAME :Tudorská přízemní stěna - část 6 + +[WTUDOR07] +STR_NAME :Tudorská přízemní stěna - část 7 + +[WTUDOR08] +STR_NAME :Tudorská přízemní stěna - část 8 + +[WTUDOR09] +STR_NAME :Tudorská stěna - část 1 + +[WTUDOR10] +STR_NAME :Tudorská stěna - část 2 + +[WTUDOR11] +STR_NAME :Tudorská stěna - část 3 + +[WWIND03] +STR_NAME :Větrem ošlehaná stěna - část + +[WWIND04] +STR_NAME :Větrem ošlehaná stěna - část + +[WWIND05] +STR_NAME :Větrem ošlehaná stěna - část + +[WWIND06] +STR_NAME :Větrem ošlehaná stěna - část + +[WBamboPC] +STR_NAME :Bambusová zeď + +[SCGAFRIC] +STR_NAME : Afrika + +[SCGARTIC] +STR_NAME : Antarktida + +[SCGASIA] +STR_NAME : Asie + +[SCGAUSTR] +STR_NAME : Austrále + +[SCGEUROP] +STR_NAME : Evropa + +[SCGNAMRC] +STR_NAME : Severní Amerika + +[SCGSAMER] +STR_NAME : Jižní Amerika + +[AFRICENT] +STR_NAME :Africý vstup do parku + +[EUROENT] +STR_NAME :Evropský vstup do parku + +[ICEENT] +STR_NAME :Ledový vstup do parku + +[JAPENT] +STR_NAME :Japonský vstup do parku + +[NAENT] +STR_NAME :Vstup do parku ve stylu severní Ameriky + +[OZENTRAN] +STR_NAME :Australský vstup do parku + +[SAMERENT] +STR_NAME :Vstup do parku ve stylu jižní Ameriky + +############################################################################### +## Time Twister Objects +############################################################################### +[SCHOOLBS] +STR_NAME :Školní autobus - tramvaj +STR_DESC :Replika amerických žlutých školních autobusů +STR_CPTY :10 míst v každém voze + +[TELEPTER] +STR_NAME :Teleportér +STR_DESC :Návštěvníci jsou transportování z jednoho patra do druhého +STR_CPTY :16 návštěvníků + +[ZEPLELIN] +STR_NAME :Jednokolejné vlaky připomínající vzducholoď +STR_DESC :Velkokapacitní jodnokolejné vlaky s aerodynamickou přídí a zádí +STR_CPTY :5 nebo 10 míst v každém vagónu + +[BMVOCTPS] +STR_NAME :Mimozemská hmota +STR_DESC :Tématická pozorovací věž s kabinou, která postupně vyjede až na vrchol a zpět dolů +STR_CPTY :20 návštěvníků + +[CYCLOPSX] +STR_NAME :Kyklopský autodrom +STR_DESC :Autodrom s elektrickými autíčky ve tvaru oka gigantického kyklopa +STR_CPTY :1 místo v každém voze + +[FIGTKNIT] +STR_NAME :Rytířský autodrom +STR_DESC :Autodrom s elektrickými autíčky ve tvaru koní +STR_CPTY :1 místo v každém voze + +[FLWRPOWR] +STR_NAME :Květinová vznášedla +STR_DESC :Autodrom se vznášedly ve tvaru květů květin +STR_CPTY :1 místo v každém voze + +[FUNHOUSE] +STR_NAME :Dům zábavy +STR_DESC :Budova s pohybujícími se zdmi a podlahou, což dezorientuje procházející návštěvníky +STR_CPTY :5 návštěvníků + +[HALOFMRS] +STR_NAME :Zrcadlové bludiště +STR_DESC :Budova s pokřivenými zrdcadly +STR_CPTY :5 návštěvníků + +[HOVERCAR] +STR_NAME :Autodráha se vznášedly +STR_DESC :Vozy ve tvaru futuristických vznášedel jezdí po postavené dráze +STR_CPTY :2 místa v každém voze + +[MGR2] +STR_NAME :Dvoupatrový kolotoč +STR_DESC :Klasický dvoupatrový kolotoč s vyřezávanými koníky +STR_CPTY :32 návštěvníků + +[PEGASUSX] +STR_NAME :Autodráha s Pegasem +STR_DESC :Vozy ve tvaru povozů tažených Pegasem jezdí po postavené dráze +STR_CPTY :2 místa v každém voze + +[SPOKPRSN] +STR_NAME :Strašidelná věznice +STR_DESC :Budova s podzemím a figurínami vězňů straší procházející návštěvníky +STR_CPTY :16 návštěvníků + +[TIMEMACH] +STR_NAME :Stroj času +STR_DESC :Návštěvníci sedí ve speciálně navržené kruhovité konstrucki a zažívají pocit cestování šasem +STR_CPTY :1 místo v každém stroji času + +[TRICATOP] +STR_NAME :Autodrom s Triceratopsem +STR_DESC :Autodrom s vozy ve tvaru Triceratopsů +STR_CPTY :1 místo v každém voze + +[BARNSTRM] +STR_NAME :Stodolní střela +STR_DESC :Vozy jsou zavěšeny na kolejnicích s ostrými zatáčkami a ostrými pády +STR_CPTY :4 místa v každém voze + +[BATTRRAM] +STR_NAME :Beranidlová horská dráha +STR_DESC :Malá ocelová horská dráha se spirálovitým profilem a vozy se sedadly za sebou +STR_CPTY :6 míst v každém voze + +[BLCKDETH] +STR_NAME :Morová horská dráha +STR_DESC :Návštěvníci jedou po propletené bobové dráze +STR_CPTY :2 místa v každém voze + +[CERBERUS] +STR_NAME :Kerberosova horská dráha +STR_DESC :Horská dráha s dlouhými pády, velkou rychlostí a pohodlnými vlaky, kde se jezdí s opěrkou v klíně, která přelétává vrcholky kopců +STR_CPTY :4 místa v každém voze + +[DRAGNFLY] +STR_NAME :Šídlí horská dráha +STR_DESC :Návštěvníci jedou na jednokolejné trati zavěšeni ve speciálním voze, který se v zatáčkách houpe +STR_CPTY :2 místa v každém voze + +[GANSTRCR] +STR_NAME :Gangsterská horská dráha +STR_DESC :Horská dráha s vozy ve stylu gangstrů 20. let, poháněnými elektromotorem, které sviští skrze propletenou dráhu +STR_CPTY :4 místa v každém voze + +[HARPIESX] +STR_NAME :Horská dráha harpií +STR_DESC :Návštěvníci jedou v leže zavěšeni do speciálního držení, ve kterém na břiše nebo na zádech projedou trať s ostrými zatáčkami +STR_CPTY :4 místa v každém voze + +[HOTRODXX] +STR_NAME :Hot Rod horská dráha +STR_DESC :Po mocném startu na stlačený vzduch se vozy rozjedou po svislé dráze, přes vrchol a svisle dolů zpět do stanice +STR_CPTY :2 místa v každém voze + +[HOVERBKE] +STR_NAME :Vznášedlová moto horská dráha +STR_DESC :Návštěvníci sedí na futuristických motorkách, která jedou po jednokolejné dráze +STR_CPTY :2 místa na každé motorce + +[HOVRBORD] +STR_NAME :Vznášedlová horská dráha +STR_DESC :Návštěvníci jezdí na futuristickách vznášedlech, houpajících se v zatáčkách ze strany na stranu +STR_CPTY :2 místa v každém voze + +[JETPACKX] +STR_NAME :Jet Pack Booster +STR_DESC :Návštěvníci sedí ve voze, který je vystřelen po kolmé dráze +STR_CPTY :8 míst v každém voze + +[JETPLANE] +STR_NAME :Stíhačková horské dráha +STR_DESC :Malá horská dráha, na které vozy po jednom projíždí trať s kroucenými pády +STR_CPTY :4 místa v každém voze + +[JOUSTING] +STR_NAME :Turnajová horská dráha +STR_DESC :Návštěvníci sedí na zádi vozů ve tvaru koní, které jedou po jednokolejné dráze +STR_CPTY :2 místa v každém voze + +[POLCHASE] +STR_NAME :Policejní honička +STR_DESC :Horská dráha s lopinky, na které návštěvníci ve vozech sedí +STR_CPTY :4 místa v každém voze + +[POLICECR] +STR_NAME :Horská dráha policejních vozů +STR_DESC :Po dřevěné dráze jedou vozy ve tvaru policejních aut 60. let, které se ve speciálních místech se otočí a jedou pozpátku +STR_CPTY :6 míst v každém voze + +[PTERODAC] +STR_NAME :Pterodaktylská horská dráha +STR_DESC :Návštěvníci sedí v pohodlných sedadlech pod tratí cestující skrze propletenou dráhu, poskytující pocit prehistorického letu +STR_CPTY :4 místa v každém voze + +[RAPTORXX] +STR_NAME :Raptorská horská dráha +STR_DESC :Návštěvníci sedí na zádi vozů ve tvaru pterodaktylů, které jedou po jednokolejné dráze +STR_CPTY :2 místa v každém voze + +[SEAPLANE] +STR_NAME :Hydroplánská horská dráha +STR_DESC :Zavěšená horská dráha z volné zavěšených vozů, které se naklání při jízdě do zatáček +STR_CPTY :4 místa v každém voze + +[STAMPHRD] +STR_NAME :Horská dráha splašeného stáda +STR_DESC :Horská dráha s lopinky a vozy ve tvaru splašeného stáda dinosaurů +STR_CPTY :4 místa v každém voze + +[VALKYRIE] +STR_NAME :Valkýrská horská dráha +STR_DESC :Extra-široké vozy letí dolů po zcela kolmé dráze a poskytují tím pocit volného pádu +STR_CPTY :6 míst v každém voze + +[1920RACR] +STR_NAME :Motokáry z 20. let +STR_DESC :Benzínové ovladatelné motokáry ve stylu 20. let +STR_CPTY :1 místo v každém voze + +[CAVMNCAR] +STR_NAME :Prehistorické motokáry +STR_DESC :Benzínové ovladatelné motokáry ve stylu pravěku +STR_CPTY :1 místo v každém voze + +[DINOEGGS] +STR_NAME :Jízda dinsouřích vajec +STR_DESC :Návštěvníci sedí po dvou ve vejcích, které se otáčejí okolo dinosaura-matky uprostřed +STR_CPTY :18 návštěvníků + +[FLALMACE] +STR_NAME :Palicová jízda +STR_DESC :Návštěvníci sedí na židlích připevněných na otáčející se ramena +STR_CPTY :1 místo na každé židli + +[GINTSPDR] +STR_NAME :Béčková pavoučí jízda +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí okolo velkého pavouka z béčkového filmu uprostřed +STR_CPTY :18 návštěvníků + +[MICROBUS] +STR_NAME :Jízda v MicroBusu +STR_DESC :Návštěvníci sledují film uvnitř simulátoru pohybu, zatímco se simulátorem hýbe hydraulika +STR_CPTY :8 návštěvníků + +[NEPTUNEX] +STR_NAME :Neptunská jízda +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí okolo suchy Neptuna uprostřed +STR_CPTY :18 návštěvníků + +[TOMMYGUN] +STR_NAME :Jízda s Thompsonem +STR_DESC :Návštěvníci sedí po dvou na sedačkách, které se otáčejí okolo velké repliky samopalu Thompson uprostřed +STR_CPTY :18 návštěvníků + +[TREBUCHT] +STR_NAME :Katapultující jízda +STR_DESC :Návštěvníci sedí v gondole zavěšené na podpěrách, otáčející se dopředu a dozadu vzhůru nohama, která vypadá jako obléhací zbraň z dávných dob +STR_CPTY :8 návštěvníků + +[FLYGBOAT] +STR_NAME :Létající lodě +STR_DESC :Vozy ve tvaru létajících lodí jedou po trati horské dráhy, což umožňuje ostré zatáčky, strmé klesání a cákající zpomalení pro mírnější říční úseky +STR_CPTY :16 míst v každé lodi + +[OAKBAREL] +STR_NAME :Jízda v dubovém sudu +STR_DESC :Lodě ve tvaru dubových barelů se plaví po meandrech na vodním kanále a sjíždějí pěnící peřeje +STR_CPTY :8 míst v každé lodi + +[RIVRSTYX] +STR_NAME :Řeka Styx +STR_DESC :Rafty se plaví po meandrech na vodním kanále +STR_CPTY :4 místa na každém raftu + +[TRILOBTE] +STR_NAME :Trilobití lodě +STR_DESC :Vozy ve tvaru trilobitů jedou po trati horské dráhy, což umožňuje ostré zatáčky, strmé klesání a cákající zpomalení pro mírnější říční úseky +STR_CPTY :16 míst v každé lodi + +[1920SAND] +STR_NAME :Art Deco stánek +STR_DESC :Malý stánek s nudlemi a čerstvou limonádou + +[1960TSRT] +STR_NAME :Hippie trička +STR_DESC :Stánek prodávající batikovaná trička s hippie motivy + +[MEDISOUP] +STR_NAME :Čarodějnický kotlík +STR_DESC :Stánek prodávající hustou polévku + +[MKTSTAL1] +STR_NAME :Jarmarkový stánek s jablky v županu +STR_DESC :Stánek prodávající jablka v županu + +[MKTSTAL2] +STR_NAME :Jarmarkový stánek s citronádou +STR_DESC :Stánek prodávající starou dobrou čerstvou citronádu + +[MOONJUCE] +STR_NAME :Šťáva z Měsíce +STR_DESC :Stánek prodávající nejnovější slazené nápoje + +[MYTHOSEA] +STR_NAME :Neptunův stánek s plody moře +STR_DESC :Stánek prodávající Neptunovy mořské dobroty + +[SOFTOYST] +STR_NAME :Stánek s plyšáky-dinosaury +STR_DESC :Stánek prodávající roztomilé plyšáky-dinosaury + +[1920SLMP] +STR_NAME :Stará pouliční lampa + +[ALENTRE1] +STR_NAME :Mimozemský strom + +[ALENTRE2] +STR_NAME :Mimozemský strom + +[ARMRBODY] +STR_NAME :Magické brnění + +[ARMRHELM] +STR_NAME :Magická helma + +[ARMRSHLD] +STR_NAME :Magický štít + +[ARMRSWRD] +STR_NAME :Magický meč + +[ARTDEC01] +STR_NAME :Art Deco stěna + +[ARTDEC02] +STR_NAME :Art Deco roh + +[ARTDEC03] +STR_NAME :Art Deco dveřní rám + +[ARTDEC04] +STR_NAME :Art Deco okno + +[ARTDEC05] +STR_NAME :Art Deco okno + +[ARTDEC06] +STR_NAME :Art Deco vrchní část + +[ARTDEC07] +STR_NAME :Art Deco rohová část + +[ARTDEC08] +STR_NAME :Art Deco vrchní rohová část + +[ARTDEC09] +STR_NAME :Art Deco stěna + +[ARTDEC10] +STR_NAME :Art Deco stěna + +[ARTDEC11] +STR_NAME :Art Deco roh s okny + +[ARTDEC12] +STR_NAME :Art Deco roh se zábradlím + +[ARTDEC13] +STR_NAME :Art Deco vrchní rohová část + +[ARTDEC14] +STR_NAME :Art Deco roh s okny + +[ARTDEC15] +STR_NAME :Art Deco stěna + +[ARTDEC16] +STR_NAME :Art Deco stěna + +[ARTDEC17] +STR_NAME :Art Deco stěna + +[ARTDEC18] +STR_NAME :Art Deco vrchní část + +[ARTDEC19] +STR_NAME :Art Deco stěna + +[ARTDEC20] +STR_NAME :Art Deco stěna + +[ARTDEC21] +STR_NAME :Art Deco stěna se zábradlím + +[ARTDEC22] +STR_NAME :Art Deco stěna se zábradlím + +[ARTDEC23] +STR_NAME :Art Deco stěna se zábradlím + +[ARTDEC24] +STR_NAME :Art Deco stěna se zábradlím + +[ARTDEC28] +STR_NAME :Art Deco střešní část + +[ARTDEC29] +STR_NAME :Art Deco roh + +[BIGBASSX] +STR_NAME :Obrovská baskytara + +[BIGGUTAR] +STR_NAME :Obrovská kytara + +[CHPRBKE1] +STR_NAME :Motorka + +[CHPRBKE2] +STR_NAME :Motorka + +[ELECFEN5] +STR_NAME :Elektrický plot - obrácená rohová část + +[FIREMANX] +STR_NAME :Pohybující se hasič + +[FUTSKY16] +STR_NAME :Pískovcový mrakodrap - roh + +[FUTSKY17] +STR_NAME :Pískovcový mrakodrap - výplň + +[FUTSKY18] +STR_NAME :Pískovcový mrakodrap - dveřní rám + +[FUTSKY19] +STR_NAME :Pískovcový mrakodrap - dolní roh + +[FUTSKY21] +STR_NAME :Pískovcový mrakodrap - střední stěna + +[FUTSKY23] +STR_NAME :Pískovcový mrakodrap - obrácený vrchní roh + +[FUTSKY29] +STR_NAME :Pískovcový mrakodrap - dolní zaoblená část + +[FUTSKY34] +STR_NAME :Pískovcový mrakodrap - střecha + +[FUTSKY35] +STR_NAME :Pískovcový mrakodrap - střední zaoblená část + +[FUTSKY42] +STR_NAME :Pískovcový mrakodrap - horní zaoblená část + +[FUTSKY52] +STR_NAME :Pískovcový mrakodrap - dolní obrácený roh + +[FUTSKY53] +STR_NAME :Pískovcový mrakodrap - střední roh + +[FUTSKY54] +STR_NAME :Mrakodrap ze sopečného skla - střecha + +[GLDCHEST] +STR_NAME :Truhla s pokladem + +[GOLDFLEC] +STR_NAME :Zlatá ovčí vlna + +[HAYBAILS] +STR_NAME :Kopa sena + +[HEVBTH05] +STR_NAME :Nebeská koupel - Oblouk + +[HEVBTH06] +STR_NAME :Nebeská koupel - Oblouk + +[HEVBTH07] +STR_NAME :Nebeská koupel - Oblouk + +[HEVBTH08] +STR_NAME :Nebeská koupel - Schodiště + +[HEVBTH09] +STR_NAME :Nebeská koupel - Schodiště + +[HEVBTH10] +STR_NAME :Nebeská koupel - Architektura + +[HEVBTH11] +STR_NAME :Nebeská koupel - Architektura + +[HEVBTH12] +STR_NAME :Nebeská koupel - Architektura + +[HEVBTH13] +STR_NAME :Nebeská koupel - Architektura + +[HEVBTH14] +STR_NAME :Nebeská koupel - Okno + +[HEVBTH15] +STR_NAME :Nebeská koupel - Podlaha + +[HEVROF01] +STR_NAME :Nebeská koupel - střecha + +[HEVROF02] +STR_NAME :Nebeská koupel - střecha + +[HEVROF03] +STR_NAME :Nebeská koupel - střecha + +[HEVROF04] +STR_NAME :Nebeská koupel - střecha + +[HRBWAL01] +STR_NAME :Přístav - stěna + +[HRBWAL02] +STR_NAME :Přístav - stěna s rybářským načiním + +[HRBWAL03] +STR_NAME :Přístav - stěna s vřešem + +[HRBWAL04] +STR_NAME :Přístav - stěna s vřešem + +[HRBWAL05] +STR_NAME :Přístav - stěna s vřešem + +[HRBWAL06] +STR_NAME :Přístav - stěna s vřešem + +[HURCLULS] +STR_NAME :Herkules + +[INDWAL01] +STR_NAME :Industriální stěny - set + +[INDWAL02] +STR_NAME :Industriální stěny - set + +[INDWAL03] +STR_NAME :Industriální stěny - set + +[INDWAL04] +STR_NAME :Industriální stěny - set + +[INDWAL05] +STR_NAME :Industriální střecha + +[INDWAL06] +STR_NAME :Industriální střecha + +[INDWAL07] +STR_NAME :Industriální dveřní rám + +[INDWAL08] +STR_NAME :Industriální dveřní rám + +[INDWAL09] +STR_NAME :Industriální dveřní rám + +[INDWAL10] +STR_NAME :Industriální dveřní rám + +[INDWAL11] +STR_NAME :Industriální dveřní rám + +[INDWAL12] +STR_NAME :Industriální dveřní rám + +[INDWAL13] +STR_NAME :Industriální dveřní rám + +[INDWAL14] +STR_NAME :Industriální roh + +[INDWAL15] +STR_NAME :Industriální roh + +[INDWAL16] +STR_NAME :Industriální okno + +[INDWAL17] +STR_NAME :Industriální okno + +[INDWAL18] +STR_NAME :Industriální okno + +[INDWAL19] +STR_NAME :Industriální okno + +[INDWAL20] +STR_NAME :Industriální střecha + +[INDWAL21] +STR_NAME :Industriální střecha + +[INDWAL22] +STR_NAME :Industriální střecha + +[INDWAL23] +STR_NAME :Industriální střecha + +[INDWAL24] +STR_NAME :Industriální střecha + +[INDWAL25] +STR_NAME :Industriální střecha + +[INDWAL26] +STR_NAME :Industriální střecha + +[INDWAL27] +STR_NAME :Industriální střecha + +[INDWAL28] +STR_NAME :Industriální střecha + +[INDWAL29] +STR_NAME :Industriální střecha + +[INDWAL30] +STR_NAME :Industriální okno + +[INDWAL31] +STR_NAME :Industriální okno + +[INDWAL32] +STR_NAME :Industriální okno + +[JAILXX01] +STR_NAME :Věznice - stěna + +[JAILXX02] +STR_NAME :Věznice - stěna + +[JAILXX03] +STR_NAME :Věznice - stěna + +[JAILXX04] +STR_NAME :Věznice - stěna + +[JAILXX05] +STR_NAME :Věznice - stěna + +[JAILXX06] +STR_NAME :Věznice - stěna + +[JAILXX07] +STR_NAME :Věznice - střecha + +[JAILXX08] +STR_NAME :Věznice - obrácená část + +[JAILXX09] +STR_NAME :Věznice - obrácená část + +[JAILXX10] +STR_NAME :Věznice - obrácená část + +[JAILXX11] +STR_NAME :Věznice - obrácená část + +[JAILXX12] +STR_NAME :Věznice - obrácená část + +[JAILXX13] +STR_NAME :Věznice - obrácená část + +[JAILXX14] +STR_NAME :Věznice - schodiště na rozhlednu + +[JAILXX15] +STR_NAME :Věznice - schodiště na rozhlednu + +[JAILXX16] +STR_NAME :Věznice - Rozhledna + +[JAILXX20] +STR_NAME :Věznice - roh + +[JAILXX21] +STR_NAME :Věznice - roh + +[JAZZMBR1] +STR_NAME :Člen jazzové kapely + +[JAZZMBR2] +STR_NAME :Člen jazzové kapely + +[JAZZMBR3] +STR_NAME :Člen jazzové kapely + +[JAZZMBR4] +STR_NAME :Člen jazzové kapely + +[MAMTHW01] +STR_NAME :Velký mamutí plot + +[MAMTHW02] +STR_NAME :Velký mamutí plot + +[MAMTHW03] +STR_NAME :Velký nahnutý mamutí plot + +[MAMTHW04] +STR_NAME :Velký nahnutý mamutí plot + +[MAMTHW05] +STR_NAME :Malý nahnutý mamutí plot + +[MAMTHW06] +STR_NAME :Malý nahnutý mamutí plot + +[MCASTL02] +STR_NAME :Hradní stěna + +[MCASTL03] +STR_NAME :Hradní stěna + +[MCASTL04] +STR_NAME :Hradní stěna + +[MCASTL05] +STR_NAME :Hradní opevnění Corner + +[MCASTL06] +STR_NAME :Hradní opevnění + +[MCASTL07] +STR_NAME :Hradní opevnění - roh + +[MCASTL08] +STR_NAME :Hradní opevnění - obrácený roh + +[MCASTL09] +STR_NAME :Hradní rohová část + +[MCASTL10] +STR_NAME :Hradní opevnění - roh + +[MCASTL19] +STR_NAME :Hradní rohová část + +[MDBUCKET] +STR_NAME :Kbelík + +[MEDSTOOL] +STR_NAME :Stolička + +[MEDTOOLS] +STR_NAME :Farmářské náčiní + +[MEDTRGET] +STR_NAME :Terč + +[METEORCR] +STR_NAME :Kráter + +[METEORST] +STR_NAME :Kráter - stěna + +[METRCRS1] +STR_NAME :Kráter - stěna s krystaly + +[METRCRS2] +STR_NAME :Kráter - stěna s krystaly + +[MINOTAUR] +STR_NAME :Socha minotaura + +[OLDNYK01] +STR_NAME :New York stěna + +[OLDNYK02] +STR_NAME :New York stěna + +[OLDNYK03] +STR_NAME :New York stěna + +[OLDNYK04] +STR_NAME :New York stěna + +[OLDNYK05] +STR_NAME :New York střecha + +[OLDNYK06] +STR_NAME :New York výpň rohu + +[OLDNYK07] +STR_NAME :New York obrácený roh + +[OLDNYK08] +STR_NAME :New York obrácený roh + +[OLDNYK09] +STR_NAME :New York obrácený roh + +[OLDNYK10] +STR_NAME :New York obrácený roh + +[OLDNYK11] +STR_NAME :New York stěna s linkou + +[OLDNYK12] +STR_NAME :New York stěna + +[OLDNYK13] +STR_NAME :New York stěna s linkou + +[OLDNYK14] +STR_NAME :New York stěna + +[OLDNYK15] +STR_NAME :New York stěna + +[OLDNYK16] +STR_NAME :New York stěna + +[OLDNYK17] +STR_NAME :New York stěna + +[OLDNYK18] +STR_NAME :New York stěna + +[OLDNYK19] +STR_NAME :New York stěna + +[OLDNYK31] +STR_NAME :New York stěna + +[OLDNYK33] +STR_NAME :New York stěna + +[OLDNYK34] +STR_NAME :New York stěna + +[OLDNYK35] +STR_NAME :New York střecha + +[PRIMWAL1] +STR_NAME :Dřevěný plot s révou + +[PRIMWAL2] +STR_NAME :Dřevěný plot s révou + +[PRIMWAL3] +STR_NAME :Dřevěný plot s révou + +[PSNTWL02] +STR_NAME :Starodávná vesnice - dolní stěna + +[PSNTWL03] +STR_NAME :Starodávná vesnice - dolní stěna + +[PSNTWL04] +STR_NAME :Starodávná vesnice - dolní stěna + +[PSNTWL05] +STR_NAME :Starodávná vesnice - dolní stěna + +[PSNTWL06] +STR_NAME :Starodávná vesnice - dolní stěna + +[PSNTWL07] +STR_NAME :Starodávná vesnice - dolní stěna + +[PSNTWL08] +STR_NAME :Starodávná vesnice - dolní roh + +[PSNTWL09] +STR_NAME :Starodávná vesnice - horní stěna + +[PSNTWL10] +STR_NAME :Starodávná vesnice - horní stěna + +[PSNTWL11] +STR_NAME :Starodávná vesnice - horní stěna + +[PSNTWL12] +STR_NAME :Starodávná vesnice - horní stěna + +[PSNTWL13] +STR_NAME :Starodávná vesnice - horní stěna + +[PSNTWL14] +STR_NAME :Starodávná vesnice - střecha + +[PSNTWL15] +STR_NAME :Starodávná vesnice - obrácená střecha + +[PSNTWL16] +STR_NAME :Starodávná vesnice - střecha + +[PSNTWL17] +STR_NAME :Starodávná vesnice - střecha + +[PSNTWL20] +STR_NAME :Starodávná vesnice - strešní okno + +[PSNTWL21] +STR_NAME :Starodávná vesnice - strešní okno + +[PSNTWL23] +STR_NAME :Starodávná vesnice - horní roh + +[PSNTWL24] +STR_NAME :Starodávná vesnice - okno + +[PSNTWL25] +STR_NAME :Starodávná vesnice - okno + +[PSNTWL29] +STR_NAME :Starodávná vesnice - strešní okno + +[PSNTWL30] +STR_NAME :Starodávná vesnice - strešní okno + +[PSNTWL31] +STR_NAME :Starodávná vesnice - rohová střecha + +[RDMETO03] +STR_NAME :Kráter - stěna + +[RDMETO04] +STR_NAME :Kráter - obrácený roh + +[RUNWAY01] +STR_NAME :Ranvej + +[RUNWAY02] +STR_NAME :Ranvej + +[RUNWAY03] +STR_NAME :Ranvej +[RUNWAY04] +STR_NAME :Ranvej + +[RUNWAY05] +STR_NAME :Ranvej + +[RUNWAY06] +STR_NAME :Ranvej + +[SCHNCRSH] +STR_NAME :Rozbitý hydroplán + +[SCHNDRUM] +STR_NAME :Barel ropy + +[SCHNPL05] +STR_NAME :Hydroplán + +[SCHNPL06] +STR_NAME :Hydroplán + +[SCHNTNNY] +STR_NAME :Závodní tannoy + +[SHWDFRST] +STR_NAME :Stromy + +[SMOKSK02] +STR_NAME :Smoke Stack Mid + +[SMOKSK03] +STR_NAME :Smoke Stack Base + +[SPCSHP06] +STR_NAME :Vesmírná loď - střední část + +[SPCSHP09] +STR_NAME :Vesmírná loď - dok + +[SPCSHP10] +STR_NAME :Vesmírná loď - motory + +[SPCSHP11] +STR_NAME :Vesmírná loď - obývací část + +[STNESTA1] +STR_NAME :Člověk přeměněný na kámen + +[STNESTA2] +STR_NAME :Člověk přeměněný na kámen + +[STNESTA3] +STR_NAME :Člověk přeměněný na kámen + +[STNESTA4] +STR_NAME :Člověk přeměněný na kámen + +[STOOLSET] +STR_NAME :Stoličky + +[SWAMPLT1] +STR_NAME :Bažina - Rostlina + +[SWAMPLT2] +STR_NAME :Bažina - Tráva + +[SWAMPLT3] +STR_NAME :Bažina - Tráva + +[SWAMPLT4] +STR_NAME :Bažina - Rostlina + +[SWAMPLT5] +STR_NAME :Bažina - Rostlina + +[SWAMPLT6] +STR_NAME :Bažina - Tráva + +[SWAMPLT7] +STR_NAME :Bažina - Tráva + +[SWAMPLT8] +STR_NAME :Bažina - Tráva + +[SWAMPLT9] +STR_NAME :Bažina - Tráva + +[SWRDSTNE] +STR_NAME :Meč v kameni + +[TARPIT04] +STR_NAME :Bublající bažina + +[TARPIT05] +STR_NAME :Bublající bažina + +[TARPIT06] +STR_NAME :Bublající bažina + +[TARPIT07] +STR_NAME :Bublající bažina + +[TARPIT08] +STR_NAME :Bublající bažina + +[TARPIT09] +STR_NAME :Bublající bažina + +[TARPIT10] +STR_NAME :Bublající bažina + +[TARPIT11] +STR_NAME :Bublající bažina + +[TARPIT12] +STR_NAME :Bublající bažina + +[TARPIT13] +STR_NAME :Bublající bažina + +[TARPIT14] +STR_NAME :Bublající bažina + +[VALKRI01] +STR_NAME :Valkýra + +[VALKRI02] +STR_NAME :Valkýra + +[WDNCART2] +STR_NAME :Dřevěný povoz + +[WEPNRACK] +STR_NAME :Set zbraní + +[WISKYBL1] +STR_NAME :Whisky barel + +[WISKYBL2] +STR_NAME :Whisky barely + +[YEWTREEX] +STR_NAME :Tis + +[ZEUSSTAT] +STR_NAME :Socha Dia + +[ALENPLT1] +STR_NAME :Mimozemská Rostlina + +[ALENPLT2] +STR_NAME :Mimozemská Rostlina + +[ALLSEEYE] +STR_NAME :Pohybující se vševidící oko + +[ALNSTR01] +STR_NAME :Mimozemská stavba + +[ALNSTR02] +STR_NAME :Mimozemská stavba + +[ALNSTR03] +STR_NAME :Mimozemská stavba + +[ALNSTR04] +STR_NAME :Mimozemské světlo + +[ALNSTR05] +STR_NAME :Mimozemská věž - dolní díl + +[ALNSTR06] +STR_NAME :Mimozemská věž - střední díl + +[ALNSTR07] +STR_NAME :Mimozemská věž - vrchní díl + +[ARGONAU1] +STR_NAME :Pohyblivá chobotnice + +[ARGONAU2] +STR_NAME :Pohyblivá chobotnice + +[ARGONAU3] +STR_NAME :Pohyblivá chobotnice + +[ASTRONGT] +STR_NAME :Pohyblivý astronaut + +[BKRGANG1] +STR_NAME :Cyklista + +[BOLPOT01] +STR_NAME :Hrnec s horkou vodou + +[CAGDSTAT] +STR_NAME :Pohybující se orel na kleci + +[CAVEMENX] +STR_NAME :Pohybující se jeskynní muž zapalující oheň + +[CHANMAID] +STR_NAME :Pohybující se Andromeda (spoutaná žena) + +[CLNSMEN1] +STR_NAME :Pohybující se člen klanu + +[COMPEYEX] +STR_NAME :Super monitor + +[COOKSPIT] +STR_NAME :Pečeně na rožni + +[DINSIGN1] +STR_NAME :Neonová cedule jídelny + +[DINSIGN2] +STR_NAME :Neonová cedule jídelny + +[DINSIGN3] +STR_NAME :Neonová cedule jídelny + +[DINSIGN4] +STR_NAME :Neonová cedule jídelny + +[DKFIGHT1] +STR_NAME :Pohybující se rytíř + +[DKFIGHT2] +STR_NAME :Pohybující se rytíř + +[DRGNATTK] +STR_NAME :Útočící drak + +[ELECFEN1] +STR_NAME :Elektrický ohradník - roh + +[ELECFEN2] +STR_NAME :Elektrický ohradník + +[ELECFEN3] +STR_NAME :Elektrický ohradník se světlem + +[ELECFEN4] +STR_NAME :Elektrický ohradník - rozbitý + +[EVALIEN1] +STR_NAME :Pohybující se ďábelský mimozemšťan + +[EVALIEN2] +STR_NAME :Pohybující se ďábelský mimozemšťan + +[EVALIEN3] +STR_NAME :Pohybující se ďábelský mimozemšťan + +[FIRCANON] +STR_NAME :Pohybující se vystřelující kanón + +[FLTSIGN1] +STR_NAME :Antigravitační LCD Billboard + +[FLTSIGN2] +STR_NAME :Antigravitační LCD Billboard + +[FRBEACON] +STR_NAME :Pochodeň / svíce + +[FUROBOT1] +STR_NAME :Robot + +[FUROBOT2] +STR_NAME :Robot + +[FUTSKY01] +STR_NAME :Pískovcový mrakodrap - brána + +[FUTSKY02] +STR_NAME :Pískovcový mrakodrap - výplň + +[FUTSKY03] +STR_NAME :Pískovcový mrakodrap - dolní roh + +[FUTSKY04] +STR_NAME :Pískovcový mrakodrap - zaoblený vršek + +[FUTSKY05] +STR_NAME :Pískovcový mrakodrap - zaoblený vršek + +[FUTSKY06] +STR_NAME :Pískovcový mrakodrap - zaoblený střed + +[FUTSKY07] +STR_NAME :Pískovcový mrakodrap - střední stěna + +[FUTSKY08] +STR_NAME :Pískovcový mrakodrap - střední stěna + +[FUTSKY09] +STR_NAME :Pískovcový mrakodrap - střední stěna + +[FUTSKY10] +STR_NAME :Pískovcový mrakodrap - zaoblený spodek + +[FUTSKY11] +STR_NAME :Pískovcový mrakodrap - střední roh + +[FUTSKY12] +STR_NAME :Pískovcový mrakodrap - střední stěna + +[FUTSKY13] +STR_NAME :Pískovcový mrakodrap - střešní díl + +[FUTSKY14] +STR_NAME :Pískovcový mrakodrap - střešní díl + +[FUTSKY15] +STR_NAME :Pískovcový mrakodrap - dok + +[FUTSKY33] +STR_NAME :Pískovcový mrakodrap - brána + +[FUTSKY36] +STR_NAME :Mrakodrap ze sopečného skla - dveře + +[FUTSKY37] +STR_NAME :Mrakodrap ze sopečného skla - zaoblený roh + +[FUTSKY38] +STR_NAME :Mrakodrap ze sopečného skla - nakloněná stěna + +[FUTSKY39] +STR_NAME :Mrakodrap ze sopečného skla - nakloněný roh + +[FUTSKY40] +STR_NAME :Mrakodrap ze sopečného skla - nakloněná stěna + +[FUTSKY41] +STR_NAME :Mrakodrap ze sopečného skla - nakloněná stěna + +[FUTSKY44] +STR_NAME :Mrakodrap ze sopečného skla - nakloněná stěna + +[FUTSKY46] +STR_NAME :Mrakodrap ze sopečného skla - nakloněný roh + +[FUTSKY47] +STR_NAME :Mrakodrap ze sopečného skla - stěna + +[FUTSKY48] +STR_NAME :Mrakodrap ze sopečného skla - okno + +[FWRPRDC1] +STR_NAME :Senzační tanečnice + +[GANGSTER] +STR_NAME :Pohybující se Gangster + +[GDALIEN1] +STR_NAME :Pohybující se hodný mimozemšťan + +[GDALIEN2] +STR_NAME :Pohybující se hodný mimozemšťan + +[GDALIEN3] +STR_NAME :Pohybující se hodný mimozemšťan + +[GEYSERXX] +STR_NAME :Gejzíry + +[GGNTOCTO] +STR_NAME :Béčková obrovská chobotnice + +[GGNTSPID] +STR_NAME :Béčkový obrovský pavouk + +[GSCORPO2] +STR_NAME :Pohybující se útočící škorpion + +[GSCORPON] +STR_NAME :Pohybující se útočící škorpion + +[GUYQWIFX] +STR_NAME :Zpěvák s patkou + +[HEVBTH01] +STR_NAME :Nebeská koupel - bazén + +[HEVBTH02] +STR_NAME :Nebeská koupel - roh bazénu + +[HEVBTH03] +STR_NAME :Nebeská koupel - fontána + +[HEVBTH04] +STR_NAME :Nebeská koupel - fontána + +[HEVBTH16] +STR_NAME :Nebeská koupel - schody do bazénu + +[HEVBTH17] +STR_NAME :Nebeská koupel - hrana bazénu + +[HORSECRT] +STR_NAME :Kůň + +[HOVRCAR1] +STR_NAME :Zaparkované vznášedlo + +[HOVRCAR2] +STR_NAME :Zaparkované vznášedlo + +[HOVRCAR3] +STR_NAME :Letící vznášedlo + +[HOVRCAR4] +STR_NAME :Letící vznášedlo + +[HVRBIKE1] +STR_NAME :Zaparkované vznášedlo + +[HVRBIKE2] +STR_NAME :Zaparkované vznášedlo + +[HVRBIKE3] +STR_NAME :Letící vznášedlo + +[HVRBIKE4] +STR_NAME :Letící vznášedlo + +[KILLRVIN] +STR_NAME :Viná réva + +[KNFIGHT1] +STR_NAME :Pohybující se temný rytíř + +[KNFIGHT2] +STR_NAME :Pohybující se temný rytíř + +[LARGECPU] +STR_NAME :Superpočítač + +[LASERX01] +STR_NAME :Laserový plot + +[LASERX02] +STR_NAME :Laserový plot - roh + +[MDUSASTA] +STR_NAME :Pohybující se Medusa + +[PDFLAG02] +STR_NAME :Stará vlajka + +[PDFLAG03] +STR_NAME :Stará vlajka + +[PDFLAG04] +STR_NAME :Stará vlajka + +[PDFLAG05] +STR_NAME :Stará vlajka + +[PDFLAG06] +STR_NAME :Stará vlajka + +[PDFLAG08] +STR_NAME :Stará vlajka + +[PDFLAG13] +STR_NAME :Stará vlajka + +[PDFLAG14] +STR_NAME :Stará vlajka + +[PDFLAG15] +STR_NAME :Stará vlajka + +[PDFLAG16] +STR_NAME :Stará vlajka + +[POLWTBTN] +STR_NAME :Pohybující se policista + +[PRIMHEAD] +STR_NAME :Dřevěný plot s mužem, který jí rostlinu + +[PRIMHEAR] +STR_NAME :Dřevěný plot s mužem, který jí rostlinu + +[PRIMROOR] +STR_NAME :Dřevěný plot s vinou révou + +[PRIMROOT] +STR_NAME :Dřevěný plot s vinou révou + +[PRIMSCRN] +STR_NAME :Dřevěný plot s mužem, který jí rostlinu + +[PRIMST01] +STR_NAME :Dřevěný plot s mužem, který jí rostlinu + +[PRIMST02] +STR_NAME :Dřevěný plot s mužem, který jí rostlinu + +[PRIMST03] +STR_NAME :Dřevěný plot s mužem, který jí rostlinu + +[PRIMTALL] +STR_NAME :Dřevěný plot s mužem, který jí rostlinu + +[PSNTWL01] +STR_NAME :Starodávná vesnice - střecha s komínem + +[RCKNROLR] +STR_NAME :Frajer + +[ROBNHOOD] +STR_NAME :Pohybující se Robin Hood + +[RSWATRES] +STR_NAME :Bruslící číšnice + +[SCHNBOST] +STR_NAME :Bóje + +[SCHNBOUY] +STR_NAME :Bóje + +[SCHNPL01] +STR_NAME :Hydroplán + +[SCHNPL02] +STR_NAME :Hydroplán + +[SCHNPL03] +STR_NAME :Hydroplán + +[SCHNPL04] +STR_NAME :Hydroplán + +[SDRAGFLY] +STR_NAME :Pohybující se vášky + +[SKELETO1] +STR_NAME :Pohybující se armáda kostlivců + +[SKELETO2] +STR_NAME :Pohybující se armáda kostlivců + +[SKELETO3] +STR_NAME :Pohybující se armáda kostlivců + +[SMALLCPU] +STR_NAME :Superpočítač + +[SMOKSK01] +STR_NAME :Velký kouřící komín + +[SOUPCRN2] +STR_NAME :Prebiotická polévka + +[SOUPCRNR] +STR_NAME :Prebiotická polévka + +[SOUPED01] +STR_NAME :Prebiotická polévka + +[SOUPED02] +STR_NAME :Prebiotická polévka + +[SOUPTL01] +STR_NAME :Prebiotická polévka + +[SOUPTL02] +STR_NAME :Prebiotická polévka + +[SPACRANG] +STR_NAME :Pohybující se Vesmírný kovboj + +[SPCSHP01] +STR_NAME :Vesmírná loď - nákladní sekce + +[SPCSHP02] +STR_NAME :Vesmírná loď - komunikační sekce + +[SPCSHP03] +STR_NAME :Vesmírná loď - solární sekce + +[SPCSHP04] +STR_NAME :Vesmírná loď - solární panely + +[SPCSHP05] +STR_NAME :Vesmírná loď - gravitační sekce + +[SPCSHP07] +STR_NAME :Vesmírná loď - kontrolní panel + +[SPCSHP08] +STR_NAME :Vesmírná loď - palivová sekce + +[SPCSHP12] +STR_NAME :Vesmírná loď - vědecká sekce + +[SPEAKR01] +STR_NAME :Malý reproduktor + +[SPEAKR02] +STR_NAME :Velký reproduktor + +[SPIKTAIL] +STR_NAME :Pohybující se stegosaurus + +[SPTERDAC] +STR_NAME :Pohybující se letící pterodaktyl + +[STGBAND1] +STR_NAME :Člen kapely + +[STGBAND2] +STR_NAME :Člen kapely + +[STGBAND3] +STR_NAME :Člen kapely + +[STGBAND4] +STR_NAME :Člen kapely + +[STMDRAN1] +STR_NAME :Kouřící kanály + +[STRICTOP] +STR_NAME :Pohybující se triceratops + +[TARPIT01] +STR_NAME :Bublající bažina + +[TARPIT02] +STR_NAME :Bublající bažina + +[TARPIT03] +STR_NAME :Bublající bažina + +[TITANSTA] +STR_NAME :Socha Atlase + +[TYRANREX] +STR_NAME :Pohybující se T-Rex + +[VOLCVENT] +STR_NAME :Aktivní sopka + +[WAVEKING] +STR_NAME :Pohybující se mávající král + +[WHCCOLDS] +STR_NAME :Čarodějnice s kotlíkem + +[ARTDEC25] +STR_NAME :Art Deco roh s okny + +[ARTDEC26] +STR_NAME :Art Deco roh se zábradlím + +[ARTDEC27] +STR_NAME :Art Deco vrchní rohová část + +[FUTSKY20] +STR_NAME :Pískovcový mrakodrap - dolní obrácenž roh + +[FUTSKY22] +STR_NAME :Pískovcový mrakodrap - dolní obrácenž roh + +[FUTSKY24] +STR_NAME :Pískovcový mrakodrap - dolní obrácenž roh + +[FUTSKY25] +STR_NAME :Pískovcový mrakodrap - dolní obrácenž roh + +[FUTSKY26] +STR_NAME :Pískovcový mrakodrap - dolní obrácenž roh + +[FUTSKY28] +STR_NAME :Pískovcová brána - T-křižovatka + +[FUTSKY30] +STR_NAME :Pískovcová brána - roh + +[FUTSKY31] +STR_NAME :Pískovcová brána - středová část + +[FUTSKY32] +STR_NAME :Pískovcová brána - koncová sekce + +[JAILXX17] +STR_NAME :Věznice - dveře + +[MAJOROAK] +STR_NAME :Velký dub + +[MCASTL01] +STR_NAME :Hradní obrácený roh + +[MCASTL11] +STR_NAME :Hradní padací most + +[MCASTL12] +STR_NAME :Hradní brána + +[MELMTREE] +STR_NAME :Americký Jilm + +[OLDNYK24] +STR_NAME :New York - obrácený roh střechy + +[OLDNYK25] +STR_NAME :New York střecha + +[OLDNYK26] +STR_NAME :New York vstup + +[OLDNYK32] +STR_NAME :New York střecha + +[1950SCAR] +STR_NAME :Auto z 50. let + +[4X4DINER] +STR_NAME :Stará jídelna + +[4X4GMANT] +STR_NAME :Mangrove + +[4X4STNHN] +STR_NAME :Chrám doby kamenné + +[4X4TRPIT] +STR_NAME :Bublající bažina + +[4X4VOLCA] +STR_NAME :Sopka s malými stromy + +[ALENCRSH] +STR_NAME :UFO havárie + +[ALNSTR08] +STR_NAME :Mimozemská velká struktura + +[ALNSTR09] +STR_NAME :Mimozemská velká struktura + +[ALNSTR10] +STR_NAME :Mimozemská velká struktura + +[ALNSTR11] +STR_NAME :Mimozemské světlo + +[ASHNYMPH] +STR_NAME :Jasan s bludičkami + +[BANDBUSX] +STR_NAME :Autobus rokové kapely + +[BIGDRUMS] +STR_NAME :Obrovské bubny + +[CAVENTRA] +STR_NAME :Vstup do jeskyně + +[CORNS2X2] +STR_NAME :Římský palác - roh + +[CORVS2X2] +STR_NAME :Římský palác - roh + +[CRATR2X2] +STR_NAME :Malý kráter + +[CRATR4X4] +STR_NAME :Velký kráter + +[CRSSS2X2] +STR_NAME :Římský palác - střední sekce + +[CRSVS2X2] +STR_NAME :Římský palác - střední sekce + +[CYCLOPSS] +STR_NAME :Socha kyklopa + +[FEASTABL] +STR_NAME :Stůl (hody) + +[FOOTPRNT] +STR_NAME :Stopa velkého dinosaura + +[FORBIDFT] +STR_NAME :Zakázané ovoce + +[GBEETLEX] +STR_NAME :Auto z 50. let + +[GHOTROD1] +STR_NAME :Hot Rod auto + +[GHOTROD2] +STR_NAME :Hot Rod auto + +[GSCHLBUS] +STR_NAME :Americký školní autobus + +[HADESXXX] +STR_NAME :Socha Hadese + +[HISTFIX1] +STR_NAME :Mimozemská historická struktura + +[HISTFIX2] +STR_NAME :Mimozemská historická struktura + +[HODSHUT1] +STR_NAME :Chata Robina Hooda + +[HODSHUT2] +STR_NAME :Chata Robina Hooda + +[HRBWAL07] +STR_NAME :Přístav - roh + +[HRBWAL08] +STR_NAME :Přístav - roh + +[HRBWAL09] +STR_NAME :Přístav - stěna s dokem + +[HRBWAL11] +STR_NAME :Přístav - dok + +[JAILXX18] +STR_NAME :Věznice - vodní věž + +[JETPLAN1] +STR_NAME :Stíhačka + +[JETPLAN2] +STR_NAME :Stíhačka + +[JETPLAN3] +STR_NAME :Stíhačka + +[MCASTL13] +STR_NAME :Hradní věž - roh + +[MCASTL14] +STR_NAME :Hradní věž - roh + +[MCASTL15] +STR_NAME :Hradní věž - střední část + +[MCASTL16] +STR_NAME :Hradní věž - rovná část + +[MCASTL17] +STR_NAME :Hradní věž - T-křižovatka + +[MCASTL18] +STR_NAME :Hradní věž - T-křižovatka + +[METOAN01] +STR_NAME :Roh kráteru + +[METOAN02] +STR_NAME :Roh kráteru - obrácený + +[OLDNYK20] +STR_NAME :New York střecha + +[OLDNYK21] +STR_NAME :New York stěna + +[OLDNYK22] +STR_NAME :New York stěna + +[OLDNYK23] +STR_NAME :New York stěna + +[OLDNYK27] +STR_NAME :New York stěna + +[OLDNYK28] +STR_NAME :New York stěna + +[OLDNYK29] +STR_NAME :New York stěna + +[OLDNYK30] +STR_NAME :New York stěna + +[PEASTHUT] +STR_NAME :Rolnická chatrč + +[PERAMOB1] +STR_NAME :Staré auto + +[PERAMOB2] +STR_NAME :Staré auto + +[PERDTK01] +STR_NAME :Staré nákladní auto + +[PERDTK02] +STR_NAME :Staré nákladní auto + +[PLOUGHXX] +STR_NAME :Pluh + +[PRDYACHT] +STR_NAME :Stará plachetnice + +[PSNTWL26] +STR_NAME :Starodávná vesnice - střecha + +[PSNTWL27] +STR_NAME :Starodávná vesnice - rohová střecha + +[PSNTWL28] +STR_NAME :Starodávná vesnice - obrácená střecha + +[RDMET2X2] +STR_NAME :Malý kráter + +[RDMET4X4] +STR_NAME :Velký kráter + +[RDMETO01] +STR_NAME :Kráter - roh + +[RDMETO02] +STR_NAME :Kráter - roh + +[ROBNCAMP] +STR_NAME :Kemp Robina Hooda + +[ROMNC2X2] +STR_NAME :Římský palác - roh + +[ROMNE2X1] +STR_NAME :Římský palác - koncová část + +[ROMNM2X2] +STR_NAME :Římský palác - střední část + +[ROMNS2X2] +STR_NAME :Římský palác - rovná část + +[ROMVC2X2] +STR_NAME :Římský palác - roh + +[ROMVE2X1] +STR_NAME :Římský palác - koncová část + +[ROMVM2X2] +STR_NAME :Římský palác - střední část + +[ROMVS2X2] +STR_NAME :Římský palác - rovná část + +[SCHNPIT2] +STR_NAME :Hydroplán + +[SCHNPITS] +STR_NAME :Hydroplán + +[SCHNTENT] +STR_NAME :Stan + +[SHIPB4X4] +STR_NAME :Luxusní parník - loďka + +[SHIPM4X4] +STR_NAME :Luxusní parník - střední část + +[SHIPS4X4] +STR_NAME :Luxusní parník - záď + +[STRGS2X2] +STR_NAME :Římský palác - rovná část + +[STRVS2X2] +STR_NAME :Římský palác - rovná část + +[TAVERNXX] +STR_NAME :Starodávný hostinec + +[TRAVLR01] +STR_NAME :Cestovatelský vůz + +[TRAVLR02] +STR_NAME :Microbus + +[JAILXX19] +STR_NAME :Věznice - plot + +[MSPKWA01] +STR_NAME :Ostnatý plot + +[1920PATH] +STR_NAME :Chodník + +[FUTRPAT2] +STR_NAME :Sky Walk cesta + +[FUTRPATH] +STR_NAME :Elektronická cesta + +[JURRPATH] +STR_NAME :Kamenitá cesta + +[MEDIPATH] +STR_NAME :Dřevená cesta + +[MYTHPATH] +STR_NAME :Mosaická cesta + +[RANBPATH] +STR_NAME :Duhová cesta + +[FIRHYDRT] +STR_NAME :Požární hydrant + +[MEDBENCH] +STR_NAME :Lavičky + +[SCG1920S] +STR_NAME : Bouřlivá 20. léta + +[SCG1920W] +STR_NAME : Bouřlivá 20. léta - stěny + +[SCG1960S] +STR_NAME : Rock 'n' Roll + +[SCGFUTUR] +STR_NAME : Budoucnost + +[SCGJURRA] +STR_NAME : Pravěk + +[SCGMEDIV] +STR_NAME : Starodávné časy + +[SCGMYTHO] +STR_NAME : Mytologie + +[1920SENT] +STR_NAME :Bouřlivá 20. léta - vstup do parku + +[FUTURENT] +STR_NAME :Futuristický vstup do parku + +[GLDYRENT] +STR_NAME :Rock 'n' Roll - vstup do parku + +[JURASENT] +STR_NAME :Pravěký vstup + +[MEDIENTR] +STR_NAME :Starodávný vstup + +[MYTHENTR] +STR_NAME :Mytologický vsutp + +############################################################################### +## RCT2 Scenarios +############################################################################### + +STR_SCNR :Alpine Adventures +STR_PARK :Alpine Adventures +STR_DTLS :Přestavte malý horský ski-resort na sněžný zábavní park + + +STR_SCNR :Amity Airfield +STR_PARK :Amity Airfield +STR_DTLS :Postavte letecky-orientovaný zábavní park na tomto opuštěném letišti + + +STR_SCNR :Botany Breakers +STR_PARK :Botany Breakers +STR_DTLS :Vaším úkolem je postavit vysoce výnosný zábavní park na tomto rajském ostrově + + +STR_SCNR :Postavte si svůj vlastní Six Flags Belgium +STR_PARK :Six Flags Belgium +STR_DTLS :Postavte si svou vlastní verzi tohoto evropského Six Flags zábavního parku + + +STR_SCNR :Postavte si svůj vlastní Six Flags Great Adventure +STR_PARK :Six Flags Great Adventure +STR_DTLS :Využijte svých návrhářských dovedností a vytvořte tento Six Flags zábavní park + + +STR_SCNR :Postavte si svůj vlastní Six Flags Holland +STR_PARK :Six Flags Holland +STR_DTLS :Postavte tento evropský Six Flags zábavní park tak, jak jen budete chtít + + +STR_SCNR :Postavte si svůj vlastní Six Flags Magic Mountain +STR_PARK :Six Flags Magic Mountain +STR_DTLS :Postavte si svou vlastní verzi tohoto masivního Six Flags zábavního parku + + +STR_SCNR :Postavte si svůj vlastní Six Flags over Texas +STR_PARK :Six Flags over Texas +STR_DTLS :Postavte atrakce tohoto Six Flags zábavního parku na zelené louce + + +STR_SCNR :Postavte si svůj vlastní Six Flags Park +STR_PARK :Six Flags +STR_DTLS :Postavte si svůj vlastní návrh Six Flags zábavního parku - použijte buď atrakce z jiných Six Flags parků, nebo si navrhněte vlastní + + +STR_SCNR :Bumbly Bazaar +STR_PARK :Bumbly Bazaar +STR_DTLS :Začínáte s malým bazarem, přičemž vaším úkolem je zvýšit zisky z obchodů a stánků stavbou nových atrakcí k přilákání nových zákazníků + + +STR_SCNR :Crazy Castle +STR_PARK :Crazy Castle +STR_DTLS :Zdědili jste velký hrad - a vaším úkolem je přeměnit ho na malý zábavní park + + +STR_SCNR :Dusty Greens +STR_PARK :Dusty Greens +STR_DTLS :Poblíž pouštního dálničního křížení představuje Dusty Greens možnost přestavět malý golfový resort na vzkvétající zábavní park + + +STR_SCNR :Electric Fields +STR_PARK :Electric Fields +STR_DTLS :Zdědili jste malou farmu - a vaším úkolem je postavit malý zábavní park mezi poli a farmářskými budovami + + +STR_SCNR :Extreme Heights +STR_PARK :Extreme Heights +STR_DTLS :Bez finančních omezení - vaším úkolem je rozšířit tento pouštní zábavní park pro přilákání většího počtu návštěvníků, vyhledávajících pořádnou dávku adrenalinu + + +STR_SCNR :Factory Capers +STR_PARK :Factory Capers +STR_DTLS :Opuštěný tovární komplex nabízí možnost postavit mechanicky-zaměřený zábavní park + + +STR_SCNR :Fungus Woods +STR_PARK :Fungus Woods +STR_DTLS :Omezeni pouze na starší, dřevěné, dráhy, postavte vzkvétající zábavní park ve Fungus Woods + + +STR_SCNR :Ghost Town +STR_PARK :Ghost Town +STR_DTLS :Velký řetěze zábavních parků si vás najal, abyste postavili obrovský zábavní park plný horských drah v okolí opuštěného dulního městečka + + +STR_SCNR :Gravity Gardens +STR_PARK :Gravity Gardens +STR_DTLS :Postavte zábavní park s horskými drahami v nádherných Gravity Gardens - Jen horské dráhy, nic jiného! + + +STR_SCNR :Infernal Views +STR_PARK :Infernal Views +STR_DTLS :Zábavní park, postavený na úpatní neklidné sopky + + +STR_SCNR :Lucky Lake +STR_PARK :Lucky Lake +STR_DTLS :S neomezenými financemi v nesnadném terénu okolo jezera - bude obtížné zábavní park dále rozšiřovat + + +STR_SCNR :Rainbow Summit +STR_PARK :Rainbow Summit +STR_DTLS :Zábavní park vybudovaný na straně kopce má zakázány výškové stavby. Dokážete i přes to park rozšířit a dosáhnout úspěchu? + + +STR_SCNR :Six Flags Belgium +STR_PARK :Six Flags Belgium +STR_DTLS :Vyzkoušejte si provoz a vylepšování tohoto Six Flags zábavního parku + + +STR_SCNR :Six Flags Great Adventure +STR_PARK :Six Flags Great Adventure +STR_DTLS :Postavte chybějící Six Flags atrakce, nebo vytvořte své vlastní! Nezapomeňte ale na hlavní cíl - přilákat co nejvíce návštěvníků! + + +STR_SCNR :Six Flags Holland +STR_PARK :Six Flags Holland +STR_DTLS :Vyzkoušejte si provoz a vylepšování tohoto Six Flags zábavního parku + + +STR_SCNR :Six Flags Magic Mountain +STR_PARK :Six Flags Magic Mountain +STR_DTLS :Postavte chybějící Six Flags atrakce, nebo vytvořte své vlastní! Nezapomeňte ale na hlavní cíl - vyrovnat dluhy bez propadu hodnoty parku! + + +STR_SCNR :Six Flags over Texas +STR_PARK :Six Flags over Texas +STR_DTLS :Postavte chybějící Six Flags atrakce, nebo vytvořte své vlastní! Nezapomeňte ale na hlavní cíl - přilákat co nejvíce návštěvníků! + +############################################################################### +## Wacky Worlds Scenarios +############################################################################### + +STR_SCNR :Africa - African Diamond Mine +STR_PARK :Mines of Africa +STR_DTLS :Zdědili jste diamantový důl mimo provoz a nalezli hodnotný diamant. Rozhodli jste se tedy investovat peníze do stavby světoznámého zábavního parku. + + +STR_SCNR :Africa - Oasis +STR_PARK :Mirage Madness +STR_DTLS :Byla objevena pouštní oáza, která nabízí nádherné místo pro zábavní park. Přeprava do oázy zajištěna. + + +STR_SCNR :Africa - Victoria Falls +STR_PARK :Over The Edge +STR_DTLS :Postavená přehrada zajišťuje velké množství levné hydroelektrické energie pro váš zábavní park. Dosáhněte vysokého hodnoce parku, abyste snáze splatili půjčku na přehradu. + + +STR_SCNR :Antarctic - Ecological Salvage +STR_PARK :Icy Adventures +STR_DTLS :Obrátili se na vás ochranáři životního prostředí s prosbou, abyste přeměnili neekologickou rafinerii na vysoce navštěvovanou turistickou destinaci. Pozemky jsou levné, ale úrok z půjčky vysoký. Zkuste prodat staré budovy. + + +STR_SCNR :Asia - Great Wall of China Tourism Enhancement +STR_PARK :Great Wall of China +STR_DTLS :Místní správa se rozhodla podpořit cestovní ruch a vytvořit Velkou zeď stavbou přilehlého zábavního parku. Peníze nehrají roli. + + +STR_SCNR :Asia - Japanese Coastal Reclaim +STR_PARK :Okinawa Coast +STR_DTLS :Současnému zábavnímu parku došlo místo. Jedinou možností je začít stavět na moři, takže budete potřebovat velkou půjčku. V této oblasti jsou častá zemětřesení, proto nesmíte stavět vysoké budovy. + + +STR_SCNR :Asia - Maharaja Palace +STR_PARK :Park Maharaja +STR_DTLS :Mahárádža vás vybral, abyste přinesli zábavu pro místní velkou populaci. Postavte záabavní park inspirovaný Mahárádžovým palácem + + +STR_SCNR :Australasia - Ayers Rock +STR_PARK :Ayers Adventure +STR_DTLS :Pomáháte domorodcům postavit zábavní park pro upozornění na jejich kuluru. Musíte poučit co nejvíce lidí o unikátní kultuře domorodých obyvatel. + + +STR_SCNR :Australasia - Fun at the Beach +STR_PARK :Beach Barbecue Blast +STR_DTLS :Místní mořský svět bankrotoval a vy jste ho odkoupili. Vám už ale jeden malý park patří - postavte tedy ze dvou malých parků jeden obrovský! + + +STR_SCNR :Europe - European Cultural Festival +STR_PARK :European Extravaganza +STR_DTLS :Byli jste přizváni, abyste převzali kontorlu nad Evropskou Kulturní Návštěvnickou Atrakcí a musíte zajistit nárůst návštěvnosti, jinak nebudete moci zaplatit za EU dotaci do konce vládního období. + + +STR_SCNR :Europe - Renovation +STR_PARK :From The Ashes +STR_DTLS :Evropská Unie vám dala grant, abyste zajistil obnovu starého, neudržovaného zábavního parku a přinesl zpět jeho tehdejší slávu. Musíte celý park renovovat a splatit grant. + + +STR_SCNR :N. America - Extreme Hawaiian Island +STR_PARK :Wacky Waikiki +STR_DTLS :Havajané jsou znudění ze surfování a chtějí zažít něco adrenalinovějšího. Postavte zábavní park a nezapomeňte na to - pomůže vám to s dosažením dobrého hodnocení parku. + + +STR_SCNR :North America - Grand Canyon +STR_PARK :Canyon Calamities +STR_DTLS :Omezený terén vás nutí vybudovat zábavní park po stranách národní památky. Můžete ale od Indiánů nakupovat pozemky. Abyste si udrželi hodnocení místní správy, splňte cíl! + + +STR_SCNR :North America - Rollercoaster Heaven +STR_PARK :Rollercoaster Heaven +STR_DTLS :Jste úspěšný obchodní magnát, který si přeje přetvořit městský park v místo nebeských horských dráh. Peníze nehrají žádnou roli! + + +STR_SCNR :South America - Inca Lost City +STR_PARK :Lost City Founder +STR_DTLS :Abyste zvýšili počet místních turistů, musíte potavit zábavní park, který zapadá do okolí a nemá žádné výškové budovy. + + +STR_SCNR :South America - Rain Forest Plateau +STR_PARK :Rainforest Romp +STR_DTLS :Prostor je limitovaný drahoceným deštným pralesem - musíte toho namáčknout co nejvíce do dosavadních pozemků, abyste mohli konkurovat místním dřevorubeckým společnostem. + + +STR_SCNR :South America - Rio Carnival +STR_PARK :Sugarloaf Shores +STR_DTLS :Provozujete malý zábavní park poblíž Ria, ale banka chce vrátit půjčku. Musíte rychle zvýšit vaše příjmy, abyste mohli dluh splatit. + +############################################################################### +## Time Twister Scenarios +############################################################################### + +STR_SCNR :Dark Age - Castle +STR_PARK :Cliffside Castle +STR_DTLS :Členové místní skupiny pro rekonstrukci historických bitev berou své hobby trochu moc vážně. Svěřili vám stavbu starověkého zábavního parku na území Cliffside Castle. + + +STR_SCNR :Dark Age - Robin Hood +STR_PARK :Sherwood Forest +STR_DTLS :Abyste mohli brát mohatým a dávat chudým, rozhodli jste se postavit zábavní park v Sherwood Forest. + + +STR_SCNR :Future - First Encounters +STR_PARK :Extraterrestrial Extravaganza +STR_DTLS :Byl objeven život na vzdálené planetě. Postavte mimozemsky zaměřený zábavní park, abyste se svezli na vlně nového nepřevídaného zájmu. + + +STR_SCNR :Future - Future World +STR_PARK :Gemini City +STR_DTLS :Ukažte svou vynalézavou, utopickou vizi budoucnosti - přijďte s futuristickým zábavním parkem, který zahrnuje ty nejnovější atrakce. + + +STR_SCNR :Mythological - Animatronic Film Set +STR_PARK :Animatronic Antics +STR_DTLS :Byl vám zadán úkol správy a vylepšování stávajícího zábavního parku, který byl postaven na starém filmařském místě. Vybudujte odkaz průkopníkům-animátorům, kteří poprvé přinesli mýtické postavy k životu na stříbrném plátně. + + +STR_SCNR :Mythological - Cradle of Civilisation +STR_PARK :Mythological Madness +STR_DTLS :Vlastníte ostrov velké archeologické hodnoty. Rozhodli jste se podpořit jeho zachování vybudováním zábavního parku založném na mytologii tohoto místa. + + +STR_SCNR :Prehistoric - After the Asteroid +STR_PARK :Crater Carnage +STR_DTLS :Vlastníte velký kráter a jakožto opravdový průkopník jste se rozhodl vybudovat zábavní park ve stylu asteroidů a přeměnit tuto zdánlivě bezcenou půdu v profitující a vyledávanou oblast. + + +STR_SCNR :Prehistoric - Jurassic Safari +STR_PARK :Coastersaurus +STR_DTLS :Byli jste zaúkolování stavbou zábavního parku ve stylu období Jura. Pro zlepšení přístupu návštěvníků k exotickým rostlinám a zvířatům budete muset postavit mosty do a přes údolí. + + +STR_SCNR :Prehistoric - Stone Age +STR_PARK :Rocky Rambles +STR_DTLS :Abyste se vyhnuli stavbě dálnice a zachovali mysteriózní prehistorické kamenné kruhy, budete muset postavit zábavní park ve stylu doby kamenné a začít vydělávat. Nicméně přiláakt návštěvníky bude těžké, protože terén je opravdu nehostinný. + + +STR_SCNR :Roaring Twenties - Prison Island +STR_PARK :Alcatraz +STR_DTLS :Nechvalně proslavená ostrovní věznice - jejíž populace jednou překypovala pašeráky a vyděrači - je nyný na prodej. Rozhodli jste se jí přetvořit na velkou turistickou atrakci - na peníze berte ohled! + + +STR_SCNR :Roaring Twenties - Schneider Cup +STR_PARK :Schneider Shores +STR_DTLS :75. leté výročí výhry Schneider Cup vašeho dědečka se blíží a zbývá už jen pár let. Poctíte jeho úspěch stavbou zábavního parku založeném na proslulém závodu hydroplánů. + + +STR_SCNR :Roaring Twenties - Skyscrapers +STR_PARK :Metropolis +STR_DTLS :Vlastníte volný pozemek v městské oblasti téměř bez růstu. Abyste vymačkali co nejvíce z vaší nemovitosti, postavíte mrakodrap-zábavní park inspirovaný architekturou dvacátých let. + + +STR_SCNR :Rock 'n' Roll - Flower Power +STR_PARK :Woodstock +STR_DTLS :Obrovský každoroční hudební festival se bude konat na vašem pozemku. Postavte pořádný park, abyste zabavili návštěvníky. + + +STR_SCNR :Rock 'n' Roll - Rock 'n' Roll +STR_PARK :Rock 'n' Roll Revival +STR_DTLS :Tento stárnoucí zábavní park už viděl lepší dny. Pomocte majiteli dát parku retro rock 'n' roll vzhled a udělat z něho vyhledávané místo. \ No newline at end of file diff --git a/data/language/dutch.txt b/data/language/dutch.txt index cf42a3debb..cdc49e1950 100644 --- a/data/language/dutch.txt +++ b/data/language/dutch.txt @@ -27,7 +27,7 @@ STR_0025 :Boomstamattractie STR_0026 :Wildwaterbaan STR_0027 :Botsauto's STR_0028 :Schommelschip -STR_0029 :Schommelschip dat over de kop gaat +STR_0029 :Loopingschip STR_0030 :Eetkraam STR_0031 :Onbekende kraam (1D) STR_0032 :Drankkraam @@ -61,7 +61,7 @@ STR_0059 :Vliegachtbaan STR_0060 :Onbekende attractie (3A) STR_0061 :Virginia Reel STR_0062 :Plonsboten -STR_0063 :Minihelicopters +STR_0063 :Minihelikopters STR_0064 :Liggende achtbaan STR_0065 :Omgekeerde monorail STR_0066 :Onbekende attractie (40) @@ -562,7 +562,7 @@ STR_0560 : STR_0561 : STR_0562 :Aangedreven karretjes rijden langs eng decor en special effects over een baan met hoogteverschillen. STR_0563 :Bezoekers zitten in comfortabele treinen met enkel een schootbeugel en gaan soepel door grote afdalingen en kronkelende stukken baan, met veel 'airtime' in de heuvels. -STR_0564 :Deze over een houten baan lopende achtbaan is snel, ruw, luidruchting en geeft het gevoel van controleverlies met veel 'airtime'. +STR_0564 :Deze over een houten baan lopende achtbaan is snel, ruw, luidruchtig en geeft het gevoel van controleverlies met veel 'airtime'. STR_0565 :Een simpele houten achtbaan die enkel in staat is rustige hellingen en bochten te bedwingen, de karretjes worden enkel op de baan gehouden door middel van zijfrictiewielen en zwaartekracht. STR_0566 :Losse karretjes rijden over een kronkelende baan met scherpe bochten en korte felle afdalingen. STR_0567 :Bezoekers zitten in stoelen aan beide kanten van de baan, en draaien alle kanten op terwijl ze door diepe afdalingen en diverse omkeringen gaan. @@ -571,7 +571,7 @@ STR_0569 :Bezoekers hangen in treinen onder de baan met enkel schouderbeugels STR_0570 : STR_0571 :Ronde karretjes gaan over een zigzaggende houten baan en draaien daarbij rond. STR_0572 :Boten met een hoge capaciteit varen door een brede waterbak, worden naar boven vervoerd door een lopende band, en gaan met hoge snelheid steile heuvels af om met een grote plons de passagiers te doorweken. -STR_0573 :Aangedreven karretjes in de vorm van een helicopter rijden over een stalen baan, bestuurd door het trappen van de passagiers. +STR_0573 :Aangedreven karretjes in de vorm van een helikopter rijden over een stalen baan, bestuurd door het trappen van de passagiers. STR_0574 :Passagiers worden door middel van een speciale beugel in een liggende positie vastgehouden, waarna ze op hun rug of met hun gezicht naar de grond door kronkelende stukken baan en omkeringen heen gaan. STR_0575 :Aangedreven treinen hangen aan een enkele rail en vervoeren mensen door het park heen. STR_0576 : @@ -1747,11 +1747,11 @@ STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COM STR_1745 :{COMMA16} STR_1746 :Kan dit niet aanpassen... STR_1747 :{WINDOW_COLOUR_2}Tijdslimiet: -STR_1748 :{SMALLFONT}{BLACK}Tijdsmiliet voor deze attractie +STR_1748 :{SMALLFONT}{BLACK}Tijdslimiet voor deze attractie STR_1749 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{DURATION} STR_1750 :{DURATION} STR_1751 :Kan de tijdslimiet voor deze attractie niet aanpassen... -STR_1752 :{SMALLFONT}{BLACK}Toon een lijst van indivuele bezoekers in het park +STR_1752 :{SMALLFONT}{BLACK}Toon een lijst van individuele bezoekers in het park STR_1753 :{SMALLFONT}{BLACK}Toon een samengevatte lijst van bezoekers in het park STR_1754 :{BLACK}{COMMA16} bezoekers STR_1755 :{BLACK}{COMMA16} bezoeker @@ -1776,7 +1776,7 @@ STR_1773 :Een attractie mag maar één actiefotogedeelte hebben STR_1774 :Een attractie mag maar één kabellift hebben STR_1775 :Uit STR_1776 :Aan -STR_1777 :{WINDOW_COLOUR_2}Muziek +STR_1777 :{WINDOW_COLOUR_2}Attractiemuziek STR_1778 :{STRINGID} - - STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Pandapak STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tijgerpak @@ -1815,7 +1815,7 @@ STR_1812 :{SMALLFONT}{BLACK}{STRINGID} STR_1813 :Overige objecten STR_1814 :Acties STR_1815 :Gedachten -STR_1816 :{SMALLFONT}{BLACK}Selecteer het type informatie dat je in de gastenlijst wilt zien +STR_1816 :{SMALLFONT}{BLACK}Selecteer het type informatie dat je in de bezoekerslijst wilt zien STR_1817 :({COMMA16}) STR_1818 :{WINDOW_COLOUR_2}Alle bezoekers STR_1819 :{WINDOW_COLOUR_2}Alle bezoekers (samengevat) @@ -1858,14 +1858,14 @@ STR_1855 :{WINDOW_COLOUR_2}Bouw: {BLACK}{COMMA16} jaar geleden STR_1856 :{WINDOW_COLOUR_2}Winst per verkocht artikel: {BLACK}{CURRENCY2DP} STR_1857 :{WINDOW_COLOUR_2}Verlies per verkocht artikel: {BLACK}{CURRENCY2DP} STR_1858 :{WINDOW_COLOUR_2}Kosten: {BLACK}{CURRENCY2DP} per maand -STR_1859 :Klusjesmannen -STR_1860 :Monteurs -STR_1861 :Bewakers -STR_1862 :Entertainers -STR_1863 :Klusjesman -STR_1864 :Monteur -STR_1865 :Bewaker -STR_1866 :Entertainer +STR_1859 :klusjesmannen +STR_1860 :monteurs +STR_1861 :bewakers +STR_1862 :entertainers +STR_1863 :klusjesman +STR_1864 :monteur +STR_1865 :bewaker +STR_1866 :entertainer STR_1867 :{BLACK}{COMMA16} {STRINGID} STR_1868 :Kan het aantal rotaties niet aanpassen... STR_1869 :{WINDOW_COLOUR_2}Aantal rotaties: @@ -1945,10 +1945,10 @@ STR_1940 :{SMALLFONT}{BLACK}Stemming, energie, hongerniveau e.d. van deze bez STR_1941 :{SMALLFONT}{BLACK}Tonen in welke attracties deze bezoeker is geweest STR_1942 :{SMALLFONT}{BLACK}Financiële informatie over deze bezoeker tonen STR_1943 :{SMALLFONT}{BLACK}Recente gedachten van deze bezoeker tonen -STR_1944 :{SMALLFONT}{BLACK}Toon de dingen die de gast bij zich heeft +STR_1944 :{SMALLFONT}{BLACK}Toon de dingen die de bezoeker bij zich heeft STR_1945 :{SMALLFONT}{BLACK}Orders en opties voor deze werknemer tonen STR_1946 :{SMALLFONT}{BLACK}Kostuum van deze entertainer selecteren -STR_1947 :{SMALLFONT}{BLACK}Werkgebieden van het geselecteerde type werknemer weergeven en de dichtstbijzijnde werknemer localiseren +STR_1947 :{SMALLFONT}{BLACK}Werkgebieden van het geselecteerde type werknemer weergeven en de dichtstbijzijnde werknemer lokaliseren STR_1948 :{SMALLFONT}{BLACK}Nieuwe werknemer van het geselecteerde type aannemen STR_1949 :Samenvatting financiën STR_1950 :Grafiek van financiën @@ -2334,7 +2334,7 @@ STR_2329 :{WINDOW_COLOUR_2}Afstanden en snelheden: STR_2330 :{WINDOW_COLOUR_2}Temperatuur: STR_2331 :{WINDOW_COLOUR_2}Hoogtemarkering: STR_2332 :Eenheden -STR_2333 :Geluid +STR_2333 :Geluidseffecten STR_2334 :Ponden ({POUND}) STR_2335 :Dollars ($) STR_2336 :Frank (F) @@ -2361,7 +2361,7 @@ STR_2356 :{WINDOW_COLOUR_2}Inspecties: {BLACK}{COMMA16} STR_2357 :Huis STR_2358 :Eenheden STR_2359 :Echte waarden -STR_2360 :{WINDOW_COLOUR_2}Schermresolutie: +STR_2360 :Schermresolutie: STR_2361 :Landschapslijnen verzachten STR_2362 :{SMALLFONT}{BLACK}Verzachting van lijnen tussen landschapstegels aan- of uitzetten STR_2363 :Raster weergeven op landschap @@ -2395,7 +2395,7 @@ STR_2390 :{BLACK}Om 10 verschillende typen achtbanen in je park te hebben, el STR_2391 :{BLACK}Om ten minste {COMMA16} bezoekers in je park te hebben. Je parkwaardering mag geen moment onder de 700 komen! STR_2392 :{BLACK}Om in één maand ten minste {POP16}{POP16}{CURRENCY} aan attractiekaartjes te verdienen STR_2393 :{BLACK}Om 10 verschillende typen achtbanen in je park te hebben, elk met een lengte van ten minste {LENGTH} en een spanningswaarde van ten minste 7,00 -STR_2394 :{BLACK}Om alle 5 deels gebouwde achtbanen in je park af te maken, ek met een spanningswaarde van ten minste {POP16}{POP16}{COMMA2DP32} +STR_2394 :{BLACK}Om alle 5 deels gebouwde achtbanen in je park af te maken, elk met een spanningswaarde van ten minste {POP16}{POP16}{COMMA2DP32} STR_2395 :{BLACK}Om je lening terug te betalen en een parkwaarde van ten minste {POP16}{POP16}{CURRENCY} te bereiken STR_2396 :{BLACK}Om in één maand ten minste {POP16}{POP16}{CURRENCY} aan de verkoop van eten, drinken en souvenirs te verdienen STR_2397 :Geen @@ -2464,7 +2464,7 @@ STR_2459 :{SMALLFONT}{BLACK}Toon grafiek van parkwaardeverloop STR_2460 :{SMALLFONT}{BLACK}Toon grafiek van wekelijkse winst STR_2461 :{SMALLFONT}{BLACK}Toon marketingcampagnes STR_2462 :{SMALLFONT}{BLACK}Toon beeld van de parkingang -STR_2463 :{SMALLFONT}{BLACK}Toon grafiek van parkwaarderingverloop +STR_2463 :{SMALLFONT}{BLACK}Toon grafiek van parkwaarderingsverloop STR_2464 :{SMALLFONT}{BLACK}Toon grafiek met verloop van het aantal bezoekers STR_2465 :{SMALLFONT}{BLACK}Toon de entreeprijs en -informatie STR_2466 :{SMALLFONT}{BLACK}Toon parkstatistieken @@ -2566,7 +2566,7 @@ STR_2561 :Home STR_2562 :Links STR_2563 :Omhoog STR_2564 :Rechts -STR_2565 :Omloog +STR_2565 :Omlaag STR_2566 :Selecteren STR_2567 :Afdrukken STR_2568 :Uitvoeren @@ -2708,7 +2708,7 @@ STR_2703 :Elke 15 minuten STR_2704 :Elke 30 minuten STR_2705 :Elk uur STR_2706 :Nooit -STR_2707 :Open nieuw scherm +STR_2707 :Systeemdialoogvenster openen STR_2708 :{WINDOW_COLOUR_1}Weet je zeker dat je {STRINGID} wilt vervangen? STR_2709 :Vervangen STR_2710 :Kies een bestandsnaam. @@ -2755,11 +2755,11 @@ STR_2750 :Alles naar boven verplaatsen STR_2751 :Alles naar beneden verplaatsen STR_2752 :Onkruid weg STR_2753 :Gras maaien -STR_2754 :Bloemen water geven -STR_2755 :Vandalisme repareren +STR_2754 :Bloemen water gev. +STR_2755 :Vandal. repareren STR_2756 :Afval verwijderen -STR_2757 :Mooi weer -STR_2758 :Regen +STR_2757 : +STR_2758 : STR_2759 :Hoogtes op nul STR_2760 :+{CURRENCY} STR_2761 : @@ -2776,7 +2776,7 @@ STR_2771 :Lagere spelsnelheid STR_2772 :Hogere spelsnelheid STR_2773 :Venster STR_2774 :Volledig scherm -STR_2775 :Volledig scherm (bureaublad) +STR_2775 :Voll. sch. (randl. venster) STR_2776 :Taal: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} @@ -2818,9 +2818,9 @@ STR_2813 :{RED}Je entreeprijs is te hoog!{NEWLINE}Verlaag de entreeprijs of v STR_2814 :{WINDOW_COLOUR_2}Prijs voor het rommeligste park STR_2815 :{WINDOW_COLOUR_2}Prijs voor het netste park STR_2816 :{WINDOW_COLOUR_2}Prijs voor de beste achtbanen -STR_2817 :{WINDOW_COLOUR_2}Prijs voor het park met de beste prijs/kwaliteitsverhouding +STR_2817 :{WINDOW_COLOUR_2}Prijs voor het park met de beste prijs-kwaliteitverhouding STR_2818 :{WINDOW_COLOUR_2}Prijs voor het mooiste park -STR_2819 :{WINDOW_COLOUR_2}Prijs voor het park met de slechtste prijs/kwaliteitsverhouding +STR_2819 :{WINDOW_COLOUR_2}Prijs voor het park met de slechtste prijs-kwaliteitverhouding STR_2820 :{WINDOW_COLOUR_2}Prijs voor het veiligste park STR_2821 :{WINDOW_COLOUR_2}Prijs voor het beste personeel STR_2822 :{WINDOW_COLOUR_2}Prijs voor het beste eten @@ -2835,9 +2835,9 @@ STR_2830 :{WINDOW_COLOUR_2}Prijs voor de beste rustige attracties STR_2831 :{TOPAZ}Je park heeft een prijs gekregen: 'Rommeligste park van het land'! STR_2832 :{TOPAZ}Je park heeft een prijs gekregen: 'Netste park van het land'! STR_2833 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste achtbanen'! -STR_2834 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste prijs/kwaliteitsverhouding'! +STR_2834 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste prijs-kwaliteitverhouding'! STR_2835 :{TOPAZ}Je park heeft een prijs gekregen: 'Mooiste park van het land'! -STR_2836 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de slechtste prijs/kwaliteitsverhouding'! +STR_2836 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de slechtste prijs-kwaliteitverhouding'! STR_2837 :{TOPAZ}Je park heeft een prijs gekregen: 'Veiligste park van het land'! STR_2838 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met de beste werknemers'! STR_2839 :{TOPAZ}Je park heeft een prijs gekregen: 'Park met het beste eten van het land'! @@ -3104,7 +3104,7 @@ STR_3099 :{SMALLFONT}{BLACK}Kleur selecteren STR_3100 :{SMALLFONT}{BLACK}Tweede kleur selecteren STR_3101 :{SMALLFONT}{BLACK}Derde kleur selecteren STR_3102 :{SMALLFONT}{BLACK}Gekleurd decor opnieuw verven -STR_3103 :Kan dit niet opnieuw ververen... +STR_3103 :Kan dit niet opnieuw verversen... STR_3104 :{SMALLFONT}{BLACK}Toon een lijst van attracties STR_3105 :{SMALLFONT}{BLACK}Toon een lijst van winkels en kraampjes STR_3106 :{SMALLFONT}{BLACK}Toon een lijst van informatiekiosken en andere faciliteiten @@ -3322,10 +3322,10 @@ STR_3317 :Nog geen details STR_3318 :{SMALLFONT}{BLACK}Selecteer in welke groep dit scenario moet verschijnen STR_3319 :{WINDOW_COLOUR_2}Scenariogroep: STR_3320 :Kan scenariobestand niet opslaan... -STR_3321 :Nieuwe objecten successvol geïnstalleerd +STR_3321 :Nieuwe objecten succesvol geïnstalleerd STR_3322 :{WINDOW_COLOUR_2}Doelstelling: {BLACK}{STRINGID} STR_3323 :Ontbrekende objectdata, ID: -STR_3324 :Vereist uitbreidingspakket: +STR_3324 :Vereist het uitbreidingspakket {STRINGID} STR_3325 :Vereist een uitbreidingspakket STR_3326 :{WINDOW_COLOUR_2}(geen plaatje) STR_3327 :Startpositie voor bezoekers niet aangegeven @@ -3411,7 +3411,7 @@ STR_3406 :{SMALLFONT}{BLACK}Dit is ons lege park. We gaan een simpele, zelfon STR_3407 :{SMALLFONT}{BLACK}Ten eerste hebben we een startpositie nodig... STR_3408 :{SMALLFONT}{BLACK}Het stuk baan dat we net gebouwd hebben is een 'station' en zorgt ervoor dat bezoekers in en uit kunnen stappen... STR_3409 :{SMALLFONT}{BLACK}We verlengen het perron een beetje door nog wat stationsgedeeltes aan te leggen... -STR_3410 :{SMALLFONT}{BLACK}De knopjes aan de bovenkant van het bouwvenster laten je tusen verschillende soorten baanstukjes kiezen... +STR_3410 :{SMALLFONT}{BLACK}De knopjes aan de bovenkant van het bouwvenster laten je tussen verschillende soorten baanstukjes kiezen... STR_3411 :{SMALLFONT}{BLACK}We gaan een bocht naar links bouwen... STR_3412 :{SMALLFONT}{BLACK}De bocht is nog niet gebouwd, maar het witte spookplaatje laat zien waar het gebouwd gaat worden. Als je op de grote knop klikt wordt het gebouwd... STR_3413 :{SMALLFONT}{BLACK}Nu willen we een recht stuk bouwen, dus klikken we op het knopje voor 'recht stuk'... @@ -3467,7 +3467,7 @@ STR_5133 :{SMALLFONT}{BLACK}Een kleiner gebied landrechten aanpassen STR_5134 :{SMALLFONT}{BLACK}Een groter gebied landrechten aanpassen STR_5135 :{SMALLFONT}{BLACK}Land en bouwrechten kopen STR_5136 :Landrechten -STR_5137 :Kettingliften en lanceringen{NEWLINE}kunnen tot {VELOCITY} +STR_5137 :Bedrijfslimieten van attracties opheffen STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} STR_5140 :Defecte remmen onmogelijk maken @@ -3511,7 +3511,7 @@ STR_5175 :Voer de naam van je Twitch-kanaal in STR_5176 :Twitch-integratie inschakelen STR_5177 :Schermmodus: STR_5178 :{SMALLFONT}{BLACK}Cheats voor financiën -STR_5179 :{SMALLFONT}{BLACK}Cheats voor gasten +STR_5179 :{SMALLFONT}{BLACK}Cheats voor bezoekers STR_5180 :{SMALLFONT}{BLACK}Cheats voor park STR_5181 :{SMALLFONT}{BLACK}Cheats voor attracties STR_5182 :{INT32} @@ -3581,7 +3581,7 @@ STR_5245 :Bovenste werkbalk STR_5246 :Onderste werkbalk STR_5247 :Onderste werkbalk baanontwerper/beheerder STR_5248 :Onderste werkbalk scenariobewerker -STR_5249 :Menuknoppen titelsherm +STR_5249 :Menuknoppen titelscherm STR_5250 :Afsluitknop titelscherm STR_5251 :Optiesknop titelscherm STR_5252 :Scenarioselectie titelscherm @@ -3618,7 +3618,7 @@ STR_5282 :Attracties openen/sluiten via RCT1-stoplichten STR_5283 :Park openen/sluiten via RCT1-stoplichten STR_5284 :Scenarioselectie-lettertype in RCT1-stijl STR_5285 :KABOEM! -STR_5286 :{SMALLFONT}{BLACK}Laat sommige gasten exploderen +STR_5286 :{SMALLFONT}{BLACK}Laat sommige bezoekers exploderen STR_5287 :Attractie is al defect STR_5288 :Attractie is gesloten STR_5289 :Deze attractie kan niet defect raken @@ -3671,8 +3671,8 @@ STR_5335 :Attractie-ingang STR_5336 :Attractie-uitgang STR_5337 :Parkingang STR_5338 :Elementtype -STR_5339 :Hoogte onderk. -STR_5340 :Hoogte bovenk. +STR_5339 :{SMALLFONT}{BLACK}Hoogte onderkant +STR_5340 :{SMALLFONT}{BLACK}Hoogte bovenkant STR_5341 :Eigenschappen STR_5342 :Kies een vakje op de kaart STR_5343 :Werknemers automatisch plaatsen @@ -3697,7 +3697,7 @@ STR_5361 :Geef alle bez.: STR_5362 :{BLACK}Zet de voorkeursintensiteit van alle bez. op: STR_5363 :Meer dan 1 STR_5364 :Minder dan 15 -STR_5365 :{BLACK}Snelheid werknemers: +STR_5365 :{BLACK}Snelh. werknemers: STR_5366 :Normaal STR_5367 :Snel STR_5368 :Crashstatus weg @@ -3787,7 +3787,7 @@ STR_5451 :Cheatsvenster openen STR_5452 :Zichtbaarheid werkbalken schakelen STR_5453 :Andere attractie selecteren STR_5454 :FPS-limiet opheffen -STR_5455 :Zandboxmodus inschakelen +STR_5455 :Zandbakmodus inschakelen STR_5456 :Hoogtecontroles uitschakelen STR_5457 :Ondersteuningslimieten uitschakelen STR_5458 :Met de klok mee draaien @@ -3888,7 +3888,7 @@ STR_5552 :{POP16}{POP16}Jaar {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {M STR_5553 :Spel pauzeren als de Steam-overlay open staat STR_5554 :{SMALLFONT}{BLACK}Overgangen met omringend land gladstrijken STR_5555 :Voertuigen van andere baantypen tonen -STR_5556 :Speler verwijderen +STR_5556 :{SMALLFONT}{BLACK}Speler verwijderen STR_5557 :Verbinding behouden na desynchronisatie (multiplayer) STR_5558 :Om deze instelling van kracht te laten worden is een herstart vereist. STR_5559 :Elke 10 min. inspect. @@ -3913,147 +3913,773 @@ STR_5577 :Zuid-Koreaanse won (W) STR_5578 :Russische roebel (R) STR_5579 :Vergrotingsfactor: STR_5580 :Tsjechische kroon (Kc) +STR_5581 :FPS tonen +STR_5582 :Aanwijzer in venster vasthouden +STR_5583 :{COMMA1DP16} m/s +STR_5584 :SI +STR_5585 :{SMALLFONT}{BLACK}Heft de limieten op het tabblad Bedrijfsopties van een attractie op, waardoor je bijvoorbeeld kettingsheuvels met snelheden tot {VELOCITY} kunt hebben. +STR_5586 :Winkels en kraampjes automatisch openen +STR_5587 :{SMALLFONT}{BLACK}Als deze optie is ingeschakeld zullen winkels en kraampjes na plaatsing automatisch worden geopend. +STR_5588 :{SMALLFONT}{BLACK}Multiplayer +STR_5589 :Berichtinstellingen +STR_5590 :Als het park een prijs heeft gekregen +STR_5591 :Als een marketingcampagne is afgelopen +STR_5592 :Waarschuwingen over het park +STR_5593 :Waarschuwingen over de parkwaardering +STR_5594 :Als een attractie kapot is gegaan +STR_5595 :Als een attractie is neergestort +STR_5596 :Waarschuwingen over attracties +STR_5597 :Als een nieuw type attractie of thema beschikbaar is +STR_5598 :Waarschuwingen over bezoekers +STR_5599 :Als een gevolgde bezoeker verdwaald is +STR_5600 :Als een gevolgde bezoeker het park verlaten heeft +STR_5601 :Als een gevolgde bezoeker in de rij staat voor een attractie +STR_5602 :Als een gevolgde bezoeker een attractie is ingegaan +STR_5603 :Als een gevolgde bezoeker een attractie is uitgegaan +STR_5604 :Als een gevolgde bezoeker iets gekocht heeft +STR_5605 :Als een gevolgde bezoeker een faciliteit gebruikt +STR_5606 :Als een bezoeker is overleden +STR_5607 :{SMALLFONT}{BLACK}Geselecteerd kaartelement geforceerd verwijderen +STR_5608 :HO +STR_5609 :HB +STR_5610 :{SMALLFONT}{BLACK}Het geselecteerde kaartelement verwijderen. Dit zal worden geforceerd, waardoor er geen geld zal worden teruggegeven of gebruikt. Gebruik deze functie voorzichtig. +STR_5611 :S +STR_5612 :{SMALLFONT}{BLACK}Spookelement (tijdelijk element) +STR_5613 :K +STR_5614 :{SMALLFONT}{BLACK}Element is kapot +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}Is het laatste element van dit vakje. +STR_5617 :{SMALLFONT}{BLACK}Geselecteerd element naar boven verplaatsen +STR_5618 :{SMALLFONT}{BLACK}Geselecteerd element naar beneden verplaatsen +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}Echte{ENDQUOTES} parken +STR_5626 :Overige parken +STR_5627 :Scenariolijst groeperen op: +STR_5628 :Oorsprong +STR_5629 :Moeilijkheidsgraad +STR_5630 :Moeilijke scenario's ontgrendelden met gemakkelijke +STR_5631 :Originele DLC +STR_5632 :Bouw je eigen... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Uitgegeven geld: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Uitgevoerde commando's: {BLACK}{COMMA16} +STR_5637 :Kan dit niet uitvoeren... +STR_5638 :Geen toestemming +STR_5639 :{SMALLFONT}{BLACK}Spelerslijst tonen +STR_5640 :{SMALLFONT}{BLACK}Groepen beheren +STR_5641 :Standaardgroep: +STR_5642 :Groep: +STR_5643 :Groep toevoegen +STR_5644 :Groep verwijderen +STR_5645 :Chatten +STR_5646 :Landschap wijzigen +STR_5647 :Spel (de)pauzeren +STR_5648 :Waterniveau aanpassen +STR_5649 :Attracties aanmaken +STR_5650 :Attracties verwijderen +STR_5651 :Attracties verbouwen +STR_5652 :Attractie-eigenschappen aanpassen +STR_5653 :Decor +STR_5654 :Pad +STR_5655 :Bezoekers +STR_5656 :Werknemers +STR_5657 :Parkeigenschappen +STR_5658 :Parkfinanciëring +STR_5659 :Speler verwijderen +STR_5660 :Groepen aanpassen +STR_5661 :Spelersgroep instellingen +STR_5662 :n.v.t. +STR_5663 :Landschap leegmaken +STR_5664 :Cheaten +STR_5665 :Clusters van decoritems bouwen +STR_5701 :{WINDOW_COLOUR_2}Laatste actie: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Laatste actie van deze speler localiseren +STR_5703 :De host kan niet worden verwijderd +STR_5704 :Laatste actie: +STR_5705 :Kan de speler niet aan deze groep toewijzen +STR_5706 :Kan geen groepen verwijderen waarin spelers zijn toegewezen +STR_5707 :Deze groep kan niet worden aangepast +STR_5708 :Kan de groep waartoe de host behoort niet aanpassen +STR_5709 :Groep hernoemen +STR_5710 :Groepnaam +STR_5711 :Voer een nieuwe naam voor deze groep in: +STR_5712 :Kan geen rechten aanpassen die je zelf niet hebt +STR_5713 :Speler verwijderen +STR_5714 :Optiesvenster tonen +STR_5715 :Nieuw spel +STR_5716 :Niet toegestaan in multiplayer +# For identifying client network version in server list window +STR_5717 :Netwerkversie: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Netwerkversie: {STRING} +STR_5719 :Zon +STR_5720 :Lichte bewolking +STR_5721 :Bewolkt +STR_5722 :Regen +STR_5723 :Flinke regen +STR_5724 :Onweer +STR_5725 :{BLACK}Weer forceren: +STR_5726 :{SMALLFONT}{BLACK}Stelt het huidige weer in het park in +STR_5727 :Opschaalkwaliteit +STR_5728 :Dit vereist 'weergave door hardware' +STR_5729 :{SMALLFONT}{BLACK}Dit vereist 'weergave door hardware' +STR_5730 :Nearest neighbour +STR_5731 :Lineair +STR_5732 :Anisotropisch +STR_5733 :Bij opschalen met gehele getallen NN gebruiken +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Rendering +STR_5735 :Netwerkstatus +STR_5736 :Speler +STR_5737 :Gesloten, nog {COMMA16} passagier +STR_5738 :Gesloten, nog {COMMA16} passagiers +STR_5739 :{WINDOW_COLOUR_2}Huidig aantal passagiers: {BLACK}{COMMA16} +STR_5740 :Oneindige marketingcampagnes +STR_5741 :{SMALLFONT}{BLACK}Marketingcampagnes verlopen nooit +STR_5742 :Authenticeren ... +STR_5743 :Verbinding maken ... +STR_5744 :Opzoeken ... +STR_5745 :Netwerkdesynchronisatie gedetecteerd +STR_5746 :Verbinding verbroken +STR_5747 :Verbinding verbroken: {STRING} +STR_5748 :Van de server verwijderd +STR_5749 :Ophoepelen! +STR_5750 :Verbinding gesloten +STR_5751 :Geen gegevens +STR_5752 :{OUTLINE}{RED}{STRING} heeft afgesloten. +STR_5753 :{OUTLINE}{RED}{STRING} heeft afgesloten ({STRING}). +STR_5754 :Ongeldige gebruikersnaam +STR_5755 :Incorrecte softwareversie +STR_5756 :Ongeldig wachtwoord +STR_5757 :Server is vol +STR_5758 :{OUTLINE}{GREEN}Nieuwe speler: {STRING}. +STR_5759 :Bezig met downloaden van de kaart ... ({INT32} / {INT32}) +STR_5760 :Hong Kong-dollar (HK$) +STR_5761 :Taiwanese dollar (NT$) +STR_5762 :Chinese yuan (CN{YEN}) +STR_5763 :Alle bestanden +STR_5764 :Ongeldig attractietype +STR_5765 :Kan attracties met een ongeldig type niet bewerken. +STR_5766 : +STR_5767 :Inkomsten +STR_5768 :Totaal aant. bez. +STR_5769 :Totale winst +STR_5770 :Bezoekers per uur +STR_5771 :Bedrijfskosten +STR_5772 :Bouwjaar +STR_5773 :Totaal aant. bez.: {COMMA32} +STR_5774 :Totale winst: {CURRENCY2DP} +STR_5775 :{COMMA32} bezoekers per uur +STR_5776 :Dit jaar +STR_5777 :Vorig jaar +STR_5778 :{COMMA16} jaar geleden +STR_5779 :Inkomsten: {CURRENCY2DP} per uur +STR_5780 :Bedrijfskosten: {CURRENCY2DP} per uur +STR_5781 :Bedrijfskosten: onbekend +STR_5782 :Je bent nu verbonden met de server. Druk op '{STRING}' om te chatten. +STR_5783 :{WINDOW_COLOUR_2}Scenario is vergrendeld +STR_5784 :{BLACK}Dit scenario is pas beschikbaar als je eerdere scenario's hebt voltooid. +STR_5785 :Kan de groep niet hernoemen... +STR_5786 :Ongeldige groepsnaam +STR_5787 :{COMMA32} spelers online +STR_5788 :Standaard inspectie-interval: +STR_5789 :Bliksemeffect uitschakelen +STR_5790 :{SMALLFONT}{BLACK}Maakt geld vragen voor zowel het park als de attracties mogelijk,{NEWLINE}zoals in RCT1. +STR_5791 :{SMALLFONT}{BLACK}Stelt het bouwjaar van alle attracties in op dit jaar{NEWLINE}en zet de betrouwbaarheid weer terug op 100%. +STR_5792 :{SMALLFONT}{BLACK}Repareert alle defecte attracties. +STR_5793 :{SMALLFONT}{BLACK}Wist de crashstatus van alle attracties,{NEWLINE}zodat de bezoekers ze niet als onveilig zien. +STR_5794 :{SMALLFONT}{BLACK}In sommige scenario's kun je bepaalde bestaande attracties niet aanpassen.{NEWLINE}Deze cheat heft deze beperkingen op. +STR_5795 :{SMALLFONT}{BLACK}Zorgt ervoor dat bezoekers in elke attractie gaan,{NEWLINE}zelfs als de intensiteit erg hoog is. +STR_5796 :{SMALLFONT}{BLACK}Forceert het openen of sluiten van het park. +STR_5797 :{SMALLFONT}{BLACK}Voorkomt dat het weer verandert. +STR_5798 :{SMALLFONT}{BLACK}Staat bouwen in pauzemodus toe. +STR_5799 :{SMALLFONT}{BLACK}Voorkomt dat de remmen van attracties kapot gaan, wat voor fatale botsingen kan zorgen. +STR_5800 :{SMALLFONT}{BLACK}Voorkomt dat attracties kapot gaan. + ############# # Scenarios # ############# +## RCT1 Original + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Bouw een bloeiend pretpark diep in het bos, op een grote open plek. + + +STR_SCNR :Dynamite Dunes +STR_PARK :Dynamite Dunes +STR_DTLS :Dit park, gebouwd in de woestijn, beschikt over slechts één achtbaan maar heeft ruimte voor uitbreiding. + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Bouw vanaf het begin een pretpark rond een groot meer. + + +STR_SCNR :Diamond Heights +STR_PARK :Diamond Heights +STR_DTLS :Diamond Heights is al een succesvol pretpark met fantastische attracties - verander het om de waarde ervan te verdubbelen. + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Verander de schitterende Evergreen Gardens in een bloeiend pretpark. + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Verander het kleine amusementspark van Bumbly Beach in een succesvol pretpark. + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Verscheidene eilanden vormen de basis voor dit nieuwe park. + + +STR_SCNR :Katie's Dreamland +STR_PARK :Katie's Dreamland +STR_DTLS :Een klein pretpark met een paar attracties en ruimte voor uitbreiding - jouw doel is om de parkwaarde te verdubbelen. + + +STR_SCNR :Pokey Park +STR_PARK :Pokey Park +STR_DTLS :Een klein, krap pretpark dat grote uitbreiding vereist. + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :Een park met enkele uitstekende waterattracties vereist uitbreiding + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Verander een grote verlaten mijn, een toeristische attractie, in een pretpark. + + +STR_SCNR :Karts & Coasters +STR_PARK :Karts & Coasters +STR_DTLS :Een groot park, verscholen in het bos, met alleen kartbanen en houten achtbanen. + + +STR_SCNR :Mel's World +STR_PARK :Mel's World +STR_DTLS :Dit pretpark heeft goed ontworpen, moderne attractions, maar heeft ook veel ruimte voor uitbreiding. + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :Bouw vanaf het begin een pretpark in de heuvelachtige bossen van Mystic Mountain. + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Verander de Egyptische ruïnes, een toeristische attractions, in een bloeiend pretpark. + + +STR_SCNR :Crumbly Woods +STR_PARK :Crumbly Woods +STR_DTLS :Een groot park met goed ontwerpen maar nogal oude attracties - vervang de oude attracties of voeg nieuwe toe om het park populairder te maken. + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :Verander de pier van dit slaperige stadje in een bloeiende attractie. + + +STR_SCNR :Lightning Peaks +STR_PARK :Lightning Peaks +STR_DTLS :De mooie bergen van Lightning Peaks zijn populair bij wandelaars en toeristen. Gebruik de beschikbare grond om nieuwe sensatiezoekende klanten aan te trekken. + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :Een reeds gevestigd park dat wat problemen heeft. + + +STR_SCNR :Rainbow Valley +STR_PARK :Rainbow Valley +STR_DTLS :Van de gemeenteraad van Rainbow Valley mag het landschap niet gewijzigd worden en mogen er geen grote bomen worden gekapt, maar je moet het gebied ontwikkelen tot een groot pretpark. + + +STR_SCNR :Thunder Rock +STR_PARK :Thunder Rock +STR_DTLS :Thunder Rock staat midden in een woestijn en trekt veel toeristen aan. Gebruik de beschikbare ruimte om attracties te bouwen en meer mensen aan te trekken. + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Gewoon voor de lol! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Ontwikkel het rotsgebied bij de kust tot een bloeiend pretpark. + + +STR_SCNR :Three Monkeys Park +STR_PARK :Three Monkeys Park +STR_DTLS :Het middelpunt van dit grote park in ontwikkeling is een enorme duellerende stalen achtbaan met drie banen. + + +STR_SCNR :Canary Mines +STR_PARK :Canary Mines +STR_DTLS :Deze verlaten mijn bezit, met een miniatuurspoorweg en een paar verticale achtbanen, reeds de kenmerken van een toeristische attractie. + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :Je hebt de beschikking over een oude, niet meer gebruikte brug. Verander deze in een pretpark. + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Dit park beslaat land aan beide zijden van een snelweg en beschikt reeds over enkele functionerende attracties. + + +STR_SCNR :Haunted Harbour +STR_PARK :Haunted Harbour +STR_DTLS :De gemeente is bereid het omliggende land voor een gunstige prijs te verkopen aan dit kleine kustpark, op voorwaarde dat bepaalde attracties behouden blijven. + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :Je mag dit kasteel naar eigen inzicht veranderen in een pretpark. + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :Dit futuristische park met buitenaards landschap heeft genoeg ruimte beschikbaar voor nieuwe attracties. + + +STR_SCNR :Gentle Glen +STR_PARK :Gentle Glen +STR_DTLS :De lokale bevolking heeft een voorkeur voor rustige en ontspannende attracties, dus is het je taak om dit park uit te breiden naar hun smaak. + + +STR_SCNR :Jolly Jungle +STR_PARK :Jolly Jungle +STR_DTLS :Dit grote stuk land, diep in het oerwoud, ligt klaar om te worden veranderd in een attractiepark. + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :Een aantal meren op verschillende hoogtes vormt de basis voor dit nieuwe park. + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :Dit oude park heeft veel historische attracties maar ook grote schulden. + + +STR_SCNR :Magic Quarters +STR_PARK :Magic Quarters +STR_DTLS :Een groot stuk land is al voor je ontruimd en gedeeltelijk gethematiseerd, zodat je het kunt ontwikkelen tot een themapark. + + +STR_SCNR :Fruit Farm +STR_PARK :Fruit Farm +STR_DTLS :Een bloeiende fruitplantage heeft een spoorweg gebouwd om haar inkomen te vergroten. Jouw taak is om het uit te breiden tot een bloeiend pretpark. + + +STR_SCNR :Butterfly Dam +STR_PARK :Butterfly Dam +STR_DTLS :Je mag het gebied rondom een dam ontwikkelen tot een attractiepark. + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :Je mag een enorme kloof ontwikkelen tot een attractiepark. + + +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 + + +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 + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters + + +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 + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people + + +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 + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? + + +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 + + +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 + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists + + +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 + + +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 + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :A large garden park needs turning into a thriving theme park + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :A dormant volcano is the setting of this coaster-building challenge + + +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 + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :A large lake in an ancient crater is the setting for this park + + +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 + + +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 + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :This sea-side cove is the setting for this coaster-building challenge + + +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 + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :A park which has much of its footpaths and coasters underground + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :A glacier-filled valley is yours to develop into a theme park + + +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 + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Five coasters require completion in this desert park + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :This historical park is only allowed to build older-styled rides + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Develop this alien park to maximize its profit + + +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 + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :A scary park with a giant centrepiece coaster + + +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 + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In this large park you must design and build ten large coasters + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :An icy landscape needs turning into a thriving theme park + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :A desert park with some cleverly designed coasters is yours to expand + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In this tiny park you must finish building the five existing coasters + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :A large park with a novel transporation system around its edge + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :This large island is all yours to develop as an amusement park + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :This urban area is all yours to develop into as an amusement park + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :A giant park already packed full of rides needs improving + + +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 + + +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 + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : + ## RCT2 Original -STR_SCNR :Alpine Adventures -STR_PARK :Alpine Adventures -STR_DTLS :Maak van een klein skistation in de bergen een amusementspark met een sneeuwthema. +STR_SCNR :Alpine Adventures +STR_PARK :Alpine Adventures +STR_DTLS :Maak van een klein skistation in de bergen een amusementspark met een sneeuwthema. -STR_SCNR :Amity Airfield -STR_PARK :Amity Airfield -STR_DTLS :Bouw een amusementspark met een luchtvaartthema op dit verlaten vliegveld. +STR_SCNR :Amity Airfield +STR_PARK :Amity Airfield +STR_DTLS :Bouw een amusementspark met een luchtvaartthema op dit verlaten vliegveld. -STR_SCNR :Botany Breakers -STR_PARK :Botany Breakers -STR_DTLS :Het is je uitdaging om een zeer winstgevend park te bouwen op dit paradijselijke eiland. +STR_SCNR :Botany Breakers +STR_PARK :Botany Breakers +STR_DTLS :Het is je uitdaging om een zeer winstgevend park te bouwen op dit paradijselijke eiland. -STR_SCNR :Bumbly Bazaar -STR_PARK :Bumbly Bazaar -STR_DTLS :Beginnend met een klein marktkraampje, is het je uitdaging om de winst van winkels en kraampjes te vergroten door attracties en achtbanen te bouwen en zo meer klanten te trekken. +STR_SCNR :Bumbly Bazaar +STR_PARK :Bumbly Bazaar +STR_DTLS :Beginnend met een klein marktkraampje, is het je uitdaging om de winst van winkels en kraampjes te vergroten door attracties en achtbanen te bouwen en zo meer klanten te trekken. -STR_SCNR :Crazy Castle -STR_PARK :Crazy Castle -STR_DTLS :Je hebt een groot kasteel geërfd - het is je opdracht er een klein themapark van te maken. +STR_SCNR :Crazy Castle +STR_PARK :Crazy Castle +STR_DTLS :Je hebt een groot kasteel geërfd - het is je opdracht er een klein themapark van te maken. -STR_SCNR :Dusty Greens -STR_PARK :Dusty Greens -STR_DTLS :Dusty Greens ligt aan een snelwegknooppunt in de woestijn, en is een gelegenheid om van een kleine golfbaan een succesvol themapark te maken. +STR_SCNR :Dusty Greens +STR_PARK :Dusty Greens +STR_DTLS :Dusty Greens ligt aan een snelwegknooppunt in de woestijn, en is een gelegenheid om van een kleine golfbaan een succesvol themapark te maken. -STR_SCNR :Electric Fields -STR_PARK :Electric Fields -STR_DTLS :Je hebt een kleine boerderij geërfd, en het is je uitdaging een klein themapark tussen de velden en de boerderijen te bouwen. +STR_SCNR :Electric Fields +STR_PARK :Electric Fields +STR_DTLS :Je hebt een kleine boerderij geërfd, en het is je uitdaging een klein themapark tussen de velden en de boerderijen te bouwen. -STR_SCNR :Extreme Heights -STR_PARK :Extreme Heights -STR_DTLS :Vrij van financiële beperkingen, is het je uitdaging om dit woestijnpark uit te breiden om mensen te trekken die de extreemste sensaties zoeken. +STR_SCNR :Extreme Heights +STR_PARK :Extreme Heights +STR_DTLS :Vrij van financiële beperkingen, is het je uitdaging om dit woestijnpark uit te breiden om mensen te trekken die de extreemste sensaties zoeken. -STR_SCNR :Factory Capers -STR_PARK :Factory Capers -STR_DTLS :Een verlaten fabriekscomplex is een gelegenheid om een amusementspark met een mechanisch thema te bouwen. +STR_SCNR :Factory Capers +STR_PARK :Factory Capers +STR_DTLS :Een verlaten fabriekscomplex is een gelegenheid om een amusementspark met een mechanisch thema te bouwen. -STR_SCNR :Fungus Woods -STR_PARK :Fungus Woods -STR_DTLS :Beperkt tot uitsluitend de ouderwetse houten attracties, is het je uitdaging om een succesvol themapark in Fungus Woods te bouwen. +STR_SCNR :Fungus Woods +STR_PARK :Fungus Woods +STR_DTLS :Beperkt tot uitsluitend de ouderwetse houten attracties, is het je uitdaging om een succesvol themapark in Fungus Woods te bouwen. -STR_SCNR :Ghost Town -STR_PARK :Ghost Town -STR_DTLS :Je wordt aangenomen door een grote keten van amusementsparken en het is je taak een gigantisch park met achtbanen te bouwen rond een verlaten mijnstadje. +STR_SCNR :Ghost Town +STR_PARK :Ghost Town +STR_DTLS :Je wordt aangenomen door een grote keten van amusementsparken en het is je taak een gigantisch park met achtbanen te bouwen rond een verlaten mijnstadje. -STR_SCNR :Gravity Gardens -STR_PARK :Gravity Gardens -STR_DTLS :Het is je uitdaging een park met achtbanen in de prachtige Gravity Gardens te bouwen... geen andere attracties, alleen maar achtbanen! +STR_SCNR :Gravity Gardens +STR_PARK :Gravity Gardens +STR_DTLS :Het is je uitdaging een park met achtbanen in de prachtige Gravity Gardens te bouwen... geen andere attracties, alleen maar achtbanen! -STR_SCNR :Infernal Views -STR_PARK :Infernal Views -STR_DTLS :Een park dat op een hachelijke plaats is gevestigd: op een vulkaanse, naast stromende lava. +STR_SCNR :Infernal Views +STR_PARK :Infernal Views +STR_DTLS :Een park dat op een hachelijke plaats is gevestigd: op een vulkaan, naast stromende lava. -STR_SCNR :Lucky Lake -STR_PARK :Lucky Lake -STR_DTLS :Met een onbeperkt budget, maar gesitueerd op een veeleisende locatie is het een uitdaging dit park uit te breiden en te beheren. +STR_SCNR :Lucky Lake +STR_PARK :Lucky Lake +STR_DTLS :Met een onbeperkt budget, maar gesitueerd op een veeleisende locatie is het een uitdaging dit park uit te breiden en te beheren. -STR_SCNR :Rainbow Summit -STR_PARK :Rainbow Summit -STR_DTLS :In dit park, gelegen op een heuvel, zijn hoge bouwwerken verboden. Kun je het park uitbreiden en het succesvol maken? +STR_SCNR :Rainbow Summit +STR_PARK :Rainbow Summit +STR_DTLS :In dit park, gelegen op een heuvel, zijn hoge bouwwerken verboden. Kun je het park uitbreiden en het succesvol maken? -STR_SCNR :Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Probeer dit Six Flags-park op je eigen manier te beheren en te verbeteren. +STR_SCNR :Six Flags Belgium +STR_PARK :Six Flags Belgium +STR_DTLS :Probeer dit Six Flags-park op je eigen manier te beheren en te verbeteren. -STR_SCNR :Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: meer bezoekers naar het park halen! +STR_SCNR :Six Flags Great Adventure +STR_PARK :Six Flags Great Adventure +STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: meer bezoekers naar het park halen! -STR_SCNR :Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Probeer dit Six Flags-park op je eigen manier te beheren en te verbeteren. +STR_SCNR :Six Flags Holland +STR_PARK :Six Flags Holland +STR_DTLS :Probeer dit Six Flags-park op je eigen manier te beheren en te verbeteren. -STR_SCNR :Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: je lening terugbetalen terwijl je de waarde van je park laat stijgen! +STR_SCNR :Six Flags Magic Mountain +STR_PARK :Six Flags Magic Mountain +STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: je lening terugbetalen terwijl je de waarde van je park laat stijgen! -STR_SCNR :Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: meer bezoekers naar het park halen! +STR_SCNR :Six Flags over Texas +STR_PARK :Six Flags over Texas +STR_DTLS :Bouw de ontbrekende Six Flags-attracties, of maak je eigen ontwerpen om het park te verbeteren! Maar vergeet je uiteindelijke doel niet: meer bezoekers naar het park halen! -STR_SCNR :Bouw je eigen Six Flags Belgium -STR_PARK :Six Flags Belgium -STR_DTLS :Bouw je eigen versie van dit Europese Six Flags-park. +STR_SCNR :Bouw je eigen Six Flags Belgium +STR_PARK :Six Flags Belgium +STR_DTLS :Bouw je eigen versie van dit Europese Six Flags-park. -STR_SCNR :Bouw je eigen Six Flags Great Adventure -STR_PARK :Six Flags Great Adventure -STR_DTLS :Gebruik je ontwerpvaardigheden om dit Six Flags-park opnieuw te maken. +STR_SCNR :Bouw je eigen Six Flags Great Adventure +STR_PARK :Six Flags Great Adventure +STR_DTLS :Gebruik je ontwerpvaardigheden om dit Six Flags-park opnieuw te maken. -STR_SCNR :Bouw je eigen Six Flags Holland -STR_PARK :Six Flags Holland -STR_DTLS :Bouw je eigen versie van dit Europese Six Flags-park. +STR_SCNR :Bouw je eigen Six Flags Holland +STR_PARK :Six Flags Holland +STR_DTLS :Bouw je eigen versie van dit Europese Six Flags-park. -STR_SCNR :Bouw je eigen Six Flags Magic Mountain -STR_PARK :Six Flags Magic Mountain -STR_DTLS :Maak je eigen versie van dit enorme Six Flags-park. +STR_SCNR :Bouw je eigen Six Flags Magic Mountain +STR_PARK :Six Flags Magic Mountain +STR_DTLS :Maak je eigen versie van dit enorme Six Flags-park. -STR_SCNR :Bouw je eigen Six Flags over Texas -STR_PARK :Six Flags over Texas -STR_DTLS :Maak je eigen versie van dit Six Flags-park. +STR_SCNR :Bouw je eigen Six Flags over Texas +STR_PARK :Six Flags over Texas +STR_DTLS :Maak je eigen versie van dit Six Flags-park. -STR_SCNR :Bouw je eigen Six Flags-park -STR_PARK :Six Flags -STR_DTLS :Maak je eigen Six Flags-park, door gebruik te maken van attracties uit andere Six Flags-parken of door zelf nieuwe attracties te ontwerpen. +STR_SCNR :Bouw je eigen Six Flags-park +STR_PARK :Six Flags +STR_DTLS :Maak je eigen Six Flags-park, door gebruik te maken van attracties uit andere Six Flags-parken of door zelf nieuwe attracties te ontwerpen. #TT -STR_SCNR : Mythologie - Animatronic-filmset -STR_PARK :Animatronic Antics -STR_DTLS :Je moet een bestaand pretpark, gebouwd op een oude filmset, beheren en verbeteren. Bouw een eerbetoon aan de pioniers van de stop-motionanimatie, die de wezens uit de mythologie tot leven brachten op het witte doek. +STR_SCNR : Mythologie - Animatronic-filmset +STR_PARK :Animatronic Antics +STR_DTLS :Je moet een bestaand pretpark, gebouwd op een oude filmset, beheren en verbeteren. Bouw een eerbetoon aan de pioniers van de stop-motionanimatie, die de wezens uit de mythologie tot leven brachten op het witte doek. ################################## # Rides/attractions / Attracties # @@ -4061,23 +4687,23 @@ STR_DTLS :Je moet een bestaand pretpark, gebouwd op een oude filmset, beheren # 3D Cinema / 3d-bioscoop [C3D] -STR_NAME :3D-bioscoop -STR_DESC :Bioscoop in een bolvormig gebouw waarin 3D-films worden getoond. -STR_CPTY :20 passagiers +STR_NAME :3D-bioscoop +STR_DESC :Bioscoop in een bolvormig gebouw waarin 3D-films worden getoond. +STR_CPTY :20 passagiers # End of 3D Cinema / 3d-bioscoop # Mine Ride / Aangedreven mijntrein [PMT1] -STR_NAME :Aangedreven mijntrein -STR_DESC :Aangedreven mijntreinen rijden over een soepele en kronkelende baan. -STR_CPTY :4 passagiers per karretje (voorste karretje 2) +STR_NAME :Aangedreven mijntrein +STR_DESC :Aangedreven mijntreinen rijden over een soepele en kronkelende baan. +STR_CPTY :4 passagiers per karretje (voorste karretje 2) # End of Mine Ride / Aangedreven mijntrein # Reverse Freefall Coaster / Achterwaartsevrijevalachtbaan [REVF1] -STR_NAME :Wagen voor achterwaartse vrije val -STR_DESC :Grote wagen voor de achterwaartstevrijevalachtbaan. -STR_CPTY :8 passagiers +STR_NAME :Wagen voor achterwaartse vrije val +STR_DESC :Grote wagen voor de achterwaartstevrijevalachtbaan. +STR_CPTY :8 passagiers #WW [KOLARIDE] @@ -4094,34 +4720,34 @@ STR_CPTY :8 passagiers # Car Ride / Autorondrit [TRUCK1] -STR_NAME :Pickuptrucks -STR_DESC :Elektrische voertuigen in de vorm van een pickuptruck. -STR_CPTY :1 passagier per truck +STR_NAME :Pickuptrucks +STR_DESC :Elektrische voertuigen in de vorm van een pickuptruck. +STR_CPTY :1 passagier per truck [RCR] -STR_NAME :Raceauto's -STR_DESC :Elektrische voertuigen in de vorm van een raceauto. -STR_CPTY :1 passagier per karretje +STR_NAME :Raceauto's +STR_DESC :Elektrische voertuigen in de vorm van een raceauto. +STR_CPTY :1 passagier per karretje [SPCAR] -STR_NAME :Sportauto's -STR_DESC :Elektrische voertuigen in de vorm van een sportauto. -STR_CPTY :1 passagier per karretje +STR_NAME :Sportauto's +STR_DESC :Elektrische voertuigen in de vorm van een sportauto. +STR_CPTY :1 passagier per karretje [VCR] -STR_NAME :Oldtimers -STR_DESC :Elektrische voertuigen in de vorm van een oldtimer. -STR_CPTY :1 passagier per karretje +STR_NAME :Oldtimers +STR_DESC :Elektrische voertuigen in de vorm van een oldtimer. +STR_CPTY :1 passagier per karretje [CTCAR] -STR_NAME :Cheshire Cats -STR_DESC :Elektrische voertuigen in de vorm van een kat. -STR_CPTY :1 passagier per karretje +STR_NAME :Cheshire Cats +STR_DESC :Elektrische voertuigen in de vorm van een kat. +STR_CPTY :1 passagier per karretje [4X4] -STR_NAME :Monstertrucks -STR_DESC :Gigantische elektrische 4x4-trucks die steile hellingen kunnen nemen. -STR_CPTY :2 passagiers per truck +STR_NAME :Monstertrucks +STR_DESC :Gigantische elektrische 4x4-trucks die steile hellingen kunnen nemen. +STR_CPTY :2 passagiers per truck #WW [CRNVBFLY] @@ -4168,27 +4794,27 @@ STR_CPTY :2 passagiers per karretje # Motion Simulator / Bewegingssimulator [SIMPOD] -STR_NAME :Bewegingssimulator -STR_DESC :Passagiers bekijken een film in de cabine van een bewegingssimulator die wordt gedraaid en bewogen door een hydraulische arm. -STR_CPTY :8 passagiers +STR_NAME :Bewegingssimulator +STR_DESC :Passagiers bekijken een film in de cabine van een bewegingssimulator die wordt gedraaid en bewogen door een hydraulische arm. +STR_CPTY :8 passagiers #TT [MICROBUS] -STR_NAME :Hippiebus -STR_DESC :Passagiers bekijken een film in de cabine van een bewegingssimulator die wordt gedraaid en bewogen door een hydraulische arm. -STR_CPTY :8 passagiers +STR_NAME :Hippiebus +STR_DESC :Passagiers bekijken een film in de cabine van een bewegingssimulator die wordt gedraaid en bewogen door een hydraulische arm. +STR_CPTY :8 passagiers # End of Motion Simulator / Bewegingssimulator # Bobsleigh Coaster / Bobslee-achtbaan [BOB1] -STR_NAME :Bobslee-achtbaan -STR_DESC :Passagiers rijden over een kronkelende baan, waarbij ze enkel worden geleid door de ronding en banking van de halfronde baan. -STR_CPTY :2 passagiers per karretje +STR_NAME :Bobslee-achtbaan +STR_DESC :Passagiers rijden over een kronkelende baan, waarbij ze enkel worden geleid door de ronding en banking van de halfronde baan. +STR_CPTY :2 passagiers per karretje [INTBOB] -STR_NAME :Zespersoonsbob -STR_DESC :Passagiers rijden over een kronkelende baan, waarbij ze enkel worden geleid door de ronding en banking van de halfronde baan. -STR_CPTY :6 passagiers per bob +STR_NAME :Zespersoonsbob +STR_DESC :Passagiers rijden over een kronkelende baan, waarbij ze enkel worden geleid door de ronding en banking van de halfronde baan. +STR_CPTY :6 passagiers per bob #WW [PENGUINB] @@ -4205,47 +4831,47 @@ STR_CPTY :2 passagiers per karretje # Log Flume / Boomstamattractie [LFB1] -STR_NAME :Boomstamattractie -STR_DESC :Boten in de vorm van een boomstam varen door een waterbak, waarbij ze van steile hellingen afdalen om de passagiers te doorweken. -STR_CPTY :4 passagiers per boot +STR_NAME :Boomstamattractie +STR_DESC :Boten in de vorm van een boomstam varen door een waterbak, waarbij ze van steile hellingen afdalen om de passagiers te doorweken. +STR_CPTY :4 passagiers per boot #WW [CROCFLUM] -STR_NAME :Krokillenrivier +STR_NAME :Krokodillenrivier STR_DESC :Boten in de vorm van een krokodil varen door een waterbak, waarbij ze van steile hellingen afdalen om de passagiers te doorweken. STR_CPTY :4 passagiers per boot # End of Log Flume / Boomstamattractie # Boat Ride / Bootverhuur [RBOAT] -STR_NAME :Roeiboten -STR_DESC :Boten waarin passagiers zelf roeien. -STR_CPTY :2 passagiers per boot +STR_NAME :Roeiboten +STR_DESC :Boten waarin passagiers zelf roeien. +STR_CPTY :2 passagiers per boot [BBOAT] -STR_NAME :Botsboten -STR_DESC :Kleine ronde bootjes, aangedreven door een centrale motor en bestuurd door de passagiers. -STR_CPTY :2 passagiers per boot +STR_NAME :Botsboten +STR_DESC :Kleine ronde bootjes, aangedreven door een centrale motor en bestuurd door de passagiers. +STR_CPTY :2 passagiers per boot [JSKI] -STR_NAME :Jetski's -STR_DESC :Eénpersoons jetski's die de bezoekers zelf kunnen besturen. -STR_CPTY :1 persoon per jetski +STR_NAME :Jetski's +STR_DESC :Eénpersoons jetski's die de bezoekers zelf kunnen besturen. +STR_CPTY :1 persoon per jetski [CBOAT] -STR_NAME :Kano's -STR_DESC :Lange kano's waarin de passagiers zelf roeien. -STR_CPTY :2 passagiers per kano +STR_NAME :Kano's +STR_DESC :Lange kano's waarin de passagiers zelf roeien. +STR_CPTY :2 passagiers per kano [TRIKE] -STR_NAME :Waterfietsen -STR_DESC :Driewielige waterfietsen met grote raderwielen. -STR_CPTY :2 passagiers per waterfiets +STR_NAME :Waterfietsen +STR_DESC :Driewielige waterfietsen met grote raderwielen. +STR_CPTY :2 passagiers per waterfiets [SWANS] -STR_NAME :Zwanenbootjes -STR_DESC :Boten in de vorm van een zwaan, voortgestuwd door het trappen van de passagiers op de eerste rij. -STR_CPTY :4 passagiers per boot +STR_NAME :Zwanenbootjes +STR_DESC :Boten in de vorm van een zwaan, voortgestuwd door het trappen van de passagiers op de eerste rij. +STR_CPTY :4 passagiers per boot #WW [DOLPHINR] @@ -4274,21 +4900,21 @@ STR_CPTY :4 passagiers per boot #WW [DHOWWATR] STR_NAME :Dhowbootjes -STR_DESC :Decoratieve visserboot waarbij de passagiers zelf trappen. +STR_DESC :Decoratieve vissersboot waarbij de passagiers zelf trappen. STR_CPTY :2 passagiers per boot #CC [AE-SWIM] STR_NAME :Zwembad -STR_DESC :Een steiger waarvan gasten het water in kunnen om een stukje te zwemmen. Door "The Amazing Earl". +STR_DESC :Een steiger waarvan bezoekers het water in kunnen om een stukje te zwemmen. Door "The Amazing Earl". STR_CPTY :1 bezoeker per "boot" # End of Boat Ride / Bootverhuur # Dodgems / Botsauto's [DODG1] -STR_NAME :Botsauto's -STR_DESC :Elektrische wagentjes die de passagiers zelf besturen. -STR_CPTY :1 passagier per botsauto +STR_NAME :Botsauto's +STR_DESC :Elektrische wagentjes die de passagiers zelf besturen. +STR_CPTY :1 passagier per botsauto #TT [TRICATOP] @@ -4305,26 +4931,26 @@ STR_CPTY :1 passagier per botsauto # Circus [CIRCUS1] -STR_NAME :Circus -STR_DESC :Een dierennummer in een circustent. -STR_CPTY :30 bezoekers +STR_NAME :Circus +STR_DESC :Een dierennummer in een circustent. +STR_CPTY :30 bezoekers # End of Circus # Compact Inverted Coaster / Compacte omgekeerde achtbaan [SLCT] -STR_NAME :Compacte omgekeerde achtbaan -STR_DESC :Passagiers zitten in stoelparen die onder de baan hangen terwijl ze door kronkelende en scherpe omkeringen gaan. -STR_CPTY :2 passagiers per karretje +STR_NAME :Compacte omgekeerde achtbaan +STR_DESC :Passagiers zitten in stoelparen die onder de baan hangen terwijl ze door kronkelende en scherpe omkeringen gaan. +STR_CPTY :2 passagiers per karretje [VEKDV] -STR_NAME :Omgekeerde verticale shuttle -STR_DESC :Passagiers zitten in karretjes die onder de baan hangen, worden achteruit een verticale baan opgetrokken en vervolgens losgelaten, waarna ze door kronkelende en scherpe omkeringen gaan. -STR_CPTY :4 passagiers per karretje +STR_NAME :Omgekeerde verticale shuttle +STR_DESC :Passagiers zitten in karretjes die onder de baan hangen, worden achteruit een verticale baan opgetrokken en vervolgens losgelaten, waarna ze door kronkelende en scherpe omkeringen gaan. +STR_CPTY :4 passagiers per karretje [SLCFO] -STR_NAME :Omgekeerde shuttle -STR_DESC :Passagiers zitten in stoelparen die onder de baan hangen terwijl ze door kronkelende en scherpe omkeringen gaan. -STR_CPTY :4 passagiers per karretje +STR_NAME :Omgekeerde shuttle +STR_DESC :Passagiers zitten in stoelparen die onder de baan hangen terwijl ze door kronkelende en scherpe omkeringen gaan. +STR_CPTY :4 passagiers per karretje #WW [POLARBER] @@ -4564,7 +5190,7 @@ STR_CPTY :4 passagiers per karretje #TT [GANSTRCR] STR_NAME :Gangsterauto-achtbaan -STR_DESC :Achtbaantreinen in de stijl van een gansterauto uit de jaren '20 worden door lineaire inductiemotoren het station uit gelanceerd en razen door een kronkelende baan die vaak over de kop gaat. +STR_DESC :Achtbaantreinen in de stijl van een gangsterauto uit de jaren '20 worden door lineaire inductiemotoren het station uit gelanceerd en razen door een kronkelende baan die vaak over de kop gaat. STR_CPTY :4 passagiers per karretje # End of LIM Launched RC / LIM-lanceringsachtbaan @@ -4646,7 +5272,7 @@ STR_CPTY :4 passagiers per karretje [JAGUARRD] STR_NAME :Jaguarkarretjes STR_DESC :Achtbaankarretjes in de vorm van een jaguar. -STR_CPTY 4 passagiers per karretje +STR_CPTY :4 passagiers per karretje #WW [LIONRIDE] @@ -4715,16 +5341,16 @@ STR_CPTY :10 passagiers per bus # Mini Golf / Minigolf [GOLF1] -STR_NAME :Miniholf +STR_NAME :Minigolf STR_DESC :Een rustig spelletje minigolf. # End of Mini Golf / Minigolf -# Mini Helicopters / Minihelicopters +# Mini helicopters / Minihelikopters [HELICAR] -STR_NAME :Minihelicopters -STR_DESC :Aangedreven karretjes in de vorm van een helicopter rijden over een stalen baan, bestuurd door het trappen van de passagiers. +STR_NAME :Minihelikopters +STR_DESC :Aangedreven karretjes in de vorm van een helikopter rijden over een stalen baan, bestuurd door het trappen van de passagiers. STR_CPTY :2 passagiers per karretje -# End of Mini Helicopters / Minihelicopters +# End of Mini helicopters / Minihelikopters # Monorail [MONO1] @@ -4810,7 +5436,7 @@ STR_CPTY :4 passagiers per karretje #TT [PTERODAC] STR_NAME :Pterodactyl Coaster -STR_DESC :Bezoekers hangen in confortabele treinen onder de baan met enkel schouderbeugels en krijgen zo de ultieme prehistorische vliegervaring. +STR_DESC :Bezoekers hangen in comfortabele treinen onder de baan met enkel schouderbeugels en krijgen zo de ultieme prehistorische vliegervaring. STR_CPTY :4 passagiers per karretje # End of Flying RC / Vliegachtbaan @@ -4840,7 +5466,7 @@ STR_CPTY :2 passagiers per karretje #TT [HOVRBORD] STR_NAME :Hoverboard Coaster -STR_DESC :Passagiers zitten op een futurisch hoverboard die onder een enkele rail hangt en naar buiten zwaait in de bochten. +STR_DESC :Passagiers zitten op een futuristisch hoverboard dat onder een enkele rail hangt en naar buiten zwaait in de bochten. STR_CPTY :2 passagiers per karretje # End of Inverted Mini RC / Omgekeerde mini-achtbaan @@ -4989,9 +5615,9 @@ STR_DESC :Groot schommelend piratenschip STR_CPTY :16 passagiers # End of Swinging ship / Schommelschip -# Swinging Inverter Ship / Schommelschip dat over de kop gaat +# Swinging Inverter Ship / Loopingschip [SWSH2] -STR_NAME :Schommelschip dat over de kop gaat +STR_NAME :Loopingschip STR_DESC :Schip dat is bevestigd aan een arm met een contragewicht, en 360 graden kan draaien. STR_CPTY :12 passagiers @@ -5000,7 +5626,7 @@ STR_CPTY :12 passagiers STR_NAME :Chinese jonk STR_DESC :Chinese jonk die is bevestigd aan een arm met een contragewicht, en 360 graden kan draaien. STR_CPTY :12 passagiers -# End of Swinging Inverter Ship / Schommelschip dat over de kop gaat +# End of Swinging Inverter Ship / Loopingschip # Spiral RC / Spiraalachtbaan [SPDRCR] @@ -5161,7 +5787,7 @@ STR_CPTY :4 passagiers per karretje #TT [CERBERUS] STR_NAME :Cerberusbaan -STR_DESC :Bezoekers zitten in comfortabele treinen met enkel eenvoudige schootbeugels terwijl ze door door soepele afdalingen gaan. +STR_DESC :Bezoekers zitten in comfortabele treinen met enkel eenvoudige schootbeugels terwijl ze door soepele afdalingen gaan. STR_CPTY :4 passagiers per karretje # End of Steel Twister RC / Stalen twisterachtbaan @@ -5174,7 +5800,7 @@ STR_CPTY :2 passagiers per paard [STEEP2] STR_NAME :Motorfietsrace STR_DESC :Passagiers zitten op voertuigen in de vorm van een motorgiets die over een enkele rail lopen. -STR_CPTY :2 rassagiers per motorfiets +STR_CPTY :2 passagiers per motorfiets [SBOX] STR_NAME :Zeepkistenrace @@ -5268,7 +5894,7 @@ STR_CPTY :18 passagiers #TT [DINOEGGS] -STR_NAME :Dinosaurei-twist +STR_NAME :Dinosaurusei-twist STR_DESC :Passagiers zitten per twee in stoelen die rond een bewegende moederdinosaurus draaien. STR_CPTY :18 passagiers @@ -5545,7 +6171,7 @@ STR_DESC :Een kraam met Neptunus' zoute lekkernijen. # Drink stalls [COFFS] STR_NAME :Koffiewinkel -STR_DESC :Een winkel in art-decostijl waar kopjes koffie worden verkocht. +STR_DESC :Een winkel in artdecostijl waar kopjes koffie worden verkocht. [CINDR] STR_NAME :Sujeonggwakraam @@ -5583,7 +6209,7 @@ STR_DESC :Een marktkraam waar ouderwetse, frisse limonade wordt verkocht. #TT [MOONJUCE] STR_NAME :Maansap -STR_DESC :Een waar de nieuwste soorten frisdrank worden verkocht. +STR_DESC :Een kraam waar de nieuwste soorten frisdrank worden verkocht. # End of Drink stalls # Shops @@ -5610,7 +6236,7 @@ STR_DESC :Een souvenirkraam waar knuffels en paraplu's worden verkocht. #TT [SOFTOYST] STR_NAME :Knuffelkraam -STR_DESC :Een kraam waar schattige zachtige dinosaurusknuffels worden verkocht. +STR_DESC :Een kraam waar schattige zachte dinosaurusknuffels worden verkocht. #TT [1960TSRT] @@ -5631,12 +6257,12 @@ STR_DESC :Toiletten in een gebouw in blokhutstijl. # Information Kiosks [INFOK] STR_NAME :Informatiekiosk -STR_DESC :Een kiosk waar gasten kaarten van het park en paraplu's kunnen kopen. +STR_DESC :Een kiosk waar bezoekers kaarten van het park en paraplu's kunnen kopen. #CC [INFO1MKY] STR_NAME :Informatiekiosk -STR_DESC :Een kiosk waar gasten kaarten van het park en paraplu's kunnen kopen. +STR_DESC :Een kiosk waar bezoekers kaarten van het park en paraplu's kunnen kopen. # End of Information Kiosks @@ -5649,7 +6275,7 @@ STR_DESC :Een geldautomaat die de bezoekers kunnen gebruiken als ze bijna doo # First Aid [FAID1] STR_NAME :Eerste hulp -STR_DESC :Een gebouw waar misselijke gasten sneller kunnen opknappen. +STR_DESC :Een gebouw waar misselijke bezoekers sneller kunnen opknappen. # End of First Aid ################################# @@ -5703,7 +6329,7 @@ STR_NAME :Futuristische parkingang #TT [GLDYRENT] -STR_NAME :Parkingang in 'rock 'n' roll'-stijl +STR_NAME :Parkingang in 'rock 'n roll'-stijl #TT [JURASENT] @@ -5786,7 +6412,7 @@ STR_NAME :Houten voetpad #TT [MYTHPATH] -STR_NAME :Mozaiek-voetpad +STR_NAME :Mozaïek-voetpad #TT [RANBPATH] @@ -5921,7 +6547,7 @@ STR_NAME : 'Roaring Twenties'-muren #TT [SCG1960S] -STR_NAME : 'Rock 'n' roll'-thema +STR_NAME : 'Rock 'n roll'-thema #TT [SCGFUTUR] @@ -5939,6 +6565,56 @@ STR_NAME : 'Donkere eeuwen'-thema [SCGMYTHO] STR_NAME : Mythologisch thema +################# +# Small objects # +################# +[BRBASE] +STR_NAME :Basisblok + +[BRBASE2] +STR_NAME :Basisblok + +[BRBASE3] +STR_NAME :Basisblok + +[TAL] +STR_NAME :Boom in alligatorvorm + +[TCB] +STR_NAME :Klaverenboom + +[TDF] +STR_NAME :Dolfijnenfontein + +[TDM] +STR_NAME :Ruitenboom + +[TEF] +STR_NAME :Olifantenfontein + +[TGS] +STR_NAME :Giraffenstandbeeld + +[THRS] +STR_NAME :Ruiterstandbeeld + +[THT] +STR_NAME :Hartenboom + +[TQF] +STR_NAME :Cupidofonteinen + +[TSD] +STR_NAME :Schoppenboom + +[TSH] +STR_NAME :Paardenstandbeeld + +[TSTD] +STR_NAME :Dolfijnenstandbeeld + +[TUS] +STR_NAME :Eenhoornstandbeeld ################# # Large objects # ################# @@ -5957,9 +6633,129 @@ STR_NAME :Rijtjeshuis ######### # Walls # ######### +[WALLBB34] +STR_NAME :Stenen muur + +[WALLCBPC] +STR_NAME :Muur met valhek + +[WALLCFAR] +STR_NAME :Muur met boog + +[WALLCFPC] +STR_NAME :Muur met valhek + +[WALLCO16] +STR_NAME :Geplooide stalen muur + +[WALLIG16] +STR_NAME :Iglomuur + +[WALLIG24] +STR_NAME :Iglomuur + +[WALLJB16] +STR_NAME :Muur van zuurtjes + +[WALLLT32] +STR_NAME :Stalen traliewerk + +[WALLNT32] +STR_NAME :Tennisnetmuur + +[WALLNT33] +STR_NAME :Tennisnetmuur + +[WALLPOST] +STR_NAME :Paal + +[WALLST16] +STR_NAME :Stalen muur + +[WALLST32] +STR_NAME :Stalen muur + +[WALLST8] +STR_NAME :Stalen muur + +[WALLSTFN] +STR_NAME :Stalen hek + [WALLTXGT] STR_NAME :'Texas Giant'-bord +[WALLWDPS] +STR_NAME :Hek van houten palen + +[WBR2] +STR_NAME :Stenen muur + +[WBR2A] +STR_NAME :Stenen muur + +[WBR3] +STR_NAME :Stenen muur + +[WC3] +STR_NAME :Romeinse zuilenmuur + +[WC16] +STR_NAME :Besneeuwd hek + +[WC17] +STR_NAME :Besneeuwde houten schutting + +[WC18] +STR_NAME :Besneeuwd hek van houten palen + +[WBW] +STR_NAME :Hek van botten + +[WCW1] +STR_NAME :Muur van speelkaarten + +[WCW2] +STR_NAME :Muur van speelkaarten + +[WEW] +STR_NAME :Egyptische muur + +[WFW1] +STR_NAME :Houten schutting + +[WFWG] +STR_NAME :Houten schutting + +[WJF] +STR_NAME :Junglehek + +[WMW] +STR_NAME :Muur in Marsstijl + +[WMWW] +STR_NAME :Houten hek + +[WPW1] +STR_NAME :Hek van houten palen + +[WPW2] +STR_NAME :Hek van houten palen + +[WPW3] +STR_NAME :Houten hek + +[WRW] +STR_NAME :Romeinse muur + +[WRWA] +STR_NAME :Romeinse muur + +[WWTW] +STR_NAME :Hoog houten hek + +[WWTWA] +STR_NAME :Houten hek + ################## # Path additions # ################## diff --git a/data/language/english_uk.txt b/data/language/english_uk.txt index 1c03cb38e3..3277ca754e 100644 --- a/data/language/english_uk.txt +++ b/data/language/english_uk.txt @@ -1779,7 +1779,7 @@ STR_1773 :Only one on-ride photo section allowed per ride STR_1774 :Only one cable lift hill allowed per ride STR_1775 :Off STR_1776 :On -STR_1777 :{WINDOW_COLOUR_2}Music +STR_1777 :{WINDOW_COLOUR_2}Ride music STR_1778 :{STRINGID} - - STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Panda costume STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tiger costume @@ -2364,7 +2364,7 @@ STR_2356 :{WINDOW_COLOUR_2}Rides inspected: {BLACK}{COMMA16} STR_2357 :House STR_2358 :Units STR_2359 :Real Values -STR_2360 :{WINDOW_COLOUR_2}Display Resolution: +STR_2360 :Display Resolution: STR_2361 :Landscape Smoothing STR_2362 :{SMALLFONT}{BLACK}Toggle landscape tile edge smoothing on/off STR_2363 :Gridlines on Landscape @@ -2689,7 +2689,7 @@ STR_2680 :All research complete STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} STR_2682 : STR_2683 : -STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive +STR_2684 :{SMALLFONT}{BLACK}Large group of guests arrive STR_2685 :Simplex Noise Parameters STR_2686 :{WINDOW_COLOUR_2}Low: STR_2687 :{WINDOW_COLOUR_2}High: @@ -2763,8 +2763,8 @@ STR_2753 :Mowed grass STR_2754 :Water plants STR_2755 :Fix vandalism STR_2756 :Remove litter -STR_2757 :Force Sun -STR_2758 :Force Thunder +STR_2757 : +STR_2758 : STR_2759 :Zero Clearance STR_2760 :+{CURRENCY} STR_2761 : @@ -2781,7 +2781,7 @@ STR_2771 :Slower Gamespeed STR_2772 :Faster Gamespeed STR_2773 :Windowed STR_2774 :Fullscreen -STR_2775 :Fullscreen (desktop) +STR_2775 :Fullscreen (borderless window) STR_2776 :Language: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} @@ -3331,7 +3331,7 @@ STR_3320 :Unable to save scenario file... STR_3321 :New objects installed successfully STR_3322 :{WINDOW_COLOUR_2}Objective: {BLACK}{STRINGID} STR_3323 :Missing object data, ID: -STR_3324 :Requires Add-On Pack: +STR_3324 :Requires Add-On Pack: {STRINGID} STR_3325 :Requires an Add-On Pack STR_3326 :{WINDOW_COLOUR_2}(no image) STR_3327 :Starting positions for people not set @@ -3465,7 +3465,7 @@ STR_5123 :Renew rides STR_5124 : STR_5125 :All destructable STR_5126 :Random title music -STR_5127 :{SMALLFONT}{BLACK}Disable land elevation +STR_5127 :{SMALLFONT}{BLACK}While dragging, paint landscape instead of changing elevation STR_5128 :Selection size STR_5129 :Enter selection size between {COMMA16} and {COMMA16} STR_5130 :Map size @@ -3475,7 +3475,7 @@ STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights STR_5136 :Land rights -STR_5137 :Allow lift hill and launch speeds{NEWLINE}up to {VELOCITY} +STR_5137 :Unlock operating limits STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} STR_5140 :Disable brakes failure @@ -3503,19 +3503,19 @@ STR_5161 :Date Format: STR_5162 :Day/Month/Year STR_5163 :Month/Day/Year STR_5164 :Twitch Channel name -STR_5165 :Name peeps after followers -STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers -STR_5167 :Track follower peeps +STR_5165 :Name guests after followers +STR_5166 :{SMALLFONT}{BLACK}Will name guests after channel's Twitch followers +STR_5167 :Track follower guests STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers -STR_5169 :Name peeps after people in Twitch chat -STR_5170 :{SMALLFONT}{BLACK}Will name peeps after people in Twitch chat -STR_5171 :Track chat peeps +STR_5169 :Name guests after people in Twitch chat +STR_5170 :{SMALLFONT}{BLACK}Will name guests after people in Twitch chat +STR_5171 :Track chat guests STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants STR_5173 :Pull Twitch chat as news STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications STR_5175 :Input the name of your Twitch channel STR_5176 :Enable Twitch integration -STR_5177 :Fullscreen mode: +STR_5177 :Screen mode: STR_5178 :{SMALLFONT}{BLACK}Show financial cheats STR_5179 :{SMALLFONT}{BLACK}Show guest cheats STR_5180 :{SMALLFONT}{BLACK}Show park cheats @@ -3569,7 +3569,7 @@ STR_5227 :Save Overwrite Prompt STR_5228 :{SMALLFONT}{BLACK}Main UI STR_5229 :{SMALLFONT}{BLACK}Park STR_5230 :{SMALLFONT}{BLACK}Tools -STR_5231 :{SMALLFONT}{BLACK}Rides and Peeps +STR_5231 :{SMALLFONT}{BLACK}Rides and Guests STR_5232 :{SMALLFONT}{BLACK}Editors STR_5233 :{SMALLFONT}{BLACK}Miscellaneous STR_5234 :{SMALLFONT}{BLACK}Prompts @@ -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 @@ -3894,7 +3894,7 @@ STR_5552 :{POP16}{POP16}Year {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {M STR_5553 :Pause game when Steam overlay is open STR_5554 :{SMALLFONT}{BLACK}Enable mountain tool STR_5555 :Show vehicles from other track types -STR_5556 :Kick Player +STR_5556 :{SMALLFONT}{BLACK}Kick player STR_5557 :Stay connected after desynchronisation (Multiplayer) STR_5558 :A restart is required for this setting to take effect STR_5559 :10 min. inspections @@ -3919,6 +3919,635 @@ STR_5577 :South Korean Won (W) STR_5578 :Russian Rouble (R) STR_5579 :Window scale factor: STR_5580 :Czech koruna (Kc) +STR_5581 :Show FPS +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 :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... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Money spent: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Commands ran: {BLACK}{COMMA16} +STR_5637 :Can't do this... +STR_5638 :Permission denied +STR_5639 :{SMALLFONT}{BLACK}Show list of players +STR_5640 :{SMALLFONT}{BLACK}Manage groups +STR_5641 :Default Group: +STR_5642 :Group: +STR_5643 :Add Group +STR_5644 :Remove Group +STR_5645 :Chat +STR_5646 :Terraform +STR_5647 :Toggle Pause +STR_5648 :Set Water Level +STR_5649 :Create Ride +STR_5650 :Remove Ride +STR_5651 :Build Ride +STR_5652 :Ride Properties +STR_5653 :Scenery +STR_5654 :Path +STR_5655 :Guest +STR_5656 :Staff +STR_5657 :Park Properties +STR_5658 :Park Funding +STR_5659 :Kick Player +STR_5660 :Modify Groups +STR_5661 :Set Player Group +STR_5662 :N/A +STR_5663 :Clear Landscape +STR_5664 :Cheat +STR_5665 :Toggle Scenery Cluster +STR_5701 :{WINDOW_COLOUR_2}Last action: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Locate player's most recent action +STR_5703 :Can't kick the host +STR_5704 :Last Action: +STR_5705 :Can't set to this group +STR_5706 :Can't remove group that players belong to +STR_5707 :This group cannot be modified +STR_5708 :Can't change the group that the host belongs to +STR_5709 :Rename Group +STR_5710 :Group name +STR_5711 :Enter new name for this group: +STR_5712 :Can't modify permission that you do not have yourself +STR_5713 :Kick Player +STR_5714 :Show options window +STR_5715 :New Game +STR_5716 :Not allowed in multiplayer mode +# For identifying client network version in server list window +STR_5717 :Network version: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Network version: {STRING} +STR_5719 :Sunny +STR_5720 :Partially Cloudy +STR_5721 :Cloudy +STR_5722 :Rain +STR_5723 :Heavy Rain +STR_5724 :Thunderstorm +STR_5725 :{BLACK}Force weather: +STR_5726 :{SMALLFONT}{BLACK}Sets the current weather in park +STR_5727 :Scaling quality +STR_5728 :Requires hardware display option +STR_5729 :{SMALLFONT}{BLACK}Requires hardware display option +STR_5730 :Nearest neighbour +STR_5731 :Linear +STR_5732 :Anisotropic +STR_5733 :Use NN scaling at integer scales +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Rendering +STR_5735 :Network Status +STR_5736 :Player +STR_5737 :Closed, {COMMA16} person still on ride +STR_5738 :Closed, {COMMA16} people still on ride +STR_5739 :{WINDOW_COLOUR_2}Customers on ride: {BLACK}{COMMA16} +STR_5740 :Never-ending marketing campaigns +STR_5741 :{SMALLFONT}{BLACK}Marketing campaigns never end +STR_5742 :Authenticating ... +STR_5743 :Connecting ... +STR_5744 :Resolving ... +STR_5745 :Network desync detected +STR_5746 :Disconnected +STR_5747 :Disconnected: {STRING} +STR_5748 :Kicked +STR_5749 :Get out of the server! +STR_5750 :Connection Closed +STR_5751 :No Data +STR_5752 :{OUTLINE}{RED}{STRING} has disconnected +STR_5753 :{OUTLINE}{RED}{STRING} has disconnected ({STRING}) +STR_5754 :Bad Player Name +STR_5755 :Incorrect Software Version +STR_5756 :Bad Password +STR_5757 :Server Full +STR_5758 :{OUTLINE}{GREEN}{STRING} has joined the game +STR_5759 :Downloading map ... ({INT32} / {INT32}) +STR_5760 :Hong Kong Dollars (HK$) +STR_5761 :New Taiwan Dollar (NT$) +STR_5762 :Chinese Yuan (CN{YEN}) +STR_5763 :All files +STR_5764 :Invalid ride type +STR_5765 :Cannot edit rides of invalid type +STR_5766 : +STR_5767 :Income +STR_5768 :Total customers +STR_5769 :Total profit +STR_5770 :Customers per hour +STR_5771 :Running cost +STR_5772 :Age +STR_5773 :Total customers: {COMMA32} +STR_5774 :Total profit: {CURRENCY2DP} +STR_5775 :Customers: {COMMA32} per hour +STR_5776 :Built: This Year +STR_5777 :Built: Last Year +STR_5778 :Built: {COMMA16} Years Ago +STR_5779 :Income: {CURRENCY2DP} per hour +STR_5780 :Running cost: {CURRENCY2DP} per hour +STR_5781 :Running cost: Unknown +STR_5782 :You are now connected. Press '{STRING}' to chat. +STR_5783 :{WINDOW_COLOUR_2}Scenario Locked +STR_5784 :{BLACK}Complete earlier scenarios to unlock this scenario. +STR_5785 :Can't rename group... +STR_5786 :Invalid group name +STR_5787 :{COMMA32} players online +STR_5788 :Default inspection interval: +STR_5789 :Disable lightning effect +STR_5790 :{SMALLFONT}{BLACK}Toggles RCT1-style pricing{NEWLINE}(e.g. both ride price and entrance price) +STR_5791 :{SMALLFONT}{BLACK}Sets the reliability of all rides to 100%{NEWLINE}and resets their built date to "this year" +STR_5792 :{SMALLFONT}{BLACK}Fixes all broken down rides +STR_5793 :{SMALLFONT}{BLACK}Resets the crash history of a ride,{NEWLINE}so guests will not complain that its unsafe +STR_5794 :{SMALLFONT}{BLACK}Some scenarios disable editing of some{NEWLINE}of the rides already in the park.{NEWLINE}This cheat lifts the restriction +STR_5795 :{SMALLFONT}{BLACK}Guests ride every attraction in the park{NEWLINE}even if the intensity is extremely high +STR_5796 :{SMALLFONT}{BLACK}Forces the park to close or open +STR_5797 :{SMALLFONT}{BLACK}Disables weather changes and{NEWLINE}freezes the selected weather +STR_5798 :{SMALLFONT}{BLACK}Allows building actions in pause mode +STR_5799 :{SMALLFONT}{BLACK}Disables ride breakdowns and crashes due to brake failure +STR_5800 :{SMALLFONT}{BLACK}Prevents rides from breaking down + +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area + + +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 + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Starting from scratch, build a theme park around a large lake + + +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 + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Develop Bumbly Beach's small amusement park into a thriving theme park + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Several islands form the basis for this new park + + +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 + + +STR_SCNR :Pokey Park +STR_PARK :Pokey Park +STR_DTLS :A small, cramped amusement park which requires major expansion + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :A park with some excellent water-based rides requires expansion + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park + + +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 + + +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 + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :In the hilly forests of Mystic Mountain, build a theme park from scratch + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park + + +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 + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :Convert this sleepy town's pier into a thriving attraction + + +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 + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :A well-established park, which has a few problems + + +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 + + +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 + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Just for fun! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Develop the seaside cliffs into a thriving amusement 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 + + +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 + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :An old redundant bridge is yours to develop into an amusement park + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Covering land both sides of a highway, this park has several rides already operating + + +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 + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :This castle is all yours to turn into a theme park + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape + + +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 + + +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 + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :A series of stepped lakes form the basis for this new park + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :This elderly park has many historical rides but is badly in debt + + +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 + + +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 + + +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 + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :A vast canyon is yours to turn into a theme 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 + + +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 + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters + + +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 + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people + + +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 + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? + + +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 + + +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 + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists + + +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 + + +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 + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :A large garden park needs turning into a thriving theme park + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :A dormant volcano is the setting of this coaster-building challenge + + +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 + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :A large lake in an ancient crater is the setting for this park + + +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 + + +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 + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :This sea-side cove is the setting for this coaster-building challenge + + +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 + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :A park which has much of its footpaths and coasters underground + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :A glacier-filled valley is yours to develop into a theme park + + +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 + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Five coasters require completion in this desert park + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :This historical park is only allowed to build older-styled rides + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Develop this alien park to maximize its profit + + +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 + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :A scary park with a giant centrepiece coaster + + +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 + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In this large park you must design and build ten large coasters + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :An icy landscape needs turning into a thriving theme park + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :A desert park with some cleverly designed coasters is yours to expand + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In this tiny park you must finish building the five existing coasters + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :A large park with a novel transporation system around its edge + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :This large island is all yours to develop as an amusement park + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :This urban area is all yours to develop into an amusement park + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :A giant park already packed full of rides needs improving + + +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 + + +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 + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : ##################### # Rides/attractions # diff --git a/data/language/english_us.txt b/data/language/english_us.txt index 5e25bea092..22727c30b0 100644 --- a/data/language/english_us.txt +++ b/data/language/english_us.txt @@ -1779,7 +1779,7 @@ STR_1773 :Only one on-ride photo section allowed per ride STR_1774 :Only one cable lift hill allowed per ride STR_1775 :Off STR_1776 :On -STR_1777 :{WINDOW_COLOUR_2}Music +STR_1777 :{WINDOW_COLOUR_2}Ride music STR_1778 :{STRINGID} - - STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Panda costume STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tiger costume @@ -2689,7 +2689,7 @@ STR_2680 :All research complete STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} STR_2682 : STR_2683 : -STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive +STR_2684 :{SMALLFONT}{BLACK}Large group of guests arrive STR_2685 :Simplex Noise Parameters STR_2686 :{WINDOW_COLOUR_2}Low: STR_2687 :{WINDOW_COLOUR_2}High: @@ -2782,7 +2782,7 @@ STR_2771 :Slower Gamespeed STR_2772 :Faster Gamespeed STR_2773 :Windowed STR_2774 :Fullscreen -STR_2775 :Fullscreen (desktop) +STR_2775 :Fullscreen (borderless) STR_2776 :Language: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} @@ -3457,470 +3457,457 @@ STR_3444 :Page 5 STR_3445 :Set Patrol Area STR_3446 :Cancel Patrol Area -# New strings, cleaner -STR_5120 :Finances -STR_5121 :Research -STR_5122 :Select rides by track type (like in RCT1) -STR_5123 :Renew rides -STR_5124 : -STR_5125 :All destructable -STR_5126 :Random title music -STR_5127 :{SMALLFONT}{BLACK}Disable land elevation -STR_5128 :Selection size -STR_5129 :Enter selection size between {COMMA16} and {COMMA16} -STR_5130 :Map size -STR_5131 :Enter map size between {COMMA16} and {COMMA16} -STR_5132 :Fix all rides -STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights -STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights -STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights -STR_5136 :Land rights -STR_5137 :Allow lift hill and launch speeds{NEWLINE}up to {VELOCITY} -STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} -STR_5139 :{WHITE}{STRINGID} -STR_5140 :Disable brakes failure -STR_5141 :Disable all breakdowns -STR_5142 :Normal Speed -STR_5143 :Quick Speed -STR_5144 :Fast Speed -STR_5145 :Turbo Speed -STR_5146 :Hyper Speed -STR_5147 :Cheats -STR_5148 :{SMALLFONT}{BLACK}Change the game speed -STR_5149 :{SMALLFONT}{BLACK}Open the cheats window -STR_5150 :Enable debugging tools -#Thousands separator -STR_5151 :, -#Decimals separator -STR_5152 :. -STR_5153 :Edit Themes... -STR_5154 :Hardware display -STR_5155 :Allow testing of unfinished tracks -STR_5156 :{SMALLFONT}{BLACK}Allows testing of most ride types even when the track is unfinished, does not apply to block sectioned modes -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_5161 :Date Format: -STR_5162 :Day/Month/Year -STR_5163 :Month/Day/Year -STR_5164 :Twitch Channel name -STR_5165 :Name peeps after followers -STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers -STR_5167 :Track follower peeps -STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers -STR_5169 :Name peeps after people in Twitch chat -STR_5170 :{SMALLFONT}{BLACK}Will name peeps after people in Twitch chat -STR_5171 :Track chat peeps -STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants -STR_5173 :Pull Twitch chat as news -STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications -STR_5175 :Input the name of your Twitch channel -STR_5176 :Enable Twitch integration -STR_5177 :Fullscreen mode: -STR_5178 :{SMALLFONT}{BLACK}Show financial cheats -STR_5179 :{SMALLFONT}{BLACK}Show guest cheats -STR_5180 :{SMALLFONT}{BLACK}Show park cheats -STR_5181 :{SMALLFONT}{BLACK}Show ride cheats -STR_5182 :{INT32} -STR_5183 :Base height -STR_5184 :Enter base height between {COMMA16} and {COMMA16} -STR_5185 :Water level -STR_5186 :Enter water level between {COMMA16} and {COMMA16} -STR_5187 :Finances -STR_5188 :New Campaign -STR_5189 :Research -STR_5190 :Map -STR_5191 :Viewport -STR_5192 :Recent News -STR_5193 :Land -STR_5194 :Water -STR_5195 :Clear Scenery -STR_5196 :Land Rights -STR_5197 :Scenery -STR_5198 :Footpath -STR_5199 :Ride Construction -STR_5200 :Track Design Place -STR_5201 :New Ride -STR_5202 :Track Design Selection -STR_5203 :Ride -STR_5204 :Ride List -STR_5205 :Guest -STR_5206 :Guest List -STR_5207 :Staff -STR_5208 :Staff List -STR_5209 :Banner -STR_5210 :Object Selection -STR_5211 :Invention List -STR_5212 :Scenario Options -STR_5213 :Objective Options -STR_5214 :Map Generation -STR_5215 :Track Design Manager -STR_5216 :Track Design Manager List -STR_5217 :Cheats -STR_5218 :Themes -STR_5219 :Options -STR_5220 :Keyboard Shortcuts -STR_5221 :Change Keyboard Shortcut -STR_5222 :Load/Save -STR_5223 :Save Prompt -STR_5224 :Demolish Ride Prompt -STR_5225 :Fire Staff Prompt -STR_5226 :Track Delete Prompt -STR_5227 :Save Overwrite Prompt -STR_5228 :{SMALLFONT}{BLACK}Main UI -STR_5229 :{SMALLFONT}{BLACK}Park -STR_5230 :{SMALLFONT}{BLACK}Tools -STR_5231 :{SMALLFONT}{BLACK}Rides and Peeps -STR_5232 :{SMALLFONT}{BLACK}Editors -STR_5233 :{SMALLFONT}{BLACK}Miscellaneous -STR_5234 :{SMALLFONT}{BLACK}Prompts -STR_5235 :{SMALLFONT}{BLACK}Settings -STR_5236 :Window: -STR_5237 :Palette: -STR_5238 :Current Theme: -STR_5239 :Duplicate -STR_5240 :Enter a name for the theme -STR_5241 :Can't change this theme -STR_5242 :Theme name already exists -STR_5243 :Invalid characters used -STR_5244 :Themes -STR_5245 :Top Toolbar -STR_5246 :Bottom Toolbar -STR_5247 :Track Editor Bottom Toolbar -STR_5248 :Scenario Editor Bottom Toolbar -STR_5249 :Title Menu Buttons -STR_5250 :Title Exit Button -STR_5251 :Title Options Button -STR_5252 :Title Scenario Selection -STR_5253 :Park Information -STR_5254 :Create -STR_5255 :{SMALLFONT}{BLACK}Create a new title sequence from scratch -STR_5256 :Create a new theme to make changes to -STR_5257 :{SMALLFONT}{BLACK}Create a new theme based on the current one -STR_5258 :{SMALLFONT}{BLACK}Delete the current theme -STR_5259 :{SMALLFONT}{BLACK}Rename the current theme -STR_5260 :Giant Screenshot -STR_5261 :Filter -STR_5262 :Wacky Worlds -STR_5263 :Time Twister -STR_5264 :Custom -STR_5265 :{SMALLFONT}{BLACK}Select which content sources are visible -STR_5266 :{SMALLFONT}{BLACK}Display -STR_5267 :{SMALLFONT}{BLACK}Culture and Units -STR_5268 :{SMALLFONT}{BLACK}Audio -STR_5269 :{SMALLFONT}{BLACK}Controls and interface -STR_5270 :{SMALLFONT}{BLACK}Miscellaneous -STR_5271 :{SMALLFONT}{BLACK}Twitch -STR_5272 :{SMALLFONT}{BLACK}Small Scenery -STR_5273 :{SMALLFONT}{BLACK}Large Scenery -STR_5274 :{SMALLFONT}{BLACK}Footpaths -STR_5275 :Search for Objects -STR_5276 :Enter the name of an object to search for -STR_5277 :Clear -STR_5278 :Sandbox mode -STR_5279 :Sandbox mode off -STR_5280 :{SMALLFONT}{BLACK}Allow editing land ownership settings through the Map window and other options that are normally restricted to the Scenario Editor -STR_5281 :{SMALLFONT}{BLACK}Features -STR_5282 :RCT1 Ride Open/Close Lights -STR_5283 :RCT1 Park Open/Close Lights -STR_5284 :RCT1 Scenario Selection Font -STR_5285 :EXPLODE!!! -STR_5286 :{SMALLFONT}{BLACK}Makes some guests explode -STR_5287 :Ride is already broken down -STR_5288 :Ride is closed -STR_5289 :No breakdowns available for this ride -STR_5290 :Fix ride -STR_5291 :Can't force breakdown -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_5298 :{RED}{STRINGID} -STR_5299 :{LIGHTPINK}{STRINGID} -STR_5300 :{SMALLFONT}{BLACK}Quick fire staff -STR_5301 :{MEDIUMFONT}{BLACK}Clear your loan -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_5308 :RollerCoaster Tycoon 2 -STR_5309 :OpenRCT2 -STR_5310 :Random -STR_5311 :{SMALLFONT}{BLACK}Debug tools -STR_5312 :Show console -STR_5313 :Show tile inspector -STR_5314 :Tile inspector -STR_5315 :Grass -STR_5316 :Sand -STR_5317 :Dirt -STR_5318 :Rock -STR_5319 :Martian -STR_5320 :Checkerboard -STR_5321 :Grass clumps -STR_5322 :Ice -STR_5323 :Grid (red) -STR_5324 :Grid (yellow) -STR_5325 :Grid (blue) -STR_5326 :Grid (green) -STR_5327 :Sand (dark) -STR_5328 :Sand (light) -STR_5329 :Checkerboard (inverted) -STR_5330 :Underground view -STR_5331 :Rock -STR_5332 :Wood (red) -STR_5333 :Wood (black) -STR_5334 :Ice -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_5341 :Flags -STR_5342 :Choose a map tile -STR_5343 :Automatically place staff -STR_5344 :Changelog -STR_5345 :Financial cheats -STR_5346 :Guest cheats -STR_5347 :Park cheats -STR_5348 :Ride cheats -STR_5349 :{SMALLFONT}{BLACK}All Rides -STR_5350 :Max -STR_5351 :Min -STR_5352 :{BLACK}Happiness: -STR_5353 :{BLACK}Energy: -STR_5354 :{BLACK}Hunger: -STR_5355 :{BLACK}Thirst: -STR_5356 :{BLACK}Nausea: -STR_5357 :{BLACK}Nausea tolerance: -STR_5358 :{BLACK}Bathroom: -STR_5359 :Remove guests -STR_5360 :{SMALLFONT}{BLACK}Removes all guests from the map -STR_5361 :Give all guests: -STR_5362 :{BLACK}Set all guests' preferred ride intensity to: -STR_5363 :More than 1 -STR_5364 :Less than 15 -STR_5365 :{BLACK}Staff speed: -STR_5366 :Normal -STR_5367 :Fast -STR_5368 :Reset crash status -STR_5369 :Park parameters... -STR_5370 :{SMALLFONT}{BLACK}Click this button to modify park{NEWLINE}parameters like restrictions,{NEWLINE}guest generation and money. -STR_5371 :Object Selection -STR_5372 :Invert right mouse dragging -STR_5373 :Name {STRINGID} -STR_5374 :Date {STRINGID} -STR_5375 :{UP} -STR_5376 :{DOWN} -STR_5377 :{SMALLFONT}{BLACK}Saves -STR_5378 :{SMALLFONT}{BLACK}Script -STR_5379 :{SMALLFONT}{BLACK}Skip to next wait command -STR_5380 :{SMALLFONT}{BLACK}Start playing title sequence -STR_5381 :{SMALLFONT}{BLACK}Stop playing title sequence -STR_5382 :{SMALLFONT}{BLACK}Restart title sequence -STR_5383 :{SMALLFONT}{BLACK}Create a new title sequence based on the current one -STR_5384 :{SMALLFONT}{BLACK}Delete the current title sequence -STR_5385 :{SMALLFONT}{BLACK}Rename the current title sequence -STR_5386 :{SMALLFONT}{BLACK}Insert a new command -STR_5387 :{SMALLFONT}{BLACK}Edit the selected command -STR_5388 :{SMALLFONT}{BLACK}Delete the selected command -STR_5389 :{SMALLFONT}{BLACK}Skip to the selected command in the title sequence -STR_5390 :{SMALLFONT}{BLACK}Move the selected command down -STR_5391 :{SMALLFONT}{BLACK}Move the selected command up -STR_5392 :{SMALLFONT}{BLACK}Add a save to the title sequence -STR_5393 :{SMALLFONT}{BLACK}Remove the selected save from the title sequence -STR_5394 :{SMALLFONT}{BLACK}Rename the selected save -STR_5395 :{SMALLFONT}{BLACK}Load the selected save in game -STR_5396 :{SMALLFONT}{BLACK}Reload the title sequence if changes have been made to it outside of the game -STR_5397 :Can only be used on the title screen -STR_5398 :Cannot edit title sequence while it's playing -STR_5399 :Press the stop button to continue editing -STR_5400 :Can't change this title sequence -STR_5401 :Create a new title sequence to make changes to -STR_5402 :Failed to load title sequence -STR_5403 :There may be no Load or Wait command or a save may be invalid -STR_5404 :Name already exists -STR_5405 :Enter a name for the save -STR_5406 :Enter a name for the title sequence -STR_5407 :Add -STR_5408 :Remove -STR_5409 :Insert -STR_5410 :Edit -STR_5411 :Reload -STR_5412 :Skip to -STR_5413 :Load -STR_5414 :Load{MOVE_X}{87}Six Flags Magic Mountain.SC6 -STR_5415 :Load{MOVE_X}{87}{STRING} -STR_5416 :Load{MOVE_X}{87}No save selected -STR_5417 :Location -STR_5418 :Location{MOVE_X}{87}{COMMA16} {COMMA16} -STR_5419 :Rotate -STR_5420 :Rotate{MOVE_X}{87}{COMMA16} -STR_5421 :Zoom -STR_5422 :Zoom{MOVE_X}{87}{COMMA16} -STR_5423 :Wait -STR_5424 :Wait{MOVE_X}{87}{COMMA16} -STR_5425 :Restart -STR_5426 :End -STR_5427 :Coordinates: -STR_5428 :Counter-clockwise rotations: -STR_5429 :Zoom level: -STR_5430 :Seconds to wait: -STR_5431 :Save to load: -STR_5432 :Command: -STR_5433 :Title Sequences -STR_5434 :Command Editor -STR_5435 :Rename save -STR_5436 :Edit Title Sequences... -STR_5437 :No save selected -STR_5438 :Can't make changes while command editor is open -STR_5439 :A wait command with at least 4 seconds is required with a restart command +# Strings added by OpenRCT2. Only add strings that differ from UK English! STR_5440 :Minimize fullscreen on focus loss -STR_5441 :{SMALLFONT}{BLACK}Identifies rides by track type,{NEWLINE}so vehicles can be changed{NEWLINE}afterwards, like in RCT1. -STR_5442 :Force park rating: -STR_5443 :Speed{MOVE_X}{87}{STRINGID} -STR_5444 :Speed: -STR_5445 :Speed -STR_5446 :Get -STR_5447 :Type {STRINGID} -STR_5448 :Ride / Vehicle {STRINGID} -STR_5449 :Reduce game speed -STR_5450 :Increase game speed -STR_5451 :Open cheats window -STR_5452 :Toggle visibility of toolbars -STR_5453 :Select another ride -STR_5454 :Uncap FPS -STR_5455 :Enable sandbox mode -STR_5456 :Disable clearance checks -STR_5457 :Disable support limits -STR_5458 :Rotate clockwise STR_5459 :Rotate counterclockwise STR_5460 :Rotate view counterclockwise -STR_5461 :Set guests' parameters -STR_5462 :{CURRENCY} -STR_5463 :Goal: Have fun! -STR_5464 :General -STR_5465 :Climate -STR_5466 :Staff -STR_5467 :ALT + -STR_5468 :Recent messages -STR_5469 :Scroll map up -STR_5470 :Scroll map left -STR_5471 :Scroll map down -STR_5472 :Scroll map right -STR_5473 :Cycle day / night -STR_5474 :Display text on banners in upper case -STR_5475 :{COMMA16} weeks -STR_5476 :Hardware -STR_5477 :Map rendering -STR_5478 :Controls -STR_5479 :Toolbar -STR_5480 :Show toolbar buttons for: -STR_5481 :Themes -STR_5482 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}1 minute -STR_5483 :{BLACK}({COMMA16} weeks remaining) -STR_5484 :{BLACK}({COMMA16} week remaining) -STR_5485 :{SMALLFONT}{STRING} -STR_5486 :{BLACK}{COMMA16} -STR_5487 :{SMALLFONT}{BLACK}Show recent messages -STR_5488 :No entrance (OpenRCT2 only!) -STR_5489 :{SMALLFONT}{BLACK}Show only tracked guests -STR_5490 :Disable audio on focus loss -STR_5491 :Inventions list -STR_5492 :Scenario options -STR_5493 :Send Message -STR_5494 : -STR_5495 :Player List -STR_5496 :Player: -STR_5497 :Ping: -STR_5498 :Server List -STR_5499 :Player Name: -STR_5500 :Add Server -STR_5501 :Start Server -STR_5502 :Multiplayer -STR_5503 :Enter hostname or IP address: -STR_5504 :{SMALLFONT}{BLACK}Show multiplayer status -STR_5505 :Unable to connect to server. -STR_5506 :Guests ignore intensities -STR_5507 :Handymen mow grass by default -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_5513 :(Quick) save game -STR_5514 :Disable vandalism STR_5515 :{SMALLFONT}{BLACK}Stops guests from vandalizing your park when they're angry -STR_5516 :{SMALLFONT}{BLACK}Black STR_5517 :{SMALLFONT}{BLACK}Gray -STR_5518 :{SMALLFONT}{BLACK}White -STR_5519 :{SMALLFONT}{BLACK}Dark purple -STR_5520 :{SMALLFONT}{BLACK}Light purple -STR_5521 :{SMALLFONT}{BLACK}Bright purple -STR_5522 :{SMALLFONT}{BLACK}Dark blue -STR_5523 :{SMALLFONT}{BLACK}Light blue -STR_5524 :{SMALLFONT}{BLACK}Icy blue -STR_5525 :{SMALLFONT}{BLACK}Dark water -STR_5526 :{SMALLFONT}{BLACK}Light water -STR_5527 :{SMALLFONT}{BLACK}Saturated green -STR_5528 :{SMALLFONT}{BLACK}Dark green -STR_5529 :{SMALLFONT}{BLACK}Moss green -STR_5530 :{SMALLFONT}{BLACK}Bright green -STR_5531 :{SMALLFONT}{BLACK}Olive green -STR_5532 :{SMALLFONT}{BLACK}Dark olive green -STR_5533 :{SMALLFONT}{BLACK}Bright yellow -STR_5534 :{SMALLFONT}{BLACK}Yellow -STR_5535 :{SMALLFONT}{BLACK}Dark yellow -STR_5536 :{SMALLFONT}{BLACK}Light orange -STR_5537 :{SMALLFONT}{BLACK}Dark orange -STR_5538 :{SMALLFONT}{BLACK}Light brown -STR_5539 :{SMALLFONT}{BLACK}Saturated brown -STR_5540 :{SMALLFONT}{BLACK}Dark brown -STR_5541 :{SMALLFONT}{BLACK}Salmon pink -STR_5542 :{SMALLFONT}{BLACK}Bordeaux red -STR_5543 :{SMALLFONT}{BLACK}Saturated red -STR_5544 :{SMALLFONT}{BLACK}Bright red -STR_5545 :{SMALLFONT}{BLACK}Dark pink -STR_5546 :{SMALLFONT}{BLACK}Bright pink -STR_5547 :{SMALLFONT}{BLACK}Light pink -STR_5548 :Show all operating modes -STR_5549 :Year/Month/Day -STR_5550 :{POP16}{POP16}Year {COMMA16}, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} -STR_5551 :Year/Day/Month -STR_5552 :{POP16}{POP16}Year {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 -STR_5556 :Kick Player STR_5557 :Stay connected after desynchronization (Multiplayer) -STR_5558 :A restart is required for this setting to take effect -STR_5559 :10 min. inspections -STR_5560 :{SMALLFONT}{BLACK}Sets the inspection time to 'Every 10 minutes' on all rides -STR_5561 :Failed to load language -STR_5562 :WARNING! -STR_5563 :This feature is currently unstable, take extra caution. -STR_5564 :Insert Corrupt Element -STR_5565 :{SMALLFONT}{BLACK}Inserts a corrupt map element at top of tile. This will hide any element above the corrupt element. -STR_5566 :Password: -STR_5567 :Advertise -STR_5568 :Password Required -STR_5569 :This server requires a password -STR_5570 :Fetch Servers -STR_5571 :Join Game STR_5572 :Add To Favorites STR_5573 :Remove From Favorites -STR_5574 :Server Name: -STR_5575 :Max Players: -STR_5576 :Port: -STR_5577 :South Korean Won (W) -STR_5578 :Russian Ruble (R) -STR_5579 :Window scale factor: -STR_5580 :Czech koruna (Kc) +STR_5620 :Corkscrew Follies + +############# +# Scenarios # +############# + +## RCT Original + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area + + +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 + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Starting from scratch, build a theme park around a large lake + + +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 + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Develop Bumbly Beach's small amusement park into a thriving theme park + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Several islands form the basis for this new park + + +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 + + +STR_SCNR :Dinky Park +STR_PARK :Dinky Park +STR_DTLS :A small, cramped amusement park which requires major expansion + + +STR_SCNR :Aqua Park +STR_PARK :Aqua Park +STR_DTLS :A park with some excellent water-based rides requires expansion + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park + + +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 + + +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 + + +STR_SCNR :Mothball Mountain +STR_PARK :Mothball Mountain +STR_DTLS :In the hilly forests of Mothball Mountain, build a theme park from scratch + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park + + +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 + + +STR_SCNR :Big Pier +STR_PARK :Big Pier +STR_DTLS :Convert this sleepy town's pier into a thriving attraction + + +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 + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :A well-established park, which has a few problems + + +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 + + +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 + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Just for fun! + +## Corkscrew Follies + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Develop the seaside cliffs into a thriving amusement 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 + + +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 + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :An old redundant bridge is yours to develop into an amusement park + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Covering land both sides of a highway, this park has several rides already operating + + +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 + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :This castle is all yours to turn into a theme park + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape + + +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 + + +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 + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :A series of stepped lakes form the basis for this new park + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :This elderly park has many historical rides but is badly in debt + + +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 + + +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 + + +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 + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :A vast canyon is yours to turn into a theme 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 + + +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 + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters + + +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 + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people + + +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 + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? + + +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 + + +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 + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists + + +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 + + +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 + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :A large garden park needs turning into a thriving theme park + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :A dormant volcano is the setting of this coaster-building challenge + + +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 + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :A large lake in an ancient crater is the setting for this park + + +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 + + +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 + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :This sea-side cove is the setting for this coaster-building challenge + + +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 + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :A park which has much of its footpaths and coasters underground + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :A glacier-filled valley is yours to develop into a theme park + + +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 + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Five coasters require completion in this desert park + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :This historical park is only allowed to build older-styled rides + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Develop this alien park to maximize its profit + + +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 + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :A scary park with a giant centrepiece coaster + + +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 + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In this large park you must design and build ten large coasters + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :An icy landscape needs turning into a thriving theme park + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :A desert park with some cleverly designed coasters is yours to expand + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In this tiny park you must finish building the five existing coasters + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :A large park with a novel transporation system around its edge + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :This large island is all yours to develop as an amusement park + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :This urban area is all yours to develop into an amusement park + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :A giant park already packed full of rides needs improving + + +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 + + +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 + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : ######### # Rides # diff --git a/data/language/finnish.txt b/data/language/finnish.txt index f36f052215..5a5ff52a1e 100644 --- a/data/language/finnish.txt +++ b/data/language/finnish.txt @@ -41,7 +41,7 @@ STR_0036 :Tuntematon koju (22) STR_0037 :Infokioski STR_0038 :Vessa STR_0039 :Maailmanpyörä -STR_0040 :Liikesimulaattori +STR_0040 :Simulaattori STR_0041 :3D-teatteri STR_0042 :Yläpyörähdys STR_0043 :Avaruusrenkaat @@ -49,7 +49,7 @@ STR_0044 :Päinvastainen vapaapudotusrata STR_0045 :Hissi STR_0046 :Pystysuora tiputusvuoristorata STR_0047 :Pankkiautomaatti -STR_0048 :Vääntely +STR_0048 :Vääntö STR_0049 :Kummitustalo STR_0050 :Ensiapuhuone STR_0051 :Sirkusesitys @@ -75,7 +75,7 @@ STR_0070 :Jättirata STR_0071 :Pyörivä tiputus STR_0072 :Lentävät lautaset STR_0073 :Kiero talo -STR_0074 :Yksiraiteinen rautatiekierto +STR_0074 :Yksiraiteiset polkupyörät STR_0075 :Tiivis käänteinen rata STR_0076 :Vesirata STR_0077 :Ilmakäyttöinen pystysuora rata @@ -557,23 +557,24 @@ STR_0551 : STR_0552 : STR_0553 : STR_0554 :The car is accelerated out of the station along a long level track using Linear Induction Motors, then heads straight up a vertical spike of track, freefalling back down to return to the station -STR_0555 :Guests ride in an elevator up or down a vertical tower to get from one level to another -STR_0556 :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_0555 :Pystysuora torni, jossa vieraat kulkevat hissillä ylös tai alas päästäkseen tasolta toiselle +STR_0556 :Leveät vaunut laskevat pystysuoraa rataa täyden vapaapudotuskokemuksen saavuttamiseksi STR_0557 : STR_0558 : STR_0559 : STR_0560 : STR_0561 : -STR_0562 :Powered cars travel along a multi-level track past spooky scenery and special effects +STR_0562 :Moottoroidut vaunut kulkevat monitasoista rataa pelottavien lavastusten ja erikoisefektien läpi +# 'Air time' is an expression used in finnish too, for the lack of a better word STR_0563 :Sitting in comfortable trains with only simple lap restraints riders enjoy giant smooth drops and twisting track as well as plenty of 'air time' over the hills -STR_0564 :Running on wooden track, this coaster is fast, rough, noisy, and gives an 'out of control' riding experience with plenty of 'air time' -STR_0565 :A simple wooden roller coaster capable of only gentle slopes and turns, where the cars are only kept on the track by side friction wheels and gravity -STR_0566 :Individual roller coaster cars zip around a tight zig-zag layout of track with sharp corners and short sharp drops -STR_0567 :Sitting in seats suspended either side of the track, riders are pitched head-over-heels while they plunge down steep drops and travel through various inversions +STR_0564 :Puisen radan takia tämä vuoristorata on nopea, raaka, meluisa ja tarjoaa 'out of control'-kokemuksen ja paljon airtimeä +STR_0565 :Yksinkertainen puinen vuoristorata joka kykenee vain lempeisiin mäkiin ja käännöksiin. Vaunut pysyvät radalla sivukitkapyörien ja painovoiman avulla +STR_0566 :Yksittäiset vuoristoratavaunut singahtelevat pitkin tiukkaa mutkarataa jossa on teräviä kaarteita ja pudotuksia +STR_0567 :Radan sivuilla olevissa tuoleissa matkustajia pyöritetään ylösalaisin kun vaunu huristaa alas jyrkkiä pudotuksia läpi useiden inversioiden STR_0568 : -STR_0569 :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air +STR_0569 :Erikoisvaljaiden ansiosta matkustajat kokevat lentävänsä ilmojen halki STR_0570 : -STR_0571 :Circular cars spin around as they travel along the zig-zagging wooden track +STR_0571 :Pyöreät vaunut pyörivät ympäri mutkikkaalla puisella radalla STR_0572 :Large capacity boats travel along a wide water channel, propelled up slopes by a conveyer belt, accelerating down steep slopes to soak the riders with a gaint splash STR_0573 :Powered helicoper shaped cars running on a steel track, controlled by the pedalling of the riders STR_0574 :Riders are held in special harnesses in a lying-down position, travlling through twisted track and inversions either on their backs or facing the ground @@ -583,7 +584,7 @@ STR_0577 :Bogied cars run on wooden tracks, turning around on special reversi STR_0578 :Cars run along track enclosed by circular hoops, traversing steep drops and heartline twists STR_0579 : STR_0580 :A giant steel roller coaster capable of smooth drops and hills of over 300ft -STR_0581 :A ring of seats is pulled to the top of a tall tower while gently rotating, then allowed to free-fall down, stopping gently at the bottom using magnetic brakes +STR_0581 :Pyöreä tuolirivi nousee korkean tornin huipulle, josta se putoaa vapaasti alas. Alhaalla magneettijarrut pysäyttävät vaunun lempeästi STR_0582 : STR_0583 : STR_0584 :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders @@ -824,22 +825,22 @@ STR_0818 :Syys STR_0819 :Loka STR_0820 :Marras STR_0821 :Joulu -STR_0822 :Kykenemätön avaamaan grafiikkadatatiedostoa +STR_0822 :Grafiikkadatatiedostoa ei saada auki STR_0823 :Puuttuva tai käyttökelvoton datatiedosto STR_0824 :{BLACK}{CROSS} STR_0825 :Nimi on jo käytössä STR_0826 :Liian monta nimeä määritetty STR_0827 :Rahaa ei ole tarpeeksi - tarvitaan {CURRENCY2DP} STR_0828 :{SMALLFONT}{BLACK}Sulje ikkuna -STR_0829 :{SMALLFONT}{BLACK}Ikkunan otsikko - Vedä tätä liikuttaakseen ikkunaa +STR_0829 :{SMALLFONT}{BLACK}Ikkunan otsikko - Vedä tätä liikuttaaksesi ikkunaa STR_0830 :{SMALLFONT}{BLACK}Suurenna STR_0831 :{SMALLFONT}{BLACK}Pienennä STR_0832 :{SMALLFONT}{BLACK}Käännä 90{DEGREE} myötäpäivään STR_0833 :{SMALLFONT}{BLACK}Pysäytä peli STR_0834 :{SMALLFONT}{BLACK}Levy- ja peliasetukset STR_0835 :Pelin alustus epäonnistui -STR_0836 :Kykenemätön aloittamaan peliä pienennetyssä tilassa -STR_0837 :Kykenemätön alustamaan grafiikkajärjestelmää +STR_0836 :Pelin aloitus ei onnistu pienennetyssä tilassa +STR_0837 :Grafiikkajärjestelmän alustus ei toimi STR_0838 : STR_0839 :{UINT16} x {UINT16} STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16} @@ -890,8 +891,8 @@ STR_0883 :Tallenna peli STR_0884 :Lataa maisema STR_0885 :Tallenna maisema STR_0886 :Lopeta peli -STR_0887 :Lopeta skenaariomuokkaaja -STR_0888 :Lopeta vuoristoratasuunnittelija +STR_0887 :Lopeta skenaarioeditori +STR_0888 :Lopeta vuoristoratasuunnittelu STR_0889 :Lopeta ratasuunnitelmahallinta STR_0890 :Kuva{COMMA16}.BMP STR_0891 :Kuvankaappaus @@ -901,20 +902,20 @@ STR_0894 :Maisematietoalue on täynnä ! STR_0895 :Ei voi rakentaa osittain maan ylle ja alle STR_0896 :{POP16}{POP16}{STRINGID} Rakenne STR_0897 :Suunta -STR_0898 :{SMALLFONT}{BLACK}Vasemman käden kaarre -STR_0899 :{SMALLFONT}{BLACK}Oikean käden kaarre -STR_0900 :{SMALLFONT}{BLACK}Vasemman käden kaarre (pieni säde) -STR_0901 :{SMALLFONT}{BLACK}Oikean käden kaarre (pieni säde) -STR_0902 :{SMALLFONT}{BLACK}Vasemman käden kaarre (todella pieni säde) -STR_0903 :{SMALLFONT}{BLACK}Oikean käden kaarre (todella pieni säde) -STR_0904 :{SMALLFONT}{BLACK}Vasemman käden kaarre (iso säde) -STR_0905 :{SMALLFONT}{BLACK}Oikean käden kaarre (iso säde) +STR_0898 :{SMALLFONT}{BLACK}Kaarre vasempaan +STR_0899 :{SMALLFONT}{BLACK}Kaarre oikeaan +STR_0900 :{SMALLFONT}{BLACK}Kaarre vasempaan (pieni säde) +STR_0901 :{SMALLFONT}{BLACK}Kaarre oikeaan (pieni säde) +STR_0902 :{SMALLFONT}{BLACK}Kaarre vasempaan (todella pieni säde) +STR_0903 :{SMALLFONT}{BLACK}Kaarre oikeaan (todella pieni säde) +STR_0904 :{SMALLFONT}{BLACK}Kaarre vasempaan (iso säde) +STR_0905 :{SMALLFONT}{BLACK}Kaarre oikeaan (iso säde) STR_0906 :{SMALLFONT}{BLACK}Suora -STR_0907 :Rinne +STR_0907 :Mäki STR_0908 :Kallistus STR_0909 :Istuimen kierto -STR_0910 :{SMALLFONT}{BLACK}Vasemmalle kaartava kallistus -STR_0911 :{SMALLFONT}{BLACK}Oikealle kaartava kallistus +STR_0910 :{SMALLFONT}{BLACK}Kallistus vasempaan +STR_0911 :{SMALLFONT}{BLACK}Kallistus oikeaan STR_0912 :{SMALLFONT}{BLACK}Ei kallistusta STR_0913 :{SMALLFONT}{BLACK}Siirry edelliseen osaan STR_0914 :{SMALLFONT}{BLACK}Siirry seuraavaan osaan @@ -927,15 +928,15 @@ STR_0920 :{SMALLFONT}{BLACK}Tasanne STR_0921 :{SMALLFONT}{BLACK}Mäki ylös STR_0922 :{SMALLFONT}{BLACK}Jyrkkä mäki ylös STR_0923 :{SMALLFONT}{BLACK}Pystynousu -STR_0924 :{SMALLFONT}{BLACK}Ruuvikierre alas -STR_0925 :{SMALLFONT}{BLACK}Ruuvikierre ylös +STR_0924 :{SMALLFONT}{BLACK}Kierre alas +STR_0925 :{SMALLFONT}{BLACK}Kierre ylös STR_0926 :Tämän poistaminen ei onnistu... STR_0927 :Tämän rakentaminen tähän ei onnistu... -STR_0928 :{SMALLFONT}{BLACK}Ketjumäki, vaunujen vetämistä varten mäissä. +STR_0928 :{SMALLFONT}{BLACK}Ketjumäki, vaunujen mäessä vetämistä varten. STR_0929 :'S' mutka (vasen) STR_0930 :'S' mutka (oikea) -STR_0931 :Pystysuora kierukka (vasen) -STR_0932 :Pystysuora kierukka (oikea) +STR_0931 :Pystysuora silmukka (vasen) +STR_0932 :Pystysuora silmukka (oikea) STR_0933 :Nosta tai laske maata ensin STR_0934 :Laitteen sisäänkäynti edessä STR_0935 :Laitteen uloskäynti edessä @@ -958,7 +959,7 @@ STR_0951 :Lopeta peli STR_0952 :Lopeta peli STR_0953 :Lataa maisema STR_0954 : -STR_0955 :{SMALLFONT}{BLACK}Valitse istuimen kiertokulma tämän radan osioon +STR_0955 :{SMALLFONT}{BLACK}Valitse istuimen kiertokulma tähän radan osioon STR_0956 :-180{DEGREE} STR_0957 :-135{DEGREE} STR_0958 :-90{DEGREE} @@ -1000,7 +1001,7 @@ STR_0993 :Romuta laite/nähtävyys STR_0994 :Romuta STR_0995 :{WINDOW_COLOUR_1}Oletko varma että haluat tuhota {STRINGID}:n? STR_0996 :Kokonaisnäkymä -STR_0997 :{SMALLFONT}{BLACK}Näe valinta +STR_0997 :{SMALLFONT}{BLACK}Katso valinta STR_0998 :Ei lisää asemia sallittu tälle laitteelle STR_0999 :Vaatii asematasanteen STR_1000 :Rata ei tee täydellistä kierrosta @@ -1010,7 +1011,7 @@ STR_1003 :Testiajo ei onnistu laitteessa {POP16}{POP16}{POP16}{STRINGID}... STR_1004 :Sulkeminen ei onnistu laitteessa {POP16}{POP16}{POP16}{STRINGID}... STR_1005 :Rakentaminen ei onnistu laitteessa {POP16}{POP16}{POP16}{STRINGID}... STR_1006 :Täytyy ensin sulkea -STR_1007 :Kykenemätön luomaan tarpeeksi kulkuneuvoja +STR_1007 :Ei voida luoda tarpeeksi kulkuneuvoja STR_1008 :{SMALLFONT}{BLACK}Avaa, sulje tai testaa laitetta/kohdetta STR_1009 :{SMALLFONT}{BLACK}Avaa tai sulje kaikki laitteet/kohteet STR_1010 :{SMALLFONT}{BLACK}Avaa tai sulje puisto @@ -1018,8 +1019,8 @@ STR_1011 :Sulje kaikki STR_1012 :Avaa kaikki STR_1013 :Sulje puisto STR_1014 :Avaa puisto -STR_1015 :Kykenemätön toimimaan useamman asematasanteen kanssa tässä toimintatilassa -STR_1016 :Kykenemätön toimimaan vähemmän kuin kahden asematasanteen kanssa tässä toimintatilassa +STR_1015 :Tämä toimintatila ei toimi useamman asematasanteen kanssa +STR_1016 :Tämä toimintatila vaatii vähintään kaksi asematasannetta STR_1017 :Ei pysty vaihtaamaan toimintatilaa... STR_1018 :Muutoksien teko ei onnistu... STR_1019 :Muutoksien teko ei onnistu... @@ -1033,12 +1034,12 @@ STR_1026 :Asematasanne on liian pitkä! STR_1027 :{SMALLFONT}{BLACK}Paikanna tämä päänäkymässä STR_1028 :Kentän laidan yli! STR_1029 :Ei voi rakentaa osittain veden pinnan ylle ja alle! -STR_1030 :Tämän voi ainoastaan rakentaa veden alle! +STR_1030 :Tämän voi rakentaa ainoastaan veden alle! STR_1031 :Tätä ei voi rakentaa veden alle! -STR_1032 :Tämän voi ainoastaan rakentaa veteen! -STR_1033 :Tämän voi ainoastaan rakentaa maanpinnan ylle! -STR_1034 :Tämän voi ainoastaan rakentaa maanpinnalle! -STR_1035 :Paikallinen virkavalta ei salli rakentaa puiden latvoja korkeammalle! +STR_1032 :Tämän voi rakentaa ainoastaan veteen! +STR_1033 :Tämän voi rakentaa ainoastaan maanpinnan ylle! +STR_1034 :Tämän voi rakentaa ainoastaan maanpinnalle! +STR_1035 :Paikallinen virkavalta ei salli rakentamista puiden latvoja korkeammalle! STR_1036 :Lataa peli STR_1037 :Lataa maisema STR_1038 :Muunna tallennettu peli skenaarioksi @@ -1065,14 +1066,14 @@ STR_1058 :Kirjoita uusi nimi tälle laitteelle/kohteelle: STR_1059 :Ei pysty uudelleennimeämään laitetta/kohdetta... STR_1060 :Virheellinen laitteen/kohteen nimi STR_1061 :Normaali toimintatila -STR_1062 :Toistuva kierros toimintatila -STR_1063 :Käänteinen-kallistus laukaistu sukkula toimintatila -STR_1064 :Voimalaukaisu (aseman ohimennen) +STR_1062 :Toistuva kierros -toimintatila +STR_1063 :Käänteinen-kallistus laukaistu sukkula -toimintatila +STR_1064 :Voimalaukaisu (aseman ohitus) STR_1065 :Sukkulatoimintatila STR_1066 :Veneajelutoimintatila STR_1067 :Ylöspäin laukaisu STR_1068 :Pyörivä hissi -toimintatila -STR_1069 :Asemalta asemalle toimintatila +STR_1069 :Asemalta asemalle -toimintatila STR_1070 :Yksi kyyti per sisäänpääsy STR_1071 :Loputtomat kyydit per sisäänpääsy STR_1072 :Labyrinttitoimintatila @@ -1081,36 +1082,36 @@ STR_1074 :Törmäysautotoimintatila STR_1075 :Keinutoimintatila STR_1076 :Kojutoimintatila STR_1077 :Pyörimistoimintatila -STR_1078 :Eteenpäin pyöriminen -STR_1079 :Taaksepäin pyöriminen +STR_1078 :Kiertosuunta eteenpäin +STR_1079 :Kiertosuunta taaksepäin STR_1080 :Elokuva: {ENDQUOTES}Kostavat lentäjät{ENDQUOTES} STR_1081 :3D-elokuva: {ENDQUOTES}Hiiren hännät{ENDQUOTES} -STR_1082 :Avaruusrenkaat toimintatila -STR_1083 :Aloittelijoille toimintatila +STR_1082 :Avaruusrenkaat -toimintatila +STR_1083 :Aloittelijoille -toimintatila STR_1084 :Induktiomoottorilaukaisu -STR_1085 :Elokuva: {ENDQUOTES}Jännityksen ratsastajat{ENDQUOTES} +STR_1085 :Elokuva: {ENDQUOTES}Jännityksen rakastajat{ENDQUOTES} STR_1086 :3D-elokuva: {ENDQUOTES}Myrskyn jahtaajat{ENDQUOTES} STR_1087 :3D-elokuva: {ENDQUOTES}Avaruusryöstäjät{ENDQUOTES} STR_1088 :Intensiivinen toimintatila STR_1089 :Hullu toimintatila -STR_1090 :Kummitustalo toimintatila -STR_1091 :Sirkusesitys toimintatila +STR_1090 :Kummitustalo -toimintatila +STR_1091 :Sirkusesitys -toimintatila STR_1092 :Alaspäin laukaisu -STR_1093 :Kiero talo toimintatila +STR_1093 :Kiero talo -toimintatila STR_1094 :Vapaapudotustoimintatila -STR_1095 :Toistuva kierros lohkojarrutuksella toiminatila -STR_1096 :Voimalaukaisu (ilman aseman ohimenemistä) -STR_1097 :Voimalaukaisu lohkojarrutuksella toimintatila -STR_1098 :Matkustetaan {POP16}{STRINGID} loppuun -STR_1099 :Odoitetaan matkustajia {POP16}{STRINGID} -STR_1100 :Odoitetaan lähtöä {POP16}{STRINGID} -STR_1101 :Lähtemässä {POP16}{STRINGID} +STR_1095 :Toistuva kierros lohkojarrutuksella -toimintatila +STR_1096 :Voimalaukaisu (ilman aseman ohitusta) +STR_1097 :Voimalaukaisu lohkojarrutuksella -toimintatila +STR_1098 :Siirrytään {POP16}{STRINGID} loppuun +STR_1099 :Odotetaan matkustajia {POP16}{STRINGID} +STR_1100 :Odotetaan lähtöä {POP16}{STRINGID} +STR_1101 :Lähtemässä asemalta {POP16}{STRINGID} STR_1102 :Nopeus {VELOCITY} -STR_1103 :Saapumassa {POP16}{STRINGID} -STR_1104 :Matkustajia puretaan {POP16}{STRINGID} +STR_1103 :Saapumassa asemalle {POP16}{STRINGID} +STR_1104 :Matkustajat poistuvat asemalla {POP16}{STRINGID} STR_1105 :Nopeus {VELOCITY} -STR_1106 :Sortuu! -STR_1107 :Sortunut! +STR_1106 :Törmää! +STR_1107 :Törmännyt! STR_1108 :Nopeus {VELOCITY} STR_1109 :Keinuu STR_1110 :Pyörii @@ -1140,20 +1141,20 @@ STR_1133 :Ajoneuvo {POP16}{COMMA16} STR_1134 :{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} {COMMA16} STR_1135 :{STRINGID} {COMMA16} STR_1136 :{SMALLFONT}{BLACK}Valitse pääväri -STR_1137 :{SMALLFONT}{BLACK}Valitse valinnainen väri 1 -STR_1138 :{SMALLFONT}{BLACK}Valitse valinnainen väri 2 +STR_1137 :{SMALLFONT}{BLACK}Valitse lisäväri 1 +STR_1138 :{SMALLFONT}{BLACK}Valitse lisäväri 2 STR_1139 :{SMALLFONT}{BLACK}Valitse tukirakenteiden väri -STR_1140 :{SMALLFONT}{BLACK}Valitse ajoneuvon väriteemava -STR_1141 :{SMALLFONT}{BLACK}Valitse mitä ajoneuvoa/junaa muuttaa +STR_1140 :{SMALLFONT}{BLACK}Valitse ajoneuvon väriteema +STR_1141 :{SMALLFONT}{BLACK}Valitse mitä ajoneuvoa/junaa muutetaan STR_1142 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1143 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRINGID} STR_1144 :Ei pysty rakentamaan/siirtämään tämän laitteen/kohteen sisäänkäyntiä... STR_1145 :Ei pysty rakentamaan/siirtämään tämän laitteen/kohteen uloskäyntiä... STR_1146 :Sisäänkäyntiä ei ole vielä rakennettu STR_1147 :Uloskäyntiä ei ole vielä rakennettu -STR_1148 :Neljännes kuorma +STR_1148 :Neljänneskuorma STR_1149 :Puolikas kuorma -STR_1150 :Kolmeneljäsosaa kuorma +STR_1150 :Kolmeneljäsosakuorma STR_1151 :Täysi kuorma STR_1152 :Mikä tahansa kuorma STR_1153 :Korkeusmerkinnät laitteiden radoissa @@ -1162,7 +1163,7 @@ STR_1155 :Korkeusmerkinnät poluissa STR_1156 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1157 :{TICK}{MOVE_X}{SMALLFONT}{STRINGID} STR_1158 :Tämän poistaminen ei onnistu... -STR_1159 :{SMALLFONT}{BLACK}Aseta maisemaa, puutarhoja, ja muita tilpehöörejä. +STR_1159 :{SMALLFONT}{BLACK}Luo maisemaa, kasvillisuutta ja kaikenlaisia tilpehöörejä. STR_1160 :{SMALLFONT}{BLACK}Luo/säädä järviä ja vettä STR_1161 :Tätä ei voi asettaa tähän... STR_1162 :{OUTLINE}{TOPAZ}{STRINGID} @@ -1181,7 +1182,7 @@ STR_1174 :Mainoskyltti on tiellä STR_1175 :Tätä ei voi rakentaa kaltevalle jalkakäytävälle STR_1176 :Jalkakäytävää ei voi rakentaa tähän... STR_1177 :Jalkakäytävää ei voi poistaa tästä... -STR_1178 :Maan kaltevuus epäsopiva +STR_1178 :Maan kaltevuus ei sovi STR_1179 :Jalkakäytävä on tiellä STR_1180 :Tätä ei voi rakentaa veden alle! STR_1181 :Jalkakäytävät @@ -1201,7 +1202,7 @@ STR_1194 :Suljettu STR_1195 :Testiajo STR_1196 :Auki STR_1197 :Rikki -STR_1198 :Sortunut! +STR_1198 :Hajonnut! STR_1199 :{COMMA16} henkilö laitteessa STR_1200 :{COMMA16} henkilöä laitteessa STR_1201 :Ei ketään jonossa @@ -1219,7 +1220,7 @@ STR_1212 :{WINDOW_COLOUR_2}Enimmäisodotusaika: STR_1213 :{SMALLFONT}{BLACK}Valitse vähimmäisodotusaika ennen lähtöä STR_1214 :{SMALLFONT}{BLACK}Valitse enimmäisodotusaika ennen lähtöä STR_1215 :{WINDOW_COLOUR_2}Synkronoi rinnakkaisasemien kanssa -STR_1216 :{SMALLFONT}{BLACK}Valitse pitäisikö synkronoida lähtö kaikkien rinnakkaisasemien kanssa ('kilpailua' varten) +STR_1216 :{SMALLFONT}{BLACK}Valitse pitäisikö synkronoida lähtö kaikkien rinnakkaisasemien kanssa ('kilpa-ajoa' varten) STR_1217 :{COMMA16} sekuntia STR_1218 :{BLACK}{SMALLUP} STR_1219 :{BLACK}{SMALLDOWN} @@ -1331,7 +1332,7 @@ STR_1324 :{COMMA16} rata STR_1325 :{COMMA16} rataa STR_1326 :Rata {COMMA16} STR_1327 :{SMALLFONT}{BLACK}Käännä esineitä 90{DEGREE} -STR_1328 :Vaatii tasaisen maan +STR_1328 :Vaaditaan tasainen maa STR_1329 :{WINDOW_COLOUR_2}Lähtönopeus: STR_1330 :{SMALLFONT}{BLACK}Enimmäisnopeus kun lähdetään asemalta STR_1331 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} @@ -1360,33 +1361,34 @@ STR_1353 :{WINDOW_COLOUR_2}Suurin sivuttainen G-voima: {OUTLINE}{RED}{COMMA2D STR_1354 :{WINDOW_COLOUR_2}Korkein pudotuskorkeus: {BLACK}{LENGTH} STR_1355 :{WINDOW_COLOUR_2}Pudotuksia: {BLACK}{COMMA16} STR_1356 :{WINDOW_COLOUR_2}Käänteitä: {BLACK}{COMMA16} -STR_1357 :{WINDOW_COLOUR_2}Reikää: {BLACK}{COMMA16} -STR_1358 :{WINDOW_COLOUR_2}ilma-aika' yhteensä: {BLACK}{COMMA2DP32}secs +STR_1357 :{WINDOW_COLOUR_2}Reikiä: {BLACK}{COMMA16} +#1358 Airtime is used in finnish for the lack of a better word +STR_1358 :{WINDOW_COLOUR_2}airtime yhteensä: {BLACK}{COMMA2DP32}secs STR_1359 :{WINDOW_COLOUR_2}Jonotusaika: {BLACK}{COMMA16} minuutti STR_1360 :{WINDOW_COLOUR_2}Jonotusaika: {BLACK}{COMMA16} minuuttia STR_1361 :Nopeuden muuttaminen ei onnistu... STR_1362 :Lähtönopeuden muuttaminen ei onnistu... STR_1363 :Liian korkealla tukia varten! -STR_1364 :Ylemmän laitteen tukia ei voida laajentaa pidemmälle! -STR_1365 :Hallittava kierre (vasen) -STR_1366 :Hallittava kierre (oikea) -STR_1367 :Puolikas silmukka +STR_1364 :Ylemmän radan tukia ei voida laajentaa pidemmälle! +STR_1365 :Suora kierre (vasen) +STR_1366 :Suora kierre (oikea) +STR_1367 :Puolisilmukka STR_1368 :Puolikas korkkiruuvi (vasen) STR_1369 :Puolikas korkkiruuvi (oikea) -STR_1370 :Tynnyrivierre (vasen) -STR_1371 :Tynnyrivierre (oikea) +STR_1370 :Tynnyrikierre (vasen) +STR_1371 :Tynnyrikierre (oikea) STR_1372 :Laukaistu nostomäki -STR_1373 :Iso puolikas silmukka (vasen) -STR_1374 :Iso puolikas silmukka (oikea) -STR_1375 :Ylempi siirto -STR_1376 :Alempi siirto -STR_1377 :Sydämen viiva vierähdys (vasen) -STR_1378 :Sydämen viiva vierähdys (oikea) -STR_1379 :Käännin (vasen) -STR_1380 :Käännin (oikea) +STR_1373 :Iso puolisilmukka (vasen) +STR_1374 :Iso puolisilmukka (oikea) +STR_1375 :Siirto ylös +STR_1376 :Siirto alas +STR_1377 :Sydänviivakierähdys (vasen) +STR_1378 :Sydänviivakierähdys (oikea) +STR_1379 :Suunnanvaihtaja (vasen) +STR_1380 :Suunnanvaihtaja (oikea) STR_1381 :Kaareva nostomäki (vasen) STR_1382 :Kaareva nostomäki (oikea) -STR_1383 :Neljännesosa silmukka +STR_1383 :Neljännesosasilmukka STR_1384 :{YELLOW}{STRINGID} STR_1385 :{SMALLFONT}{BLACK}Muut radan asetukset STR_1386 :Erikoinen... @@ -1402,10 +1404,10 @@ STR_1395 :{SMALLFONT}{BLACK}Huoltoasetukset STR_1396 :{SMALLFONT}{BLACK}Värityylin asetukset STR_1397 :{SMALLFONT}{BLACK}Ääni- ja musiikkiasetukset STR_1398 :{SMALLFONT}{BLACK}Mitat- ja testitiedot -STR_1399 :{SMALLFONT}{BLACK}Kaaviokuvat +STR_1399 :{SMALLFONT}{BLACK}Kaaviot STR_1400 :Sisäänkäynti STR_1401 :Uloskäynti -STR_1402 :{SMALLFONT}{BLACK}Rakenna tai siirrä sisäänkäynti laitteesta/kohteesta +STR_1402 :{SMALLFONT}{BLACK}Rakenna tai siirrä sisäänkäynti laitteeseen/kohteeseen STR_1403 :{SMALLFONT}{BLACK}Rakenna tai siirrä uloskäynti laitteesta/kohteesta STR_1404 :{SMALLFONT}{BLACK}Käännä 90{DEGREE} STR_1405 :{SMALLFONT}{BLACK}Peilaa kuva @@ -1420,13 +1422,13 @@ STR_1413 :{WINDOW_COLOUR_3}Tietojen keruu alkaa kun seuraava {STRINGID} läht STR_1414 :{SMALLFONT}{BLACK}{DURATION} STR_1415 :{WINDOW_COLOUR_2}Nopeus STR_1416 :{WINDOW_COLOUR_2}Korkeus -STR_1417 :{WINDOW_COLOUR_2}Vert. G-voima +STR_1417 :{WINDOW_COLOUR_2}Pyst. G-voima STR_1418 :{WINDOW_COLOUR_2}Sivut. G-voima STR_1419 :{SMALLFONT}{BLACK}{VELOCITY} STR_1420 :{SMALLFONT}{BLACK}{LENGTH} STR_1421 :{SMALLFONT}{BLACK}{COMMA16}g -STR_1422 :{SMALLFONT}{BLACK}Kerätään tietoja {POP16}{STRINGID} -STR_1423 :{SMALLFONT}{BLACK}Jonolinjaston tie +STR_1422 :{SMALLFONT}{BLACK}Kerätään tietoja kohteesta {POP16}{STRINGID} +STR_1423 :{SMALLFONT}{BLACK}Jonolinjasto STR_1424 :{SMALLFONT}{BLACK}Jalkakäytävä STR_1425 :Jalkakäytävä STR_1426 :Jonolinjasto @@ -1436,7 +1438,7 @@ STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} STR_1430 :Ilmainen STR_1431 :Kävelee STR_1432 :Menossa kohti {STRINGID} -STR_1433 :Jonottaa {STRINGID} +STR_1433 :Jonottaa laitteeseen {STRINGID} STR_1434 :Hukkuu #these following 3 would require extra coding, so i will leave them default for now STR_1435 :On {STRINGID} @@ -1486,12 +1488,12 @@ STR_1478 :{WINDOW_COLOUR_2}Pahoinvoinnin arvosana: {BLACK}{COMMA2DP32} ({STR STR_1479 :{WINDOW_COLOUR_2}Pahoinvoinnin arvosana: {BLACK}Ei viellä saatavilla STR_1480 :{SMALLFONT}{OPENQUOTES}Minulla ei ole varaa mennä {STRINGID}{ENDQUOTES} STR_1481 :{SMALLFONT}{OPENQUOTES}Kulutin kaikki rahani{ENDQUOTES} -STR_1482 :{SMALLFONT}{OPENQUOTES}Tunnen oloni kamalaksi{ENDQUOTES} -STR_1483 :{SMALLFONT}{OPENQUOTES}Tunnen oloni todella kamalaksi{ENDQUOTES} +STR_1482 :{SMALLFONT}{OPENQUOTES}Voin pahoin{ENDQUOTES} +STR_1483 :{SMALLFONT}{OPENQUOTES}Voin erittäin pahoin{ENDQUOTES} STR_1484 :{SMALLFONT}{OPENQUOTES}Tahdon mennä johonkin jännittävämpään kuin {STRINGID}{ENDQUOTES} STR_1485 :{SMALLFONT}{OPENQUOTES}{STRINGID} näyttää liian hurjalta minulle{ENDQUOTES} STR_1486 :{SMALLFONT}{OPENQUOTES}En ole syönyt/juonut {STRINGID} loppuun vielä{ENDQUOTES} -STR_1487 :{SMALLFONT}{OPENQUOTES}Pelkästään {STRINGID} katsominen saa minut tuntemaan oloni kamalaksi{ENDQUOTES} +STR_1487 :{SMALLFONT}{OPENQUOTES}Pelkästään {STRINGID} katsominen saa minut voimaan pahoin{ENDQUOTES} STR_1488 :{SMALLFONT}{OPENQUOTES}En aio maksaa noin paljon päästäkseni {STRINGID}{ENDQUOTES} STR_1489 :{SMALLFONT}{OPENQUOTES}Haluan kotiin{ENDQUOTES} STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} on todella hyvän arvoinen{ENDQUOTES} @@ -1521,33 +1523,33 @@ STR_1513 :{SMALLFONT}{OPENQUOTES}Täällä on todella paljon ilkivaltaa{ENDQU STR_1514 :{SMALLFONT}{OPENQUOTES}Mahtava maisema!{ENDQUOTES} STR_1515 :{SMALLFONT}{OPENQUOTES}Tämä puisto on todella puhdas ja siisti{ENDQUOTES} STR_1516 :{SMALLFONT}{OPENQUOTES}Hyppivät suihkulähteet ovat todella mahtavia!{ENDQUOTES} -STR_1517 :{SMALLFONT}{OPENQUOTES}Täällä oleva musiikki on hienoa{ENDQUOTES} -STR_1518 :{SMALLFONT}{OPENQUOTES}Tämä ilmapallo kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1519 :{SMALLFONT}{OPENQUOTES}Tämä pehmolelu kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1520 :{SMALLFONT}{OPENQUOTES}Tämä puiston kartta kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1521 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1522 :{SMALLFONT}{OPENQUOTES}Tämä sateenvarjo kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1523 :{SMALLFONT}{OPENQUOTES}Tämä juoma kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1524 :{SMALLFONT}{OPENQUOTES}Tämä hampurilainen kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1525 :{SMALLFONT}{OPENQUOTES}Nämä ranskalaiset kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1526 :{SMALLFONT}{OPENQUOTES}Tämä jäätelö kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1527 :{SMALLFONT}{OPENQUOTES}Tämä hattara kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} +STR_1517 :{SMALLFONT}{OPENQUOTES}Täällä oleva musiikki on mukavaa{ENDQUOTES} +STR_1518 :{SMALLFONT}{OPENQUOTES}Tämä ilmapallo kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1519 :{SMALLFONT}{OPENQUOTES}Tämä pehmolelu kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1520 :{SMALLFONT}{OPENQUOTES}Tämä puiston kartta kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1521 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1522 :{SMALLFONT}{OPENQUOTES}Tämä sateenvarjo kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1523 :{SMALLFONT}{OPENQUOTES}Tämä juoma kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1524 :{SMALLFONT}{OPENQUOTES}Tämä hampurilainen kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1525 :{SMALLFONT}{OPENQUOTES}Nämä ranskalaiset kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1526 :{SMALLFONT}{OPENQUOTES}Tämä jäätelö kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1527 :{SMALLFONT}{OPENQUOTES}Tämä hattara kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} STR_1528 : STR_1529 : STR_1530 : -STR_1531 :{SMALLFONT}{OPENQUOTES}Tämä pitsa kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} +STR_1531 :{SMALLFONT}{OPENQUOTES}Tämä pitsa kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} STR_1532 : -STR_1533 :{SMALLFONT}{OPENQUOTES}Tämä popcorn kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1534 :{SMALLFONT}{OPENQUOTES}Tämä nakkisämpylä kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1535 :{SMALLFONT}{OPENQUOTES}Tämä lonkero kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1536 :{SMALLFONT}{OPENQUOTES}Tämä hattu kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1537 :{SMALLFONT}{OPENQUOTES}Tämä toffeeomena kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1538 :{SMALLFONT}{OPENQUOTES}Tämä t-paita kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1539 :{SMALLFONT}{OPENQUOTES}Tämä donitsi kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1540 :{SMALLFONT}{OPENQUOTES}Tämä kahvi kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} +STR_1533 :{SMALLFONT}{OPENQUOTES}Tämä popcorn kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1534 :{SMALLFONT}{OPENQUOTES}Tämä nakkisämpylä kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1535 :{SMALLFONT}{OPENQUOTES}Tämä lonkero kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1536 :{SMALLFONT}{OPENQUOTES}Tämä hattu kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1537 :{SMALLFONT}{OPENQUOTES}Tämä toffeeomena kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1538 :{SMALLFONT}{OPENQUOTES}Tämä t-paita kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1539 :{SMALLFONT}{OPENQUOTES}Tämä donitsi kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1540 :{SMALLFONT}{OPENQUOTES}Tämä kahvi kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} STR_1541 : -STR_1542 :{SMALLFONT}{OPENQUOTES}Tämä friteerattu kana kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1543 :{SMALLFONT}{OPENQUOTES}Tämä limonaati {STRINGID} on todella hyvän arvoinen{ENDQUOTES} +STR_1542 :{SMALLFONT}{OPENQUOTES}Tämä friteerattu kana kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1543 :{SMALLFONT}{OPENQUOTES}Tämä limonaati {STRINGID} on todella hyvän hintainen{ENDQUOTES} STR_1544 : STR_1545 : STR_1546 : @@ -1569,7 +1571,7 @@ STR_1561 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon hattarasta kojussa {STR STR_1562 : STR_1563 : STR_1564 : -STR_1565 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon hattarasta kojussa {STRINGID}{ENDQUOTES} +STR_1565 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon pitsasta kojussa {STRINGID}{ENDQUOTES} STR_1566 : STR_1567 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon popcornista kojussa {STRINGID}{ENDQUOTES} STR_1568 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon nakkisämpylästä kojussa {STRINGID}{ENDQUOTES} @@ -1581,34 +1583,34 @@ STR_1573 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon donitsista kojussa {STR STR_1574 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon kahvista kojussa {STRINGID}{ENDQUOTES} STR_1575 : STR_1576 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon friteeratusta kanasta kojussa {STRINGID}{ENDQUOTES} -STR_1577 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon limonaatista kojussa {STRINGID}{ENDQUOTES} +STR_1577 :{SMALLFONT}{OPENQUOTES}En maksa noin paljon limonaadista kojussa {STRINGID}{ENDQUOTES} STR_1578 : STR_1579 : STR_1580 : STR_1581 : STR_1582 : STR_1583 : -STR_1584 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1585 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1586 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1587 :{SMALLFONT}{OPENQUOTES}Tämä viipurinrinkeli kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1588 :{SMALLFONT}{OPENQUOTES}Tämä kuuma kaakao kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1589 :{SMALLFONT}{OPENQUOTES}Tämä jäätee kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1590 :{SMALLFONT}{OPENQUOTES}Tämä tippaleipä kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1591 :{SMALLFONT}{OPENQUOTES}TNämä aurinkolasit kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1592 :{SMALLFONT}{OPENQUOTES}Nämä häränlihanuudelit kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1593 :{SMALLFONT}{OPENQUOTES}Nämä paistetut riisinuudelit kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1594 :{SMALLFONT}{OPENQUOTES}Tämä wontonkeitto kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1595 :{SMALLFONT}{OPENQUOTES}Tämä lihapullakeitto kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1596 :{SMALLFONT}{OPENQUOTES}Tämä hedelmämehu kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1597 :{SMALLFONT}{OPENQUOTES}Tämä soijamaito kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1598 :{SMALLFONT}{OPENQUOTES}Tämä sujongkwa kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1599 :{SMALLFONT}{OPENQUOTES}Tämä pantonki kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} -STR_1600 :{SMALLFONT}{OPENQUOTES}Tämä keksi kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} +STR_1584 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1585 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1586 :{SMALLFONT}{OPENQUOTES}Tämä kuva kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1587 :{SMALLFONT}{OPENQUOTES}Tämä viipurinrinkeli kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1588 :{SMALLFONT}{OPENQUOTES}Tämä kuuma kaakao kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1589 :{SMALLFONT}{OPENQUOTES}Tämä jäätee kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1590 :{SMALLFONT}{OPENQUOTES}Tämä tippaleipä kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1591 :{SMALLFONT}{OPENQUOTES}TNämä aurinkolasit kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1592 :{SMALLFONT}{OPENQUOTES}Nämä häränlihanuudelit kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1593 :{SMALLFONT}{OPENQUOTES}Nämä paistetut riisinuudelit kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1594 :{SMALLFONT}{OPENQUOTES}Tämä wontonkeitto kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1595 :{SMALLFONT}{OPENQUOTES}Tämä lihapullakeitto kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1596 :{SMALLFONT}{OPENQUOTES}Tämä hedelmämehu kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1597 :{SMALLFONT}{OPENQUOTES}Tämä soijamaito kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1598 :{SMALLFONT}{OPENQUOTES}Tämä sujongkwa kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1599 :{SMALLFONT}{OPENQUOTES}Tämä pantonki kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} +STR_1600 :{SMALLFONT}{OPENQUOTES}Tämä keksi kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} STR_1601 : STR_1602 : STR_1603 : -STR_1604 :{SMALLFONT}{OPENQUOTES}Tämä grillattu makkara kojusta {STRINGID} on todella hyvän arvoinen{ENDQUOTES} +STR_1604 :{SMALLFONT}{OPENQUOTES}Tämä grillattu makkara kojusta {STRINGID} on todella hyvän hintainen{ENDQUOTES} STR_1605 : STR_1606 : STR_1607 : @@ -1659,19 +1661,19 @@ STR_1651 :{SMALLFONT}{OPENQUOTES}Hieno laite! Mutta se ei ole yhtä hyvä kui STR_1652 :{SMALLFONT}{OPENQUOTES}Olen niin innoissani - se on Intaminlaite!{ENDQUOTES} STR_1653 :{SMALLFONT}{OPENQUOTES}...ja tässä me olemme {STRINGID}!{ENDQUOTES} STR_1654 :{WINDOW_COLOUR_2}Viimeisimmät ajatukset: -STR_1655 :{SMALLFONT}{BLACK}Construct footpath on land -STR_1656 :{SMALLFONT}{BLACK}Construct bridge or tunnel footpath -STR_1657 :{WINDOW_COLOUR_2}Preferred ride -STR_1658 :{WINDOW_COLOUR_2}intensity: {BLACK}less than {COMMA16} -STR_1659 :{WINDOW_COLOUR_2}intensity: {BLACK}between {COMMA16} and {COMMA16} -STR_1660 :{WINDOW_COLOUR_2}intensity: {BLACK}more than {COMMA16} -STR_1661 :{WINDOW_COLOUR_2}Nausea tolerance: {BLACK}{STRINGID} +STR_1655 :{SMALLFONT}{BLACK}Rakenna jalkakäytävä maahan +STR_1656 :{SMALLFONT}{BLACK}Rakenna jalkakäytävätunneli tai -silta +STR_1657 :{WINDOW_COLOUR_2}Suosikkilaite +STR_1658 :{WINDOW_COLOUR_2}Intensiteetti: {BLACK}vähemmän kuin {COMMA16} +STR_1659 :{WINDOW_COLOUR_2}Intensiteetti: {BLACK}{COMMA16}:n ja {COMMA16}:n välillä +STR_1660 :{WINDOW_COLOUR_2}Intensiteetti: {BLACK}enemmän kuin {COMMA16} +STR_1661 :{WINDOW_COLOUR_2}Pahoinvointitoleranssi: {BLACK}{STRINGID} STR_1662 :{WINDOW_COLOUR_2}Onnellisuus: -STR_1663 :{WINDOW_COLOUR_2}Nausea: +STR_1663 :{WINDOW_COLOUR_2}Pahoinvointi: STR_1664 :{WINDOW_COLOUR_2}Energia: STR_1665 :{WINDOW_COLOUR_2}Nälkä: STR_1666 :{WINDOW_COLOUR_2}Jano: -STR_1667 :{WINDOW_COLOUR_2}Vessa: +STR_1667 :{WINDOW_COLOUR_2}Vessahätä: STR_1668 :{WINDOW_COLOUR_2}Tyytyväisyys: {BLACK}Tuntematon STR_1669 :{WINDOW_COLOUR_2}Tyytyväisyys: {BLACK}{COMMA16}% STR_1670 :{WINDOW_COLOUR_2}Asiakkaiden määrä: {BLACK}{COMMA32} @@ -1680,29 +1682,29 @@ STR_1672 :Jarrut STR_1673 :Spinning Control Toggle Track STR_1674 :Jarrutusnopeus STR_1675 :{POP16}{VELOCITY} -STR_1676 :{SMALLFONT}{BLACK}Set speed limit for brakes +STR_1676 :{SMALLFONT}{BLACK}Aseta jarrujen nopeusrajoitus STR_1677 :{WINDOW_COLOUR_2}Suosio: {BLACK}Tuntematon STR_1678 :{WINDOW_COLOUR_2}Suosio: {BLACK}{COMMA16}% -STR_1679 :Helix up (left) -STR_1680 :Helix up (right) -STR_1681 :Helix down (left) -STR_1682 :Helix down (right) -STR_1683 :Base size 2 x 2 -STR_1684 :Base size 4 x 4 -STR_1685 :Base size 2 x 4 -STR_1686 :Base size 5 x 1 -STR_1687 :Water splash -STR_1688 :Base size 4 x 1 +STR_1679 :Ruuvikierre ylös (vasen) +STR_1680 :Ruuvikierre ylös (oikea) +STR_1681 :Ruuvikierre alas (vasen) +STR_1682 :Ruuvikierre alas (oikea) +STR_1683 :Pohjan koko 2 x 2 +STR_1684 :Pohjan koko 4 x 4 +STR_1685 :Pohjan koko 2 x 4 +STR_1686 :Pohjan koko 5 x 1 +STR_1687 :Vesieste +STR_1688 :Pohjan koko 4 x 1 STR_1689 :Block brakes STR_1690 :{WINDOW_COLOUR_2}{STRINGID}{NEWLINE}{BLACK}{STRINGID} STR_1691 :{WINDOW_COLOUR_2} Hinta: {BLACK}{CURRENCY} -STR_1692 :{WINDOW_COLOUR_2} Cost: {BLACK}from {CURRENCY} +STR_1692 :{WINDOW_COLOUR_2} Hinta: {BLACK}from {CURRENCY} STR_1693 :{SMALLFONT}{BLACK}Vieraat STR_1694 :{SMALLFONT}{BLACK}Henkilökunta STR_1695 :{SMALLFONT}{BLACK}Tulot ja kulut STR_1696 :{SMALLFONT}{BLACK}Asiakkaan tiedot -STR_1697 :Cannot place these on queue line area -STR_1698 :Can only place these on queue area +STR_1697 :Näitä ei voi asettaa jonotusalueelle +STR_1698 :Nämä täytyy asettaa jonotusalueelle STR_1699 :Liikaa henkilöitä pelissä STR_1700 :Palkkaa uusi yleismies STR_1701 :Palkkaa uusi mekaanikko @@ -1715,7 +1717,7 @@ STR_1707 :Liikaa henkilökuntaa pelissä STR_1708 :{SMALLFONT}{BLACK}Set patrol area for this staff member STR_1709 :Irtisano henkilökunta STR_1710 :Kyllä -STR_1711 :{WINDOW_COLOUR_1}Are you sure you want to sack {STRINGID}? +STR_1711 :{WINDOW_COLOUR_1}Haluatko varmasti irtisanoa {STRINGID}? STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Harjaa jalkakäytävät STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Kastele puutarhat STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Tyhjennä roskakorit @@ -1736,9 +1738,9 @@ STR_1728 :Rakennusoikeuksia ei voi ostaa tähän... STR_1729 :Maa ei ole puiston omistuksessa! STR_1730 :{RED}Suljettu - - STR_1731 :{WHITE}{STRINGID} - - -STR_1732 :Build -STR_1733 :Mode -STR_1734 :{WINDOW_COLOUR_2}Kierroston määrä: +STR_1732 :Rakenna +STR_1733 :Moodi +STR_1734 :{WINDOW_COLOUR_2}Kierrosten määrä: STR_1735 :{SMALLFONT}{BLACK}Kierrosten määrä radalla STR_1736 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1737 :{COMMA16} @@ -1746,8 +1748,8 @@ STR_1738 :Kierrosten määrää ei voitu muuttaa... STR_1739 :Kisan voitti vieras {INT32} STR_1740 :Kisan voitti {STRINGID} STR_1741 :Ei ole vielä rakennettu ! -STR_1742 :{WINDOW_COLOUR_2}Max. people on ride: -STR_1743 :{SMALLFONT}{BLACK}Maximum number of people allowed on this ride at one time +STR_1742 :{WINDOW_COLOUR_2}Laitteen suurin kävijämäärä: +STR_1743 :{SMALLFONT}{BLACK}Laitteen suurin sallittu kävijämäärä yhdellä kertaa STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1745 :{COMMA16} STR_1746 :Tätä ei voitu muuttaa... @@ -1762,9 +1764,9 @@ STR_1754 :{BLACK}{COMMA16} vieraat STR_1755 :{BLACK}{COMMA16} vieras STR_1756 :{WINDOW_COLOUR_2}Sisäänpääsymaksu: STR_1757 :{WINDOW_COLOUR_2}Luotettavuus: {MOVE_X}{255}{BLACK}{COMMA16}% -STR_1758 :{SMALLFONT}{BLACK}Build mode -STR_1759 :{SMALLFONT}{BLACK}Move mode -STR_1760 :{SMALLFONT}{BLACK}Fill-in mode +STR_1758 :{SMALLFONT}{BLACK}Rakennustoiminto +STR_1759 :{SMALLFONT}{BLACK}Siirtotoiminto +STR_1760 :{SMALLFONT}{BLACK}Täyttötoiminto STR_1761 :{SMALLFONT}{BLACK}Rakenna labyrinttia tähän suuntaan STR_1762 :Vesiputoukset STR_1763 :Kosket @@ -1778,7 +1780,7 @@ STR_1770 :{SMALLFONT}{BLACK}Kokonaisten heilahdusten määrä STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1772 :{COMMA16} STR_1773 :Only one on-ride photo section allowed per ride -STR_1774 :Only one cable lift hill allowed per ride +STR_1774 :Vain yksi nostomäki sallittu per laite STR_1775 :Pois päältä STR_1776 :Päällä STR_1777 :{WINDOW_COLOUR_2}Musiikki @@ -1796,28 +1798,28 @@ STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Seriffipuku STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Merirosvopuku STR_1790 :{SMALLFONT}{BLACK}Valitse virka-asun väri tämän tyyppisille henkilökunnille STR_1791 :{WINDOW_COLOUR_2}Virka-asun väri: -STR_1792 :Responding to {STRINGID} breakdown call -STR_1793 :Heading to {STRINGID} for an inspection +STR_1792 :Vastaamassa {STRINGID}:n hajoamisilmoitukseen +STR_1793 :Matkalla kohti {STRINGID} tarkistusta varten STR_1794 :Korjataan {STRINGID} STR_1795 :Vastataan radiopuheluun -STR_1796 :Has broken down and requires fixing -STR_1797 :This option cannot be changed for this ride +STR_1796 :Hajonnut ja korjauksen tarpeessa +STR_1797 :Tätä asetusta ei voida muuttaa tälle laitteelle STR_1798 :Whirlpool STR_1799 :{POP16}{POP16}{POP16}{POP16}{POP16}{CURRENCY2DP} -STR_1800 :Safety cut-out -STR_1801 :Restraints stuck closed -STR_1802 :Restraints stuck open -STR_1803 :Doors stuck closed -STR_1804 :Doors stuck open +STR_1800 :Turvakatkaisu +STR_1801 :Turvakaaret jumittuneet kiinni +STR_1802 :Turvakaaret jumittuneet auki +STR_1803 :Ovet jumittuneet kiinni +STR_1804 :Ovet jumittuneet auki STR_1805 :Ajoneuvotoimintahäiriö STR_1806 :Jarruvirhe STR_1807 :Ohjausvirhe -STR_1808 :{WINDOW_COLOUR_2}Last breakdown: {BLACK}{STRINGID} -STR_1809 :{WINDOW_COLOUR_2}Current breakdown: {OUTLINE}{RED}{STRINGID} -STR_1810 :{WINDOW_COLOUR_2}Carrying: +STR_1808 :{WINDOW_COLOUR_2}Viimeisin konerikko: {BLACK}{STRINGID} +STR_1809 :{WINDOW_COLOUR_2}Nykyinen konerikko: {OUTLINE}{RED}{STRINGID} +STR_1810 :{WINDOW_COLOUR_2}Kantaa: STR_1811 :Tätä ei voi rakentaa tähän... STR_1812 :{SMALLFONT}{BLACK}{STRINGID} -STR_1813 :Miscellaneous Objects +STR_1813 :Sekalaiset tavarat STR_1814 :Toiminnat STR_1815 :Ajatukset STR_1816 :{SMALLFONT}{BLACK}Valitse näytettävä tietotyyppi vieras listalle @@ -1827,9 +1829,9 @@ STR_1819 :{WINDOW_COLOUR_2}Kaikki vieraat (yhteenvetona) STR_1820 :{WINDOW_COLOUR_2}Vieraat {STRINGID} STR_1821 :{WINDOW_COLOUR_2}Vieraat ajattelevat {STRINGID} STR_1822 :{WINDOW_COLOUR_2}Vieraat ajattelevat {POP16}{STRINGID} -STR_1823 :{SMALLFONT}{BLACK}Show guests' thoughts about this ride/attraction -STR_1824 :{SMALLFONT}{BLACK}Show guests on this ride/attraction -STR_1825 :{SMALLFONT}{BLACK}Show guests queuing for this ride/attraction +STR_1823 :{SMALLFONT}{BLACK}Näytä vieraiden ajatukset tästä laitteesta/kohteesta +STR_1824 :{SMALLFONT}{BLACK}Näytä vieraat tässä laitteessa/kohteessa +STR_1825 :{SMALLFONT}{BLACK}Näytä tähän laitteeseen/kohteesen jonottavat vieraat STR_1826 :Tilanne STR_1827 :Suosio STR_1828 :Tyytyväisyys @@ -1846,9 +1848,9 @@ STR_1838 :Tyytyväisyys: {COMMA16}% STR_1839 :Luotettavuus: {COMMA16}% STR_1840 :Keskeytysaika: {COMMA16}% STR_1841 :Tuotto: {CURRENCY2DP} per tunti -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_1842 :{COMMA16} vieraan lempilaite +STR_1843 :{COMMA16} vieraan lempilaite +STR_1844 :{SMALLFONT}{BLACK}valitse tietotyyppi laite-/kohdelistalle STR_1845 :{MONTHYEAR} STR_1846 :{COMMA16} vierasta STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} vierasta @@ -1872,9 +1874,9 @@ STR_1864 :Mekaanikko STR_1865 :Vartija STR_1866 :Viihdyttäjä STR_1867 :{BLACK}{COMMA16} {STRINGID} -STR_1868 :Can't change number of rotations... -STR_1869 :{WINDOW_COLOUR_2}Number of rotations: -STR_1870 :{SMALLFONT}{BLACK}Number of complete rotations +STR_1868 :Kierrosten määrää ei voi muuttaa... +STR_1869 :{WINDOW_COLOUR_2}Kierrosten määrä: +STR_1870 :{SMALLFONT}{BLACK}Täysien kierrosten määrä STR_1871 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1872 :{COMMA16} STR_1873 :{WINDOW_COLOUR_2}Tulo: {BLACK}{CURRENCY2DP} per tunti @@ -1895,65 +1897,65 @@ STR_1887 :{WINDOW_COLOUR_2}Viimeinen tarkastus: {BLACK}{COMMA16} minuuttia si STR_1888 :{WINDOW_COLOUR_2}Viimeinen tarkistus: {BLACK}yli 4 tuntia sitten STR_1889 :{WINDOW_COLOUR_2}Keskeytysaika: {MOVE_X}{255}{BLACK}{COMMA16}% STR_1890 :{SMALLFONT}{BLACK}Valitse kuinka usein mekaanikko tarkistaa tämän ajelun -STR_1891 :No {STRINGID} in park yet! +STR_1891 :Puistossa ei vielä ole {STRINGID} ! # The following two strings were used to display an error when the disc was missing. # This has been replaced in OpenRCT2. STR_1892 : STR_1893 : STR_1894 :{WINDOW_COLOUR_2}{STRINGID} myyty: {BLACK}{COMMA32} -STR_1895 :{SMALLFONT}{BLACK}Build new ride/attraction -STR_1896 :{WINDOW_COLOUR_2}Expenditure/Income -STR_1897 :{WINDOW_COLOUR_2}Ride construction -STR_1898 :{WINDOW_COLOUR_2}Ajelun käyttökulut +STR_1895 :{SMALLFONT}{BLACK}Rakenna uusi laite/kohde +STR_1896 :{WINDOW_COLOUR_2}Rahan käyttö/tulot +STR_1897 :{WINDOW_COLOUR_2}Laitteiden rakennus +STR_1898 :{WINDOW_COLOUR_2}Laitteiden käyttökulut STR_1899 :{WINDOW_COLOUR_2}Maahankinnat STR_1900 :{WINDOW_COLOUR_2}Maisemointi STR_1901 :{WINDOW_COLOUR_2}Puiston sisäänpääsyliput -STR_1902 :{WINDOW_COLOUR_2}Ajeluliput +STR_1902 :{WINDOW_COLOUR_2}Liput laitteisiin STR_1903 :{WINDOW_COLOUR_2}Kojujen myynnit -STR_1904 :{WINDOW_COLOUR_2}Shop stock +STR_1904 :{WINDOW_COLOUR_2}Kauppojen varasto STR_1905 :{WINDOW_COLOUR_2}Ruoka-/juomamyynnit -STR_1906 :{WINDOW_COLOUR_2}Food/drink stock +STR_1906 :{WINDOW_COLOUR_2}Ruoka-/juomavarasto STR_1907 :{WINDOW_COLOUR_2}Henkilökunnan palkat STR_1908 :{WINDOW_COLOUR_2}Markkinointi STR_1909 :{WINDOW_COLOUR_2}Tutkimustyö STR_1910 :{WINDOW_COLOUR_2}Lainan korko -STR_1911 :{BLACK} at {COMMA16}% per year +STR_1911 :{BLACK} {COMMA16}% vuodessa STR_1912 :{MONTH} STR_1913 :{BLACK}+{CURRENCY2DP} STR_1914 :{BLACK}{CURRENCY2DP} STR_1915 :{RED}{CURRENCY2DP} STR_1916 :{WINDOW_COLOUR_2}Laina: STR_1917 :{POP16}{POP16}{POP16}{CURRENCY} -STR_1918 :Ei voi enempää lainata rahaa! +STR_1918 :Ei voi lainata enempää rahaa! STR_1919 :Rahaa ei ole tarpeeksi! STR_1920 :Lainan takaisin maksaminen ei onnistunut! STR_1921 :{SMALLFONT}{BLACK}Aloita uusi peli STR_1922 :{SMALLFONT}{BLACK}Jatka tallennetun pelin pelaamista -STR_1923 :{SMALLFONT}{BLACK}Show tutorial +STR_1923 :{SMALLFONT}{BLACK}Näytä tutoriaali STR_1924 :{SMALLFONT}{BLACK}Lopeta STR_1925 :Henkilöä ei voi sijoittaa tähän... STR_1926 :{SMALLFONT} STR_1927 :{YELLOW}{STRINGID} on hajonnut STR_1928 :{RED}{STRINGID} on hajonnut! -STR_1929 :{RED}{STRINGID} still hasn't been fixed{NEWLINE}Check where your mechanics are and consider organizing them better -STR_1930 :{SMALLFONT}{BLACK}Turn on/off tracking information for this guest - (If tracking is on, guest's movements will be reported in the message area) -STR_1931 :{STRINGID} has joined the queue line for {STRINGID} -STR_1932 :{STRINGID} is on {STRINGID} -STR_1933 :{STRINGID} is in {STRINGID} -STR_1934 :{STRINGID} has left {STRINGID} +STR_1929 :{RED}{STRINGID} ei vieläkään ole korjattu{NEWLINE}tarkista missä mekaanikkosi ovat ja pohdi niiden parempaa sijoittelua +STR_1930 :{SMALLFONT}{BLACK}Laita vieraan seuranta päälle/pois - (kun seuranta on päällä, vieraan liikkeet raportoidaan viestialueelle) +STR_1931 :{STRINGID} on jonottamassa laitteeseen {STRINGID} +STR_1932 :{STRINGID} on laitteessa {STRINGID} +STR_1933 :{STRINGID} on laitteessa {STRINGID} +STR_1934 :{STRINGID} poistui laitteesta {STRINGID} STR_1935 :{STRINGID} on lähtenyt puistosta -STR_1936 :{STRINGID} has bought {STRINGID} -STR_1937 :{SMALLFONT}{BLACK}Show information about the subject of this message +STR_1936 :{STRINGID} osti {STRINGID} +STR_1937 :{SMALLFONT}{BLACK}Näytä tietoa tämän viestin kohteesta STR_1938 :{SMALLFONT}{BLACK}Näytä vierasnäkymä STR_1939 :{SMALLFONT}{BLACK}Näytä henkilöstönäkymä -STR_1940 :{SMALLFONT}{BLACK}Show happiness, energy, hunger etc. for this guest -STR_1941 :{SMALLFONT}{BLACK}Show which rides this guest has been on +STR_1940 :{SMALLFONT}{BLACK}Näytä tämän vieraan iloisuus, energia, nälkä yms. +STR_1941 :{SMALLFONT}{BLACK}Näytä missä laitteissa tämä vieras on käynyt STR_1942 :{SMALLFONT}{BLACK}Näytä vieraan taloustiedot STR_1943 :{SMALLFONT}{BLACK}Näytä vieraan viimeiset ajatukset STR_1944 :{SMALLFONT}{BLACK}Näytä mitä esineitä vieras kantaa -STR_1945 :{SMALLFONT}{BLACK}Show orders and options for this staff member +STR_1945 :{SMALLFONT}{BLACK}Näytä henkilökunnan jäsenen ohjeet ja asetukset STR_1946 :{SMALLFONT}{BLACK}Valitse puku viihdyttäjälle -STR_1947 :{SMALLFONT}{BLACK}Show areas patrolled by selected staff type, and locate the nearest staff member +STR_1947 :{SMALLFONT}{BLACK}Näytä valitun henkilökuntatyypin partiointialueet ja etsi lähin henkilökunnan jäsen STR_1948 :{SMALLFONT}{BLACK}Palkkaa uusi tietyn tyyppinen henkilöstön jäsen STR_1949 :Taloudellinen yhteenveto STR_1950 :Talouskuvaaja @@ -1961,11 +1963,11 @@ STR_1951 :Puiston arvokuvaaja STR_1952 :Tuottokuvaaja STR_1953 :Markkinointi STR_1954 :Tutkimustyön rahoitus -STR_1955 :{WINDOW_COLOUR_2}Number of circuits: -STR_1956 :{SMALLFONT}{BLACK}Number of circuits of track per ride +STR_1955 :{WINDOW_COLOUR_2}Kierrosten määrä: +STR_1956 :{SMALLFONT}{BLACK}Ratakierrosten määrä yhdellä käyntikerralla STR_1957 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1958 :{COMMA16} -STR_1959 :Can't change number of circuits... +STR_1959 :Kierrosten määrää ei voi muuttaa... STR_1960 :{WINDOW_COLOUR_2}Ilmapallon hinta: STR_1961 :{WINDOW_COLOUR_2}Pehmolelun hinta: STR_1962 :{WINDOW_COLOUR_2}Puiston kartan hinta: @@ -2080,8 +2082,8 @@ STR_2070 :Tyhjä rasia STR_2071 :Tyhjä pullo STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Ilmapallo STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Pehmolelu -STR_2074 :Map of {STRINGID} -STR_2075 :On-Ride Photo of {STRINGID} +STR_2074 :{STRINGID}:n Kartta +STR_2075 :Kuva {STRINGID}:sta STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Sateenvarjo STR_2077 :Juoma STR_2078 :Hampurilainen @@ -2092,7 +2094,7 @@ STR_2082 :Tyhjä tölkki STR_2083 :Roska STR_2084 :Tyhjä hampurilaisrasia STR_2085 :Pizza -STR_2086 :Voucher for {STRINGID} +STR_2086 :{STRINGID} -kuponki STR_2087 :Popcorn STR_2088 :Hot Dog STR_2089 :Lonkero @@ -2225,7 +2227,7 @@ STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOU1R_2}{COMMA16}{DEGREE}C STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F STR_2218 :{RED}{STRINGID} on {STRINGID} hasn't returned to the {STRINGID} yet!{NEWLINE}Check whether it is stuck or has stalled -STR_2219 :{RED}{COMMA16} people have died in an accident on {STRINGID} +STR_2219 :{RED}{COMMA16} ihmistä kuoli tapaturmassa kohteessa {STRINGID} STR_2220 :{WINDOW_COLOUR_2}Puiston luokitus: {BLACK}{COMMA16} STR_2221 :{SMALLFONT}{BLACK}Puiston luokitus: {COMMA16} STR_2222 :{SMALLFONT}{BLACK}{STRINGID} @@ -2234,11 +2236,11 @@ STR_2224 :{WINDOW_COLOUR_2}Kassa: {BLACK}{CURRENCY2DP} STR_2225 :{WINDOW_COLOUR_2}Kassa: {RED}{CURRENCY2DP} STR_2226 :{WINDOW_COLOUR_2}Puiston arvo: {BLACK}{CURRENCY} STR_2227 :{WINDOW_COLOUR_2}Yrityksen arvo: {BLACK}{CURRENCY} -STR_2228 :{WINDOW_COLOUR_2}Last month's profit from food/drink and{NEWLINE}merchandise sales: {BLACK}{CURRENCY} -STR_2229 :Slope up to vertical -STR_2230 :Vertical track -STR_2231 :Holding brake for drop -STR_2232 :Cable lift hill +STR_2228 :{WINDOW_COLOUR_2}Viimekuun tulot ruoan, juomien ja{NEWLINE}tavaroiden myynnistä: {BLACK}{CURRENCY} +STR_2229 :Nousu pystysuoraan +STR_2230 :Pystysuora rata +STR_2231 :Pidätysjarru pudotukseen +STR_2232 :Kaapelinostomäki STR_2233 :{SMALLFONT}{BLACK}Puiston tiedot STR_2234 :Viimeiset viestit STR_2235 :{SMALLFONT}{STRINGID} {STRINGID} @@ -2254,18 +2256,18 @@ STR_2244 :Syyskuu STR_2245 :Lokakuu STR_2246 :Marraskuu STR_2247 :Joulukuu -STR_2248 :Can't demolish ride/attraction... -STR_2249 :{BABYBLUE}New ride/attraction now available:{NEWLINE}{STRINGID} -STR_2250 :{BABYBLUE}New scenery/themeing now available:{NEWLINE}{STRINGID} -STR_2251 :Can only be built on paths! -STR_2252 :Can only be built across paths! -STR_2253 :Transport Rides -STR_2254 :Gentle Rides +STR_2248 :Ei voi romuttaa laitetta/kohdetta... +STR_2249 :{BABYBLUE}Uusi laite/kohde saatavilla:{NEWLINE}{STRINGID} +STR_2250 :{BABYBLUE}Uusi maisema/teemaus saatavilla:{NEWLINE}{STRINGID} +STR_2251 :Voidaan rakentaa ainoastaan poluille! +STR_2252 :Voidaan rakentaa ainoastaan polun poikki! +STR_2253 :Transportaatiolaitteet +STR_2254 :Lempeät laitteet STR_2255 :Vuoristoradat -STR_2256 :Thrill Rides +STR_2256 :Jännittävät Laitteet STR_2257 :Vesiajelut -STR_2258 :Shops & Stalls -STR_2259 :Scenery & Themeing +STR_2258 :Kaupat & Kojut +STR_2259 :Maisemointi & Teemaus STR_2260 :Ei rahoitusta STR_2261 :Vähimmäisrahoitus STR_2262 :Normaali rahoitus @@ -2274,65 +2276,65 @@ STR_2264 :Tutkimustyön rahoitus STR_2265 :{WINDOW_COLOUR_2}Kustannus: {BLACK}{CURRENCY} kuukaudessa STR_2266 :Tutkimustyön tärkeysjärjestykset STR_2267 :Paraikaa suunnitteilla -STR_2268 :Last development +STR_2268 :Viimeinen kehitys STR_2269 :{WINDOW_COLOUR_2}Tyyppi: {BLACK}{STRINGID} STR_2270 :{WINDOW_COLOUR_2}Edistys: {BLACK}{STRINGID} STR_2271 :{WINDOW_COLOUR_2}Odotettavista: {BLACK}{STRINGID} -STR_2272 :{WINDOW_COLOUR_2}Ride/attraction:{NEWLINE}{BLACK}{STRINGID} -STR_2273 :{WINDOW_COLOUR_2}Scenery/themeing:{NEWLINE}{BLACK}{STRINGID} -STR_2274 :{SMALLFONT}{BLACK}Show details of this invention or development +STR_2272 :{WINDOW_COLOUR_2}Laitteet/kohteet:{NEWLINE}{BLACK}{STRINGID} +STR_2273 :{WINDOW_COLOUR_2}Maisemointi/teemaus:{NEWLINE}{BLACK}{STRINGID} +STR_2274 :{SMALLFONT}{BLACK}Näytä tämän keksinnön tai kehityksen yksityiskohdat STR_2275 :{SMALLFONT}{BLACK}Show funding and options for research & development STR_2276 :{SMALLFONT}{BLACK}Show research & development status STR_2277 :Tuntematon -STR_2278 :Transport Ride -STR_2279 :Gentle Ride -STR_2280 :Roller Coaster -STR_2281 :Thrill Ride +STR_2278 :Transportaatiolaite +STR_2279 :Lempeä laite +STR_2280 :Vuoristorata +STR_2281 :Jännittävä laite STR_2282 :Vesiajelu -STR_2283 :Shop/Stall -STR_2284 :Scenery/Themeing -STR_2285 :Initial research +STR_2283 :Kauppa/Koju +STR_2284 :Maisemointi/Teemaus +STR_2285 :Pohjatutkimus STR_2286 :Suunnitellaan -STR_2287 :Completing design +STR_2287 :Viimeistellään suunnittelua STR_2288 :Tuntematon STR_2289 :{STRINGID} {STRINGID} STR_2290 :{SMALLFONT}{BLACK}{STRINGID} {STRINGID} -STR_2291 :Select scenario for new game -STR_2292 :{WINDOW_COLOUR_2}Rides been on: +STR_2291 :Valitse uuden pelin skenaario +STR_2292 :{WINDOW_COLOUR_2}Käytyjä laitteita: STR_2293 :{BLACK} Ei mitään -STR_2294 :{SMALLFONT}{BLACK}Change base land style -STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land -STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} paid to enter park -STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} ride -STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} rides -STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} item of food -STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} items of food -STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drink -STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drinks -STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenir -STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenirs -STR_2305 :Track design files -STR_2306 :Save track design -STR_2307 :Select {STRINGID} design -STR_2308 :{STRINGID} Track Designs -STR_2309 :Install New Track Design -STR_2310 :Build custom design -STR_2311 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} (approx.) -STR_2312 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} (approx.) -STR_2313 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} (approx.) +STR_2294 :{SMALLFONT}{BLACK}Vaihda pohjamaan tyyliä +STR_2295 :{SMALLFONT}{BLACK}Vaihda pystysuorien seinämien tyyliä +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Maksettu sisäänpääsyssä +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} laitteessa +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} laitteessa +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} ruokaan +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} ruokaan +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} juomaan +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} juomaan +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} matkamuistoon +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} Kulutettu {BLACK}{COMMA16} matkamuistoon +STR_2305 :Ratasuunnitelmatiedostot +STR_2306 :Tallenna ratasuunnitelma +STR_2307 :Valitse {STRINGID} suunnitelma +STR_2308 :{STRINGID} Ratasuunnitelmat +STR_2309 :Asenna uusi ratasuunnitelma +STR_2310 :Rakenna oma rata +STR_2311 :{WINDOW_COLOUR_2}Jännittävyys arvosana: {BLACK}{COMMA2DP32} (approx.) +STR_2312 :{WINDOW_COLOUR_2}Intensiteettiarvosana: {BLACK}{COMMA2DP32} (approx.) +STR_2313 :{WINDOW_COLOUR_2}Pahoinvointiarvosana: {BLACK}{COMMA2DP32} (approx.) STR_2314 :{WINDOW_COLOUR_2}Ajelun pituus: {BLACK}{STRINGID} STR_2315 :{WINDOW_COLOUR_2}Kustannus: {BLACK}noin {CURRENCY} -STR_2316 :{WINDOW_COLOUR_2}Tilaa tarvitaan: {BLACK}{COMMA16} x {COMMA16} neliöä +STR_2316 :{WINDOW_COLOUR_2}Tilaa tarvitaan: {BLACK}{COMMA16} x {COMMA16} neliötä STR_2317 : STR_2318 : STR_2319 : STR_2320 : -STR_2321 :{WINDOW_COLOUR_2}Number of rides/attractions: {BLACK}{COMMA16} +STR_2321 :{WINDOW_COLOUR_2}Laitteiden/kohteiden määrä: {BLACK}{COMMA16} STR_2322 :{WINDOW_COLOUR_2}Henkilökunta: {BLACK}{COMMA16} STR_2323 :{WINDOW_COLOUR_2}Puiston koko: {BLACK}{COMMA32}m{SQUARED} STR_2324 :{WINDOW_COLOUR_2}Puiston koko: {BLACK}{COMMA32}sq.ft. STR_2325 :{SMALLFONT}{BLACK}Osta maata laajentaakseen puistoa -STR_2326 :{SMALLFONT}{BLACK}Buy construction rights to allow construction above or below land outside the park +STR_2326 :{SMALLFONT}{BLACK}Osta rakennusoikeudet maan päälle tai alle puiston ulkopuolella STR_2327 :Asetukset STR_2328 :{WINDOW_COLOUR_2}Valuutta: STR_2329 :{WINDOW_COLOUR_2}Etäisyys ja nopeus: @@ -2354,7 +2356,7 @@ STR_2344 :Brittiläinen STR_2345 :Metrinen STR_2346 :Näytä STR_2347 :{RED}{STRINGID} on hukkunut! -STR_2348 :{SMALLFONT}{BLACK}Show statistics for this staff member +STR_2348 :{SMALLFONT}{BLACK}Näytä tämän henkilökunnan jäsenen tarkemmat tiedot STR_2349 :{WINDOW_COLOUR_2}Palkat: {BLACK}{CURRENCY} per kuukausi STR_2350 :{WINDOW_COLOUR_2}Työllistetty: {BLACK}{MONTHYEAR} STR_2351 :{WINDOW_COLOUR_2}Nurmikkoa ajettu: {BLACK}{COMMA16} @@ -2367,10 +2369,10 @@ STR_2357 :Talo STR_2358 :Yksiköt STR_2359 :Oikeat arvot STR_2360 :{WINDOW_COLOUR_2}Näytön tarkkuus -STR_2361 :Landscape Smoothing -STR_2362 :{SMALLFONT}{BLACK}Toggle landscape tile edge smoothing on/off -STR_2363 :Gridlines on Landscape -STR_2364 :{SMALLFONT}{BLACK}Toggle gridlines on landscape on/off +STR_2361 :Maan pehmennys +STR_2362 :{SMALLFONT}{BLACK}Kytke maan ruutujen pehmennys päälle/pois +STR_2363 :Ruudukko maan päällä +STR_2364 :{SMALLFONT}{BLACK}Kytke maan päällinen ruudukko päälle/pois STR_2365 :Pankki ei suostu korottamaan lainaasi! STR_2366 :Celsius ({DEGREE}C) STR_2367 :Fahrenheit ({DEGREE}F) @@ -2384,37 +2386,37 @@ STR_2374 :Korkea STR_2375 :Todella korkea STR_2376 :Extreme STR_2377 :Ultra-Extreme -STR_2378 :{SMALLFONT}{BLACK}Säädä pienempi alue maata -STR_2379 :{SMALLFONT}{BLACK}Säädä suurempi alue maata -STR_2380 :{SMALLFONT}{BLACK}Säädä pienempi alue vettä -STR_2381 :{SMALLFONT}{BLACK}Säädä suurempi alue vettä +STR_2378 :{SMALLFONT}{BLACK}Säädä pienempää maa-aluetta +STR_2379 :{SMALLFONT}{BLACK}Säädä suurempaa maa-aluetta +STR_2380 :{SMALLFONT}{BLACK}Säädä pienempää vesialuetta +STR_2381 :{SMALLFONT}{BLACK}Säädä suurempaa vesialuetta STR_2382 :Maa STR_2383 :Vesi STR_2384 :{WINDOW_COLOUR_2}Tavoitteesi: STR_2385 :{BLACK}Ei mitään -STR_2386 :{BLACK}To have at least {COMMA16} guests in your park at the end of {MONTHYEAR}, with a park rating of at least 600 -STR_2387 :{BLACK}To achieve a park value of at least {POP16}{POP16}{CURRENCY} at the end of {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} +STR_2386 :{BLACK}Puistossasi tulee olla vähintään {COMMA16} vierasta {MONTHYEAR} loppuun mennessä ja puiston arvosanan tulee olla vähintään 600 +STR_2387 :{BLACK}Saavuta puiston arvoksi vähintään {POP16}{POP16}{CURRENCY} vuoden {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} loppuun mennessä STR_2388 :{BLACK}Pidä hauskaa! -STR_2389 :{BLACK}Rakenna paras {STRINGID} kuin voit! -STR_2390 :{BLACK}To have 10 different types of roller coasters operating in your park, each with an excitement value of at least 6.00 -STR_2391 :{BLACK}To have at least {COMMA16} guests in your park. You must not let the park rating drop below 700 at any time! -STR_2392 :{BLACK}To achieve a monthly income from ride tickets of at least {POP16}{POP16}{CURRENCY} -STR_2393 :{BLACK}To have 10 different types of roller coasters operating in your park, each with a minimum length of {LENGTH}, and an excitement rating of at least 7.00 -STR_2394 :{BLACK}To finish building all 5 of the partially built roller coasters in this park, designing them to achieve excitement ratings of at least {POP16}{POP16}{COMMA2DP32} each -STR_2395 :{BLACK}To repay your loan and achieve a park value of at least {POP16}{POP16}{CURRENCY} -STR_2396 :{BLACK}To achieve a monthly profit from food, drink and merchandise sales of at least {POP16}{POP16}{CURRENCY} +STR_2389 :{BLACK}Rakenna niin hyvä {STRINGID} kuin voit! +STR_2390 :{BLACK}Puistossasi tulee olla 10 eri tyyppistä toiminnassa olevaa vuoristorataa joiden innostavuus on vähintään 6.00 +STR_2391 :{BLACK}Puistossasi tulee olla vähintään {COMMA16} vierasta, eikä puiston arvosana saa pudota alle 700 hetkeksikään! +STR_2392 :{BLACK}Sinun tulee saada {POP16}{POP16}{CURRENCY} kuukausituloja laitteiden lipputuloista +STR_2393 :{BLACK}Puistossasi tulee olla 10 eri tyyppistä toiminnassa olevaa vuoristorataa, joiden pitää olla vähintään {LENGTH} pitkiä ja joiden innostavuus on vähintään 7.00 +STR_2394 :{BLACK}Viimeistele puiston 5 osittain rakennettua vuoristorataa niin, että jokaisen innostavuus on vähintään {POP16}{POP16}{COMMA2DP32} +STR_2395 :{BLACK}Maksa lainasi takaisin ja saavuta puistolle arvo {POP16}{POP16}{CURRENCY} +STR_2396 :{BLACK}Sinun tulee saada {POP16}{POP16}{CURRENCY} kuukausituloja ruoan, juomien ja tavaroiden myynnistä STR_2397 :Ei mitään STR_2398 :Vieraiden määrä tiettynä päivänä STR_2399 :Puiston arvo tiettynä päivänä STR_2400 :Pidä hauskaa -STR_2401 :Rakenna parhaat ajelut joita voit +STR_2401 :Rakenna parhaat radat joita voit STR_2402 :Rakenna 10 vuoristorataa STR_2403 :Vieraiden määrä puistossa -STR_2404 :Kuukausittainen tulo ajelujen tuloista +STR_2404 :Kuukausitulo laitteiden tuloista STR_2405 :Rakenna 10 vuoristorataa tietyssä ajassa STR_2406 :Rakenna valmiiksi 5 vuoristorataa STR_2407 :Maksa laina pois ja saavuta tietty puiston arvo -STR_2408 :Monthly profit from food/merchandise +STR_2408 :Kuukausitulo ruuasta/kauppatavaroista STR_2409 :{WINDOW_COLOUR_2}Markkinointikampanjoja käynnissä STR_2410 :{BLACK}Ei mitään STR_2411 :{WINDOW_COLOUR_2}Markkinointikampanjoja saatavilla @@ -2424,24 +2426,24 @@ STR_2414 :(Ei valittu) STR_2415 :{WINDOW_COLOUR_2}Ajelu: STR_2416 :{WINDOW_COLOUR_2}Esine: STR_2417 :{WINDOW_COLOUR_2}Kesto: -STR_2418 :Free entry to {STRINGID} -STR_2419 :Free ride on {STRINGID} -STR_2420 :Half-price entry to {STRINGID} +STR_2418 :Vapaa pääsy laitteeseen {STRINGID} +STR_2419 :Vapaa ajelu laitteessa {STRINGID} +STR_2420 :Puolen hinnan pääsy laitteeseen {STRINGID} STR_2421 :Ilmainen {STRINGID} -STR_2422 :Advertising campaign for {STRINGID} -STR_2423 :Advertising campaign for {STRINGID} -STR_2424 :{WINDOW_COLOUR_2}Vouchers for free entry to the park -STR_2425 :{WINDOW_COLOUR_2}Vouchers for free rides on a particular ride -STR_2426 :{WINDOW_COLOUR_2}Vouchers for half-price entry to the park -STR_2427 :{WINDOW_COLOUR_2}Vouchers for free food or drink +STR_2422 :Mainoskampanja {STRINGID}:n mainostamiseksi +STR_2423 :Mainoskampanja {STRINGID}:n mainostamiseksi +STR_2424 :{WINDOW_COLOUR_2}Vapaa sisäänpääsy -kuponkeja +STR_2425 :{WINDOW_COLOUR_2}Ilmainen ajelu tietyssä laitteessa -kuponkeja +STR_2426 :{WINDOW_COLOUR_2}Puolen hinnan sisäänpääsy -kuponkeja +STR_2427 :{WINDOW_COLOUR_2}Ilmaisen ruoan tai juoman kuponkeja STR_2428 :{WINDOW_COLOUR_2}Mainoskampanja puistollesi -STR_2429 :{WINDOW_COLOUR_2}Mainoskampanja tietylle ajelulle -STR_2430 :{BLACK}Vouchers for free entry to {STRINGID} -STR_2431 :{BLACK}Vouchers for free ride on {STRINGID} -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_2429 :{WINDOW_COLOUR_2}Mainoskampanja tietylle laitteelle +STR_2430 :{BLACK}Ilmaiskuponkeja kohteeseen {STRINGID} +STR_2431 :{BLACK}Ilmaiskuponkeja laitteeseen {STRINGID} +STR_2432 :{BLACK}Puolen hinnan kuponkeja laitteeseen {STRINGID} +STR_2433 :{BLACK}Kuponkeja joilla saa ilmaisen {STRINGID} +STR_2434 :{BLACK}Mainoskampanja {STRINGID}:n mainostamiseksi +STR_2435 :{BLACK}Mainoskampanja {STRINGID}:n mainostamiseksi STR_2436 :1 viikko STR_2437 : STR_2438 : @@ -2452,76 +2454,76 @@ STR_2442 : STR_2443 :{WINDOW_COLOUR_2}Viikottainen kustannus: {BLACK}{CURRENCY2DP} STR_2444 :{WINDOW_COLOUR_2}Kokonaiskustannus: {BLACK}{CURRENCY2DP} STR_2445 :Aloita tämä markkinointikampanja -STR_2446 :{YELLOW}Markkinointikampanja ilmaisille sisäänpääsyille puistossasi on loppunut -STR_2447 :{YELLOW}Your marketing campaign for free rides on {STRINGID} has finished +STR_2446 :{YELLOW}Markkinointikampanja ilmaisille sisäänpääsyille puistoosi on loppunut +STR_2447 :{YELLOW}Markkinointikampanja ilmainen ajelu laitteella {STRINGID} on loppunut STR_2448 :{YELLOW}Markkinointikampanja sisäänpääsy puoleen hintaan puistoosi on loppunut -STR_2449 :{YELLOW}Your marketing campaign for free {STRINGID} has finished +STR_2449 :{YELLOW}Markkinointikampanja ilmaiselle {STRINGID}:lle on loppunut STR_2450 :{YELLOW}Mainoskampanjasi puistolle on loppunut -STR_2451 :{YELLOW}Your advertising campaign for {STRINGID} has finished -STR_2452 :{WINDOW_COLOUR_2}Cash (less loan): {BLACK}{CURRENCY2DP} -STR_2453 :{WINDOW_COLOUR_2}Cash (less loan): {RED}{CURRENCY2DP} +STR_2451 :{YELLOW}Mainoskampanjasi laitteelle {STRINGID} on loppunut +STR_2452 :{WINDOW_COLOUR_2}Raha (less loan): {BLACK}{CURRENCY2DP} +STR_2453 :{WINDOW_COLOUR_2}Raha (less loan): {RED}{CURRENCY2DP} STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - STR_2455 :{SMALLFONT}{BLACK}+{CURRENCY2DP} - STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} - -STR_2457 :{SMALLFONT}{BLACK}Show financial accounts -STR_2458 :{SMALLFONT}{BLACK}Show graph of cash (less loan) over time +STR_2457 :{SMALLFONT}{BLACK}Näytä taloustiedot +STR_2458 :{SMALLFONT}{BLACK}Näytä kuvaaja rahan määrästä (less loan) over time STR_2459 :{SMALLFONT}{BLACK}Näytä kuvaaja puiston arvosta STR_2460 :{SMALLFONT}{BLACK}Näytä kuvaaja viikottaisesta tuotosta STR_2461 :{SMALLFONT}{BLACK}Näytä markkinointikampanjat STR_2462 :{SMALLFONT}{BLACK}Näytä puiston sisäänkäynti -STR_2463 :{SMALLFONT}{BLACK}Show graph of park ratings over time -STR_2464 :{SMALLFONT}{BLACK}Show graph of guest numbers over time +STR_2463 :{SMALLFONT}{BLACK}Näytä kuvaaja puiston arvosanasta +STR_2464 :{SMALLFONT}{BLACK}Näytä kuvaaja vierasmääristä STR_2465 :{SMALLFONT}{BLACK}Näytä sisäänpääsyhinta ja -tiedot STR_2466 :{SMALLFONT}{BLACK}Näytä puiston tilastot STR_2467 :{SMALLFONT}{BLACK}Näytä pelin tavoitteet STR_2468 :{SMALLFONT}{BLACK}Näytä viimeiset palkinnot mitä tämä puisto on saanut -STR_2469 :{SMALLFONT}{BLACK}Select level of research & development -STR_2470 :{SMALLFONT}{BLACK}Research new transport rides -STR_2471 :{SMALLFONT}{BLACK}Research new gentle rides -STR_2472 :{SMALLFONT}{BLACK}Research new roller coasters -STR_2473 :{SMALLFONT}{BLACK}Research new thrill rides -STR_2474 :{SMALLFONT}{BLACK}Tutki uusia vesiajeluja -STR_2475 :{SMALLFONT}{BLACK}Research new shops and stalls -STR_2476 :{SMALLFONT}{BLACK}Research new scenery and themeing -STR_2477 :{SMALLFONT}{BLACK}Select operating mode for this ride/attraction -STR_2478 :{SMALLFONT}{BLACK}Show graph of velocity against time -STR_2479 :{SMALLFONT}{BLACK}Show graph of altitude against time -STR_2480 :{SMALLFONT}{BLACK}Show graph of vertical acceleration against time -STR_2481 :{SMALLFONT}{BLACK}Show graph of lateral acceleration against time -STR_2482 :{SMALLFONT}{BLACK}Tuotte: {CURRENCY} viikossa, puiston arvo: {CURRENCY} +STR_2469 :{SMALLFONT}{BLACK}Valitse tutkinnan ja kehityksen taso +STR_2470 :{SMALLFONT}{BLACK}Kehitä uusia transportaatiolaitteita +STR_2471 :{SMALLFONT}{BLACK}Kehitä uusia lempeitä laitteita +STR_2472 :{SMALLFONT}{BLACK}Kehitä uusia vuoristoratoja +STR_2473 :{SMALLFONT}{BLACK}Kehitä uusia jännittäviä laitteita +STR_2474 :{SMALLFONT}{BLACK}Kehitä uusia vesilaitteita +STR_2475 :{SMALLFONT}{BLACK}Kehitä uusia Kauppoja/Kojuja +STR_2476 :{SMALLFONT}{BLACK}Kehitä maisemointia ja teemausta +STR_2477 :{SMALLFONT}{BLACK}Valitse tämän laitteen/kohteen toimintamoodi +STR_2478 :{SMALLFONT}{BLACK}Näytä nopeuden kuvaaja ajalle +STR_2479 :{SMALLFONT}{BLACK}Näytä korkeuden kuvaaja ajalle +STR_2480 :{SMALLFONT}{BLACK}Näytä pystysuoran kiihtyvyyden kuvaaja ajalle +STR_2481 :{SMALLFONT}{BLACK}Näytä poikittaisen kiihtyvyyden kuvaaja ajalle +STR_2482 :{SMALLFONT}{BLACK}Tuotto: {CURRENCY} viikossa, puiston arvo: {CURRENCY} STR_2483 :{WINDOW_COLOUR_2}Viikottainen tuotto: {BLACK}+{CURRENCY2DP} STR_2484 :{WINDOW_COLOUR_2}Viikottainen tuotto: {RED}{CURRENCY2DP} STR_2485 :Ohjaimet STR_2486 :Yleiset STR_2487 :Näytä vieraiden 'oikeat' nimet -STR_2488 :{SMALLFONT}{BLACK}Toggle between showing 'real' names of guests and guest numbers +STR_2488 :{SMALLFONT}{BLACK}Vaihda vieraiden nimen ja numeron näyttämisen välillä STR_2489 :Pikanäppäimet... STR_2490 :Näppäimistön pikanäppäimet -STR_2491 :Reset keys -STR_2492 :{SMALLFONT}{BLACK}Set all keyboard shortcuts back to default settings -STR_2493 :Close top-most window -STR_2494 :Close all floating windows -STR_2495 :Cancel construction mode +STR_2491 :Palauta näppäinasetukset +STR_2492 :{SMALLFONT}{BLACK}Aseta kaikki pikanäppäimet takaisin alkuperäisiin asetuksiin +STR_2493 :Sulje päällimmäinen ikkuna +STR_2494 :Sulje kaikki ikkunat +STR_2495 :Poistu rakennustilasta STR_2496 :Pysäytä peli -STR_2497 :Zoom view out -STR_2498 :Zoom view in -STR_2499 :Rotate view clockwise -STR_2500 :Rotate construction object -STR_2501 :Underground view toggle -STR_2502 :Remove base land toggle -STR_2503 :Remove vertical land toggle -STR_2504 :See-through rides toggle -STR_2505 :See-through scenery toggle -STR_2506 :Invisible supports toggle -STR_2507 :Invisible people toggle -STR_2508 :Height marks on land toggle -STR_2509 :Height marks on ride tracks toggle -STR_2510 :Height marks on paths toggle +STR_2497 :Zoomaa näkymää ulos +STR_2498 :Zoomaa näkymää sisään +STR_2499 :Käännä näkymää myötäpäivään +STR_2500 :Käännä rakennettavaa tavaraa +STR_2501 :Maanalainen näkymä -kytkin +STR_2502 :Maanpinnan näkyvyys -kytkin +STR_2503 :Pystysuorien seinämien näkyvyys -kytkin +STR_2504 :Läpinäkyvät laitteet -kytkin +STR_2505 :Läpinäkyvä maisemointi -kytkin +STR_2506 :Näkymättömät tukirakenteet -kytkin +STR_2507 :Näkymättömät kävijät -kytkin +STR_2508 :Korkeusmerkit maanpinnalla -kytkin +STR_2509 :Korkeusmerkit radoilla -kytkin +STR_2510 :Korkeusmerkit kävelyteillä -kytkin STR_2511 :Säädä maata STR_2512 :Säädä vettä -STR_2513 :Build scenery -STR_2514 :Build paths -STR_2515 :Rakenna uusi ajelu +STR_2513 :Rakenna maisemaa +STR_2514 :Rakenna polkuja +STR_2515 :Rakenna uusi laite STR_2516 :Näytä taloustiedot STR_2517 :Näytä tutkimustyötiedot STR_2518 :Näytä ajelulista @@ -2688,17 +2690,17 @@ STR_2677 :??? STR_2678 :??? STR_2679 :??? STR_2680 :Kaikki tutkimustyö on tehty -STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} +STR_2681 :{MEDIUMFONT}{BLACK}Saat {CURRENCY} lisää rahaa STR_2682 : STR_2683 : -STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive +STR_2684 :{SMALLFONT}{BLACK}Suuri kävijäryhmä saapuu STR_2685 :Simplex Noise Parameters STR_2686 :{WINDOW_COLOUR_2}Matala: STR_2687 :{WINDOW_COLOUR_2}Korkea: STR_2688 :{WINDOW_COLOUR_2}Base Frequency: STR_2689 :{WINDOW_COLOUR_2}Octaves: -STR_2690 :Map Generation -STR_2691 :{WINDOW_COLOUR_2}Base height: +STR_2690 :Kartan luonti +STR_2691 :{WINDOW_COLOUR_2}Peruskorkeus: STR_2692 :{WINDOW_COLOUR_2}Vedentaso: STR_2693 :{WINDOW_COLOUR_2}Ympäristö: STR_2694 :Luo @@ -2750,7 +2752,7 @@ STR_2739 :Ei mitään STR_2740 :RollerCoaster Tycoon 1 STR_2741 :RollerCoaster Tycoon 2 STR_2742 :css50.dat ei löydy -STR_2743 :Copy data\css17.dat from your RCT1 installation to data\css50.dat in your RCT2 installation. +STR_2743 :Kopioi data\css17.dat RCT1-asennuksestasi tiedostoon data\css50.dat RCT2-asennuksessasi. STR_2744 :[ STR_2745 :\ STR_2746 :] @@ -2760,7 +2762,7 @@ STR_2749 :My new scenario # New strings used in the cheats window previously these were ??? STR_2750 :Siirrä kaikki esineet ylös STR_2751 :Siirrä kaikki esineet alas -STR_2752 :Clear grass +STR_2752 :Tyhjennä ruoho STR_2753 :Leikattu ruoho STR_2754 :Kastele kasvit STR_2755 :Korjaa tärvelöinti @@ -2774,9 +2776,9 @@ STR_2762 : STR_2763 :??? STR_2764 : STR_2765 :Large Tram -STR_2766 :Win scenario +STR_2766 :Voita skenaario STR_2767 :Jäädytä ilmasto -STR_2768 :Unfreeze Climate +STR_2768 :Sulata ilmasto STR_2769 :Avaa puisto STR_2770 :Sulje puisto STR_2771 :Hitaampi pelinopeus @@ -2794,81 +2796,81 @@ STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} STR_2782 :SHIFT + STR_2783 :CTRL + STR_2784 :Muuta näppäimistön pikanäppäintä -STR_2785 :{WINDOW_COLOUR_2}Press new shortcut key for:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} -STR_2786 :{SMALLFONT}{BLACK}Click on shortcut description to select new key +STR_2785 :{WINDOW_COLOUR_2}Paina uusi näppäinyhdistelmä toiminnolle:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2786 :{SMALLFONT}{BLACK}Paina pikanäppäimen kuvausta valitaksesi uuden näppäinyhdistelmän STR_2787 :{WINDOW_COLOUR_2}Puiston arvo: {BLACK}{CURRENCY} -STR_2788 :{WINDOW_COLOUR_2}Congratulations !{NEWLINE}{BLACK}You achieved your objective with a company value of {CURRENCY} ! +STR_2788 :{WINDOW_COLOUR_2}Onnittelut !{NEWLINE}{BLACK}Saavutit tavoitteesi ! Yhtiösi arvo: {CURRENCY} ! STR_2789 :{WINDOW_COLOUR_2}Epäonnistuit tavoitteessasi ! STR_2790 :Enter name into scenario chart STR_2791 :Anna nimi STR_2792 :Please enter your name for the scenario chart: -STR_2793 :{SMALLFONT}(Completed by {STRINGID}) -STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY} +STR_2793 :{SMALLFONT}(Suorittanut {STRINGID}) +STR_2794 :{WINDOW_COLOUR_2}Suorittanut: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} Yhtiön arvolla: {BLACK}{CURRENCY} STR_2795 :Järjestä -STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed -STR_2797 :Scroll view when pointer at screen edge -STR_2798 :{SMALLFONT}{BLACK}Select whether to scroll the view when the mouse pointer is at the screen edge -STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments +STR_2796 :{SMALLFONT}{BLACK}Järjestä laitelistaus valitun tietotyypin mukaan +STR_2797 :Vieritä näkymää kun hiiri on näytön reunassa +STR_2798 :{SMALLFONT}{BLACK}Valitse vieritetäänkö näkymää kun hiiri on näytön reunassa +STR_2799 :{SMALLFONT}{BLACK}Näytä ja aseta näppäinasetukset STR_2800 :{WINDOW_COLOUR_2}Sisäänpääsyt: {BLACK}{COMMA32} STR_2801 :{WINDOW_COLOUR_2}Tulot sisäänpääsyistä: {BLACK}{CURRENCY2DP} STR_2802 :Kartta -STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map -STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map +STR_2803 :{SMALLFONT}{BLACK}Näytä nämä kävijät kartalla +STR_2804 :{SMALLFONT}{BLACK}Näytä nämä henkilökunnan jäsenet kartalla STR_2805 :{SMALLFONT}{BLACK}Näytä puiston kartta -STR_2806 :{RED}Guests are complaining about the disgusting state of the paths in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2807 :{RED}Guests are complaining about the amount of litter in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2808 :{RED}Guests are complaining about the vandalism in your park{NEWLINE}Check where your security guards are and consider organising them better -STR_2809 :{RED}Vieraat ovat nälkäisiä eivätkä löydä paikkaa mistä saisi ruokaa +STR_2806 :{RED}Vieraat valittavat puistosi kuvottavista poluista{NEWLINE}Tarkista ja uudelleenjärjestele yleismiestesi sijainnit +STR_2807 :{RED}Vieraat valittavat roskan määrästä puistossasi{NEWLINE}Tarkista ja uudelleenjärjestele yleismiestesi sijainnit +STR_2808 :{RED}Vieraat valittavat puistosi vandalismista{NEWLINE}Tarkista ja uudelleenjärjestele yleismiestesi sijainnit +STR_2809 :{RED}Vieraat ovat nälkäisiä eivätkä löydä paikkaa josta saisi ruokaa STR_2810 :{RED}Vieraat ovat janoisia eivätkä löydä paikkaa josta saisi juotavaa STR_2811 :{RED}Vieraat valittavat etteivät löydä vessaa puistostasi -STR_2812 :{RED}Guests are getting lost or stuck{NEWLINE}Check whether the layout of your footpaths needs improving to help the guests find their way around -STR_2813 :{RED}Your park entrance fee is too high!{NEWLINE}Reduce your entrance fee or improve the value of the park to attract more guests +STR_2812 :{RED}Vieraat eksyvät tai jäävät jumiink{NEWLINE}Tarkista jalkakäytäväsi että vieraat löytävä tiensä paikasta toiseen +STR_2813 :{RED}Sisäänpääsyn hinta on liian korkea!{NEWLINE}Laske sisäänpääsyhintaa tai paranna puiston arvoa jotta puistosi houkuttelee enemmän kävijöitä STR_2814 :{WINDOW_COLOUR_2}Sotkuisin puisto -palkinto STR_2815 :{WINDOW_COLOUR_2}Siistein puisto -palkinto -STR_2816 :{WINDOW_COLOUR_2}Award for the park with the best roller coasters -STR_2817 :{WINDOW_COLOUR_2}Best value park award +STR_2816 :{WINDOW_COLOUR_2}Parhaat vuoristoradat -palkinto +STR_2817 :{WINDOW_COLOUR_2}Paras hinta/laatu-suhde -palkinto STR_2818 :{WINDOW_COLOUR_2}Kaunein puisto -palkinto -STR_2819 :{WINDOW_COLOUR_2}Worst value park award +STR_2819 :{WINDOW_COLOUR_2}Huonoin hinta/laatu-suhde -palkinto STR_2820 :{WINDOW_COLOUR_2}Turvallisin puisto -palkinto STR_2821 :{WINDOW_COLOUR_2}Paras henkilöstö -palkinto STR_2822 :{WINDOW_COLOUR_2}Parhaat puistoruuat -palkinto STR_2823 :{WINDOW_COLOUR_2}Huonoimmat puistoruuat -palkinto STR_2824 :{WINDOW_COLOUR_2}Parhaat puistovessat -palkinto STR_2825 :{WINDOW_COLOUR_2}Pettymyksellisin puisto -palkinto -STR_2826 :{WINDOW_COLOUR_2}Parhaat vesiajelut -palkinto -STR_2827 :{WINDOW_COLOUR_2}Best custom-designed rides award -STR_2828 :{WINDOW_COLOUR_2}Most dazzling ride colour schemes award -STR_2829 :{WINDOW_COLOUR_2}Most confusing park layout award -STR_2830 :{WINDOW_COLOUR_2}Best gentle ride award -STR_2831 :{TOPAZ}Puistosi sai 'Sotkuisin puisto maassa' -palkinnon! -STR_2832 :{TOPAZ}Puistosi sai 'Siistein puisto maassa' -palkinnon! +STR_2826 :{WINDOW_COLOUR_2}Parhaat vesilaitteet -palkinto +STR_2827 :{WINDOW_COLOUR_2}Parhaat kustomoidut laitteet -palkinto +STR_2828 :{WINDOW_COLOUR_2}Häikäisevimmät värivalinnat -palkinto +STR_2829 :{WINDOW_COLOUR_2}Sekavin kartta -palkinto +STR_2830 :{WINDOW_COLOUR_2}Parhaat lempeät laitteet -palkinto +STR_2831 :{TOPAZ}Puistosi sai 'Maan sotkuisin puisto' -palkinnon! +STR_2832 :{TOPAZ}Puistosi sai 'Maan Siistein puisto' -palkinnon! STR_2833 :{TOPAZ}Puistosi sai 'Puisto parhaimmilla vuoristoradoilla' -palkinnon! -STR_2834 :{TOPAZ}Your park has received an award for being 'The best value park in the country'! -STR_2835 :{TOPAZ}Puistosi sai 'Kaunein puisto maassa' -palkinnon! -STR_2836 :{TOPAZ}Your park has received an award for being 'The worst value park in the country'! -STR_2837 :{TOPAZ}Puistosi sai 'Turvallisin puisto maassa' -palkinnon! +STR_2834 :{TOPAZ}Puistosi sai 'Maan paras hinta/laatu-suhde' -palkinnon! +STR_2835 :{TOPAZ}Puistosi sai 'Maan kaunein puisto' -palkinnon! +STR_2836 :{TOPAZ}Puistosi sai 'Maan huonoin hinta/laatu-suhde' -palkinnon! +STR_2837 :{TOPAZ}Puistosi sai 'Maan turvallisin puisto' -palkinnon! STR_2838 :{TOPAZ}Puistosi sai 'Puisto parhaimmalla henkilöstöllä' -palkinnon! -STR_2839 :{TOPAZ}Puistosi sai 'Puisto parhaimmalla ruualla maassa' -palkinnon! -STR_2840 :{TOPAZ}Puisto sai 'Puisto huonoimmalla ruualla maassa' -palkinnon! -STR_2841 :{TOPAZ}Puistosi sai 'Puisto parhaimmilla vessatiloilla maassa' -palkinnon! -STR_2842 :{TOPAZ}Puistosi sai 'Pettymyksellisin puisto maassa' -palkinnon! -STR_2843 :{TOPAZ}Puistosi sai 'Parhaat vesiajelut maassa' -palkinnon! -STR_2844 :{TOPAZ}Your park has received an award for being 'The park with the best custom-designed rides'! -STR_2845 :{TOPAZ}Your park has received an award for being 'The park with the most dazzling choice of colour schemes'! -STR_2846 :{TOPAZ}Your park has received an award for being 'The park with the most confusing layout'! -STR_2847 :{TOPAZ}Your park has received an award for being 'The park with the best gentle rides'! +STR_2839 :{TOPAZ}Puistosi sai 'Puisto maan parhaimmalla ruualla' -palkinnon! +STR_2840 :{TOPAZ}Puistosi sai 'Puisto maan huonoimmalla ruualla' -palkinnon! +STR_2841 :{TOPAZ}Puistosi sai 'Puisto maan parhaimmilla vessatiloilla' -palkinnon! +STR_2842 :{TOPAZ}Puistosi sai 'Maan pettymyksellisin puisto' -palkinnon! +STR_2843 :{TOPAZ}Puistosi sai 'Maan parhaat vesilaitteet' -palkinnon! +STR_2844 :{TOPAZ}Puistosi sai 'Parhaat kustomoidut laitteet' -palkinnon! +STR_2845 :{TOPAZ}Puistosi sai 'Häikäisevimmät värivalinnat' -palkinnon! +STR_2846 :{TOPAZ}Puistosi sai 'Sekavin kartta' -palkinnon! +STR_2847 :{TOPAZ}Puistosi sai 'Parhaat lempeät laitteet' -palkinnon! STR_2848 :{WINDOW_COLOUR_2}Ei tuoreita palkintoja STR_2849 :Uusi skenaario asennettiin onnistuneesti -STR_2850 :New track design installed successfully -STR_2851 :Skenaario jo asennettu -STR_2852 :Track design already installed +STR_2850 :Uusi ratasuunnitelma asennettiin onnistuneesti +STR_2851 :Skenaario on jo asennettu +STR_2852 :Ratasuunnitelma on jo asennettu STR_2853 :Kiellettyä paikallisten viranomaisten mukaan! -STR_2854 :{RED}Guests can't get to the entrance of {STRINGID} !{NEWLINE}Construct a path to the entrance -STR_2855 :{RED}{STRINGID} has no path leading from its exit !{NEWLINE}Construct a path from the ride exit -STR_2856 :{WINDOW_COLOUR_2}Tutorial -STR_2857 :{WINDOW_COLOUR_2}(Press a key or mouse button to take control) +STR_2854 :{RED}Kävijät eivät pääse laitteen {STRINGID} sisäänkäynnille !{NEWLINE}Rakenna polku sisäänkäynnille +STR_2855 :{RED}Laitteen {STRINGID} uloskäynnistä ei lähde polkua !{NEWLINE}Rakenna polku uloskäynniltä +STR_2856 :{WINDOW_COLOUR_2}Tutoriaali +STR_2857 :{WINDOW_COLOUR_2}(Paina nappia ohjataksesi) STR_2858 :Markkinointikampanjaa ei voitu aloittaa... -STR_2859 :Another instance of OpenRCT2 is already running +STR_2859 :Toinen OpenRCT2-ohjelma on jo auki STR_2860 :Infogrames Interactiven lopputekstit... STR_2861 :{WINDOW_COLOUR_2}Lisensoinut Infogrames Interactive Inc. STR_2862 :Music acknowledgements... diff --git a/data/language/french.txt b/data/language/french.txt index 82aaa48471..2766946146 100644 --- a/data/language/french.txt +++ b/data/language/french.txt @@ -5,95 +5,95 @@ STR_0000 : STR_0001 :{STRINGID} {COMMA16} STR_0002 :Montagnes russes en spirales STR_0003 :Montagnes russes debout -STR_0004 :Suspended Swinging Coaster +STR_0004 :Montagnes russes suspendues STR_0005 :Montagnes russes inversées STR_0006 :Montagnes russes junior STR_0007 :Chemin de fer miniature STR_0008 :Monorail -STR_0009 :Mini montagnes russes suspendues -STR_0010 :Boat Hire -STR_0011 :Wooden Wild Mouse -STR_0012 :Steeplechase +STR_0009 :Mini-montagnes russes suspendues +STR_0010 :Balade en bateau +STR_0011 :Souris folle en bois +STR_0012 :Rodéo montagnes STR_0013 :Balade en voiture -STR_0014 :Launched Freefall -STR_0015 :Bobsleigh Coaster +STR_0014 :Chute libre lancée +STR_0015 :Bobsleigh STR_0016 :Tour d'observation -STR_0017 :Looping Roller Coaster -STR_0018 :Dinghy Slide +STR_0017 :Montagnes russe looping +STR_0018 :Canotube STR_0019 :Train de la mine -STR_0020 :Chairlift -STR_0021 :Corkscrew Roller Coaster +STR_0020 :Télésiège +STR_0021 :Montagnes russes tire-bouchon STR_0022 :Labyrinthe -STR_0023 :Toboggan spiral -STR_0024 :Go Karts -STR_0025 :Log Flume -STR_0026 :River Rapids -STR_0027 :Dodgems +STR_0023 :Toboggan en spirale +STR_0024 :Karts +STR_0025 :Bûches +STR_0026 :Rapides de la rivière +STR_0027 :Autos tamponneuses STR_0028 :Bateau pirate -STR_0029 :Swinging Inverter Ship +STR_0029 :Bateau renverseur STR_0030 :Stand de nourriture -STR_0031 :Unknown Stall (1D) +STR_0031 :Stand inconnu (1D) STR_0032 :Stand de boissons -STR_0033 :Unknown Stall (1F) +STR_0033 :Stand inconnu (1F) STR_0034 :Boutique -STR_0035 :Manège -STR_0036 :Unknown Stall (22) +STR_0035 :Carrousel +STR_0036 :Stand inconnu (22) STR_0037 :Kiosque d'information STR_0038 :Toilettes STR_0039 :Grande roue STR_0040 :Simulateur de mouvements STR_0041 :Cinéma 3D -STR_0042 :Top Spin +STR_0042 :Vrille STR_0043 :Anneaux de l'espace -STR_0044 :Reverse Freefall Coaster +STR_0044 :Chute libre renversée STR_0045 :Ascenseur -STR_0046 :Vertical Drop Roller Coaster +STR_0046 :Montagnes russes en chute vert. STR_0047 :Distributeur de monnaie STR_0048 :Twist STR_0049 :Maison hantée STR_0050 :Infirmerie STR_0051 :Spectacle de cirque STR_0052 :Train fantôme -STR_0053 :Steel Twister Roller Coaster +STR_0053 :Montagnes tornado STR_0054 :Montagnes russes en bois -STR_0055 :Side-Friction Roller Coaster -STR_0056 :Souris sauvage -STR_0057 :Multi-Dimension Roller Coaster -STR_0058 :Unknown Ride (38) +STR_0055 :Montagnes frottement latéral +STR_0056 :Souris folle +STR_0057 :Montagnes multidimension +STR_0058 :Manège Inconnu (38) STR_0059 :Montagnes russes volantes -STR_0060 :Unknown Ride (3A) +STR_0060 :Manège Inconnu (3A) STR_0061 :Virginia Reel STR_0062 :Splash Boats STR_0063 :Mini hélicoptères -STR_0064 :Lay-down Roller Coaster +STR_0064 :Mont. russes - posit. couchée STR_0065 :Monorail suspendu -STR_0066 :Unknown Ride (40) -STR_0067 :Reverser Roller Coaster -STR_0068 :Heartline Twister Coaster +STR_0066 :Manège Inconnu (40) +STR_0067 :Inverseur +STR_0068 :Tornado Heartline STR_0069 :Mini-golf -STR_0070 :Giga Coaster -STR_0071 :Roto-Drop -STR_0072 :Flying Saucers -STR_0073 :Maison bizarre -STR_0074 :Monorail Cycles -STR_0075 :Compact Inverted Coaster -STR_0076 :Water Coaster -STR_0077 :Air Powered Vertical Coaster -STR_0078 :Inverted Hairpin Coaster +STR_0070 :Giga montagnes russes +STR_0071 :Roto-toboggan +STR_0072 :Soucoupes volantes +STR_0073 :Maison biscornue +STR_0074 :Vélos monorail +STR_0075 :Montagnes compactes inversées +STR_0076 :Montagnes aquatiques +STR_0077 :Voiture propulsée dans les airs +STR_0078 :Epingle à cheveux inversée STR_0079 :Tapis volant STR_0080 :Balade sous-marine -STR_0081 :River Rafts -STR_0082 :Unknown Ride (50) +STR_0081 :Radeau +STR_0082 :Manège Inconnu (50) STR_0083 :Enterprise -STR_0084 :Unknown Ride (52) -STR_0085 :Unknown Ride (53) -STR_0086 :Unknown Ride (54) -STR_0087 :Unknown Ride (55) -STR_0088 :Inverted Impulse Coaster -STR_0089 :Mini montagnes russes -STR_0090 :Mine Ride -STR_0091 :Unknown Ride (59) -STR_0092 :LIM Launched Roller Coaster +STR_0084 :Manège Inconnu (52) +STR_0085 :Manège Inconnu (53) +STR_0086 :Manège Inconnu (54) +STR_0087 :Manège Inconnu (55) +STR_0088 :Impulsion inversée +STR_0089 :Mini-montagnes russes +STR_0090 :Mineur +STR_0091 :Manège Inconnu (59) +STR_0092 :Moteur à induction linéaire STR_0093 : STR_0094 : STR_0095 : @@ -513,31 +513,31 @@ STR_0508 : STR_0509 : STR_0510 : STR_0511 : -STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. -STR_0513 :A looping roller coaster where the riders ride in a standing position -STR_0514 :Trains suspended beneath the roller coaster track swing out to the side around corners -STR_0515 :A steel roller coaster with trains that are held beneath the track, with many complex and twisting track elements -STR_0516 :A gentle roller coaster for people who haven't yet got the courage to face the larger rides -STR_0517 :Passengers ride in miniature trains along a narrow-gauge railway track -STR_0518 :Passengers travel in electric trains along a monorail track -STR_0519 :Passengers ride in small cars hanging beneath the single-rail track, swinging freely from side to side around corners -STR_0520 :A dock platform where guests can drive/row personal watercraft on a body of water -STR_0521 :A fast and twisting roller coaster with tight turns and steep drops. Intensity is bound to be high. -STR_0522 :A smaller roller coaster where the riders sit above the track with no car around them -STR_0523 :Riders travel slowly in powered vehicles along a track-based route -STR_0524 :Freefall car is pneumatically launched up a tall steel tower and then allowed to freefall down -STR_0525 :Riders career down a twisting track guided only by the curvature and banking of the semi-circular track -STR_0526 :Passengers travel in a rotating observation cabin which travels up a tall tower -STR_0527 :A smooth steel-tracked roller coaster capable of vertical loops -STR_0528 :Riders travel in inflatable dinghies down a twisting semi-circular or completely enclosed tube track -STR_0529 :Mine train themed roller coaster trains career along steel roller coaster track made to look like old railway track -STR_0530 :Cars hang from a steel cable which runs continuously from one end of the ride to the other and back again -STR_0531 :A compact steel-tracked roller coaster where the train travels through corkscrews and loops +STR_0512 :Des voitures individuelles descendent des pentes régulières en virage +STR_0513 :Grand huit que les passagers parcourent debout +STR_0514 :Des voitures suspendues sous la voie se balancent dans les virages des montagnes russes +STR_0515 :Les passagers parcourent des boucles géantes, des virages et des grandes descentes en piqué, installés sur des sièges suspendus à la voie +STR_0516 :Des montagnes russes tranquilles pour ceux qui n'osent pas encore aller plus loin +STR_0517 :Balade à bord d'un train miniature sur une voie ferrée étroite +STR_0518 :Balade à bord d'un train électrique sur un monorail +STR_0519 :Les passagers voyagent dans de petites voitures suspendues à un rail et qui se balancent dans les virages +STR_0520 :Le pont d'embarquement est constitué d'une plate-forme en bois construite sur un lac. Des voies guides peuvent être construites pour limiter la zone où les passagers peuvent diriger les bateaux +STR_0521 :De petites voitures dévalent une voie en bois et sont chahutées dans des virages en épingle à cheveux et des descentes abruptes +STR_0522 :La voie est constituée de deux rails en acier tubulaire, placés l'un sur l'autre et reliés par un renforcement. Les voitures sont maintenues sur la voie par des roues au-dessus, en-dessous en de chaque côté des rails. +STR_0523 :Balade à vitesse lente à bord d'une voiture à propulsion électrique +STR_0524 :La voiture est propulsée hors de la station à l'aide de moteurs à induction linéaire puis, après avoir atteint une pointe verticale, revient à la station en chute libre. +STR_0525 :Les passagers descendent un parcours plein de virages à bord d'une voiture en forme de bobsleigh dirigée uniquement par les courbes et l'inclinaison de la voie semi-circulaire +STR_0526 :Cabine rotative d'observation qui se hisse au sommet d'une grande tour +STR_0527 :Des montagnes russes métalliques régulières avec des boucles verticales +STR_0528 :Les passagers descendent un tube semi-circulaire ou entièrement fermé à bord d'un canot pneumatique +STR_0529 :Trains emmenant les passagers sur des montagnes russes dont les voies rappellent les vieilles voies ferrées +STR_0530 :Des voitures suspendues à un câble métallique font des allers-retours continus +STR_0531 :Montagnes russes compactes dont les voies en acier prennent la forme de tire-bouchons et de boucles STR_0532 : STR_0533 : -STR_0534 :Self-drive petrol-engined go karts -STR_0535 :Log-shaped boats travel along a water channel, splashing down steep slopes to soak the riders -STR_0536 :Circular boats meander along a wide water channel, splashing through waterfalls and thrilling riders through foaming rapids +STR_0534 :Karts individuels constitués de moteurs à essence +STR_0535 :Bateaux en forme de bûches géantes parcourant un tube aquatique dont les pentes abruptes auront pour effet de tremper les passagers +STR_0536 :Des bateaux de forme circulaire serpentent le long d'un large cours d'eau, puis dévalent des rapides et des chutes d'eau spectaculaires STR_0537 : STR_0538 : STR_0539 : @@ -555,55 +555,55 @@ STR_0550 : STR_0551 : STR_0552 : STR_0553 : -STR_0554 :The car is accelerated out of the station along a long level track using Linear Induction Motors, then heads straight up a vertical spike of track, freefalling back down to return to the station -STR_0555 :Guests ride in an elevator up or down a vertical tower to get from one level to another -STR_0556 :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_0554 :La voiture est propulsée hors de la station à l'aide de moteurs à induction linéaire puis, après avoir atteint une pointe verticale, revient à la station en chute libre +STR_0555 :Les passagers passent aux différents niveaux d'une tour verticale à bord d'un ascenceur +STR_0556 :Des voitures très larges descendent des voies en pente verticale. pour amateurs de chute libre STR_0557 : STR_0558 : STR_0559 : STR_0560 : STR_0561 : -STR_0562 :Powered cars travel along a multi-level track past spooky scenery and special effects -STR_0563 :Sitting in comfortable trains with only simple lap restraints riders enjoy giant smooth drops and twisting track as well as plenty of 'air time' over the hills -STR_0564 :Running on wooden track, this coaster is fast, rough, noisy, and gives an 'out of control' riding experience with plenty of 'air time' -STR_0565 :A simple wooden roller coaster capable of only gentle slopes and turns, where the cars are only kept on the track by side friction wheels and gravity -STR_0566 :Individual roller coaster cars zip around a tight zig-zag layout of track with sharp corners and short sharp drops -STR_0567 :Sitting in seats suspended either side of the track, riders are pitched head-over-heels while they plunge down steep drops and travel through various inversions +STR_0562 :Des voitures à propulsion parcourent les étages d'un bâtiment bourré d'effets spéciaux et de décors +STR_0563 :Retenus uniquement par les jambes dans des voitures confortables, les visiteurs effectuent des descentes géantes le long d'un tracé sinueux et décollent de leur siège en haut des collines +STR_0564 :Ces montagnes russes en bois sont rapides, ardues et bruyantes. C'est le grand frisson garanti. +STR_0565 :Des montagnes russes en bois simples avec des pentes et des virages modérés et dont les voitures se maintiennent grâce à des roues à frottement latéral et à la gravité +STR_0566 :Des voitures individuelles filent sur des montagnes russes en zigzag avec des virages serrés et des chutes à pic +STR_0567 :Les visiteurs, suspendus à des sièges de chaque côté de la voie, descendent des inclinaisons abruptes la tête en bas et subissent quelques inversions STR_0568 : -STR_0569 :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air +STR_0569 :Installés dans des sièges confortables, les passagers sont suspendus à une voie alambiquée leur donnant le sentiment de voler STR_0570 : -STR_0571 :Circular cars spin around as they travel along the zig-zagging wooden track -STR_0572 :Large capacity boats travel along a wide water channel, propelled up slopes by a conveyer belt, accelerating down steep slopes to soak the riders with a gaint splash -STR_0573 :Powered helicoper shaped cars running on a steel track, controlled by the pedalling of the riders -STR_0574 :Riders are held in special harnesses in a lying-down position, travlling through twisted track and inversions either on their backs or facing the ground -STR_0575 :Powered trains hanging from a single rail transport people around the park +STR_0571 :Voitures de forme circulaire tournant sur elles-mêmes tout en parcourant une voie en bois faite de zigzags +STR_0572 :Grand bateau qui serpente le long d'une large voie navigable, monte sur des pentes grâce à un tapis roulant, et descend à toute vitesse de l'autre côté, éclaboussant allègrement les passagers +STR_0573 :Installés dans des voitures en forme d'hélicoptère, les passagers parcourent une voie métallique en pédalant pour avancer +STR_0574 :Les passagers franchissent une voie alambiquée pleine d'inversions, couchés à plat ventre ou sur le dos, et maintenus par des harnais spéciaux +STR_0575 :Les visiteurs font le tour du parc à bord d'un train à propulsion électrique suspendu à un rail STR_0576 : -STR_0577 :Bogied cars run on wooden tracks, turning around on special reversing sections -STR_0578 :Cars run along track enclosed by circular hoops, traversing steep drops and heartline twists +STR_0577 :Chariot dévalant une voie en bois, tournant à des sections inverseuses spéciales +STR_0578 :Une voiture fonce dans des anneaux circulaires, des pentes abruptes et des inversions à 360{DEGREE} STR_0579 : STR_0580 : STR_0581 : STR_0582 : STR_0583 : -STR_0584 :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders -STR_0585 :Riders sit in pairs of seats suspended beneath the track as they loop and twist through tight inversions -STR_0586 :Boat shaped cars run on roller coaster track to allow twisting curves and steep drops, splashing down into sections of water for gentle river sections -STR_0587 :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station -STR_0588 :Individual cars run beneath a zig-zagging track with hairpin turns and sharp drops +STR_0584 :Des vélos spéciaux parcourent une voie monorail métallique +STR_0585 :Les passagers sont assis par deux, suspendus à la voie tandis qu'ils zigzaguent et sont chahutés lors d'inversions serrées +STR_0586 :Des voitures en forme de bateau franchissent des virages serrés et des descentes abruptes, et plongent dans des zones aquatiques +STR_0587 :Après avoir été propulsé dans les airs, le train accélère sur une voie verticale, passe le sommet, et retombe de l'autre côté en direction de la station +STR_0588 :Des voitures individuelles placées sous la voie zigzaguent à travers les virages en épingle à cheveux et les chutes abruptes STR_0589 : -STR_0590 :Riders ride in a submerged submarine through an underwater course -STR_0591 :Raft-shaped boats gently meander around a river track +STR_0590 :Sous-marin immergé qui transporte les passagers dans un parcours sub-aquatique +STR_0591 :Des bateaux en forme de radeau descendent paisiblement une voie navigable STR_0592 : STR_0593 : STR_0594 : STR_0595 : STR_0596 : STR_0597 : -STR_0598 :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track -STR_0599 :A compact roller coaster with individual cars and smooth twisting drops -STR_0600 :Powered mine trains career along a smooth and twisted track layout +STR_0598 :Les trains de montagnes russes à impulsion sont propulsés hors de la station puis, après avoir atteint une pointe verticale, redescendent vers la station et entament une nouvelle montée verticale en sens inverse +STR_0599 :Des voitures individuelles descendent des pentes régulières en virage +STR_0600 :Train de mine à propulsion franchissant une voie régulière et alambiquée STR_0601 : -STR_0602 :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions +STR_0602 :Train de montagnes russes propulsé hors de la station par des moteurs à induction linéaire et fonçant dans des inversions renversantes STR_0603 :Visiteur {INT32} STR_0604 :Visiteur {INT32} STR_0605 :Visiteur {INT32} @@ -769,7 +769,7 @@ STR_0764 :Visiteur {INT32} STR_0765 :Visiteur {INT32} STR_0766 :Visiteur {INT32} STR_0767 :Visiteur {INT32} -STR_0768 :Homme de service {INT32} +STR_0768 :Agent d'entretien {INT32} STR_0769 :Mécanicien {INT32} STR_0770 :Agent de sécurité {INT32} STR_0771 :Animateur {INT32} @@ -779,50 +779,50 @@ STR_0774 :Parc sans nom{POP16}{POP16} STR_0775 :Parc sans nom{POP16}{POP16} STR_0776 :Parc sans nom{POP16}{POP16} STR_0777 :Parc sans nom{POP16}{POP16} -STR_0778 :Sign +STR_0778 :Panneau STR_0779 :1er -STR_0780 :2ème -STR_0781 :3ème -STR_0782 :4ème -STR_0783 :5ème -STR_0784 :6ème -STR_0785 :7ème -STR_0786 :8ème -STR_0787 :9ème -STR_0788 :10ème -STR_0789 :11ème -STR_0790 :12ème -STR_0791 :13ème -STR_0792 :14ème -STR_0793 :15ème -STR_0794 :16ème -STR_0795 :17ème -STR_0796 :18ème -STR_0797 :19ème -STR_0798 :20ème -STR_0799 :21ème -STR_0800 :22ème -STR_0801 :23ème -STR_0802 :24ème -STR_0803 :25ème -STR_0804 :26ème -STR_0805 :27ème -STR_0806 :28ème -STR_0807 :29ème -STR_0808 :30ème -STR_0809 :31ème -STR_0810 :Jan -STR_0811 :Fév -STR_0812 :Mar -STR_0813 :Avr -STR_0814 :Mai -STR_0815 :Jun -STR_0816 :Jul -STR_0817 :Aoû -STR_0818 :Sep -STR_0819 :Oct -STR_0820 :Nov -STR_0821 :Déc +STR_0780 :2 +STR_0781 :3 +STR_0782 :4 +STR_0783 :5 +STR_0784 :6 +STR_0785 :7 +STR_0786 :8 +STR_0787 :9 +STR_0788 :10 +STR_0789 :11 +STR_0790 :12 +STR_0791 :13 +STR_0792 :14 +STR_0793 :15 +STR_0794 :16 +STR_0795 :17 +STR_0796 :18 +STR_0797 :19 +STR_0798 :20 +STR_0799 :21 +STR_0800 :22 +STR_0801 :23 +STR_0802 :24 +STR_0803 :25 +STR_0804 :26 +STR_0805 :27 +STR_0806 :28 +STR_0807 :29 +STR_0808 :30 +STR_0809 :31 +STR_0810 :janv +STR_0811 :fév +STR_0812 :mars +STR_0813 :avr +STR_0814 :mai +STR_0815 :juin +STR_0816 :juil +STR_0817 :août +STR_0818 :sept +STR_0819 :oct +STR_0820 :nov +STR_0821 :déc STR_0822 :Impossible d'accéder au fichier de données graphiques STR_0823 :Fichier de données manquant ou inaccessible STR_0824 :{BLACK}{CROSS} @@ -831,14 +831,14 @@ STR_0826 :Trop de noms définis STR_0827 :Pas assez d'argent - Nécessite {CURRENCY2DP} STR_0828 :{SMALLFONT}{BLACK}Fermer la fenêtre STR_0829 :{SMALLFONT}{BLACK}Titre de la fenêtre - Faites glisser ceci pour déplacer la fenêtre -STR_0830 :{SMALLFONT}{BLACK}Zoomer sur la vue -STR_0831 :{SMALLFONT}{BLACK}Dézoomer sur la vue +STR_0830 :{SMALLFONT}{BLACK}Zoom avant +STR_0831 :{SMALLFONT}{BLACK}Zoom arrière STR_0832 :{SMALLFONT}{BLACK}Tourner la vue de 90{DEGREE} dans le sens des aiguilles d'une montre STR_0833 :{SMALLFONT}{BLACK}Mettre en pause le jeu STR_0834 :{SMALLFONT}{BLACK}Options du jeu et du disque -STR_0835 :L'initialisation du jeu a échouée -STR_0836 :Impossible de démarrer le jeu minimisé -STR_0837 :Impossible d'initialiser le système de graphiques +STR_0835 :Echec de l'initialisation du jeu +STR_0836 :Impossible de commencer une partie dans une fenêtre réduite +STR_0837 :Initialisation du système graphique impossible STR_0838 : STR_0839 :{UINT16} x {UINT16} STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16} @@ -858,9 +858,9 @@ STR_0851 :{WINDOW_COLOUR_2}Conçu et programmé par Chris Sawyer STR_0852 :{WINDOW_COLOUR_2}Graphismes : Simon Foster STR_0853 :{WINDOW_COLOUR_2}Son et musique : Allister Brimble STR_0854 :{WINDOW_COLOUR_2}Enregistrement sons additionnels : David Ellis -STR_0855 :{WINDOW_COLOUR_2}Représentation :Jacqui Lyons, Marjacq Ltd. -STR_0856 :{WINDOW_COLOUR_2}Remerciements: -STR_0857 :{WINDOW_COLOUR_2}Peter James Adcock, Joe Booth, and John Wardley +STR_0855 :{WINDOW_COLOUR_2}Représentation : Jacqui Lyons, Marjacq Ltd. +STR_0856 :{WINDOW_COLOUR_2}Remerciements : +STR_0857 :{WINDOW_COLOUR_2}Peter James Adcock, Joe Booth, et John Wardley STR_0858 :{WINDOW_COLOUR_2} STR_0859 :{WINDOW_COLOUR_2} STR_0860 :{WINDOW_COLOUR_2} @@ -880,8 +880,8 @@ STR_0873 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0874 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0875 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0876 :{BLACK}{DOWN} -STR_0877 :Trop bas! -STR_0878 :Trop haut! +STR_0877 :Trop bas ! +STR_0878 :Trop haut ! STR_0879 :Impossible d'abaisser le terrain ici... STR_0880 :Impossible de surélever le terrain ici... STR_0881 :Objet dans le passage @@ -890,58 +890,58 @@ STR_0883 :Sauvegarder partie STR_0884 :Charger paysage STR_0885 :Sauvegarder paysage STR_0886 :Quitter la partie -STR_0887 :Quitter l'Éditeur de scénario +STR_0887 :Quitter l'éditeur de scénario STR_0888 :Quitter le concepteur de montagnes russes STR_0889 :Quitter le gestionnaire des voies STR_0890 :SCR{COMMA16}.BMP STR_0891 :Capture d'écran STR_0892 :Capture d'écran sauvegardée en tant que '{STRINGID}' -STR_0893 :La capture d'écran a échouée! +STR_0893 :Echec de la capture d'écran! STR_0894 :Landscape data area full ! -STR_0895 :Impossible de construire partiellement au dessus et partiellement en dessous du sol +STR_0895 :Impossible de construire à la fois au-dessus et en-dessous du sol STR_0896 :{POP16}{POP16}{STRINGID} Construction STR_0897 :Direction -STR_0898 :{SMALLFONT}{BLACK}Courbe à gauche -STR_0899 :{SMALLFONT}{BLACK}Courbe à droite -STR_0900 :{SMALLFONT}{BLACK}Courbe à gauche (petit rayon) -STR_0901 :{SMALLFONT}{BLACK}Courbe à droite (petit rayon) -STR_0902 :{SMALLFONT}{BLACK}Courbe à gauche (très petit rayon) -STR_0903 :{SMALLFONT}{BLACK}Courbe à droite (très petit rayon) -STR_0904 :{SMALLFONT}{BLACK}Courbe à gauche (grand rayon) -STR_0905 :{SMALLFONT}{BLACK}Courbe à droite (grand rayon) -STR_0906 :{SMALLFONT}{BLACK}Droit -STR_0907 :Pente -STR_0908 :Roll/Banking -STR_0909 :Rot. des sièges. -STR_0910 :{SMALLFONT}{BLACK}Roll for left-hand curve -STR_0911 :{SMALLFONT}{BLACK}Roll for right-hand curve -STR_0912 :{SMALLFONT}{BLACK}No roll +STR_0898 :{SMALLFONT}{BLACK}Virage à gauche +STR_0899 :{SMALLFONT}{BLACK}Virage à droite +STR_0900 :{SMALLFONT}{BLACK}Virage à gauche (petit rayon) +STR_0901 :{SMALLFONT}{BLACK}Virage à droite (petit rayon) +STR_0902 :{SMALLFONT}{BLACK}Virage à gauche (très petit rayon) +STR_0903 :{SMALLFONT}{BLACK}Virage à droite (très petit rayon) +STR_0904 :{SMALLFONT}{BLACK}Virage à gauche (grand rayon) +STR_0905 :{SMALLFONT}{BLACK}Virage à droite (grand rayon) +STR_0906 :{SMALLFONT}{BLACK}Ligne droite +STR_0907 :Inclinaison +STR_0908 :Tonneau/virage +STR_0909 :Rot. des sièges +STR_0910 :{SMALLFONT}{BLACK}Inclinaison pour virage gauche +STR_0911 :{SMALLFONT}{BLACK}Inclinaison pour virage droite +STR_0912 :{SMALLFONT}{BLACK}Pas d'inclinaison STR_0913 :{SMALLFONT}{BLACK}Aller à la section précédente STR_0914 :{SMALLFONT}{BLACK}Aller à la section suivante -STR_0915 :{SMALLFONT}{BLACK}Construct the selected section -STR_0916 :{SMALLFONT}{BLACK}Remove the highlighted section -STR_0917 :{SMALLFONT}{BLACK}Chute verticale -STR_0918 :{SMALLFONT}{BLACK}Steep slope down -STR_0919 :{SMALLFONT}{BLACK}Slope down +STR_0915 :{SMALLFONT}{BLACK}Construire la section sélectionnée +STR_0916 :{SMALLFONT}{BLACK}Supprimer la section sélectionnée +STR_0917 :{SMALLFONT}{BLACK}Descente verticale +STR_0918 :{SMALLFONT}{BLACK}Descente abrupte +STR_0919 :{SMALLFONT}{BLACK}Descente STR_0920 :{SMALLFONT}{BLACK}Niveau -STR_0921 :{SMALLFONT}{BLACK}Slope up -STR_0922 :{SMALLFONT}{BLACK}Steep slope up -STR_0923 :{SMALLFONT}{BLACK}Vertical rise +STR_0921 :{SMALLFONT}{BLACK}Montée +STR_0922 :{SMALLFONT}{BLACK}Montée abrupte +STR_0923 :{SMALLFONT}{BLACK}Montée verticale STR_0924 :{SMALLFONT}{BLACK}Hélice descendante STR_0925 :{SMALLFONT}{BLACK}Hélice montante -STR_0926 :Impossible de supprimer ceci... -STR_0927 :Impossible de construire ceci ici... -STR_0928 :{SMALLFONT}{BLACK}Chain lift, to pull cars up slopes +STR_0926 :Suppression impossible... +STR_0927 :Construction impossible ici... +STR_0928 :{SMALLFONT}{BLACK}Remontée à chaîne pour hisser les voitures STR_0929 :Courbe en 'S' (gauche) STR_0930 :Courbe en 'S' (droite) STR_0931 :Boucle verticale (gauche) STR_0932 :Boucle verticale (droite) -STR_0933 :Surélevez ou abaissez le terrain d'abord -STR_0934 :Entrée de l'attraction dans le passage -STR_0935 :Sortie de l'attraction dans le passage +STR_0933 :Abaissez ou surélevez d'abord le terrain +STR_0934 :Entrée d'attraction dans le passage +STR_0935 :Sortie d'attraction dans le passage STR_0936 :Entrée du parc dans le passage -STR_0937 :{SMALLFONT}{BLACK}Voir les options -STR_0938 :{SMALLFONT}{BLACK}Adjust land height and slope +STR_0937 :{SMALLFONT}{BLACK}Options d'affichage +STR_0938 :{SMALLFONT}{BLACK}Ajuster hauteur et inclinaison du terrain STR_0939 :Vue souterraine/intérieure STR_0940 :Supprimer surface de base STR_0941 :Supprimer surfaces verticales @@ -956,7 +956,7 @@ STR_0949 :Sauvegarder ceci avant de quitter ? STR_0950 :Charger une partie STR_0951 :Quitter la partie STR_0952 :Quitter la partie -STR_0953 :Charger le paysage +STR_0953 :Charger un paysage STR_0954 : STR_0955 :{SMALLFONT}{BLACK}Sélectionnez l'angle de rotation des sièges pour cette section de voie STR_0956 :-180{DEGREE} @@ -978,14 +978,14 @@ STR_0971 :+495{DEGREE} STR_0972 :Annuler STR_0973 :OK STR_0974 :Attractions -STR_0975 :Magasins et stands +STR_0975 :Magasins et boutiques STR_0976 :Toilettes et kiosques d'information -STR_0977 :Nouveaux moyens de transport -STR_0978 :Nouvelles attractions calmes +STR_0977 :Nouvelles attractions de transport +STR_0978 :Nouvelles attractions tranquilles STR_0979 :Nouvelles montagnes russes STR_0980 :Nouvelles attractions à frissons STR_0981 :Nouvelles attractions aquatiques -STR_0982 :Nouveaux magasins et stands +STR_0982 :Nouveaux magasins et boutiques STR_0983 :Recherche & Développement STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP} STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP} @@ -998,17 +998,17 @@ STR_0991 :Quai STR_0992 :{SMALLFONT}{BLACK}Démolir toute l'attraction STR_0993 :Démolir l'attraction STR_0994 :Démolir -STR_0995 :{WINDOW_COLOUR_1}Êtes-vous vraiment sûr de vouloir démolir {STRINGID}? -STR_0996 :Vue générale +STR_0995 :{WINDOW_COLOUR_1}Souhaitez-vous vraiment démolir {STRINGID}? +STR_0996 :Vue d'ensemble STR_0997 :{SMALLFONT}{BLACK}Vue sur la sélection -STR_0998 :Plus de stations autorisées sur cette attraction +STR_0998 :Plus de quai autorisé sur cette attraction STR_0999 :Nécessite un quai -STR_1000 :La voie n'est pas un circuit complet +STR_1000 :La voie ne constitue pas un circuit complet STR_1001 :La voie est inadaptée à ce type de train STR_1002 :Impossible d'ouvrir {POP16}{POP16}{POP16}{STRINGID}... -STR_1003 ::Impossible de tester {POP16}{POP16}{POP16}{STRINGID}... -STR_1004 ::Impossible de fermer {POP16}{POP16}{POP16}{STRINGID}... -STR_1005 ::Impossible de commencer la construction sur {POP16}{POP16}{POP16}{STRINGID}... +STR_1003 :Impossible de tester {POP16}{POP16}{POP16}{STRINGID}... +STR_1004 :Impossible de fermer {POP16}{POP16}{POP16}{STRINGID}... +STR_1005 :Impossible de commencer la construction sur {POP16}{POP16}{POP16}{STRINGID}... STR_1006 :Doit être fermé d'abord STR_1007 :Impossible de créer suffisamment de véhicules STR_1008 :{SMALLFONT}{BLACK}Ouvrir, fermer ou tester une attraction @@ -1018,27 +1018,27 @@ STR_1011 :Tout fermer STR_1012 :Tout ouvrir STR_1013 :Fermer le parc STR_1014 :Ouvrir le parc -STR_1015 :Impossible de fonctionner avec plus d'une platforme de station dans ce mode -STR_1016 :Impossible de fonctionner avec moins de deux stations dans ce mode -STR_1017 :Impossible de changer le mode d'opération... -STR_1018 :Impossible d'appliquer les changements... -STR_1019 :Impossible d'appliquer les changements... -STR_1020 :Impossible d'appliquer les changements... +STR_1015 :Impossible de gérer plus d'un quai dans ce mode +STR_1016 :Impossible de fonctionner avec moins de deux quais dans ce mode +STR_1017 :Impossible de changer le mode de fonctionnement... +STR_1018 :Modification impossible... +STR_1019 :Modification impossible... +STR_1020 :Modification impossible... STR_1021 :{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_1022 :{POP16}{POP16}{POP16}{COMMA16} voiture par train -STR_1023 :{POP16}{POP16}{POP16}{COMMA16} voitures par trains +STR_1023 :{POP16}{POP16}{POP16}{COMMA16} voitures par train STR_1024 :{COMMA16} voiture par train STR_1025 :{COMMA16} voitures par train -STR_1026 :Le quai est trop long! +STR_1026 :Le quai est trop long ! STR_1027 :{SMALLFONT}{BLACK}Localiser sur la vue générale -STR_1028 :En dehors de la carte! -STR_1029 :Impossible de construire partiellement au dessus et partiellement en dessous de l'eau! -STR_1030 :Ne peut être construit que sous l'eau! -STR_1031 :Impossible de construire ceci sous l'eau! -STR_1032 :Ne peut être construit que sur l'eau! -STR_1033 :Ne peut être construit qu'au dessus du sol! -STR_1034 :Ne peut être construit que sur le sol! -STR_1035 :Les autorités locales n'autoriseront pas les constructions plus hautes qu'un arbre! +STR_1028 :En dehors de la carte ! +STR_1029 :Impossible de construire à la fois au-dessus et en-dessous de l'eau ! +STR_1030 :Ne peut être construit que sous l'eau ! +STR_1031 :Impossible de construire ceci sous l'eau ! +STR_1032 :Ne peut être construit que sur l'eau ! +STR_1033 :Ne peut être construit qu'au dessus du sol ! +STR_1034 :Ne peut être construit que sur le sol ! +STR_1035 :Les autorités locales n'autorisent pas les constructions plus hautes qu'un arbre ! STR_1036 :Charger une partie STR_1037 :Charger un paysage STR_1038 :Convertir une partie sauvegardée en scénario @@ -1050,80 +1050,80 @@ STR_1043 :Partie sauvegardée OpenRCT2 STR_1044 :Fichier de scénario OpenRCT2 STR_1045 :Fichier de paysage OpenRCT2 STR_1046 :Modèle de voie OpenRCT2 -STR_1047 :La sauvegarde du jeu a échouée! -STR_1048 :La sauvegarde du scénario a échouée! -STR_1049 :La sauvegarde du paysage a échouée! -STR_1050 :Impossible de charger...{NEWLINE}Le fichier contient des données invalides! +STR_1047 :Echec de la sauvegarde de la partie ! +STR_1048 :Echec de la sauvegarde du scénario ! +STR_1049 :Echec de la sauvegarde du paysage ! +STR_1050 :Echec du chargement...{NEWLINE}Le fichier contient des données invalides! STR_1051 :Supports invisibles STR_1052 :Visiteurs invisibles STR_1053 :{SMALLFONT}{BLACK}Attractions dans le parc -STR_1054 :{SMALLFONT}{BLACK}Nommer l'attraction -STR_1055 :{SMALLFONT}{BLACK}Nommer la personne -STR_1056 :{SMALLFONT}{BLACK}Nommer l'employé +STR_1054 :{SMALLFONT}{BLACK}Renommer l'attraction +STR_1055 :{SMALLFONT}{BLACK}Renommer le visiteur +STR_1056 :{SMALLFONT}{BLACK}Renommer l'employé STR_1057 :Nom de l'attraction STR_1058 :Entrez un nom pour cette attraction : STR_1059 :Impossible de renommer l'attraction... STR_1060 :Nom d'attraction invalide STR_1061 :Mode normal STR_1062 :Mode circuit continu -STR_1063 :Reverse-Incline launched shuttle mode -STR_1064 :Lancement (avec passage de la station) -STR_1065 :Shuttle mode -STR_1066 :Boat hire mode -STR_1067 :Upward launch -STR_1068 :Mode ascenseur en rotation +STR_1063 :Mode navette départ marche arrière +STR_1064 :Lancement à autopropulsion +STR_1065 :Mode navette +STR_1066 :Mode location bateaux +STR_1067 :Lancement vers le haut +STR_1068 :Mode montée rotative STR_1069 :Mode station à station STR_1070 :Un seul tour par entrée STR_1071 :Tours illimités par entrée STR_1072 :Mode labyrinthe STR_1073 :Mode course -STR_1074 :Mode auto-tamponneuses -STR_1075 :Swing mode -STR_1076 :Mode stand de boutique +STR_1074 :Mode auto-tamponneuses +STR_1075 :Mode Balancement +STR_1076 :Mode Magasins et boutiques STR_1077 :Mode rotation -STR_1078 :Rotation vers l'avant -STR_1079 :Rotation vers l'arrière -STR_1080 :Film: {ENDQUOTES}Les aviateurs vengeurs{ENDQUOTES} -STR_1081 :3D film: {ENDQUOTES}Queues de souris{ENDQUOTES} +STR_1078 :Rotation avant +STR_1079 :Rotation arrière +STR_1080 :Film : {ENDQUOTES}Les aviateurs vengeurs{ENDQUOTES} +STR_1081 :Film 3D : {ENDQUOTES}Les queues de souris{ENDQUOTES} STR_1082 :Mode anneaux de l'espace STR_1083 :Mode débutants -STR_1084 :LIM-powered launch -STR_1085 :Film: {ENDQUOTES}Le grand frisson{ENDQUOTES} -STR_1086 :3D film: {ENDQUOTES}Chasseurs de tempêtes{ENDQUOTES} -STR_1087 :3D film: {ENDQUOTES}Commandos de l'espace{ENDQUOTES} +STR_1084 :Lancement à induction linéaire +STR_1085 :Film : {ENDQUOTES}Le grand frisson{ENDQUOTES} +STR_1086 :Film 3D : {ENDQUOTES}Chasseurs de tempêtes{ENDQUOTES} +STR_1087 :Film 3D : {ENDQUOTES}Commandos de l'espace{ENDQUOTES} STR_1088 :Mode intense -STR_1089 :Berserk mode +STR_1089 :Mode fou furieux STR_1090 :Mode maison hantée STR_1091 :Mode spectacle de cirque -STR_1092 :Downward launch +STR_1092 :Lancement vers le bas STR_1093 :Mode maison biscornue STR_1094 :Mode chute libre -STR_1095 :Continuous circuit block sectioned mode -STR_1096 :Lancement (sans passage de la station) -STR_1097 :Powered launch block sectioned mode -STR_1098 :Se déplace vers la fin de {POP16}{STRINGID} +STR_1095 :Mode blocs de voie sur circuit continu +STR_1096 :Lancement à autopropulsion +STR_1097 :Mode blocs de voie avec lancement à autopropulsion +STR_1098 :Se déplace au bout de {POP16}{STRINGID} STR_1099 :Attend des passagers à {POP16}{STRINGID} STR_1100 :Attend pour quitter {POP16}{STRINGID} STR_1101 :Part de {POP16}{STRINGID} -STR_1102 :Voyage à {VELOCITY} +STR_1102 :Se déplace à {VELOCITY} STR_1103 :Arrive à {POP16}{STRINGID} STR_1104 :Dépose des passagers à {POP16}{STRINGID} -STR_1105 :Voyage à {VELOCITY} -STR_1106 :S'écrase! -STR_1107 :Écrasé! -STR_1108 :Voyage à {VELOCITY} +STR_1105 :Se déplace à {VELOCITY} +STR_1106 :Accident ! +STR_1107 :Accidenté ! +STR_1108 :Se déplace à {VELOCITY} STR_1109 :Se balance -STR_1110 :Pivote -STR_1111 :Pivote +STR_1110 :Tourne +STR_1111 :Tourne STR_1112 :Fonctionne STR_1113 :Diffuse le film -STR_1114 :Pivote +STR_1114 :Tourne STR_1115 :Fonctionne STR_1116 :Fonctionne STR_1117 :Spectacle de cirque en cours STR_1118 :Fonctionne STR_1119 :Attend la montée par câble -STR_1120 :Voyage à{VELOCITY} +STR_1120 :Se déplace à{VELOCITY} STR_1121 :S'arrête STR_1122 :Attend des passagers STR_1123 :Attend le départ @@ -1131,7 +1131,7 @@ STR_1124 :Démarre STR_1125 :Fonctionne STR_1126 :S'arrête STR_1127 :Dépose des passagers -STR_1128 :Arrété par les blocs de freins +STR_1128 :Arrêté par les freins de blocs STR_1129 :Tous les véhicules de la même couleur STR_1130 :Couleurs différentes par {STRINGID} STR_1131 :Couleurs différentes par véhicule @@ -1142,9 +1142,9 @@ STR_1135 :{STRINGID} {COMMA16} STR_1136 :{SMALLFONT}{BLACK}Sélectionnez la couleur principale STR_1137 :{SMALLFONT}{BLACK}Sélectionnez la couleur supplémentaire 1 STR_1138 :{SMALLFONT}{BLACK}Sélectionnez la couleur supplémentaire 2 -STR_1139 :{SMALLFONT}{BLACK}Sélectionnez la couleur de la structure de support -STR_1140 :{SMALLFONT}{BLACK}Sélectionnez le motif de couleur du véhicule -STR_1141 :{SMALLFONT}{BLACK}Sélectionnez quel véhicule/train à modifier +STR_1139 :{SMALLFONT}{BLACK}Sélectionnez la couleur de la structure +STR_1140 :{SMALLFONT}{BLACK}Sélectionnez la palette de couleur du véhicule +STR_1141 :{SMALLFONT}{BLACK}Sélectionnez le véhicule/train à modifier STR_1142 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1143 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRINGID} STR_1144 :Impossible de construire/déplacer l'entrée de cette attraction... @@ -1152,38 +1152,38 @@ STR_1145 :Impossible de construire/déplacer la sortie de cette attraction... STR_1146 :Entrée pas encore construite STR_1147 :Sortie pas encore construite STR_1148 :Quart de la charge -STR_1149 :Moitiée de la charge +STR_1149 :Moitié de la charge STR_1150 :Trois-quarts de la charge STR_1151 :Charge totale STR_1152 :N'importe quelle charge -STR_1153 :Niveau de hauteur sur les voies -STR_1154 :Niveau de hauteur sur le terrain -STR_1155 :Niveau de hauteur sur les chemins +STR_1153 :Repère de hauteur sur les voies +STR_1154 :Repère de hauteur sur le terrain +STR_1155 :Repère de hauteur sur les chemins STR_1156 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1157 :{TICK}{MOVE_X}{SMALLFONT}{STRINGID} STR_1158 :Impossible de supprimer ceci... STR_1159 :{SMALLFONT}{BLACK}Placer le décor, les jardins, et autres accessoires -STR_1160 :{SMALLFONT}{BLACK}Créer/Adjuster les lacs et l'eau -STR_1161 :Impossible de positionner ceci ici... +STR_1160 :{SMALLFONT}{BLACK}Créer/ajuster les étendues d'eau +STR_1161 :Positionnement impossible... STR_1162 :{OUTLINE}{TOPAZ}{STRINGID} -STR_1163 :{STRINGID}{NEWLINE}(Clic-droit pour modifier) -STR_1164 :{STRINGID}{NEWLINE}(Clic-droit pour supprimer) +STR_1163 :{STRINGID}{NEWLINE}(Clic droit pour modifier) +STR_1164 :{STRINGID}{NEWLINE}(Clic droit pour supprimer) STR_1165 :{STRINGID} - {STRINGID} {COMMA16} STR_1166 :Impossible d'abaisser le niveau de l'eau ici... STR_1167 :Impossible de surélever le niveau de l'eau ici... STR_1168 :Options -STR_1169 :(None) +STR_1169 :(Aucun) STR_1170 :{STRING} STR_1171 :{RED}Fermé - - STR_1172 :{YELLOW}{STRINGID} - - -STR_1173 :{SMALLFONT}{BLACK}Construire des chemins et des files d'attentes +STR_1173 :{SMALLFONT}{BLACK}Construire des allées et des files d'attentes STR_1174 :Panneau d'affichage sur le passage -STR_1175 :Impossible de construire ceci sur un chemin en pente -STR_1176 :Impossible de construire un chemin ici... -STR_1177 :Impossible de supprimer ce chemin... -STR_1178 :Terrain en pente inadapté -STR_1179 :Chemin sur le passage -STR_1180 :Impossible de construire ceci sous l'eau! +STR_1175 :Impossible de construire ceci sur une allée en pente +STR_1176 :Impossible de construire une allée ici... +STR_1177 :Impossible de supprimer cette allée... +STR_1178 :Inclinaison inappropriée +STR_1179 :Allée dans le passage +STR_1180 :Impossible de construire ceci sous l'eau ! STR_1181 :Allées STR_1182 :Type STR_1183 :Direction @@ -1192,8 +1192,8 @@ STR_1185 :{SMALLFONT}{BLACK}Direction STR_1186 :{SMALLFONT}{BLACK}Pente descendante STR_1187 :{SMALLFONT}{BLACK}Niveau STR_1188 :{SMALLFONT}{BLACK}Pente montante -STR_1189 :{SMALLFONT}{BLACK}Construire la section de chemin sélectionnée -STR_1190 :{SMALLFONT}{BLACK}Supprimer la section de chemin précédente +STR_1189 :{SMALLFONT}{BLACK}Construire la section d'allée sélectionnée +STR_1190 :{SMALLFONT}{BLACK}Supprimer la section d'allée précédente STR_1191 :{BLACK}{STRINGID} STR_1192 :{OUTLINE}{RED}{STRINGID} STR_1193 :{WINDOW_COLOUR_2}{STRINGID} @@ -1201,7 +1201,7 @@ STR_1194 :Fermé STR_1195 :En test STR_1196 :Ouvert STR_1197 :En panne -STR_1198 :Écrasé! +STR_1198 :Accident ! STR_1199 :{COMMA16} personne sur l'attraction STR_1200 :{COMMA16} personnes sur l'attraction STR_1201 :Personne dans la file d'attente @@ -1209,29 +1209,29 @@ STR_1202 :Une personne dans la file d'attente STR_1203 :{COMMA16} personnes dans la file d'attente STR_1204 :{COMMA16} minute d'attente STR_1205 :{COMMA16} minutes d'attente -STR_1206 :{WINDOW_COLOUR_2}Attendre: -STR_1207 :{WINDOW_COLOUR_2}Quitter si un autre train arrive à la station -STR_1208 :{WINDOW_COLOUR_2}Quitter si un autre bateau arrive à la station -STR_1209 :{SMALLFONT}{BLACK}Sélectionnez si il faut attendre des passagers avant de partir -STR_1210 :{SMALLFONT}{BLACK}Sélectionnez si il faut partir quand un autre véhicule arrive à la même station -STR_1211 :{WINDOW_COLOUR_2}Temps d'attente minimum: -STR_1212 :{WINDOW_COLOUR_2}Temps d'attente maximum: +STR_1206 :{WINDOW_COLOUR_2}Attend : +STR_1207 :{WINDOW_COLOUR_2}Démarre dès qu'un train arrive à quai +STR_1208 :{WINDOW_COLOUR_2}Démarre dès qu'un bateau arrive à quai +STR_1209 :{SMALLFONT}{BLACK}Sélectionnez s'il faut attendre des passagers avant de partir +STR_1210 :{SMALLFONT}{BLACK}Sélectionnez s'il faut partir quand un autre véhicule arrive au même quai +STR_1211 :{WINDOW_COLOUR_2}Temps d'attente min. : +STR_1212 :{WINDOW_COLOUR_2}Temps d'attente max. : STR_1213 :{SMALLFONT}{BLACK}Sélectionnez la durée minimum à attendre avant de partir STR_1214 :{SMALLFONT}{BLACK}Sélectionnez la durée maximum à attendre avant de partir STR_1215 :{WINDOW_COLOUR_2}Synchroniser avec les stations adjacentes -STR_1216 :{SMALLFONT}{BLACK}Sélectionnez si il faut synchroniser le départ avec toutes les stations adjacentes +STR_1216 :{SMALLFONT}{BLACK}Sélectionnez s'il faut synchroniser le départ avec toutes les stations adjacentes STR_1217 :{COMMA16} secondes STR_1218 :{BLACK}{SMALLUP} STR_1219 :{BLACK}{SMALLDOWN} -STR_1220 :Sortie seulement +STR_1220 :Sortie uniquement STR_1221 :Pas d'entrée STR_1222 :Pas de sortie -STR_1223 :{SMALLFONT}{BLACK}Moyens de transports -STR_1224 :{SMALLFONT}{BLACK}Attractions calmes +STR_1223 :{SMALLFONT}{BLACK}Attractions de transports +STR_1224 :{SMALLFONT}{BLACK}Attractions tranquilles STR_1225 :{SMALLFONT}{BLACK}Montagnes russes STR_1226 :{SMALLFONT}{BLACK}Attractions à frissons STR_1227 :{SMALLFONT}{BLACK}Attractions aquatiques -STR_1228 :{SMALLFONT}{BLACK}Magasins et stands +STR_1228 :{SMALLFONT}{BLACK}Magasins et boutiques STR_1229 :train STR_1230 :trains STR_1231 :Train @@ -1253,13 +1253,13 @@ STR_1246 :Voies STR_1247 :{COMMA16} voie STR_1248 :{COMMA16} voies STR_1249 :Voie {COMMA16} -STR_1250 :plateforme d'arrimage -STR_1251 :plateformes d'arrimage -STR_1252 :Plateforme d'arrimage -STR_1253 :Plateformes d'arrimage -STR_1254 :{COMMA16} plateforme d'arrimage -STR_1255 :{COMMA16} plateformes d'arrimage -STR_1256 :Plateforme d'arrimage {COMMA16} +STR_1250 :quai +STR_1251 :quais +STR_1252 :Quai +STR_1253 :Quais +STR_1254 :{COMMA16} quai +STR_1255 :{COMMA16} quais +STR_1256 :Quai {COMMA16} STR_1257 :station STR_1258 :stations STR_1259 :Station @@ -1323,16 +1323,16 @@ STR_1316 :Joueurs STR_1317 :{COMMA16} joueur STR_1318 :{COMMA16} joueurs STR_1319 :Joueur {COMMA16} -STR_1320 :course -STR_1321 :courses -STR_1322 :Course -STR_1323 :Courses -STR_1324 :{COMMA16} course -STR_1325 :{COMMA16} courses -STR_1326 :Course {COMMA16} +STR_1320 :parcours +STR_1321 :parcours +STR_1322 :Parcours +STR_1323 :Parcours +STR_1324 :{COMMA16} parcours +STR_1325 :{COMMA16} parcours +STR_1326 :Parcours {COMMA16} STR_1327 :{SMALLFONT}{BLACK}Pivoter les objets de 90{DEGREE} STR_1328 :Niveau de terrain requis -STR_1329 :{WINDOW_COLOUR_2}Vitesse de lancement: +STR_1329 :{WINDOW_COLOUR_2}Vitesse de lancement : STR_1330 :{SMALLFONT}{BLACK}Vitesse maximale en quittant la station STR_1331 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} STR_1332 :{VELOCITY} @@ -1343,49 +1343,49 @@ STR_1336 :{STRINGID} - Entrée de station {POP16}{COMMA16} STR_1337 :{STRINGID} - Sortie{POP16}{POP16} STR_1338 :{STRINGID} - Sortie de station {POP16}{COMMA16} STR_1339 :{BLACK}Pas encore de résultats de test... -STR_1340 :{WINDOW_COLOUR_2}Vitesse max.: {BLACK}{VELOCITY} -STR_1341 :{WINDOW_COLOUR_2}Durée de l'attraction: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1340 :{WINDOW_COLOUR_2}Vitesse maximale : {BLACK}{VELOCITY} +STR_1341 :{WINDOW_COLOUR_2}Durée de l'attraction : {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1342 :{DURATION} STR_1343 :{DURATION} / -STR_1344 :{WINDOW_COLOUR_2}Longueur de l'attraction: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1344 :{WINDOW_COLOUR_2}Longueur de l'attraction : {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1345 :{LENGTH} STR_1346 :{LENGTH} / -STR_1347 :{WINDOW_COLOUR_2}Vitesse moyenne: {BLACK}{VELOCITY} -STR_1348 :{WINDOW_COLOUR_2}Max. positive vertical G's: {BLACK}{COMMA2DP32}g -STR_1349 :{WINDOW_COLOUR_2}Max. positive vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1350 :{WINDOW_COLOUR_2}Max. negative vertical G's: {BLACK}{COMMA2DP32}g -STR_1351 :{WINDOW_COLOUR_2}Max. negative vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1352 :{WINDOW_COLOUR_2}Max. lateral G's: {BLACK}{COMMA2DP32}g -STR_1353 :{WINDOW_COLOUR_2}Max. lateral G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1354 :{WINDOW_COLOUR_2}Plus haute hauteur de chute: {BLACK}{LENGTH} -STR_1355 :{WINDOW_COLOUR_2}Chutes: {BLACK}{COMMA16} -STR_1356 :{WINDOW_COLOUR_2}Inversions: {BLACK}{COMMA16} -STR_1357 :{WINDOW_COLOUR_2}Trous: {BLACK}{COMMA16} -STR_1358 :{WINDOW_COLOUR_2}Total 'air' time: {BLACK}{COMMA2DP32}secs -STR_1359 :{WINDOW_COLOUR_2}Temps d'attente: {BLACK}{COMMA16} minute -STR_1360 :{WINDOW_COLOUR_2}Temps d'attente: {BLACK}{COMMA16} minutes +STR_1347 :{WINDOW_COLOUR_2}Vitesse moyenne : {BLACK}{VELOCITY} +STR_1348 :{WINDOW_COLOUR_2}Gravité verticale positive maximale : {BLACK}{COMMA2DP32}g +STR_1349 :{WINDOW_COLOUR_2}Gravité verticale positive maximale : {OUTLINE}{RED}{COMMA2DP32}g +STR_1350 :{WINDOW_COLOUR_2}Gravité verticale négative maximale : {BLACK}{COMMA2DP32}g +STR_1351 :{WINDOW_COLOUR_2}Gravité verticale négative maximale : {OUTLINE}{RED}{COMMA2DP32}g +STR_1352 :{WINDOW_COLOUR_2}Gravité latérale maximale : {BLACK}{COMMA2DP32}g +STR_1353 :{WINDOW_COLOUR_2}Gravité latérale maximale : {OUTLINE}{RED}{COMMA2DP32}g +STR_1354 :{WINDOW_COLOUR_2}Hauteur de chute maximale : {BLACK}{LENGTH} +STR_1355 :{WINDOW_COLOUR_2}Chutes : {BLACK}{COMMA16} +STR_1356 :{WINDOW_COLOUR_2}Inversions : {BLACK}{COMMA16} +STR_1357 :{WINDOW_COLOUR_2}Trous : {BLACK}{COMMA16} +STR_1358 :{WINDOW_COLOUR_2}Temps total en l'air : {BLACK}{COMMA2DP32}secs +STR_1359 :{WINDOW_COLOUR_2}Temps d'attente : {BLACK}{COMMA16} minute +STR_1360 :{WINDOW_COLOUR_2}Temps d'attente : {BLACK}{COMMA16} minutes STR_1361 :Impossible de changer la vitesse... -STR_1362 :Impossidle de changer la vitesse de lancement... -STR_1363 :Trop haut pour les supports! -STR_1364 :Les supports pour la voie d'au dessus ne peuvent être plus étendus! -STR_1365 :In-line Twist (left) -STR_1366 :In-line Twist (right) -STR_1367 :Demi boucle -STR_1368 :Half Corkscrew (left) -STR_1369 :Half Corkscrew (right) +STR_1362 :Impossible de changer la vitesse de lancement... +STR_1363 :Trop haut pour les supports ! +STR_1364 :Les supports pour la voie d'au dessus ne peuvent être plus étendus ! +STR_1365 :Balanc. intér. (gauche) +STR_1366 :Balanc. intér. (droite) +STR_1367 :Demie boucle +STR_1368 :Demi tire-bouchon (gauche) +STR_1369 :Demi tire-bouchon (droite) STR_1370 :Tonneau (gauche) STR_1371 :Tonneau (droite) -STR_1372 :Launched Lift Hill -STR_1373 :Large Half Loop (left) -STR_1374 :Large Half Loop (right) -STR_1375 :Upper Transfer -STR_1376 :Lower Transfer -STR_1377 :Heartline Roll (left) -STR_1378 :Heartline Roll (right) -STR_1379 :Reverser (left) -STR_1380 :Reverser (right) -STR_1381 :Curved Lift Hill (left) -STR_1382 :Curved Lift Hill (right) +STR_1372 :Remontée à propulsion +STR_1373 :Grande demie boucle (gauche) +STR_1374 :Grande demie boucle (droite) +STR_1375 :Transfert supérieur +STR_1376 :Transfert inférieur +STR_1377 :Inversion à 360{DEGREE} (gauche) +STR_1378 :Inversion à 360{DEGREE} (droite) +STR_1379 :Inverseur (gauche) +STR_1380 :Inverseur (droite) +STR_1381 :Remontée courbe (gauche) +STR_1382 :Remontée courbe (droite) STR_1383 :Quart de boucle STR_1384 :{YELLOW}{STRINGID} STR_1385 :{SMALLFONT}{BLACK}Autres configurations de voie @@ -1397,7 +1397,7 @@ STR_1390 :{CURRENCY2DP} STR_1391 :{RED}{CURRENCY2DP} STR_1392 :{SMALLFONT}{BLACK}Vue sur l'attraction STR_1393 :{SMALLFONT}{BLACK}Détails des véhicules -STR_1394 :{SMALLFONT}{BLACK}Options d'opération +STR_1394 :{SMALLFONT}{BLACK}Options d'exploitation STR_1395 :{SMALLFONT}{BLACK}Options de maintenance STR_1396 :{SMALLFONT}{BLACK}Options des couleurs STR_1397 :{SMALLFONT}{BLACK}Options de son et musique @@ -1412,38 +1412,38 @@ STR_1405 :{SMALLFONT}{BLACK}Miroir STR_1406 :{SMALLFONT}{BLACK}Activer/Désactiver le décor (si disponible pour ce modèle) STR_1407 :{WINDOW_COLOUR_2}Construire ceci... STR_1408 :{WINDOW_COLOUR_2}Prix : {BLACK}{CURRENCY} -STR_1409 :Plateforme d'entrée/sortie +STR_1409 :Quai d'entrée/sortie STR_1410 :Tour verticale STR_1411 :{STRINGID} dans le passage -STR_1412 :{WINDOW_COLOUR_3}Data logging not available for this type of ride -STR_1413 :{WINDOW_COLOUR_3}Data logging will start when next {STRINGID} leaves {STRINGID} +STR_1412 :{WINDOW_COLOUR_3}Inscription des données non disponible pour ce type d'attraction +STR_1413 :{WINDOW_COLOUR_3}Début inscript. données quand {STRINGID} partira de {STRINGID} STR_1414 :{SMALLFONT}{BLACK}{DURATION} STR_1415 :{WINDOW_COLOUR_2}Vitesse STR_1416 :{WINDOW_COLOUR_2}Altitude -STR_1417 :{WINDOW_COLOUR_2}Vert.G's -STR_1418 :{WINDOW_COLOUR_2}Lat.G's +STR_1417 :{WINDOW_COLOUR_2}G. vert. +STR_1418 :{WINDOW_COLOUR_2}G. lat. STR_1419 :{SMALLFONT}{BLACK}{VELOCITY} STR_1420 :{SMALLFONT}{BLACK}{LENGTH} STR_1421 :{SMALLFONT}{BLACK}{COMMA16}g -STR_1422 :{SMALLFONT}{BLACK}Prise en note des données de {POP16}{STRINGID} +STR_1422 :{SMALLFONT}{BLACK}Enregistrement des données de {POP16}{STRINGID} STR_1423 :{SMALLFONT}{BLACK}Chemin de la file d'attente STR_1424 :{SMALLFONT}{BLACK}Chemin STR_1425 :Chemin STR_1426 :File d'attente -STR_1427 :{WINDOW_COLOUR_2}Clients: {BLACK}{COMMA32} par heure -STR_1428 :{WINDOW_COLOUR_2}Prix d'entrée: +STR_1427 :{WINDOW_COLOUR_2}Clients : {BLACK}{COMMA32} par heure +STR_1428 :{WINDOW_COLOUR_2}Prix d'entrée : STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} STR_1430 :Gratuit STR_1431 :Marche STR_1432 :Se dirige vers {STRINGID} STR_1433 :Fait la queue pour {STRINGID} STR_1434 :Se noie -STR_1435 :En {STRINGID} +STR_1435 :Sur {STRINGID} STR_1436 :Dans {STRINGID} STR_1437 :A {STRINGID} STR_1438 :Est assis -STR_1439 :(select location) -STR_1440 :Tond le gazon +STR_1439 :(choisir lieu) +STR_1440 :Tond la pelouse STR_1441 :Balaye l'allée STR_1442 :Vide la poubelle STR_1443 :Arrose les jardins @@ -1451,83 +1451,83 @@ STR_1444 :Regarde {STRINGID} STR_1445 :Regarde la construction de {STRINGID} STR_1446 :Regarde le décor STR_1447 :Quitte le parc -STR_1448 :Regarde une nouvelle attraction en cours de construction +STR_1448 :Regarde la construction d'une nouvelle attraction STR_1449 :{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1450 :{INLINE_SPRITE}{09}{20}{00}{00}{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1451 :{STRINGID}{NEWLINE}({STRINGID}) STR_1452 :Nom du visiteur -STR_1453 :Entrez un nom pour ce visiteur: -STR_1454 :Impossible de nommer le visiteur... +STR_1453 :Entrez un nom pour ce visiteur : +STR_1454 :Impossible de renommer le visiteur... STR_1455 :Nom de visiteur invalide -STR_1456 :{WINDOW_COLOUR_2}Argent dépensé: {BLACK}{CURRENCY2DP} -STR_1457 :{WINDOW_COLOUR_2}Argent dans la poche: {BLACK}{CURRENCY2DP} -STR_1458 :{WINDOW_COLOUR_2}Temps dans le parc: {BLACK}{REALTIME} +STR_1456 :{WINDOW_COLOUR_2}Argent dépensé : {BLACK}{CURRENCY2DP} +STR_1457 :{WINDOW_COLOUR_2}Argent en poche : {BLACK}{CURRENCY2DP} +STR_1458 :{WINDOW_COLOUR_2}Temps dans le parc : {BLACK}{REALTIME} STR_1459 :Type de voie STR_1460 :{SMALLFONT}{BLACK}Voie ouverte en forme de 'U' STR_1461 :{SMALLFONT}{BLACK}Voie fermée en forme de 'O' -STR_1462 :Too steep for lift hill +STR_1462 :Trop abrupte pour une remontée STR_1463 :Visiteurs STR_1464 :Hélice montante (petite) STR_1465 :Hélice montante (grande) STR_1466 :Hélice descendante (petite) STR_1467 :Hélice descendante (grande) STR_1468 :Personnel -STR_1469 :L'attraction doit commencer et finir avec des stations -STR_1470 :Station pas assez longue -STR_1471 :{WINDOW_COLOUR_2}Vitesse: +STR_1469 :L'attraction doit commencer et finir avec un quai +STR_1470 :Quai trop court +STR_1471 :{WINDOW_COLOUR_2}Vitesse : STR_1472 :{SMALLFONT}{BLACK}Vitesse de cette attraction -STR_1473 :{WINDOW_COLOUR_2}Niveau d'excitation: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1474 :{WINDOW_COLOUR_2}Niveau d'excitation: {BLACK}Pas encore disponible -STR_1475 :{WINDOW_COLOUR_2}Niveau d'intensité: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1476 :{WINDOW_COLOUR_2}Niveau d'intensité: {BLACK}Pas encore disponible -STR_1477 :{WINDOW_COLOUR_2}Niveau d'intensité: {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) -STR_1478 :{WINDOW_COLOUR_2}Niveau de nausée: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1479 :{WINDOW_COLOUR_2}Niveau de nausée: {BLACK}Pas encore disponible -STR_1480 :{SMALLFONT}{OPENQUOTES}Je ne peux pas me payer{STRINGID}{ENDQUOTES} +STR_1473 :{WINDOW_COLOUR_2}Niveau d'excitation : {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1474 :{WINDOW_COLOUR_2}Niveau d'excitation : {BLACK}Pas encore disponible +STR_1475 :{WINDOW_COLOUR_2}Niveau d'intensité : {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1476 :{WINDOW_COLOUR_2}Niveau d'intensité : {BLACK}Pas encore disponible +STR_1477 :{WINDOW_COLOUR_2}Niveau d'intensité : {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) +STR_1478 :{WINDOW_COLOUR_2}Niveau de nausée : {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1479 :{WINDOW_COLOUR_2}Niveau de nausée : {BLACK}Pas encore disponible +STR_1480 :{SMALLFONT}{OPENQUOTES}Je ne peux pas me payer {STRINGID}{ENDQUOTES} STR_1481 :{SMALLFONT}{OPENQUOTES}J'ai dépensé tout mon argent{ENDQUOTES} -STR_1482 :{SMALLFONT}{OPENQUOTES}Je me sens malade{ENDQUOTES} -STR_1483 :{SMALLFONT}{OPENQUOTES}Je me sens très malade{ENDQUOTES} -STR_1484 :{SMALLFONT}{OPENQUOTES}Je veux aller sur quelque chose de plus excitant que {STRINGID}{ENDQUOTES} +STR_1482 :{SMALLFONT}{OPENQUOTES}Je me sens mal{ENDQUOTES} +STR_1483 :{SMALLFONT}{OPENQUOTES}Je me sens vraiment très mal{ENDQUOTES} +STR_1484 :{SMALLFONT}{OPENQUOTES}Je veux faire quelque chose de plus excitant que {STRINGID}{ENDQUOTES} STR_1485 :{SMALLFONT}{OPENQUOTES}{STRINGID} a l'air trop intense pour moi{ENDQUOTES} STR_1486 :{SMALLFONT}{OPENQUOTES}Je n'ai pas encore fini mon {STRINGID} {ENDQUOTES} STR_1487 :{SMALLFONT}{OPENQUOTES}Rien que le fait de regarder {STRINGID} me rend malade{ENDQUOTES} -STR_1488 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour aller sur {STRINGID}{ENDQUOTES} +STR_1488 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour aller sur {STRINGID}{ENDQUOTES} STR_1489 :{SMALLFONT}{OPENQUOTES}Je veux rentrer chez moi{ENDQUOTES} STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} est un très bon choix{ENDQUOTES} STR_1491 :{SMALLFONT}{OPENQUOTES}J'ai déjà un {STRINGID}{ENDQUOTES} STR_1492 :{SMALLFONT}{OPENQUOTES}Je ne peux pas me payer {STRINGID}{ENDQUOTES} STR_1493 :{SMALLFONT}{OPENQUOTES}Je n'ai pas faim{ENDQUOTES} STR_1494 :{SMALLFONT}{OPENQUOTES}Je n'ai pas soif{ENDQUOTES} -STR_1495 :{SMALLFONT}{OPENQUOTES}À l'aide! Je me noie!{ENDQUOTES} -STR_1496 :{SMALLFONT}{OPENQUOTES}Je suis perdu!{ENDQUOTES} +STR_1495 :{SMALLFONT}{OPENQUOTES}À l'aide ! Je me noie !{ENDQUOTES} +STR_1496 :{SMALLFONT}{OPENQUOTES}Je suis perdu !{ENDQUOTES} STR_1497 :{SMALLFONT}{OPENQUOTES}{STRINGID} était génial{ENDQUOTES} -STR_1498 :{SMALLFONT}{OPENQUOTES}Je fais la queue pour {STRINGID} depuis des années{ENDQUOTES} +STR_1498 :{SMALLFONT}{OPENQUOTES}Je fais la queue pour {STRINGID} depuis des heures{ENDQUOTES} STR_1499 :{SMALLFONT}{OPENQUOTES}Je suis fatigué{ENDQUOTES} STR_1500 :{SMALLFONT}{OPENQUOTES}J'ai faim{ENDQUOTES} STR_1501 :{SMALLFONT}{OPENQUOTES}J'ai soif{ENDQUOTES} STR_1502 :{SMALLFONT}{OPENQUOTES}Je dois aller aux toilettes{ENDQUOTES} -STR_1503 :{SMALLFONT}{OPENQUOTES}Je ne peux pas trouver {STRINGID}{ENDQUOTES} -STR_1504 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour utiliser {STRINGID}{ENDQUOTES} -STR_1505 :{SMALLFONT}{OPENQUOTES}Je ne vais pas sur {STRINGID} pendant qu'il pleut{ENDQUOTES} -STR_1506 :{SMALLFONT}{OPENQUOTES}La poubelle est mauvaise ici{ENDQUOTES} -STR_1507 :{SMALLFONT}{OPENQUOTES}Je ne peux pas trouver la sortie du parc{ENDQUOTES} +STR_1503 :{SMALLFONT}{OPENQUOTES}Je ne trouve pas {STRINGID}{ENDQUOTES} +STR_1504 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour utiliser {STRINGID}{ENDQUOTES} +STR_1505 :{SMALLFONT}{OPENQUOTES}Je n'irai pas sur {STRINGID} tant qu'il pleuvra{ENDQUOTES} +STR_1506 :{SMALLFONT}{OPENQUOTES}Les poubelles ne sont pas vidées ici{ENDQUOTES} +STR_1507 :{SMALLFONT}{OPENQUOTES}Je trouve pas la sortie du parc{ENDQUOTES} STR_1508 :{SMALLFONT}{OPENQUOTES}Je veux descendre de {STRINGID}{ENDQUOTES} STR_1509 :{SMALLFONT}{OPENQUOTES}Je veux sortir de {STRINGID}{ENDQUOTES} -STR_1510 :{SMALLFONT}{OPENQUOTES}Je ne vais pas sur {STRINGID} - Ce n'est pas sécurisé{ENDQUOTES} -STR_1511 :{SMALLFONT}{OPENQUOTES}Ce chemin me dégoûte{ENDQUOTES} +STR_1510 :{SMALLFONT}{OPENQUOTES}Je n'irai pas sur {STRINGID} - C'est trop risqué{ENDQUOTES} +STR_1511 :{SMALLFONT}{OPENQUOTES}Cette allée est dégoûtante{ENDQUOTES} STR_1512 :{SMALLFONT}{OPENQUOTES}Il y a trop de monde ici{ENDQUOTES} -STR_1513 :{SMALLFONT}{OPENQUOTES}Le vandalisme ici est vraiment mauvais{ENDQUOTES} -STR_1514 :{SMALLFONT}{OPENQUOTES}Super décor!{ENDQUOTES} -STR_1515 :{SMALLFONT}{OPENQUOTES}Ce parc est très propre et organisé{ENDQUOTES} +STR_1513 :{SMALLFONT}{OPENQUOTES}Il y a beaucoup de vandalisme ici{ENDQUOTES} +STR_1514 :{SMALLFONT}{OPENQUOTES}Quel beau décor !{ENDQUOTES} +STR_1515 :{SMALLFONT}{OPENQUOTES}Ce parc est d'une propreté exemplaire{ENDQUOTES} STR_1516 :{SMALLFONT}{OPENQUOTES}Les jets d'eau sont super{ENDQUOTES} STR_1517 :{SMALLFONT}{OPENQUOTES}La musique est sympa ici{ENDQUOTES} STR_1518 :{SMALLFONT}{OPENQUOTES}Ce ballon de {STRINGID} est un très bon choix{ENDQUOTES} STR_1519 :{SMALLFONT}{OPENQUOTES}Cette peluche de {STRINGID} est un très bon choix{ENDQUOTES} -STR_1520 :{SMALLFONT}{OPENQUOTES}Cette carte du parc de {STRINGID} est un très bon choix{ENDQUOTES} +STR_1520 :{SMALLFONT}{OPENQUOTES}Ce plan du parc de {STRINGID} est un très bon choix{ENDQUOTES} STR_1521 :{SMALLFONT}{OPENQUOTES}Cette photo sur le vif de {STRINGID} est un très bon choix{ENDQUOTES} STR_1522 :{SMALLFONT}{OPENQUOTES}Ce parapluie de {STRINGID} est un très bon choix{ENDQUOTES} STR_1523 :{SMALLFONT}{OPENQUOTES}Cette boisson de {STRINGID} est un très bon choix{ENDQUOTES} -STR_1524 :{SMALLFONT}{OPENQUOTES}Ce burger de {STRINGID} est un très bon choix{ENDQUOTES} +STR_1524 :{SMALLFONT}{OPENQUOTES}Cet hamburger de {STRINGID} est un très bon choix{ENDQUOTES} STR_1525 :{SMALLFONT}{OPENQUOTES}Ces frites de {STRINGID} sont un très bon choix{ENDQUOTES} STR_1526 :{SMALLFONT}{OPENQUOTES}Cette glace de {STRINGID} est un très bon choix{ENDQUOTES} STR_1527 :{SMALLFONT}{OPENQUOTES}Cette barbe-à-papa de {STRINGID} est un très bon choix{ENDQUOTES} @@ -1553,34 +1553,34 @@ STR_1546 : STR_1547 : STR_1548 : STR_1549 : -STR_1550 :{SMALLFONT}{OPENQUOTES}Wow!{ENDQUOTES} -STR_1551 :{SMALLFONT}{OPENQUOTES}J'ai l'étrange impression que quelqu'un me regarde{ENDQUOTES} -STR_1552 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un ballon de {STRINGID}{ENDQUOTES} -STR_1553 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une peluche de {STRINGID}{ENDQUOTES} -STR_1554 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une carte du parc de {STRINGID}{ENDQUOTES} -STR_1555 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une photo sur le vif de {STRINGID}{ENDQUOTES} -STR_1556 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un parapluie de {STRINGID}{ENDQUOTES} -STR_1557 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une boisson de {STRINGID}{ENDQUOTES} -STR_1558 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un burger de {STRINGID}{ENDQUOTES} -STR_1559 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour des frites de {STRINGID}{ENDQUOTES} -STR_1560 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une glace de {STRINGID}{ENDQUOTES} -STR_1561 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une barbe-à-papa de {STRINGID}{ENDQUOTES} +STR_1550 :{SMALLFONT}{OPENQUOTES}Ouah!{ENDQUOTES} +STR_1551 :{SMALLFONT}{OPENQUOTES}J'ai l'étrange impression que quelqu'un m'observe{ENDQUOTES} +STR_1552 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un ballon de {STRINGID}{ENDQUOTES} +STR_1553 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une peluche de {STRINGID}{ENDQUOTES} +STR_1554 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un plan du parc de {STRINGID}{ENDQUOTES} +STR_1555 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une photo sur le vif de {STRINGID}{ENDQUOTES} +STR_1556 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un parapluie de {STRINGID}{ENDQUOTES} +STR_1557 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une boisson de {STRINGID}{ENDQUOTES} +STR_1558 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un hamburger de {STRINGID}{ENDQUOTES} +STR_1559 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour des frites de {STRINGID}{ENDQUOTES} +STR_1560 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une glace de {STRINGID}{ENDQUOTES} +STR_1561 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une barbe-à-papa de {STRINGID}{ENDQUOTES} STR_1562 : STR_1563 : STR_1564 : -STR_1565 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une pizza de {STRINGID}{ENDQUOTES} +STR_1565 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une pizza de {STRINGID}{ENDQUOTES} STR_1566 : -STR_1567 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour du popcorn de {STRINGID}{ENDQUOTES} -STR_1568 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un hot dog de {STRINGID}{ENDQUOTES} -STR_1569 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour du poulpe de {STRINGID}{ENDQUOTES} -STR_1570 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un chapeau de {STRINGID}{ENDQUOTES} -STR_1571 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une pomme d'amour de {STRINGID}{ENDQUOTES} -STR_1572 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un T-shirt de {STRINGID}{ENDQUOTES} -STR_1573 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un donut de {STRINGID}{ENDQUOTES} -STR_1574 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un café de {STRINGID}{ENDQUOTES} +STR_1567 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour du popcorn de {STRINGID}{ENDQUOTES} +STR_1568 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un hot dog de {STRINGID}{ENDQUOTES} +STR_1569 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour du poulpe de {STRINGID}{ENDQUOTES} +STR_1570 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un chapeau de {STRINGID}{ENDQUOTES} +STR_1571 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une pomme d'amour de {STRINGID}{ENDQUOTES} +STR_1572 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un T-shirt de {STRINGID}{ENDQUOTES} +STR_1573 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un donut de {STRINGID}{ENDQUOTES} +STR_1574 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un café de {STRINGID}{ENDQUOTES} STR_1575 : -STR_1576 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour du poulet frit de {STRINGID}{ENDQUOTES} -STR_1577 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un limonade de {STRINGID}{ENDQUOTES} +STR_1576 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour du poulet frit de {STRINGID}{ENDQUOTES} +STR_1577 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un limonade de {STRINGID}{ENDQUOTES} STR_1578 : STR_1579 : STR_1580 : @@ -1602,7 +1602,7 @@ STR_1595 :{SMALLFONT}{OPENQUOTES}Cette soupe aux boulettes de viande de {STRI STR_1596 :{SMALLFONT}{OPENQUOTES}Ce jus de fruits de {STRINGID} est un très bon choix{ENDQUOTES} STR_1597 :{SMALLFONT}{OPENQUOTES}Ce lait de soja de {STRINGID} est un très bon choix{ENDQUOTES} STR_1598 :{SMALLFONT}{OPENQUOTES}Ce sujongkwa de {STRINGID} est un très bon choix{ENDQUOTES} -STR_1599 :{SMALLFONT}{OPENQUOTES}Ce sub sandwich de {STRINGID} est un très bon choix{ENDQUOTES} +STR_1599 :{SMALLFONT}{OPENQUOTES}Ce sandwich de {STRINGID} est un très bon choix{ENDQUOTES} STR_1600 :{SMALLFONT}{OPENQUOTES}Ce cookie de {STRINGID} est un très bon choix{ENDQUOTES} STR_1601 : STR_1602 : @@ -1619,27 +1619,27 @@ STR_1612 : STR_1613 : STR_1614 : STR_1615 : -STR_1616 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une photo sur le vif de {STRINGID}{ENDQUOTES} -STR_1617 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une photo sur le vif de {STRINGID}{ENDQUOTES} -STR_1618 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une photo sur le vif de {STRINGID}{ENDQUOTES} -STR_1619 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un bretzel de {STRINGID}{ENDQUOTES} -STR_1620 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un chocolat chaud de {STRINGID}{ENDQUOTES} -STR_1621 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour du thé glacé de {STRINGID}{ENDQUOTES} -STR_1622 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un funnel cake de {STRINGID}{ENDQUOTES} -STR_1623 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour des lunettes de soleil de {STRINGID}{ENDQUOTES} -STR_1624 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour des nouilles au boeuf de {STRINGID}{ENDQUOTES} -STR_1625 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour des nouilles au riz frit de {STRINGID}{ENDQUOTES} -STR_1626 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une soupe aux raviolis de {STRINGID}{ENDQUOTES} -STR_1627 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une soupe aux boulettes de viandes de {STRINGID}{ENDQUOTES} -STR_1628 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un jus de fruits de {STRINGID}{ENDQUOTES} -STR_1629 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour du lait de soja de {STRINGID}{ENDQUOTES} -STR_1630 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un sujongkwa de {STRINGID}{ENDQUOTES} -STR_1631 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un sub sandwich de {STRINGID}{ENDQUOTES} -STR_1632 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour un cookie de {STRINGID}{ENDQUOTES} +STR_1616 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une photo sur le vif de {STRINGID}{ENDQUOTES} +STR_1617 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une photo sur le vif de {STRINGID}{ENDQUOTES} +STR_1618 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une photo sur le vif de {STRINGID}{ENDQUOTES} +STR_1619 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un bretzel de {STRINGID}{ENDQUOTES} +STR_1620 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un chocolat chaud de {STRINGID}{ENDQUOTES} +STR_1621 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour du thé glacé de {STRINGID}{ENDQUOTES} +STR_1622 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un funnel cake de {STRINGID}{ENDQUOTES} +STR_1623 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour des lunettes de soleil de {STRINGID}{ENDQUOTES} +STR_1624 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour des nouilles au boeuf de {STRINGID}{ENDQUOTES} +STR_1625 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour des nouilles au riz frit de {STRINGID}{ENDQUOTES} +STR_1626 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une soupe aux raviolis de {STRINGID}{ENDQUOTES} +STR_1627 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une soupe aux boulettes de viandes de {STRINGID}{ENDQUOTES} +STR_1628 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un jus de fruits de {STRINGID}{ENDQUOTES} +STR_1629 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour du lait de soja de {STRINGID}{ENDQUOTES} +STR_1630 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un sujongkwa de {STRINGID}{ENDQUOTES} +STR_1631 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un sandwich de {STRINGID}{ENDQUOTES} +STR_1632 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour un cookie de {STRINGID}{ENDQUOTES} STR_1633 : STR_1634 : STR_1635 : -STR_1636 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas autant pour une saucisse grillée de {STRINGID}{ENDQUOTES} +STR_1636 :{SMALLFONT}{OPENQUOTES}Je ne paierai pas si cher pour une saucisse grillée de {STRINGID}{ENDQUOTES} STR_1637 : STR_1638 : STR_1639 : @@ -1651,116 +1651,116 @@ STR_1644 : STR_1645 : STR_1646 : STR_1647 : -STR_1648 :{SMALLFONT}{OPENQUOTES}À l'aide! Déposez-moi!{ENDQUOTES} -STR_1649 :{SMALLFONT}{OPENQUOTES}Je n'ai plus d'argent!{ENDQUOTES} -STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! Une nouvelle attraction en cours de construction!{ENDQUOTES} -STR_1651 :{SMALLFONT}{OPENQUOTES}Super attraction! Mais pas aussi bien que le Phoenix...{ENDQUOTES} -STR_1652 :{SMALLFONT}{OPENQUOTES}Je suis tellement excité - C'est une attraction Intamin!{ENDQUOTES} -STR_1653 :{SMALLFONT}{OPENQUOTES}...et là nous sommes sur {STRINGID}!{ENDQUOTES} -STR_1654 :{WINDOW_COLOUR_2}Pensées récentes: -STR_1655 :{SMALLFONT}{BLACK}Construire un chemin sur le terrain +STR_1648 :{SMALLFONT}{OPENQUOTES}À l'aide ! Déposez-moi !{ENDQUOTES} +STR_1649 :{SMALLFONT}{OPENQUOTES}Je n'ai plus d'argent !{ENDQUOTES} +STR_1650 :{SMALLFONT}{OPENQUOTES}Ouah! Ils construisent une nouvelle attraction !{ENDQUOTES} +STR_1651 :{SMALLFONT}{OPENQUOTES}Super attraction ! Mais pas aussi bien que le Phoenix...{ENDQUOTES} +STR_1652 :{SMALLFONT}{OPENQUOTES}Je suis tellement excité: c'est une attraction Intamin!{ENDQUOTES} +STR_1653 :{SMALLFONT}{OPENQUOTES}... et là nous sommes sur {STRINGID}!{ENDQUOTES} +STR_1654 :{WINDOW_COLOUR_2}Pensées récentes : +STR_1655 :{SMALLFONT}{BLACK}Construire une allée sur le terrain STR_1656 :{SMALLFONT}{BLACK}Construire un pont ou un tunnel -STR_1657 :{WINDOW_COLOUR_2}Attraction favorite -STR_1658 :{WINDOW_COLOUR_2}intensité: {BLACK}moins de {COMMA16} -STR_1659 :{WINDOW_COLOUR_2}intensité: {BLACK}entre {COMMA16} et {COMMA16} -STR_1660 :{WINDOW_COLOUR_2}intensité: {BLACK}plus de {COMMA16} -STR_1661 :{WINDOW_COLOUR_2}Tolérance nausée: {BLACK}{STRINGID} -STR_1662 :{WINDOW_COLOUR_2}Bonheur: -STR_1663 :{WINDOW_COLOUR_2}Nausée: -STR_1664 :{WINDOW_COLOUR_2}Énergie: -STR_1665 :{WINDOW_COLOUR_2}Faim: -STR_1666 :{WINDOW_COLOUR_2}Soif: -STR_1667 :{WINDOW_COLOUR_2}Toilettes: -STR_1668 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}Inconnue -STR_1669 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}{COMMA16}% -STR_1670 :{WINDOW_COLOUR_2}Total de clients: {BLACK}{COMMA32} -STR_1671 :{WINDOW_COLOUR_2}Profit total: {BLACK}{CURRENCY2DP} +STR_1657 :{WINDOW_COLOUR_2}Aime les attractions +STR_1658 :{WINDOW_COLOUR_2}d'intensité : {BLACK}moins de {COMMA16} +STR_1659 :{WINDOW_COLOUR_2}d'intensité : {BLACK}entre {COMMA16} et {COMMA16} +STR_1660 :{WINDOW_COLOUR_2}d'intensité : {BLACK}plus de {COMMA16} +STR_1661 :{WINDOW_COLOUR_2}Tolérance nausée : {BLACK}{STRINGID} +STR_1662 :{WINDOW_COLOUR_2}Bonheur : +STR_1663 :{WINDOW_COLOUR_2}Nausée : +STR_1664 :{WINDOW_COLOUR_2}Énergie : +STR_1665 :{WINDOW_COLOUR_2}Faim : +STR_1666 :{WINDOW_COLOUR_2}Soif : +STR_1667 :{WINDOW_COLOUR_2}Toilettes : +STR_1668 :{WINDOW_COLOUR_2}Satisfaction : {BLACK}Inconnue +STR_1669 :{WINDOW_COLOUR_2}Satisfaction : {BLACK}{COMMA16}% +STR_1670 :{WINDOW_COLOUR_2}Total de clients : {BLACK}{COMMA32} +STR_1671 :{WINDOW_COLOUR_2}Bénéfice total : {BLACK}{CURRENCY2DP} STR_1672 :Freins -STR_1673 :Spinning Control Toggle Track -STR_1674 :Vitesse des freins +STR_1673 :Voie avec permutation de virage +STR_1674 :Vitesse de freinage STR_1675 :{POP16}{VELOCITY} -STR_1676 :{SMALLFONT}{BLACK}Définir la limite de vitesse pour les freins -STR_1677 :{WINDOW_COLOUR_2}Popularité: {BLACK}Inconnue -STR_1678 :{WINDOW_COLOUR_2}Popularité: {BLACK}{COMMA16}% +STR_1676 :{SMALLFONT}{BLACK}Fixer une vitesse de déclenchement des freins +STR_1677 :{WINDOW_COLOUR_2}Popularité : {BLACK}Inconnue +STR_1678 :{WINDOW_COLOUR_2}Popularité : {BLACK}{COMMA16}% STR_1679 :Hélice montante (gauche) STR_1680 :Hélice montante (droite) STR_1681 :Hélice descendante (gauche) STR_1682 :Hélice descendante (droite) -STR_1683 :Base size 2 x 2 -STR_1684 :Base size 4 x 4 -STR_1685 :Base size 2 x 4 -STR_1686 :Base size 5 x 1 -STR_1687 :Water splash -STR_1688 :Base size 4 x 1 -STR_1689 :Blocs de freins +STR_1683 :Taille de base 2 x 2 +STR_1684 :Taille de base 4 x 4 +STR_1685 :Taille de base 2 x 4 +STR_1686 :Taille de base 5 x 1 +STR_1687 :Plongeon +STR_1688 :Taille de base 4 x 1 +STR_1689 :Freins de blocs STR_1690 :{WINDOW_COLOUR_2}{STRINGID}{NEWLINE}{BLACK}{STRINGID} -STR_1691 :{WINDOW_COLOUR_2} Coût: {BLACK}{CURRENCY} -STR_1692 :{WINDOW_COLOUR_2} Coût: {BLACK}de {CURRENCY} +STR_1691 :{WINDOW_COLOUR_2} Coût : {BLACK}{CURRENCY} +STR_1692 :{WINDOW_COLOUR_2} Coût : {BLACK}de {CURRENCY} STR_1693 :{SMALLFONT}{BLACK}Visiteurs STR_1694 :{SMALLFONT}{BLACK}Personnel -STR_1695 :{SMALLFONT}{BLACK}Profit et coûts +STR_1695 :{SMALLFONT}{BLACK}Revenus et coûts STR_1696 :{SMALLFONT}{BLACK}Informations sur les clients -STR_1697 :Impossible de les placer sur une file d'attente +STR_1697 :Impossible de placer sur une file d'attente STR_1698 :Ne peut être placé que sur une file d'attente -STR_1699 :Trop de personnes en jeu -STR_1700 :Embaucher un nouvel homme de service -STR_1701 :Embaucher un nouveau mécanicien -STR_1702 :Embaucher un nouvel agent de sécurité -STR_1703 :Embaucher un nouvel animateur +STR_1699 :Trop de personnes dans la partie +STR_1700 :Embaucher ag. d'entretien +STR_1701 :Embaucher mécanicien +STR_1702 :Embaucher ag. de sécurité +STR_1703 :Embaucher animateur STR_1704 :Impossible d'embaucher de nouveaux employés... STR_1705 :{SMALLFONT}{BLACK}Licencier cet employé -STR_1706 :{SMALLFONT}{BLACK}Déplacer cette personne vers une nouvelle localisation -STR_1707 :Trop d'employés en jeu +STR_1706 :{SMALLFONT}{BLACK}Déplacer cette personne +STR_1707 :Trop d'employés dans la partie STR_1708 :{SMALLFONT}{BLACK}Définir une zone de patrouille pour cet employé STR_1709 :Licencier des employés STR_1710 :Oui -STR_1711 :{WINDOW_COLOUR_1}Êtes-vous sûr de vouloir licencier {STRINGID}? -STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Balayer les chemins +STR_1711 :{WINDOW_COLOUR_1}Êtes-vous sûr de vouloir licencier {STRINGID} ? +STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Balayer les allées STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Arroser les jardins STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Vider les poubelles -STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Tondre le gazon +STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Tondre la pelouse STR_1716 :Nom du parc non valide STR_1717 :Impossible de renommer le parc... STR_1718 :Nom du parc -STR_1719 :Saisir nom du parc: -STR_1720 :{SMALLFONT}{BLACK}Nommer le parc +STR_1719 :Saisir nom du parc : +STR_1720 :{SMALLFONT}{BLACK}Renommer le parc STR_1721 :Parc fermé STR_1722 :Parc ouvert STR_1723 :Impossible d'ouvrir le parc... STR_1724 :Impossible de fermer le parc... STR_1725 :Impossible d'acheter ce terrain... -STR_1726 :Ce terrain n'est pas a vendre! -STR_1727 :Les droits de construction ne sont pas à vendre! +STR_1726 :Ce terrain n'est pas a vendre ! +STR_1727 :Les droits de construction ne sont pas à vendre ! STR_1728 :Impossible d'acheter les droits de construction ici... -STR_1729 :Ce terrain n'appartient pas au parc! -STR_1730 :{RED}Fermé - - +STR_1729 :Ce terrain n'appartient pas au parc ! +STR_1730 :{RED}Fermé - - STR_1731 :{WHITE}{STRINGID} - - -STR_1732 :Construire +STR_1732 :Construction STR_1733 :Mode -STR_1734 :{WINDOW_COLOUR_2}Nombre de tours: +STR_1734 :{WINDOW_COLOUR_2}Nombre de tours : STR_1735 :{SMALLFONT}{BLACK}Nombre de tours du circuit STR_1736 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1737 :{COMMA16} STR_1738 :Impossible de changer le nombre de tours... -STR_1739 :Course gagnée par visiteur {INT32} +STR_1739 :Course gagnée par le visiteur {INT32} STR_1740 :Course gagnée par {STRINGID} -STR_1741 :Pas encore construit! -STR_1742 :{WINDOW_COLOUR_2}Personnes max. sur l'attraction: +STR_1741 :Pas encore construit ! +STR_1742 :{WINDOW_COLOUR_2}Maximum de personnes : STR_1743 :{SMALLFONT}{BLACK}Nombre maximum de personnes autorisées sur cette attraction en même temps STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1745 :{COMMA16} STR_1746 :Impossible de changer ceci... -STR_1747 :{WINDOW_COLOUR_2}Limite de temps: +STR_1747 :{WINDOW_COLOUR_2}Limite de temps : STR_1748 :{SMALLFONT}{BLACK}Limite de temps pour l'attraction STR_1749 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{DURATION} STR_1750 :{DURATION} STR_1751 :Impossible de changer la limite de temps pour l'attraction... -STR_1752 :{SMALLFONT}{BLACK}Afficher la liste de chaque visiteur dans le parc +STR_1752 :{SMALLFONT}{BLACK}Afficher la liste de tous les visiteurs dans le parc STR_1753 :{SMALLFONT}{BLACK}Afficher la liste résumée des visiteurs dans le parc STR_1754 :{BLACK}{COMMA16} visiteurs STR_1755 :{BLACK}{COMMA16} visiteur -STR_1756 :{WINDOW_COLOUR_2}Prix d'entrée: -STR_1757 :{WINDOW_COLOUR_2}Fiabilité: {MOVE_X}{255}{BLACK}{COMMA16}% +STR_1756 :{WINDOW_COLOUR_2}Prix d'entrée : +STR_1757 :{WINDOW_COLOUR_2}Fiabilité : {MOVE_X}{255}{BLACK}{COMMA16}% STR_1758 :{SMALLFONT}{BLACK}Mode construction STR_1759 :{SMALLFONT}{BLACK}Mode déplacement STR_1760 :{SMALLFONT}{BLACK}Mode remplissage @@ -1770,14 +1770,14 @@ STR_1763 :Rapides STR_1764 :Rondins de bois STR_1765 :Section photo sur le vif STR_1766 :Reverser turntable -STR_1767 :Spinning tunnel -STR_1768 :Can't change number of swings... -STR_1769 :{WINDOW_COLOUR_2}Number of swings: -STR_1770 :{SMALLFONT}{BLACK}Number of complete swings +STR_1767 :Tunnel tournoyant +STR_1768 :Impossible de modifier le nombre de vrilles... +STR_1769 :{WINDOW_COLOUR_2}Nombre de vrilles : +STR_1770 :{SMALLFONT}{BLACK}Nombre de vrilles complètes STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1772 :{COMMA16} -STR_1773 :Seulement une section photo sur le vif autorisée par attraction -STR_1774 :Seulement une montée par câble autorisée par attraction +STR_1773 :Une seule section photo sur le vif autorisée par attraction +STR_1774 :Une seule montée par câble autorisée par attraction STR_1775 :Éteint STR_1776 :Allumé STR_1777 :{WINDOW_COLOUR_2}Musique @@ -1794,41 +1794,41 @@ STR_1787 :{INLINE_SPRITE}{06}{20}{00}{00} Costume de bandit STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Costume de shérif STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Costume de pirate STR_1790 :{SMALLFONT}{BLACK}Sélectionnez la couleur de l'uniforme pour ce type d'employé -STR_1791 :{WINDOW_COLOUR_2}Couleur d'uniforme: -STR_1792 :Répond à l'appel sur l'incident de {STRINGID} +STR_1791 :{WINDOW_COLOUR_2}Couleur d'uniforme : +STR_1792 :Va réparer {STRINGID} STR_1793 :Se rend à {STRINGID} pour une inspection STR_1794 :Répare {STRINGID} STR_1795 :Répond à l'appel radio -STR_1796 :S'est cassé et nécessite une réparation +STR_1796 :Est en panne et nécessite une réparation STR_1797 :Cette option ne peut être changée pour cette attraction STR_1798 :Tourbillon STR_1799 :{POP16}{POP16}{POP16}{POP16}{POP16}{CURRENCY2DP} -STR_1800 :Contour de sécurité -STR_1801 :Restraints stuck closed -STR_1802 :Restraints stuck open -STR_1803 :Portes restent fermées -STR_1804 :Portes restent ouvertes -STR_1805 :Malfonction d'un véhicule +STR_1800 :Disjoncteurs de sécurité +STR_1801 :Ceintures bloquées, fermées +STR_1802 :Ceintures bloquées, ouvertes +STR_1803 :Portes bloquées, fermées +STR_1804 :Portes bloquées, ouvertes +STR_1805 :Défaillance d'un véhicule STR_1806 :Défaillance des freins -STR_1807 :Défaillance des contrôles -STR_1808 :{WINDOW_COLOUR_2}Dernier incident: {BLACK}{STRINGID} -STR_1809 :{WINDOW_COLOUR_2}Incident actuel: {OUTLINE}{RED}{STRINGID} -STR_1810 :{WINDOW_COLOUR_2}Porte: +STR_1807 :Défaillance des commandes +STR_1808 :{WINDOW_COLOUR_2}Dernière panne : {BLACK}{STRINGID} +STR_1809 :{WINDOW_COLOUR_2}Panne actuelle : {OUTLINE}{RED}{STRINGID} +STR_1810 :{WINDOW_COLOUR_2}Transporte : STR_1811 :Impossible de construire ça ici... STR_1812 :{SMALLFONT}{BLACK}{STRINGID} STR_1813 :Objets divers STR_1814 :Actions STR_1815 :Pensées -STR_1816 :{SMALLFONT}{BLACK}Select information type to show in guest list +STR_1816 :{SMALLFONT}{BLACK}Choisir le type d'informations à afficher dans la liste des visiteurs STR_1817 :({COMMA16}) STR_1818 :{WINDOW_COLOUR_2}Tous les visiteurs STR_1819 :{WINDOW_COLOUR_2}Tous les visiteurs (résumé) STR_1820 :{WINDOW_COLOUR_2}Visiteurs {STRINGID} STR_1821 :{WINDOW_COLOUR_2}Visiteurs pensant {STRINGID} STR_1822 :{WINDOW_COLOUR_2}Visiteurs pensant à {POP16}{STRINGID} -STR_1823 :{SMALLFONT}{BLACK}Show guests' thoughts about this ride/attraction -STR_1824 :{SMALLFONT}{BLACK}Show guests on this ride/attraction -STR_1825 :{SMALLFONT}{BLACK}Show guests queuing for this ride/attraction +STR_1823 :{SMALLFONT}{BLACK}Voir les opinions des visiteurs sur cette attraction +STR_1824 :{SMALLFONT}{BLACK}Voir les visiteurs sur cette attraction +STR_1825 :{SMALLFONT}{BLACK}Voir les visiteurs attendant pour cette attraction STR_1826 :Statut STR_1827 :Popularité STR_1828 :Satisfaction @@ -1837,47 +1837,47 @@ STR_1830 :Longueur file STR_1831 :Temps d'attente STR_1832 :Fiabilité STR_1833 :Immobilisation -STR_1834 :Plébiscitée +STR_1834 :Plébiscite STR_1835 :Popularité : Inconnue STR_1836 :Popularité : {COMMA16}% STR_1837 :Satisfaction : Inconnue STR_1838 :Satisfaction : {COMMA16}% STR_1839 :Fiabilité : {COMMA16}% -STR_1840 :Immobilisation: {COMMA16}% -STR_1841 :Revenu : {CURRENCY} par heure -STR_1842 :Attraction préférée de : {COMMA16} visiteur -STR_1843 :Attraction préférée de : {COMMA16} visiteurs +STR_1840 :Immobilisation : {COMMA16}% +STR_1841 :Bénéfice : {CURRENCY} par heure +STR_1842 :Préférée de : {COMMA16} visiteur +STR_1843 :Préférée de : {COMMA16} visiteurs STR_1844 :{SMALLFONT}{BLACK}Sélectionnez le type d'information à afficher dans la liste des attractions STR_1845 :{MONTHYEAR} STR_1846 :{COMMA16} visiteurs STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} visiteurs STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16} visiteurs STR_1849 :{WINDOW_COLOUR_2}Jouer de la musique -STR_1850 :{SMALLFONT}{BLACK}Select whether music should be played for this ride -STR_1851 :{WINDOW_COLOUR_2}Coût de fonctionnement: {BLACK}{CURRENCY2DP} par heure -STR_1852 :{WINDOW_COLOUR_2}Coût de fonctionnement: {BLACK}Inconnu -STR_1853 :{WINDOW_COLOUR_2}Construit: {BLACK}Cette année -STR_1854 :{WINDOW_COLOUR_2}Construit: {BLACK}L'année dernière -STR_1855 :{WINDOW_COLOUR_2}Construit: {BLACK}il y a {COMMA16} ans -STR_1856 :{WINDOW_COLOUR_2}Bénéfice par objet vendu: {BLACK}{CURRENCY2DP} -STR_1857 :{WINDOW_COLOUR_2}Perte par objet vendu: {BLACK}{CURRENCY2DP} -STR_1858 :{WINDOW_COLOUR_2}Coût: {BLACK}{CURRENCY2DP} par mois -STR_1859 :Hommes de service +STR_1850 :{SMALLFONT}{BLACK}Choisir si vous souhaitez de la musique pour cette attraction +STR_1851 :{WINDOW_COLOUR_2}Coût de fonctionnement : {BLACK}{CURRENCY2DP} par heure +STR_1852 :{WINDOW_COLOUR_2}Coût de fonctionnement : {BLACK}Inconnu +STR_1853 :{WINDOW_COLOUR_2}Construit : {BLACK}Cette année +STR_1854 :{WINDOW_COLOUR_2}Construit : {BLACK}L'année dernière +STR_1855 :{WINDOW_COLOUR_2}Construit : {BLACK}il y a {COMMA16} ans +STR_1856 :{WINDOW_COLOUR_2}Bénéfice par article vendu : {BLACK}{CURRENCY2DP} +STR_1857 :{WINDOW_COLOUR_2}Perte par article vendu : {BLACK}{CURRENCY2DP} +STR_1858 :{WINDOW_COLOUR_2}Coût : {BLACK}{CURRENCY2DP} par mois +STR_1859 :Agents d'entretien STR_1860 :Mécaniciens STR_1861 :Gardes de sécurité STR_1862 :Animateurs -STR_1863 :Homme de service +STR_1863 :Agent d'entretien STR_1864 :Mécanicien STR_1865 :Garde de sécurité STR_1866 :Animateur STR_1867 :{BLACK}{COMMA16} {STRINGID} STR_1868 :Impossible de changer le nombre de rotations... -STR_1869 :{WINDOW_COLOUR_2}Nombre de rotations: +STR_1869 :{WINDOW_COLOUR_2}Nombre de rotations : STR_1870 :{SMALLFONT}{BLACK}Nombre de rotations complètes STR_1871 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1872 :{COMMA16} -STR_1873 :{WINDOW_COLOUR_2}Revenu: {BLACK}{CURRENCY2DP} par heure -STR_1874 :{WINDOW_COLOUR_2}Profit: {BLACK}{CURRENCY2DP} par heure +STR_1873 :{WINDOW_COLOUR_2}Revenu : {BLACK}{CURRENCY2DP} par heure +STR_1874 :{WINDOW_COLOUR_2}Bénéfice : {BLACK}{CURRENCY2DP} par heure STR_1875 :{BLACK} {SPRITE}{BLACK} {STRINGID} STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Inspecter les attractions STR_1877 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{252}{19}{00}{00}Réparer les attractions @@ -1890,16 +1890,16 @@ STR_1883 :Toutes les heures STR_1884 :Toutes les 2 heures STR_1885 :Jamais STR_1886 :En train d'inspecter {STRINGID} -STR_1887 :{WINDOW_COLOUR_2}Temps écoulé depuis la dernière inspection: {BLACK}{COMMA16} minutes -STR_1888 :{WINDOW_COLOUR_2}Temps écoulé depuis la dernière inspection: {BLACK}plus de 4 heures -STR_1889 :{WINDOW_COLOUR_2}Temps d'arrêt: {MOVE_X}{255}{BLACK}{COMMA16}% +STR_1887 :{WINDOW_COLOUR_2}Temps écoulé depuis la dernière inspection : {BLACK}{COMMA16} minutes +STR_1888 :{WINDOW_COLOUR_2}Temps écoulé depuis la dernière inspection : {BLACK}plus de 4 heures +STR_1889 :{WINDOW_COLOUR_2}Temps d'arrêt : {MOVE_X}{255}{BLACK}{COMMA16}% STR_1890 :{SMALLFONT}{BLACK}Sélectionnez la fréquence de vérification de l'attraction -STR_1891 :Pas encore de {STRINGID} dans le parc! +STR_1891 :Pas encore de {STRINGID} dans le parc ! # The following two strings were used to display an error when the disc was missing. # This has been replaced in OpenRCT2. STR_1892 : STR_1893 : -STR_1894 :{WINDOW_COLOUR_2}{STRINGID} vendu: {BLACK}{COMMA32} +STR_1894 :{WINDOW_COLOUR_2}{STRINGID} vendu : {BLACK}{COMMA32} STR_1895 :{SMALLFONT}{BLACK}Construire une nouvelle attraction STR_1896 :{WINDOW_COLOUR_2}Dépenses/Revenus STR_1897 :{WINDOW_COLOUR_2}Constr. attraction @@ -1910,8 +1910,8 @@ STR_1901 :{WINDOW_COLOUR_2}Tickets parc STR_1902 :{WINDOW_COLOUR_2}Tickets attraction STR_1903 :{WINDOW_COLOUR_2}Ventes magasins STR_1904 :{WINDOW_COLOUR_2}Stocks magasins -STR_1905 :{WINDOW_COLOUR_2}Ventes Nourr./Boiss. -STR_1906 :{WINDOW_COLOUR_2}Stocks Nourr./Noiss. +STR_1905 :{WINDOW_COLOUR_2}Ventes nourr./boiss. +STR_1906 :{WINDOW_COLOUR_2}Stocks nourr./boiss. STR_1907 :{WINDOW_COLOUR_2}Salaires employés STR_1908 :{WINDOW_COLOUR_2}Marketing STR_1909 :{WINDOW_COLOUR_2}Recherche @@ -1923,17 +1923,17 @@ STR_1914 :{BLACK}{CURRENCY2DP} STR_1915 :{RED}{CURRENCY2DP} STR_1916 :{WINDOW_COLOUR_2}Emprunt: STR_1917 :{POP16}{POP16}{POP16}{CURRENCY} -STR_1918 :Impossible d'emprunter d'avantage! La banque refuse d'augmenter votre emprunt! -STR_1919 :Pas assez d'argent disponible! -STR_1920 :Impossible de rembourser l'emprunt! +STR_1918 :Impossible d'emprunter d'avantage ! La banque refuse d'augmenter votre emprunt ! +STR_1919 :Pas assez d'argent disponible ! +STR_1920 :Impossible de rembourser l'emprunt ! STR_1921 :{SMALLFONT}{BLACK}Commencer une nouvelle partie STR_1922 :{SMALLFONT}{BLACK}Continuer une partie sauvegardée STR_1923 :{SMALLFONT}{BLACK}Didacticiel STR_1924 :{SMALLFONT}{BLACK}Quitter STR_1925 :Impossible de placer quelqu'un ici... STR_1926 :{SMALLFONT} -STR_1927 :{YELLOW}{STRINGID} s'est cassé -STR_1928 :{RED}{STRINGID} s'est écrasé! +STR_1927 :{YELLOW}{STRINGID} est tombé en panne +STR_1928 :{RED}{STRINGID} a eu un accident! STR_1929 :{RED}{STRINGID} n'est toujours pas réparé{NEWLINE}Vérifiez où sont vos mécaniciens et pensez à leur attribuer des zones de patrouilles STR_1930 :{SMALLFONT}{BLACK}Activer/Désactiver la surveillance de ce visiteur - (Si la surveillance est activée, les mouvements du visiteur seront annoncés dans la zone de notifications) STR_1931 :{STRINGID} a rejoint la file d'attente pour {STRINGID} @@ -1945,11 +1945,11 @@ STR_1936 :{STRINGID} a acheté {STRINGID} STR_1937 :{SMALLFONT}{BLACK}Afficher des informations à propos du sujet de ce message STR_1938 :{SMALLFONT}{BLACK}Afficher vue du visiteur STR_1939 :{SMALLFONT}{BLACK}Afficher vue de l'employé -STR_1940 :{SMALLFONT}{BLACK}Afficher l'humeur, l'énergie, la faim... de ce visiteur +STR_1940 :{SMALLFONT}{BLACK}Afficher l'humeur, l'énergie, la faim, etc. de ce visiteur STR_1941 :{SMALLFONT}{BLACK}Afficher sur quelles attractions ce visiteur est allé STR_1942 :{SMALLFONT}{BLACK}Afficher les informations financières à propos de ce visiteur STR_1943 :{SMALLFONT}{BLACK}Afficher les pensées récentes de ce visiteur -STR_1944 :{SMALLFONT}{BLACK}Afficher les objets que porte ce visiteur +STR_1944 :{SMALLFONT}{BLACK}Afficher les objets transportés par ce visiteur STR_1945 :{SMALLFONT}{BLACK}Afficher les ordres et options pour cet employé STR_1946 :{SMALLFONT}{BLACK}Sélectionner le costume de cet animateur STR_1947 :{SMALLFONT}{BLACK}Afficher les zones de patrouilles des employés de ce type, et localiser l'employé le plus proche @@ -1960,46 +1960,46 @@ STR_1951 :Graphique valeur du parc STR_1952 :Graphique bénéfices STR_1953 :Marketing STR_1954 :Financement recherches -STR_1955 :{WINDOW_COLOUR_2}Nombre de circuits: +STR_1955 :{WINDOW_COLOUR_2}Nombre de circuits : STR_1956 :{SMALLFONT}{BLACK}Nombre de circuits de voie par attraction STR_1957 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1958 :{COMMA16} -STR_1959 :Impossible de changer le nombre de circuits -STR_1960 :{WINDOW_COLOUR_2}Prix d'un ballon: -STR_1961 :{WINDOW_COLOUR_2}Prix d'une peluche: -STR_1962 :{WINDOW_COLOUR_2}Prix d'une carte du parc: -STR_1963 :{WINDOW_COLOUR_2}Prix d'une photo sur le vif: -STR_1964 :{WINDOW_COLOUR_2}Prix d'un parapluie: -STR_1965 :{WINDOW_COLOUR_2}Prix d'une boisson: -STR_1966 :{WINDOW_COLOUR_2}Prix d'un burger: -STR_1967 :{WINDOW_COLOUR_2}Prix des frites: -STR_1968 :{WINDOW_COLOUR_2}Prix d'une glace: -STR_1969 :{WINDOW_COLOUR_2}Prix d'une barbe-à-papa: +STR_1959 :Impossible de changer le nombre de circuits... +STR_1960 :{WINDOW_COLOUR_2}Prix d'un ballon : +STR_1961 :{WINDOW_COLOUR_2}Prix d'une peluche : +STR_1962 :{WINDOW_COLOUR_2}Prix d'un plan du parc : +STR_1963 :{WINDOW_COLOUR_2}Prix photo sur le vif : +STR_1964 :{WINDOW_COLOUR_2}Prix d'un parapluie : +STR_1965 :{WINDOW_COLOUR_2}Prix d'une boisson : +STR_1966 :{WINDOW_COLOUR_2}Prix d'un hamburger : +STR_1967 :{WINDOW_COLOUR_2}Prix des frites : +STR_1968 :{WINDOW_COLOUR_2}Prix d'une glace : +STR_1969 :{WINDOW_COLOUR_2}Prix d'une barbe-à-papa : STR_1970 :{WINDOW_COLOUR_2} STR_1971 :{WINDOW_COLOUR_2} STR_1972 :{WINDOW_COLOUR_2} -STR_1973 :{WINDOW_COLOUR_2}Prix d'une pizza: +STR_1973 :{WINDOW_COLOUR_2}Prix d'une pizza : STR_1974 :{WINDOW_COLOUR_2} -STR_1975 :{WINDOW_COLOUR_2}Prix du popcorn: -STR_1976 :{WINDOW_COLOUR_2}Prix d'un hot-dog: -STR_1977 :{WINDOW_COLOUR_2}Prix du pouple: -STR_1978 :{WINDOW_COLOUR_2}Prix d'un chapeau: -STR_1979 :{WINDOW_COLOUR_2}Prix d'une pomme d'amour: -STR_1980 :{WINDOW_COLOUR_2}Prix d'un T-Shirt: -STR_1981 :{WINDOW_COLOUR_2}Prix d'un donut: -STR_1982 :{WINDOW_COLOUR_2}Prix d'un café: +STR_1975 :{WINDOW_COLOUR_2}Prix du popcorn : +STR_1976 :{WINDOW_COLOUR_2}Prix d'un hot-dog : +STR_1977 :{WINDOW_COLOUR_2}Prix du poulpe : +STR_1978 :{WINDOW_COLOUR_2}Prix d'un chapeau : +STR_1979 :{WINDOW_COLOUR_2}Prix d'une pomme d'amour : +STR_1980 :{WINDOW_COLOUR_2}Prix d'un T-shirt : +STR_1981 :{WINDOW_COLOUR_2}Prix d'un donut : +STR_1982 :{WINDOW_COLOUR_2}Prix d'un café : STR_1983 :{WINDOW_COLOUR_2} -STR_1984 :{WINDOW_COLOUR_2}Prix du poulet frit: -STR_1985 :{WINDOW_COLOUR_2}Prix de la limonade: +STR_1984 :{WINDOW_COLOUR_2}Prix du poulet frit : +STR_1985 :{WINDOW_COLOUR_2}Prix de la limonade : STR_1986 :{WINDOW_COLOUR_2} STR_1987 :{WINDOW_COLOUR_2} STR_1988 :Ballon STR_1989 :Peluche -STR_1990 :Carte du parc +STR_1990 :Plan du parc STR_1991 :Photo sur le vif STR_1992 :Parapluie STR_1993 :Boisson gazeuse -STR_1994 :Burger +STR_1994 :Hamurger STR_1995 :Frites STR_1996 :Glace STR_1997 :Barbe-à-papa @@ -2007,13 +2007,13 @@ STR_1998 :Canette vide STR_1999 :Déchet STR_2000 :Boite à Burger vide STR_2001 :Pizza -STR_2002 :Coupon +STR_2002 :Bon STR_2003 :Popcorn STR_2004 :Hot-Dog STR_2005 :Poulpe STR_2006 :Chapeau STR_2007 :Pomme d'amour -STR_2008 :T-Shirt +STR_2008 :T-shirt STR_2009 :Donut STR_2010 :Café STR_2011 :Tasse vide @@ -2023,11 +2023,11 @@ STR_2014 :Boite vide STR_2015 :Bouteille vide STR_2016 :Ballons STR_2017 :Peluches -STR_2018 :Cartes du parc +STR_2018 :Plans du parc STR_2019 :Photos sur le vif STR_2020 :Parapluies STR_2021 :Boissons gazeuses -STR_2022 :Burgers +STR_2022 :Hamurgers STR_2023 :Frites STR_2024 :Glaces STR_2025 :Barbes-à-papa @@ -2035,13 +2035,13 @@ STR_2026 :Canettes vides STR_2027 :Déchets STR_2028 :Boites à Burger vides STR_2029 :Pizzas -STR_2030 :Coupons +STR_2030 :Bons STR_2031 :Popcorn STR_2032 :Hot-Dogs STR_2033 :Poulpe STR_2034 :Chapeaux STR_2035 :Pommes d'amour -STR_2036 :T-Shirts +STR_2036 :T-shirts STR_2037 :Donuts STR_2038 :Cafés STR_2039 :Tasses vides @@ -2049,41 +2049,41 @@ STR_2040 :Poulet frit STR_2041 :Limonade STR_2042 :Boites vides STR_2043 :Bouteilles vides -STR_2044 :un Ballon -STR_2045 :une Peluche -STR_2046 :une carte du parc +STR_2044 :un ballon +STR_2045 :une peluche +STR_2046 :un plan du parc STR_2047 :une photo sur le vif STR_2048 :un parapluie STR_2049 :une boisson gazeuse -STR_2050 :un Burger -STR_2051 :des Frites +STR_2050 :un hamurger +STR_2051 :des frites STR_2052 :une glace STR_2053 :une barbe-à-papa STR_2054 :une canette vide STR_2055 :un déchet -STR_2056 :une Boite à Burger vide -STR_2057 :une Pizza -STR_2058 :un Coupon -STR_2059 :du Popcorn -STR_2060 :un Hot-Dog -STR_2061 :du Poulpe +STR_2056 :une boîte à hamurger vide +STR_2057 :une pizza +STR_2058 :un bon +STR_2059 :du popcorn +STR_2060 :un hot-Dog +STR_2061 :du poulpe STR_2062 :un chapeau STR_2063 :une pomme d'amour -STR_2064 :un T-Shirt -STR_2065 :un Donut +STR_2064 :un T-shirt +STR_2065 :un donut STR_2066 :un café STR_2067 :une tasse vide STR_2068 :du poulet frit STR_2069 :de la limonade STR_2070 :une boite vide STR_2071 :une bouteille vide -STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Ballon -STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Peluche -STR_2074 :Carte de {STRINGID} +STR_2072 :Ballon {OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2073 :Peluche {OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2074 :Plan de {STRINGID} STR_2075 :Photo sur le vif de {STRINGID} -STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Parapluie +STR_2076 :Parapluie {OPENQUOTES}{STRINGID}{ENDQUOTES} STR_2077 :Boisson gazeuse -STR_2078 :Burger +STR_2078 :Hamurger STR_2079 :Frites STR_2080 :Glace STR_2081 :Barbe-à-papa @@ -2091,13 +2091,13 @@ STR_2082 :Canette vide STR_2083 :Déchet STR_2084 :Boite à Burger vide STR_2085 :Pizza -STR_2086 :Coupon pour {STRINGID} +STR_2086 :Bon pour {STRINGID} STR_2087 :Popcorn STR_2088 :Hot-Dog STR_2089 :Poulpe -STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Chapeau +STR_2090 :Chapeau {OPENQUOTES}{STRINGID}{ENDQUOTES} STR_2091 :Pomme d'amour -STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} T-Shirt +STR_2092 :T-shirt {OPENQUOTES}{STRINGID}{ENDQUOTES} STR_2093 :Donut STR_2094 :Café STR_2095 :Tasse vide @@ -2105,27 +2105,27 @@ STR_2096 :Poulet frit STR_2097 :Limonade STR_2098 :Boite vide STR_2099 :Bouteille vide -STR_2100 :{WINDOW_COLOUR_2}Prix d'une photo sur le vif: -STR_2101 :{WINDOW_COLOUR_2}Prix d'une photo sur le vif: -STR_2102 :{WINDOW_COLOUR_2}Prix d'une photo sur le vif: -STR_2103 :{WINDOW_COLOUR_2}Prix d'un bretzel: -STR_2104 :{WINDOW_COLOUR_2}Prix d'un chocolat chaud: -STR_2105 :{WINDOW_COLOUR_2}Prix d'un thé glacé: -STR_2106 :{WINDOW_COLOUR_2}Prix d'un funnel cake: -STR_2107 :{WINDOW_COLOUR_2}Prix des lunettes de soleil: -STR_2108 :{WINDOW_COLOUR_2}Prix des nouilles au boeuf: -STR_2109 :{WINDOW_COLOUR_2}Prix des nouilles au riz frit: -STR_2110 :{WINDOW_COLOUR_2}Prix de la soupe aux raviolis: -STR_2111 :{WINDOW_COLOUR_2}Prix de la soupe aux boulettes de viande: -STR_2112 :{WINDOW_COLOUR_2}Prix d'un jus de fruits: -STR_2113 :{WINDOW_COLOUR_2}Prix d'un lait de soja: -STR_2114 :{WINDOW_COLOUR_2}Prix d'un sujongkwa: -STR_2115 :{WINDOW_COLOUR_2}Prix d'un sub sandwich: -STR_2116 :{WINDOW_COLOUR_2}Prix d'un cookie: +STR_2100 :{WINDOW_COLOUR_2}Prix d'une photo sur le vif : +STR_2101 :{WINDOW_COLOUR_2}Prix d'une photo sur le vif : +STR_2102 :{WINDOW_COLOUR_2}Prix d'une photo sur le vif : +STR_2103 :{WINDOW_COLOUR_2}Prix d'un bretzel : +STR_2104 :{WINDOW_COLOUR_2}Prix d'un chocolat chaud : +STR_2105 :{WINDOW_COLOUR_2}Prix d'un thé glacé : +STR_2106 :{WINDOW_COLOUR_2}Prix d'un gâteau : +STR_2107 :{WINDOW_COLOUR_2}Prix des lunettes de soleil : +STR_2108 :{WINDOW_COLOUR_2}Prix des nouilles au boeuf : +STR_2109 :{WINDOW_COLOUR_2}Prix des nouilles au riz frit : +STR_2110 :{WINDOW_COLOUR_2}Prix de la soupe aux raviolis : +STR_2111 :{WINDOW_COLOUR_2}Prix de la soupe aux boulettes de viande : +STR_2112 :{WINDOW_COLOUR_2}Prix d'un jus de fruits : +STR_2113 :{WINDOW_COLOUR_2}Prix d'un lait de soja : +STR_2114 :{WINDOW_COLOUR_2}Prix d'un sujongkwa : +STR_2115 :{WINDOW_COLOUR_2}Prix d'un sandwich : +STR_2116 :{WINDOW_COLOUR_2}Prix d'un cookie : STR_2117 :{WINDOW_COLOUR_2} STR_2118 :{WINDOW_COLOUR_2} STR_2119 :{WINDOW_COLOUR_2} -STR_2120 :{WINDOW_COLOUR_2}Prix d'une saucisse grillée: +STR_2120 :{WINDOW_COLOUR_2}Prix d'une saucisse grillée : STR_2121 :{WINDOW_COLOUR_2} STR_2122 :Photo sur le vif STR_2123 :Photo sur le vif @@ -2133,7 +2133,7 @@ STR_2124 :Photo sur le vif STR_2125 :Bretzel STR_2126 :Chocolat chaud STR_2127 :Thé glacé -STR_2128 :Funnel Cake +STR_2128 :Gâteau STR_2129 :Lunettes de soleil STR_2130 :Nouilles au boeuf STR_2131 :Nouilles au riz frit @@ -2142,7 +2142,7 @@ STR_2133 :Soupe aux boulettes de viande STR_2134 :Jus de fruits STR_2135 :Lait de soja STR_2136 :Sujongkwa -STR_2137 :Sub Sandwich +STR_2137 :Sandwich STR_2138 :Cookie STR_2139 :Bol vide STR_2140 :Brique vide @@ -2155,7 +2155,7 @@ STR_2146 :Photos sur le vif STR_2147 :Bretzels STR_2148 :Chocolats chaud STR_2149 :Thés glacés -STR_2150 :Funnel Cakes +STR_2150 :Gâteaux STR_2151 :Lunettes de soleil STR_2152 :Nouilles au boeuf STR_2153 :Nouilles au riz frit @@ -2164,7 +2164,7 @@ STR_2155 :Soupes aux boulettes de viande STR_2156 :Jus de fruits STR_2157 :Laits de soja STR_2158 :Sujongkwa -STR_2159 :Sub Sandwichs +STR_2159 :Sandwichs STR_2160 :Cookies STR_2161 :Bols vides STR_2162 :Briques vides @@ -2177,7 +2177,7 @@ STR_2168 :une photo sur le vif STR_2169 :un bretzel STR_2170 :un chocolat chaud STR_2171 :un thé glacé -STR_2172 :un Funnel Cake +STR_2172 :un gâteau STR_2173 :une paire de lunettes de soleil STR_2174 :des nouilles au boeuf STR_2175 :des nouilles au riz frit @@ -2186,8 +2186,8 @@ STR_2177 :de la soupe aux boulettes de viande STR_2178 :un jus de fruits STR_2179 :du lait de soja STR_2180 :du Sujongkwa -STR_2181 :un Sub Sandwich -STR_2182 :un Cookie +STR_2181 :un sandwich +STR_2182 :un cookie STR_2183 :un bol vide STR_2184 :une brique vide STR_2185 :une tasse de jus vide @@ -2199,7 +2199,7 @@ STR_2190 :Photo sur le vif de {STRINGID} STR_2191 :Bretzel STR_2192 :Chocolat chaud STR_2193 :Thé glacé -STR_2194 :Funnel Cake +STR_2194 :Gâteau STR_2195 :Lunettes de soleil STR_2196 :Nouilles au boeuf STR_2197 :Nouilles au riz frit @@ -2208,56 +2208,56 @@ STR_2199 :Soupe aux boulettes de viande STR_2200 :Jus de fruits STR_2201 :Lait de soja STR_2202 :Sujongkwa -STR_2203 :Sub Sandwich +STR_2203 :Sandwich STR_2204 :Cookie STR_2205 :Bol vide STR_2206 :Brique vide STR_2207 :Tasse de jus vide STR_2208 :Saucisse grillée STR_2209 :Bol vide -STR_2210 :{SMALLFONT}{BLACK}Afficher la liste des hommes de service dans le parc +STR_2210 :{SMALLFONT}{BLACK}Afficher la liste des agents d'entretien dans le parc STR_2211 :{SMALLFONT}{BLACK}Afficher la liste des mécaniciens dans le parc STR_2212 :{SMALLFONT}{BLACK}Afficher la liste des agents de sécurité dans le parc STR_2213 :{SMALLFONT}{BLACK}Afficher la liste des animateurs dans le parc -STR_2214 :Construction impossible durant la pause! +STR_2214 :Construction impossible tant que le jeu est en pause ! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F -STR_2218 :{RED}{STRINGID} sur {STRINGID} n'est pas encore revenu à {STRINGID}!{NEWLINE}Vérifiez si il est coinçé ou au point mort +STR_2218 :{RED}{STRINGID} sur {STRINGID} n'est pas encore revenu à {STRINGID}!{NEWLINE}Vérifiez s'il est coincé ou au point mort STR_2219 :{RED}{COMMA16} personnes sont mortes dans un accident sur {STRINGID} -STR_2220 :{WINDOW_COLOUR_2}Notation du parc: {BLACK}{COMMA16} -STR_2221 :{SMALLFONT}{BLACK}Notation du parc: {COMMA16} +STR_2220 :{WINDOW_COLOUR_2}Evaluation du parc : {BLACK}{COMMA16} +STR_2221 :{SMALLFONT}{BLACK}Evaluation du parc : {COMMA16} STR_2222 :{SMALLFONT}{BLACK}{STRINGID} -STR_2223 :{WINDOW_COLOUR_2}Visiteurs dans le parc: {BLACK}{COMMA16} -STR_2224 :{WINDOW_COLOUR_2}Argent: {BLACK}{CURRENCY2DP} -STR_2225 :{WINDOW_COLOUR_2}Argent: {RED}{CURRENCY2DP} -STR_2226 :{WINDOW_COLOUR_2}Valeur du parc: {BLACK}{CURRENCY} -STR_2227 :{WINDOW_COLOUR_2}Valeur de l'entreprise: {BLACK}{CURRENCY} +STR_2223 :{WINDOW_COLOUR_2}Visiteurs dans le parc : {BLACK}{COMMA16} +STR_2224 :{WINDOW_COLOUR_2}Argent : {BLACK}{CURRENCY2DP} +STR_2225 :{WINDOW_COLOUR_2}Argent : {RED}{CURRENCY2DP} +STR_2226 :{WINDOW_COLOUR_2}Valeur du parc : {BLACK}{CURRENCY} +STR_2227 :{WINDOW_COLOUR_2}Valeur de l'entreprise : {BLACK}{CURRENCY} STR_2228 :{WINDOW_COLOUR_2}Profits du mois dernier provenant de l'alimentation et{NEWLINE} de la vente de marchandise: {BLACK}{CURRENCY} -STR_2229 :Slope up to vertical -STR_2230 :Vertical track -STR_2231 :Holding brake for drop +STR_2229 :Incl. jusque vertical +STR_2230 :Voie verticale +STR_2231 :Maint. frein en chute STR_2232 :Montée par câble STR_2233 :{SMALLFONT}{BLACK}Informations sur le parc STR_2234 :Messages récents STR_2235 :{SMALLFONT}{STRINGID} {STRINGID} -STR_2236 :Janvier -STR_2237 :Février -STR_2238 :Mars -STR_2239 :Avril -STR_2240 :Mai -STR_2241 :Juin -STR_2242 :Juillet -STR_2243 :Août -STR_2244 :Septembre -STR_2245 :Octobre -STR_2246 :Novembre -STR_2247 :Décembre +STR_2236 :janvier +STR_2237 :février +STR_2238 :mars +STR_2239 :avril +STR_2240 :mai +STR_2241 :juin +STR_2242 :juillet +STR_2243 :août +STR_2244 :septembre +STR_2245 :octobre +STR_2246 :novembre +STR_2247 :décembre STR_2248 :Impossible de démolir l'attraction... -STR_2249 :{BABYBLUE}Nouvelle attraction disponible:{NEWLINE}{STRINGID} -STR_2250 :{BABYBLUE}Nouveau paysage disponible:{NEWLINE}{STRINGID} -STR_2251 :Ne peut être construit que sur les chemins! -STR_2252 :Ne peut être construit qu'à travers les chemins! +STR_2249 :{BABYBLUE}Nouvelle attraction disponible :{NEWLINE}{STRINGID} +STR_2250 :{BABYBLUE}Nouveau décor/thème disponible :{NEWLINE}{STRINGID} +STR_2251 :Ne peut être construit que sur les allées ! +STR_2252 :Ne peut être construit qu'à travers les allées ! STR_2253 :Attractions de transport STR_2254 :Attractions tranquilles STR_2255 :Montagnes russes @@ -2269,19 +2269,19 @@ STR_2260 :Aucun financement STR_2261 :Financement minimum STR_2262 :Financement normal STR_2263 :Financement maximum -STR_2264 :Financement recherches -STR_2265 :{WINDOW_COLOUR_2}Coût: {BLACK}{CURRENCY} par mois -STR_2266 :Priorités recherches +STR_2264 :Financement des recherches +STR_2265 :{WINDOW_COLOUR_2}Coût : {BLACK}{CURRENCY} par mois +STR_2266 :Priorités de recherche STR_2267 :En cours de développement STR_2268 :Dernier développement -STR_2269 :{WINDOW_COLOUR_2}Type: {BLACK}{STRINGID} -STR_2270 :{WINDOW_COLOUR_2}Progression: {BLACK}{STRINGID} -STR_2271 :{WINDOW_COLOUR_2}Fin prévue: {BLACK}{STRINGID} -STR_2272 :{WINDOW_COLOUR_2}Ride/attraction:{NEWLINE}{BLACK}{STRINGID} -STR_2273 :{WINDOW_COLOUR_2}Scenery/themeing:{NEWLINE}{BLACK}{STRINGID} -STR_2274 :{SMALLFONT}{BLACK}Afficher détails de cette invention -STR_2275 :{SMALLFONT}{BLACK}Afficher financement et options de la recherche et du développement -STR_2276 :{SMALLFONT}{BLACK}Afficher status de la recherche et du développement +STR_2269 :{WINDOW_COLOUR_2}Type : {BLACK}{STRINGID} +STR_2270 :{WINDOW_COLOUR_2}Progression : {BLACK}{STRINGID} +STR_2271 :{WINDOW_COLOUR_2}Fin prévue : {BLACK}{STRINGID} +STR_2272 :{WINDOW_COLOUR_2}Attraction :{NEWLINE}{BLACK}{STRINGID} +STR_2273 :{WINDOW_COLOUR_2}Décor/thème:{NEWLINE}{BLACK}{STRINGID} +STR_2274 :{SMALLFONT}{BLACK}Afficher les détails de cette invention +STR_2275 :{SMALLFONT}{BLACK}Afficher le financement et les options de la recherche et du développement +STR_2276 :{SMALLFONT}{BLACK}Afficher le statut de la recherche et du développement STR_2277 :Inconnu STR_2278 :Attraction de transport STR_2279 :Attraction tranquille @@ -2297,47 +2297,47 @@ STR_2288 :Inconnu STR_2289 :{STRINGID} {STRINGID} STR_2290 :{SMALLFONT}{BLACK}{STRINGID} {STRINGID} STR_2291 :Choisir scénario pour nouvelle partie -STR_2292 :{WINDOW_COLOUR_2}Attractions utilisées: +STR_2292 :{WINDOW_COLOUR_2}A été sur ces attractions : STR_2293 :{BLACK} Rien -STR_2294 :{SMALLFONT}{BLACK}Change base land style -STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land -STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} payé pour entrer dans le parc -STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} attraction -STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} attractions -STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} aliment -STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} aliments -STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} boisson -STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} boissons -STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} souvenir -STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensé pour {BLACK}{COMMA16} souvenirs -STR_2305 :Fichiers de concepts de voie -STR_2306 :Sauvegarder le concept de voie -STR_2307 :Sélectionner le concept {STRINGID} -STR_2308 :{STRINGID} Concepts de Voies -STR_2309 :Installer un Nouveau Concept de Voie -STR_2310 :Construire un concept personnalisé -STR_2311 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} (approx.) -STR_2312 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} (approx.) -STR_2313 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} (approx.) -STR_2314 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID} -STR_2315 :{WINDOW_COLOUR_2}Cost: {BLACK}around {CURRENCY} -STR_2316 :{WINDOW_COLOUR_2}Space required: {BLACK}{COMMA16} x {COMMA16} blocks +STR_2294 :{SMALLFONT}{BLACK}Modifier le style de la surface +STR_2295 :{SMALLFONT}{BLACK}Modifier les bords verticaux du terrain +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} payés pour entrer dans le parc +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} attraction +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} attractions +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} aliment +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} aliments +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} boisson +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} boissons +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} souvenir +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} dépensés pour {BLACK}{COMMA16} souvenirs +STR_2305 :Fichiers de conception de voie +STR_2306 :Sauvegarder la conception de voie +STR_2307 :Sélectionner la conception {STRINGID} +STR_2308 :{STRINGID} Conceptions de voies +STR_2309 :Installer une nouvelle conception de voie +STR_2310 :Construire une conception personnalisé +STR_2311 :{WINDOW_COLOUR_2}Indice excitation : {BLACK}{COMMA2DP32} (approx.) +STR_2312 :{WINDOW_COLOUR_2}Indice intensité : {BLACK}{COMMA2DP32} (approx.) +STR_2313 :{WINDOW_COLOUR_2}Indice nausée : {BLACK}{COMMA2DP32} (approx.) +STR_2314 :{WINDOW_COLOUR_2}Long. attr. : {BLACK}{STRINGID} +STR_2315 :{WINDOW_COLOUR_2}Coût : {BLACK}{CURRENCY} environ +STR_2316 :{WINDOW_COLOUR_2}Espace requis : {BLACK}{COMMA16} x {COMMA16} blocs STR_2317 : STR_2318 : STR_2319 : STR_2320 : -STR_2321 :{WINDOW_COLOUR_2}Nombre d'attractions: {BLACK}{COMMA16} -STR_2322 :{WINDOW_COLOUR_2}Personnel: {BLACK}{COMMA16} -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_2321 :{WINDOW_COLOUR_2}Nombre d'attractions : {BLACK}{COMMA16} +STR_2322 :{WINDOW_COLOUR_2}Personnel : {BLACK}{COMMA16} +STR_2323 :{WINDOW_COLOUR_2}Taille du parc : {BLACK}{COMMA32}m{SQUARED} +STR_2324 :{WINDOW_COLOUR_2}Taille du parc : {BLACK}{COMMA32}sq.ft. +STR_2325 :{SMALLFONT}{BLACK}Acheter terrain pour agrandir parc +STR_2326 :{SMALLFONT}{BLACK}Acheter les droits de construction pour autoriser la construction en dehors du parc (au-dessus ou en-dessous du sol) 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_2328 :{WINDOW_COLOUR_2}Devise : +STR_2329 :{WINDOW_COLOUR_2}Distance, vitesse : +STR_2330 :{WINDOW_COLOUR_2}Température : +STR_2331 :{WINDOW_COLOUR_2}Altitude : +STR_2332 :Unités STR_2333 :Son STR_2334 :Pounds ({POUND}) STR_2335 :Dollars ($) @@ -2349,98 +2349,98 @@ STR_2340 :Lira (L) STR_2341 :Florins (fl.) STR_2342 :Krona (kr) STR_2343 :Euros ({EURO}) -STR_2344 :Imperial -STR_2345 :Metric -STR_2346 :Display -STR_2347 :{RED}{STRINGID} has drowned! -STR_2348 :{SMALLFONT}{BLACK}Show statistics for this staff member -STR_2349 :{WINDOW_COLOUR_2}Wages: {BLACK}{CURRENCY} per month -STR_2350 :{WINDOW_COLOUR_2}Employed: {BLACK}{MONTHYEAR} -STR_2351 :{WINDOW_COLOUR_2}Lawns mown: {BLACK}{COMMA16} -STR_2352 :{WINDOW_COLOUR_2}Gardens watered: {BLACK}{COMMA16} -STR_2353 :{WINDOW_COLOUR_2}Litter swept: {BLACK}{COMMA16} -STR_2354 :{WINDOW_COLOUR_2}Bins emptied: {BLACK}{COMMA16} -STR_2355 :{WINDOW_COLOUR_2}Rides fixed: {BLACK}{COMMA16} -STR_2356 :{WINDOW_COLOUR_2}Rides inspected: {BLACK}{COMMA16} -STR_2357 :House -STR_2358 :Units -STR_2359 :Real Values -STR_2360 :{WINDOW_COLOUR_2}Display Resolution: -STR_2361 :Landscape Smoothing -STR_2362 :{SMALLFONT}{BLACK}Toggle landscape tile edge smoothing on/off -STR_2363 :Gridlines on Landscape -STR_2364 :{SMALLFONT}{BLACK}Toggle gridlines on landscape on/off -STR_2365 :The bank refuses to increase your loan! +STR_2344 :Impérial +STR_2345 :Métrique +STR_2346 :Affichage +STR_2347 :{RED}{STRINGID} s'est noyé ! +STR_2348 :{SMALLFONT}{BLACK}Voir statistiques pour cet employé +STR_2349 :{WINDOW_COLOUR_2}Salaire : {BLACK}{CURRENCY} par mois +STR_2350 :{WINDOW_COLOUR_2}Embauché : {BLACK}{MONTHYEAR} +STR_2351 :{WINDOW_COLOUR_2}Pelouses tondues : {BLACK}{COMMA16} +STR_2352 :{WINDOW_COLOUR_2}Jardins arrosés : {BLACK}{COMMA16} +STR_2353 :{WINDOW_COLOUR_2}Déchets nettoyés : {BLACK}{COMMA16} +STR_2354 :{WINDOW_COLOUR_2}Poubelles vidées : {BLACK}{COMMA16} +STR_2355 :{WINDOW_COLOUR_2}Attractions réparées : {BLACK}{COMMA16} +STR_2356 :{WINDOW_COLOUR_2}Attractions inspectées : {BLACK}{COMMA16} +STR_2357 :Maison +STR_2358 :Unités +STR_2359 :Valeurs réelles +STR_2360 :{WINDOW_COLOUR_2}Résolution d'affichage : +STR_2361 :Lissage du paysage +STR_2362 :{SMALLFONT}{BLACK}Activer/Désactiver le lissage des arrêtes des carrés de paysage +STR_2363 :Quadrillage du paysage +STR_2364 :{SMALLFONT}{BLACK}Activer/Désactiver quadrillage du paysage +STR_2365 :La banque refuse d'augmenter votre emprunt ! STR_2366 :Celsius ({DEGREE}C) STR_2367 :Fahrenheit ({DEGREE}F) -STR_2368 :None -STR_2369 :Low -STR_2370 :Average -STR_2371 :High -STR_2372 :Low -STR_2373 :Medium -STR_2374 :High -STR_2375 :Very high -STR_2376 :Extreme -STR_2377 :Ultra-Extreme -STR_2378 :{SMALLFONT}{BLACK}Adjust smaller area of land -STR_2379 :{SMALLFONT}{BLACK}Adjust larger area of land -STR_2380 :{SMALLFONT}{BLACK}Adjust smaller area of water -STR_2381 :{SMALLFONT}{BLACK}Adjust larger area of water -STR_2382 :Land -STR_2383 :Water +STR_2368 :Aucun +STR_2369 :Bas +STR_2370 :Moyen +STR_2371 :Elevé +STR_2372 :Bas +STR_2373 :Moyen +STR_2374 :Elevé +STR_2375 :Très élevé +STR_2376 :Extrême +STR_2377 :Ultra-Extrême +STR_2378 :{SMALLFONT}{BLACK}Ajuster zone terrain + petite +STR_2379 :{SMALLFONT}{BLACK}Ajuster zone terrain + grande +STR_2380 :{SMALLFONT}{BLACK}Ajuster zone aquatique + petite +STR_2381 :{SMALLFONT}{BLACK}Ajuster zone aquatique + grande +STR_2382 :Terrain +STR_2383 :Eau STR_2384 :{WINDOW_COLOUR_2}Votre objectif: STR_2385 :{BLACK}Aucun -STR_2386 :{BLACK}To have at least {COMMA16} guests in your park at the end of {MONTHYEAR}, with a park rating of at least 600 -STR_2387 :{BLACK}To achieve a park value of at least {POP16}{POP16}{CURRENCY} at the end of {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} -STR_2388 :{BLACK}Have Fun! -STR_2389 :{BLACK}Build the best {STRINGID} you can! -STR_2390 :{BLACK}To have 10 different types of roller coasters operating in your park, each with an excitement value of at least 6.00 -STR_2391 :{BLACK}To have at least {COMMA16} guests in your park. You must not let the park rating drop below 700 at any time! +STR_2386 :{BLACK}Avoir au moins {COMMA16} visiteurs dans votre parc à la fin {MONTHYEAR}, avec une évaluation de parc d'au moins 600 +STR_2387 :{BLACK}Atteindre une valeur de parc d'au moins {POP16}{POP16}{CURRENCY} à la fin {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} +STR_2388 :{BLACK}Amusez-vous ! +STR_2389 :{BLACK}Construisez la meilleure attraction {STRINGID} possible ! +STR_2390 :{BLACK}Avoir construit au moins 10 montagnes russes différentes dans votre parc, chacune d'entre elles atteignant un indice d'engouement d'au moins 6.00 +STR_2391 :{BLACK}Avoir reçu au moins {COMMA16} visiteurs dans votre parc. L'évaluation du parc ne doit jamais descendre en dessous des 700 ! STR_2392 :{BLACK}Obtenir un revenu mensuel avec les tickets d'attraction d'au moins {POP16}{POP16}{CURRENCY} -STR_2393 :{BLACK}To have 10 different types of roller coasters operating in your park, each with a minimum length of {LENGTH}, and an excitement rating of at least 7.00 -STR_2394 :{BLACK}To finish building all 5 of the partially built roller coasters in this park, designing them to achieve excitement ratings of at least {POP16}{POP16}{COMMA2DP32} each -STR_2395 :{BLACK}To repay your loan and achieve a park value of at least {POP16}{POP16}{CURRENCY} -STR_2396 :{BLACK}To achieve a monthly profit from food, drink and merchandise sales of at least {POP16}{POP16}{CURRENCY} +STR_2393 :{BLACK}Avoir construit au moins 10 montagnes russes différentes dans votre parc, chacune d'entre elles atteignant une longueur d'au moins {LENGTH}, avec un indice d'engouement d'au moins 7.00 +STR_2394 :{BLACK}Terminer la construction des 5 montagnes russes entamées dans ce parc, avec une conception leur permettant d'atteindre un indice d'engouement d'au moins {POP16}{POP16}{COMMA2DP32} chacune +STR_2395 :{BLACK}Rembourser votre emprunt et faire en sorte que la valeur de votre parc atteigne au moins {POP16}{POP16}{CURRENCY} +STR_2396 :{BLACK}Obtenir avec la nourriture, les boissons et les ventes d'articles un revenu mensuel d'au moins {POP16}{POP16}{CURRENCY} STR_2397 :Aucun -STR_2398 :Number of guests at a given date -STR_2399 :Park value at a given date -STR_2400 :Have fun -STR_2401 :Build the best ride you can -STR_2402 :Build 10 roller coasters -STR_2403 :Number of guests in park -STR_2404 :Monthly income from ride tickets -STR_2405 :Build 10 roller coasters of a given length -STR_2406 :Finish building 5 roller coasters -STR_2407 :Repay loan and achieve a given park value -STR_2408 :Monthly profit from food/merchandise +STR_2398 :Nombre de visiteurs à une date donnée +STR_2399 :Valeur du parc à une date donnée +STR_2400 :Amusez-vous +STR_2401 :Constr. la meilleure attraction possible +STR_2402 :Construire 10 montagnes russes +STR_2403 :Nombre de visiteurs dans le parc +STR_2404 :Revenu mensuel des tickets d'attractions +STR_2405 :Constr. 10 mont. russes avec long. donnée +STR_2406 :Terminer la constr. de 5 mont. russes +STR_2407 :Remb. emprunt + obt. valeur de parc donnée +STR_2408 :Revenu mensuel nourr./articles STR_2409 :{WINDOW_COLOUR_2}Campagnes marketing en cours STR_2410 :{BLACK}Aucune STR_2411 :{WINDOW_COLOUR_2}Campagnes marketing disponibles -STR_2412 :{SMALLFONT}{BLACK}Commencer campagne marketing -STR_2413 :{BLACK}({CURRENCY2DP} per week) -STR_2414 :(Not Selected) -STR_2415 :{WINDOW_COLOUR_2}Attraction: -STR_2416 :{WINDOW_COLOUR_2}Item: -STR_2417 :{WINDOW_COLOUR_2}Length of time: -STR_2418 :Free entry to {STRINGID} -STR_2419 :Free ride on {STRINGID} -STR_2420 :Half-price entry to {STRINGID} -STR_2421 :Free {STRINGID} -STR_2422 :Advertising campaign for {STRINGID} -STR_2423 :Advertising campaign for {STRINGID} -STR_2424 :{WINDOW_COLOUR_2}Vouchers for free entry to the park +STR_2412 :{SMALLFONT}{BLACK}Commencer cette campagne marketing +STR_2413 :{BLACK}({CURRENCY2DP} par semaine) +STR_2414 :(Non sélectionné) +STR_2415 :{WINDOW_COLOUR_2}Attraction : +STR_2416 :{WINDOW_COLOUR_2}Article : +STR_2417 :{WINDOW_COLOUR_2}Duréee : +STR_2418 :entrée gratuite pour {STRINGID} +STR_2419 :tour gratuit sur {STRINGID} +STR_2420 :entrée demi-tarif pour {STRINGID} +STR_2421 :{STRINGID} +STR_2422 :Campagne publicitaire pour {STRINGID} +STR_2423 :Campagne publicitaire pour {STRINGID} +STR_2424 :{WINDOW_COLOUR_2}Bons pour une entrée gratuite STR_2425 :{WINDOW_COLOUR_2}Bons pour une attraction gratuite -STR_2426 :{WINDOW_COLOUR_2}Vouchers for half-price entry to the park -STR_2427 :{WINDOW_COLOUR_2}Bons pour nourriture/boisson gratuites +STR_2426 :{WINDOW_COLOUR_2}Bons pour une entrée demi-tarif +STR_2427 :{WINDOW_COLOUR_2}Bons pour nourriture/boisson gratuite STR_2428 :{WINDOW_COLOUR_2}Campagne publicitaire pour le parc STR_2429 :{WINDOW_COLOUR_2}Campagne publicitaire pour une attraction -STR_2430 :{BLACK}Vouchers for free entry to {STRINGID} -STR_2431 :{BLACK}Vouchers for free ride on {STRINGID} -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_2430 :{BLACK}Bons pour entrée gratuite à {STRINGID} +STR_2431 :{BLACK}Bons pour tour gratuit sur {STRINGID} +STR_2432 :{BLACK}Bons pour entrée demi-tarif à {STRINGID} +STR_2433 :{BLACK}Bons pour {STRINGID} +STR_2434 :{BLACK}Campagne publicitaire pour {STRINGID} +STR_2435 :{BLACK}Campagne publicitaire {STRINGID} STR_2436 :1 semaine STR_2437 : STR_2438 : @@ -2448,87 +2448,87 @@ STR_2439 : STR_2440 : STR_2441 : STR_2442 : -STR_2443 :{WINDOW_COLOUR_2}Cost per week: {BLACK}{CURRENCY2DP} -STR_2444 :{WINDOW_COLOUR_2}Total cost: {BLACK}{CURRENCY2DP} +STR_2443 :{WINDOW_COLOUR_2}Coût hebdomadaire : {BLACK}{CURRENCY2DP} +STR_2444 :{WINDOW_COLOUR_2}Coût total : {BLACK}{CURRENCY2DP} STR_2445 :Commencer campagne marketing -STR_2446 :{YELLOW}Your marketing campaign for free entry to the park has finished -STR_2447 :{YELLOW}Your marketing campaign for free rides on {STRINGID} has finished -STR_2448 :{YELLOW}Your marketing campaign for half-price entry to the park has finished -STR_2449 :{YELLOW}Your marketing campaign for free {STRINGID} has finished -STR_2450 :{YELLOW}Your advertising campaign for the park has finished -STR_2451 :{YELLOW}Your advertising campaign for {STRINGID} has finished +STR_2446 :{YELLOW}Votre campagne marketing d'entrées gratuites au parc est terminée +STR_2447 :{YELLOW}Votre campagne marketing de tours gratuits sur {STRINGID} est terminée +STR_2448 :{YELLOW}Votre campagne marketing d'entrées demi-tarif est terminée +STR_2449 :{YELLOW}Votre campagne marketing pour les {STRINGID} gratuits est terminée +STR_2450 :{YELLOW}Votre campagne marketing pour le parc est terminée +STR_2451 :{YELLOW}Votre campagne marketing pour {STRINGID} est terminée STR_2452 :{WINDOW_COLOUR_2}Argent (moins l'emprunt): {BLACK}{CURRENCY2DP} STR_2453 :{WINDOW_COLOUR_2}Argent (moins l'emprunt): {RED}{CURRENCY2DP} STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - STR_2455 :{SMALLFONT}{BLACK}+{CURRENCY2DP} - STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} - -STR_2457 :{SMALLFONT}{BLACK}Show financial accounts -STR_2458 :{SMALLFONT}{BLACK}Show graph of cash (less loan) over time -STR_2459 :{SMALLFONT}{BLACK}Show graph of park value over time -STR_2460 :{SMALLFONT}{BLACK}Show graph of weekly profit -STR_2461 :{SMALLFONT}{BLACK}Show marketing campaigns -STR_2462 :{SMALLFONT}{BLACK}Show view of park entrance -STR_2463 :{SMALLFONT}{BLACK}Show graph of park ratings over time -STR_2464 :{SMALLFONT}{BLACK}Show graph of guest numbers over time -STR_2465 :{SMALLFONT}{BLACK}Show park entrance price and information -STR_2466 :{SMALLFONT}{BLACK}Show park statistics -STR_2467 :{SMALLFONT}{BLACK}Show objectives for this game -STR_2468 :{SMALLFONT}{BLACK}Show recent awards this park has received -STR_2469 :{SMALLFONT}{BLACK}Select level of research & development -STR_2470 :{SMALLFONT}{BLACK}Research new transport rides -STR_2471 :{SMALLFONT}{BLACK}Research new gentle rides -STR_2472 :{SMALLFONT}{BLACK}Research new roller coasters -STR_2473 :{SMALLFONT}{BLACK}Research new thrill rides -STR_2474 :{SMALLFONT}{BLACK}Research new water rides -STR_2475 :{SMALLFONT}{BLACK}Research new shops and stalls -STR_2476 :{SMALLFONT}{BLACK}Research new scenery and themeing -STR_2477 :{SMALLFONT}{BLACK}Select operating mode for this ride/attraction -STR_2478 :{SMALLFONT}{BLACK}Show graph of velocity against time -STR_2479 :{SMALLFONT}{BLACK}Show graph of altitude against time -STR_2480 :{SMALLFONT}{BLACK}Show graph of vertical acceleration against time -STR_2481 :{SMALLFONT}{BLACK}Show graph of lateral acceleration against time -STR_2482 :{SMALLFONT}{BLACK}Bénéfice: {CURRENCY} par semaine, Valeur du parc: {CURRENCY} -STR_2483 :{WINDOW_COLOUR_2}Weekly profit: {BLACK}+{CURRENCY2DP} -STR_2484 :{WINDOW_COLOUR_2}Weekly profit: {RED}{CURRENCY2DP} -STR_2485 :Controls -STR_2486 :General +STR_2457 :{SMALLFONT}{BLACK}Voir comptes financiers +STR_2458 :{SMALLFONT}{BLACK}Voir graphique Argent (moins emprunt) sur durée +STR_2459 :{SMALLFONT}{BLACK}Voir graphique Valeur du parc sur durée +STR_2460 :{SMALLFONT}{BLACK}Voir graphique Bénéfices hebdomadaires +STR_2461 :{SMALLFONT}{BLACK}Voir campagnes marketing +STR_2462 :{SMALLFONT}{BLACK}Voir entrée du parc +STR_2463 :{SMALLFONT}{BLACK}Voir graphique Evaluation du parc sur durée +STR_2464 :{SMALLFONT}{BLACK}Voir graphique Nombre de visiteurs sur durée +STR_2465 :{SMALLFONT}{BLACK}Voir tarif d'entrée et informations +STR_2466 :{SMALLFONT}{BLACK}Voir statistiques du parc +STR_2467 :{SMALLFONT}{BLACK}Voir objectifs pour cette partie +STR_2468 :{SMALLFONT}{BLACK}Voir récompenses obtenues récemment par ce parc +STR_2469 :{SMALLFONT}{BLACK}Choisir niveau de recherche & développement +STR_2470 :{SMALLFONT}{BLACK}Rechercher nouvelles attractions de transport +STR_2471 :{SMALLFONT}{BLACK}Rechercher nouvelles attractions tranquilles +STR_2472 :{SMALLFONT}{BLACK}Rechercher nouvelles montagnes russes +STR_2473 :{SMALLFONT}{BLACK}Rechercher nouvelles attractions à frissons +STR_2474 :{SMALLFONT}{BLACK}Rechercher nouvelles attractions aquatiques +STR_2475 :{SMALLFONT}{BLACK}Rechercher nouveaux magasins/boutiques +STR_2476 :{SMALLFONT}{BLACK}Rechercher nouveaux décors/thèmes +STR_2477 :{SMALLFONT}{BLACK}Choisir le mode de fonctionnement de cette attraction +STR_2478 :{SMALLFONT}{BLACK}Voir graphique Rapidité sur durée +STR_2479 :{SMALLFONT}{BLACK}Voir graphique Altitude sur durée +STR_2480 :{SMALLFONT}{BLACK}Voir graphique Accélération verticale sur durée +STR_2481 :{SMALLFONT}{BLACK}Voir graphique Accélération latérale sur durée +STR_2482 :{SMALLFONT}{BLACK}Bénéfice : {CURRENCY} par semaine, {NEWLINE}Valeur du parc : {CURRENCY} +STR_2483 :{WINDOW_COLOUR_2}Bénéfice hebdomadaire : {BLACK}+{CURRENCY2DP} +STR_2484 :{WINDOW_COLOUR_2}Bénéfice hebdomadaire : {RED}{CURRENCY2DP} +STR_2485 :Contrôles +STR_2486 :Général STR_2487 :Afficher le 'vrai' nom des visiteurs -STR_2488 :{SMALLFONT}{BLACK}Toggle between showing 'real' names of guests and guest numbers -STR_2489 :Shortcut keys... -STR_2490 :Keyboard shortcuts -STR_2491 :Reset keys -STR_2492 :{SMALLFONT}{BLACK}Set all keyboard shortcuts back to default settings -STR_2493 :Close top-most window -STR_2494 :Close all floating windows -STR_2495 :Cancel construction mode -STR_2496 :Pause game -STR_2497 :Zoom view out -STR_2498 :Zoom view in -STR_2499 :Rotate view clockwise -STR_2500 :Rotate construction object -STR_2501 :Underground view toggle -STR_2502 :Remove base land toggle -STR_2503 :Remove vertical land toggle -STR_2504 :See-through rides toggle -STR_2505 :See-through scenery toggle -STR_2506 :Invisible supports toggle -STR_2507 :Invisible people toggle -STR_2508 :Height marks on land toggle -STR_2509 :Height marks on ride tracks toggle -STR_2510 :Height marks on paths toggle -STR_2511 :Adjust land -STR_2512 :Adjust water -STR_2513 :Build scenery -STR_2514 :Build paths -STR_2515 :Build new ride -STR_2516 :Show financial information -STR_2517 :Show research information -STR_2518 :Show rides list -STR_2519 :Show park information -STR_2520 :Show guest list -STR_2521 :Show staff list -STR_2522 :Show recent messages -STR_2523 :Show map +STR_2488 :{SMALLFONT}{BLACK}Passer du 'vrai' nom des visiteurs à leur numéro +STR_2489 :Raccourcis... +STR_2490 :Raccourcis clavier +STR_2491 :Réinitial. +STR_2492 :{SMALLFONT}{BLACK}Réinitialiser tous les raccourcis +STR_2493 :Fermer fenêtre supérieure +STR_2494 :Fermer toutes les fenêtres +STR_2495 :Annuler mode construction +STR_2496 :Mettre en pause +STR_2497 :Zoom arrière +STR_2498 :Zoom avant +STR_2499 :Pivoter vue +STR_2500 :Pivoter objet construction +STR_2501 :Vue souterraine +STR_2502 :Supprimer surface +STR_2503 :Supprimer terrain vertical +STR_2504 :Attractions transparentes +STR_2505 :Décor transparent +STR_2506 :Supports invisibles +STR_2507 :Personnes invisibles +STR_2508 :Repères de hauteur sur terrain +STR_2509 :Repères de hauteur sur attractions +STR_2510 :Repères de hauteur dans allées +STR_2511 :Ajuster terrain +STR_2512 :Ajuster étendue d'eau +STR_2513 :Construire décor +STR_2514 :Construire allées +STR_2515 :Construire nouvelle attraction +STR_2516 :Voir informations financières +STR_2517 :Voir informations recherches +STR_2518 :Voir liste des attractions +STR_2519 :Voir informations sur le parc +STR_2520 :Voir liste des visiteurs +STR_2521 :Voir liste des employés +STR_2522 :Voir messages récents +STR_2523 :Voir la carte STR_2524 :Capture d'écran STR_2525 :??? STR_2526 :??? @@ -2538,46 +2538,46 @@ STR_2529 :??? STR_2530 :??? STR_2531 :??? STR_2532 :??? -STR_2533 :Backspace +STR_2533 :Retour arr. STR_2534 :Tab STR_2535 :??? STR_2536 :??? -STR_2537 :Clear -STR_2538 :Return +STR_2537 :Effacer +STR_2538 :Retour STR_2539 :??? STR_2540 :??? STR_2541 :??? STR_2542 :??? STR_2543 :Alt/Menu STR_2544 :Pause -STR_2545 :Caps +STR_2545 :Verr. Maj. STR_2546 :??? STR_2547 :??? STR_2548 :??? STR_2549 :??? STR_2550 :??? STR_2551 :??? -STR_2552 :Escape +STR_2552 :Echap. STR_2553 :??? STR_2554 :??? STR_2555 :??? STR_2556 :??? -STR_2557 :Spacebar -STR_2558 :PgUp -STR_2559 :PgDn -STR_2560 :End -STR_2561 :Home -STR_2562 :Left -STR_2563 :Up -STR_2564 :Right -STR_2565 :Down -STR_2566 :Select -STR_2567 :Print -STR_2568 :Execute -STR_2569 :Snapshot -STR_2570 :Insert -STR_2571 :Delete -STR_2572 :Help +STR_2557 :Barre d'espace +STR_2558 :Page Haut +STR_2559 :Page Bas +STR_2560 :Fin +STR_2561 :Orig. +STR_2562 :Gauche +STR_2563 :Haut +STR_2564 :Droite +STR_2565 :Bas +STR_2566 :Sélectionner +STR_2567 :Imprimer +STR_2568 :Exécuter +STR_2569 :Capture d'écran +STR_2570 :Insertion +STR_2571 :Supprimer +STR_2572 :Aide STR_2573 :0 STR_2574 :1 STR_2575 :2 @@ -2626,22 +2626,22 @@ STR_2617 :??? STR_2618 :Menu STR_2619 :??? STR_2620 :??? -STR_2621 :NumPad 0 -STR_2622 :NumPad 1 -STR_2623 :NumPad 2 -STR_2624 :NumPad 3 -STR_2625 :NumPad 4 -STR_2626 :NumPad 5 -STR_2627 :NumPad 6 -STR_2628 :NumPad 7 -STR_2629 :NumPad 8 -STR_2630 :NumPad 9 -STR_2631 :NumPad * -STR_2632 :NumPad + +STR_2621 :0 (pavé numérique) +STR_2622 :1 (pavé numérique) +STR_2623 :2 (pavé numérique) +STR_2624 :3 (pavé numérique) +STR_2625 :4 (pavé numérique) +STR_2626 :5 (pavé numérique) +STR_2627 :6 (pavé numérique) +STR_2628 :7 (pavé numérique) +STR_2629 :8 (pavé numérique) +STR_2630 :9 (pavé numérique) +STR_2631 :* (pavé numérique) +STR_2632 :+ (pavé numérique) STR_2633 :??? -STR_2634 :NumPad - -STR_2635 :NumPad . -STR_2636 :NumPad / +STR_2634 :- (pavé numérique) +STR_2635 :. (pavé numérique) +STR_2636 :/ (pavé numérique) STR_2637 :F1 STR_2638 :F2 STR_2639 :F3 @@ -2674,8 +2674,8 @@ STR_2665 :??? STR_2666 :??? STR_2667 :??? STR_2668 :??? -STR_2669 :NumLock -STR_2670 :Scroll +STR_2669 :Verr num +STR_2670 :Défil. STR_2671 :??? STR_2672 :??? STR_2673 :??? @@ -2685,37 +2685,37 @@ STR_2676 :??? STR_2677 :??? STR_2678 :??? STR_2679 :??? -STR_2680 :All research complete -STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} +STR_2680 :Toutes les recherches effectuées +STR_2681 :{MEDIUMFONT}{BLACK}Augmenter votre argent de {CURRENCY} STR_2682 : STR_2683 : -STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive -STR_2685 :Simplex Noise Parameters -STR_2686 :{WINDOW_COLOUR_2}Low: -STR_2687 :{WINDOW_COLOUR_2}High: -STR_2688 :{WINDOW_COLOUR_2}Base Frequency: -STR_2689 :{WINDOW_COLOUR_2}Octaves: -STR_2690 :Map Generation -STR_2691 :{WINDOW_COLOUR_2}Base height: -STR_2692 :{WINDOW_COLOUR_2}Water level: -STR_2693 :{WINDOW_COLOUR_2}Terrain: -STR_2694 :Generate -STR_2695 :Random terrain -STR_2696 :Place trees +STR_2684 :{SMALLFONT}{BLACK}Un grand groupe de visiteurs arrive +STR_2685 :Paramètres de bruit Simplex +STR_2686 :{WINDOW_COLOUR_2}Graves : +STR_2687 :{WINDOW_COLOUR_2}Aigus : +STR_2688 :{WINDOW_COLOUR_2}Fréquence de base : +STR_2689 :{WINDOW_COLOUR_2}Octaves : +STR_2690 :Génération de carte +STR_2691 :{WINDOW_COLOUR_2}Hauteur de base : +STR_2692 :{WINDOW_COLOUR_2}Niveau de l'eau : +STR_2693 :{WINDOW_COLOUR_2}Terrain : +STR_2694 :Générer +STR_2695 :Terrain aléatoire +STR_2696 :Placer les arbres STR_2697 :??? STR_2698 :??? STR_2699 :??? -STR_2700 :Autosave frequency: +STR_2700 :Fréquence sauv. auto. : STR_2701 :Toutes les minutes STR_2702 :Toutes les 5 minutes STR_2703 :Toutes les 15 minutes STR_2704 :Toutes les 30 minutes STR_2705 :Toutes les heures STR_2706 :Jamais -STR_2707 :Open new window -STR_2708 :{WINDOW_COLOUR_1}Are you sure you want to overwrite {STRINGID}? -STR_2709 :Overwrite -STR_2710 :Type the name of the file. +STR_2707 :Fenêtre de dialogue système +STR_2708 :{WINDOW_COLOUR_1}Etes vous sûr de vouloir écraser {STRINGID}? +STR_2709 :Ecraser +STR_2710 :Entrez le nom du fichier. STR_2711 :; STR_2712 := STR_2713 :, @@ -2723,7 +2723,7 @@ STR_2714 :- STR_2715 :. STR_2716 :/ STR_2717 :' -STR_2718 :(up) +STR_2718 :(dossier parent) STR_2719 :(nouveau fichier) STR_2720 :{UINT16}s STR_2721 :{UINT16}s @@ -2741,203 +2741,203 @@ STR_2732 :{COMMA16}ft STR_2733 :{COMMA16}m STR_2734 :{COMMA16}mph STR_2735 :{COMMA16}km/h -STR_2736 :{MONTH}, an {COMMA16} -STR_2737 :{STRINGID} {MONTH}, an {COMMA16} -STR_2738 :Title screen music: +STR_2736 :{MONTH}, année {COMMA16} +STR_2737 :{STRINGID} {MONTH}, année {COMMA16} +STR_2738 :Musique de titre : STR_2739 :Aucun STR_2740 :RollerCoaster Tycoon 1 STR_2741 :RollerCoaster Tycoon 2 -STR_2742 :css50.dat n'est pas trouvé -STR_2743 :Copy data\css17.dat from your RCT1 installation to data\css50.dat in your RCT2 installation. +STR_2742 :css50.dat introuvable +STR_2743 :Renommez et déplacez data\css17.dat depuis votre dossier RCT1 en data\css50.dat dans votre dossier RCT2 STR_2744 :[ STR_2745 :\ STR_2746 :] STR_2747 :{ENDQUOTES} STR_2748 :Bar STR_2749 :Mon nouveau scénario -STR_2750 :Move all items to top -STR_2751 :Move all items to bottom -STR_2752 :Clear grass -STR_2753 :Mowed grass -STR_2754 :Water plants -STR_2755 :Fix vandalism -STR_2756 :Remove litter -STR_2757 :Force Sun -STR_2758 :Force Thunder -STR_2759 :Zero Clearance +STR_2750 :Déplacer tous les éléments en haut +STR_2751 :Déplacer tous les éléments en bas +STR_2752 :Pelouse propre +STR_2753 :Pelouse tondue +STR_2754 :Arroser plantes +STR_2755 :Réparer vandalisme +STR_2756 :Nettoyer déchets +STR_2757 :Forcer le soleil +STR_2758 :Forcer l'orage +STR_2759 :Pas de collisions # New strings used in the cheats window previously these were ??? STR_2760 :+{CURRENCY} STR_2761 : STR_2762 : STR_2763 :??? STR_2764 : -STR_2765 :Large Tram -STR_2766 :Win scenario -STR_2767 :Freeze Climate -STR_2768 :Unfreeze Climate +STR_2765 :Grand tram +STR_2766 :Gagner +STR_2767 :Bloquer climat +STR_2768 :Débloquer climat STR_2769 :Ouvrir le parc STR_2770 :Fermer le parc -STR_2771 :Slower Gamespeed -STR_2772 :Faster Gamespeed -STR_2773 :En une fenêtre +STR_2771 :Vitesse de jeu plus lente +STR_2772 :Vitesse de jeu plus rapide +STR_2773 :Fenêtré STR_2774 :Plein écran -STR_2775 :Plein écran (desktop) -STR_2776 :Langue: +STR_2775 :Plein écran (nv. bureau) +STR_2776 :Langue : STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} # End of new strings -STR_2779 :Viewport #{COMMA16} -STR_2780 :Extra viewport +STR_2779 :Vue #{COMMA16} +STR_2780 :Vue supplémentaire STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} STR_2782 :SHIFT + STR_2783 :CTRL + -STR_2784 :Change keyboard shortcut -STR_2785 :{WINDOW_COLOUR_2}Press new shortcut key for:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} -STR_2786 :{SMALLFONT}{BLACK}Click on shortcut description to select new key -STR_2787 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} -STR_2788 :{WINDOW_COLOUR_2}Congratulations !{NEWLINE}{BLACK}You achieved your objective with a company value of {CURRENCY} ! -STR_2789 :{WINDOW_COLOUR_2}You have failed your objective ! -STR_2790 :Enter name into scenario chart -STR_2791 :Enter name -STR_2792 :Please enter your name for the scenario chart: -STR_2793 :{SMALLFONT}(Completed by {STRINGID}) -STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY} +STR_2784 :Modifier raccourci clavier +STR_2785 :{WINDOW_COLOUR_2}Nouveau raccourci clavier pour :{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2786 :{SMALLFONT}{BLACK}Cliquer sur la description du raccourci pour choisir une nouvelle touche +STR_2787 :{WINDOW_COLOUR_2}Valeur du parc : {BLACK}{CURRENCY} +STR_2788 :{WINDOW_COLOUR_2}Félicitations !{NEWLINE}{BLACK}Vous avez atteint votre objectif, votre société a une valeur de {CURRENCY} ! +STR_2789 :{WINDOW_COLOUR_2}Vous n'avez pas atteint votre objectif ! +STR_2790 :Saisir nom dans le tableau de scénarios +STR_2791 :Saisir nom +STR_2792 :Veuillez saisir votre nom pour le tableau de scénarios : +STR_2793 :{SMALLFONT}(Réussi par {STRINGID}) +STR_2794 :{WINDOW_COLOUR_2}Réussi par : {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} avec une valeur de société de : {BLACK}{CURRENCY} STR_2795 :Trier -STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed -STR_2797 :Scroll view when pointer at screen edge -STR_2798 :{SMALLFONT}{BLACK}Select whether to scroll the view when the mouse pointer is at the screen edge -STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments -STR_2800 :{WINDOW_COLOUR_2}Total admissions: {BLACK}{COMMA32} -STR_2801 :{WINDOW_COLOUR_2}Income from admissions: {BLACK}{CURRENCY2DP} -STR_2802 :Plan -STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map -STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map -STR_2805 :{SMALLFONT}{BLACK}Show map of park -STR_2806 :{RED}Guests are complaining about the disgusting state of the paths in your park{NEWLINE}Check where your handymen are and consider organizing them better -STR_2807 :{RED}Guests are complaining about the amount of litter in your park{NEWLINE}Check where your handymen are and consider organizing them better -STR_2808 :{RED}Guests are complaining about the vandalism in your park{NEWLINE}Check where your security guards are and consider organizing them better -STR_2809 :{RED}Guests are hungry and can't find anywhere to buy food -STR_2810 :{RED}Guests are thirsty and can't find anywhere to buy drinks -STR_2811 :{RED}Guests are complaining because they can't find the toilets in your park -STR_2812 :{RED}Guests are getting lost or stuck{NEWLINE}Check whether the layout of your footpaths needs improving to help the guests find their way around -STR_2813 :{RED}Your park entrance fee is too high!{NEWLINE}Reduce your entrance fee or improve the value of the park to attract more guests -STR_2814 :{WINDOW_COLOUR_2}Most untidy park award -STR_2815 :{WINDOW_COLOUR_2}Tidiest park award -STR_2816 :{WINDOW_COLOUR_2}Award for the park with the best roller coasters -STR_2817 :{WINDOW_COLOUR_2}Best value park award -STR_2818 :{WINDOW_COLOUR_2}Most beautiful park award -STR_2819 :{WINDOW_COLOUR_2}Worst value park award -STR_2820 :{WINDOW_COLOUR_2}Safest park award -STR_2821 :{WINDOW_COLOUR_2}Best staff award -STR_2822 :{WINDOW_COLOUR_2}Best park food award -STR_2823 :{WINDOW_COLOUR_2}Worst park food award -STR_2824 :{WINDOW_COLOUR_2}Best park toilets award -STR_2825 :{WINDOW_COLOUR_2}Most disappointing park award -STR_2826 :{WINDOW_COLOUR_2}Best water rides award -STR_2827 :{WINDOW_COLOUR_2}Best custom-designed rides award -STR_2828 :{WINDOW_COLOUR_2}Most dazzling ride colour schemes award -STR_2829 :{WINDOW_COLOUR_2}Most confusing park layout award -STR_2830 :{WINDOW_COLOUR_2}Best gentle ride award -STR_2831 :{TOPAZ}Your park has received an award for being 'The most untidy park in the country'! -STR_2832 :{TOPAZ}Your park has received an award for being 'The tidiest park in the country'! -STR_2833 :{TOPAZ}Your park has received an award for being 'The park with the best roller coasters'! -STR_2834 :{TOPAZ}Your park has received an award for being 'The best value park in the country'! -STR_2835 :{TOPAZ}Your park has received an award for being 'The most beautiful park in the country'! -STR_2836 :{TOPAZ}Your park has received an award for being 'The worst value park in the country'! -STR_2837 :{TOPAZ}Your park has received an award for being 'The safest park in the country'! -STR_2838 :{TOPAZ}Your park has received an award for being 'The park with the best staff'! -STR_2839 :{TOPAZ}Your park has received an award for being 'The park with the best food in the country'! -STR_2840 :{TOPAZ}Your park has received an award for being 'The park with the worst food in the country'! -STR_2841 :{TOPAZ}Your park has received an award for being 'The park with the best toilet facilities in the country'! -STR_2842 :{TOPAZ}Your park has received an award for being 'The most disappointing park in the country'! -STR_2843 :{TOPAZ}Your park has received an award for being 'The park with the best water rides in the country'! -STR_2844 :{TOPAZ}Your park has received an award for being 'The park with the best custom-designed rides'! -STR_2845 :{TOPAZ}Your park has received an award for being 'The park with the most dazzling choice of colour schemes'! -STR_2846 :{TOPAZ}Your park has received an award for being 'The park with the most confusing layout'! -STR_2847 :{TOPAZ}Your park has received an award for being 'The park with the best gentle rides'! -STR_2848 :{WINDOW_COLOUR_2}Pas de récompense récente -STR_2849 :New scenario installed successfully -STR_2850 :New track design installed successfully -STR_2851 :Scenario already installed -STR_2852 :Track design already installed -STR_2853 :Forbidden by the local authority! -STR_2854 :{RED}Guests can't get to the entrance of {STRINGID} !{NEWLINE}Construct a path to the entrance -STR_2855 :{RED}{STRINGID} has no path leading from its exit !{NEWLINE}Construct a path from the ride exit +STR_2796 :{SMALLFONT}{BLACK}Trier la liste des attractions dans l'ordre avec le type d'informations affiché +STR_2797 :Faire défiler vue quand curseur atteint bord de l'écran +STR_2798 :{SMALLFONT}{BLACK}Choisir s'il faut faire défiler la vue quand le curseur atteint e bord de l'écran +STR_2799 :{SMALLFONT}{BLACK}Voir ou modifier les touches de raccourci +STR_2800 :{WINDOW_COLOUR_2}Nombre total d'entrées : {BLACK}{COMMA32} +STR_2801 :{WINDOW_COLOUR_2}Revenu issu des entrées : {BLACK}{CURRENCY2DP} +STR_2802 :Carte +STR_2803 :{SMALLFONT}{BLACK}Voir les visiteurs sélectionnés sur la carte +STR_2804 :{SMALLFONT}{BLACK}Voir les employés sélectionnés sur la carte +STR_2805 :{SMALLFONT}{BLACK}Voir carte +STR_2806 :{RED}Vos visiteurs se plaignent de l'état déplorable des allées dans votre parc{NEWLINE}Vérifiez la position de vos agents d'entretien et améliorez leur efficacité +STR_2807 :{RED}Vos visiteurs se plaignent des détritus qui jonchent votre parc{NEWLINE}Vérifiez la position de vos agents d'entretien et améliorez leur efficacité +STR_2808 :{RED}Vos visiteurs se plaignent d'actes de vandalisme dans votre parc{NEWLINE}Vérifiez la position de vos agents de sécurité et améliorez leur efficacité +STR_2809 :{RED}Vos visiteurs ont faim et n'ont aucun endroit où se restaurer +STR_2810 :{RED}Vos visiteurs ont soif et n'ont aucun endroit où se désaltérer +STR_2811 :{RED}Vos visiteurs se plaignent car ils ne trouvent pas de toilettes dans votre parc +STR_2812 :{RED}Vos visiteurs se perdent ou se trouvent bloqués{NEWLINE}Améliorez la disposition de vos allées afin de faciliter leurs déplacements +STR_2813 :{RED}Le tarif d'entrée de votre parc est trop élevé !{NEWLINE}Diminuez-le ou améliorez la valeur de votre parc pour attirer plus de visiteurs +STR_2814 :{WINDOW_COLOUR_2}Prix du parc le plus sale +STR_2815 :{WINDOW_COLOUR_2}Prix du parc le plus propre +STR_2816 :{WINDOW_COLOUR_2}Prix du parc ayant les meilleures attractions +STR_2817 :{WINDOW_COLOUR_2}Prix du parc ayant la plus grande valeur du pays +STR_2818 :{WINDOW_COLOUR_2}Prix du parc le plus beau du pays +STR_2819 :{WINDOW_COLOUR_2}Prix du parc ayant la plus faible valeur +STR_2820 :{WINDOW_COLOUR_2}Prix du parc le plus sûr +STR_2821 :{WINDOW_COLOUR_2}Prix du parc ayant les meilleurs employés +STR_2822 :{WINDOW_COLOUR_2}Prix du parc ayant la meilleure nourriture +STR_2823 :{WINDOW_COLOUR_2}Prix du parc ayant la pire nourriture +STR_2824 :{WINDOW_COLOUR_2}Prix du parc ayant les meilleures toilettes +STR_2825 :{WINDOW_COLOUR_2}Prix du parc le plus décevant +STR_2826 :{WINDOW_COLOUR_2}Prix du parc ayant les meilleures attraction aquatiques +STR_2827 :{WINDOW_COLOUR_2}Prix du parc ayant les meilleures attractions personnalisées +STR_2828 :{WINDOW_COLOUR_2}Prix du parc ayant les couleurs les plus éclatantes +STR_2829 :{WINDOW_COLOUR_2}Prix du parc le plus confus +STR_2830 :{WINDOW_COLOUR_2}Prix du parc ayant les meilleures attractions tranquilles +STR_2831 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc le plus sale du pays{ENDQUOTES} ! +STR_2832 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc le plus propre du pays{ENDQUOTES} ! +STR_2833 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant les meilleures attractions du pays{ENDQUOTES} ! +STR_2834 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant la plus grande valeur du pays{ENDQUOTES} ! +STR_2835 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc le plus beau du pays{ENDQUOTES} ! +STR_2836 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant la plus faible valeur du pays{ENDQUOTES} ! +STR_2837 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc le plus sûr du pays{ENDQUOTES} ! +STR_2838 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant les meilleurs employés{ENDQUOTES} ! +STR_2839 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant la meilleure nourriture du pays{ENDQUOTES} ! +STR_2840 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant la pire nourriture du pays{ENDQUOTES} ! +STR_2841 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant les meilleures toilettes du pays{ENDQUOTES} ! +STR_2842 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc le plus décevant du pays{ENDQUOTES} ! +STR_2843 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant les meilleures attraction aquatiques du pays{ENDQUOTES} ! +STR_2844 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant les meilleures attractions personnalisées du pays{ENDQUOTES} ! +STR_2845 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant les couleurs les plus éclatantes du pays{ENDQUOTES} ! +STR_2846 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc le plus confus du pays{ENDQUOTES} ! +STR_2847 :{TOPAZ}Votre parc a reçu le prix du {OPENQUOTES}parc ayant les meilleures attractions tranquilles du pays{ENDQUOTES} ! +STR_2848 :{WINDOW_COLOUR_2}Pas de récompenses récentes +STR_2849 :Nouveau scénario installé avec succès +STR_2850 :Nouvelle voie installée avec succès +STR_2851 :Scénario déjà installé +STR_2852 :Voie déjà installée +STR_2853 :Interdit par les autorités locales ! +STR_2854 :{RED}Vos visiteurs ne peuvent atteindre l'entrée de {STRINGID} !{NEWLINE}Construisez une allée vers l'entrée +STR_2855 :{RED}{STRINGID} ne dispose pas d'allée à partir de sa sortie !{NEWLINE}Construisez une allée à la sortie de l'attraction STR_2856 :{WINDOW_COLOUR_2}Didacticiel STR_2857 :{WINDOW_COLOUR_2}(Appuyez sur une touche ou un bouton de la souris pour essayer vous-même) -STR_2858 :Can't start marketing campaign... -STR_2859 :Another instance of OpenRCT2 is already running -STR_2860 :Infogrames Interactive credits... -STR_2861 :{WINDOW_COLOUR_2}Licensed to Infogrames Interactive Inc. +STR_2858 :Impossible de commencer campagne marketing... +STR_2859 :Une session de RollerCoaster Tycoon 2 est déjà ouverte +STR_2860 :Crédits Infogrames Interactive... +STR_2861 :{WINDOW_COLOUR_2}Sous licence d'Infogrames Interactive Inc. STR_2862 :Remerciements musique... STR_2863 :Remerciements musique -STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) non copyright -STR_2865 :{WINDOW_COLOUR_2}Heyken's Serenade: (J.Heyken) British Standard Music Coy; GEMA, BRITICO -STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Composer unknown) Copyright Control -STR_2867 :{WINDOW_COLOUR_2}Wedding Journey: (Traditional) -STR_2868 :{WINDOW_COLOUR_2}Tales from the Vienna Woods: (Johann Strauss) non copyright -STR_2869 :{WINDOW_COLOUR_2}Slavonic Dance: (Traditional) -STR_2870 :{WINDOW_COLOUR_2}Das Alpenhorn: (Traditional) -STR_2871 :{WINDOW_COLOUR_2}The Blond Sailor: (Traditional) -STR_2872 :{WINDOW_COLOUR_2}Overture - Poet and Peasant: (Suppe) non copyright -STR_2873 :{WINDOW_COLOUR_2}Waltz Medley: (Johann Strauss) non copyright -STR_2874 :{WINDOW_COLOUR_2}Bella Bella Bimba: (Traditional) -STR_2875 :{WINDOW_COLOUR_2}Original recordings (P) 1976 C.J.Mears Organization, used with consent -STR_2876 :{WINDOW_COLOUR_2}RollerCoaster Tycoon 2 Title Music: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2877 :{WINDOW_COLOUR_2}Dodgems Beat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2878 :{WINDOW_COLOUR_2}Mid Summer's Heat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2879 :{WINDOW_COLOUR_2}Pharaoh's Tomb: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2880 :{WINDOW_COLOUR_2}Caesar's March: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2881 :{WINDOW_COLOUR_2}Drifting To Heaven: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2882 :{WINDOW_COLOUR_2}Invaders: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2883 :{WINDOW_COLOUR_2}Eternal Toybox: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2884 :{WINDOW_COLOUR_2}Jungle Juice: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2885 :{WINDOW_COLOUR_2}Ninja's Noodles: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2886 :{WINDOW_COLOUR_2}Voyage to Andromeda: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2887 :{WINDOW_COLOUR_2}Brimble's Beat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2888 :{WINDOW_COLOUR_2}Atlantis: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2889 :{WINDOW_COLOUR_2}Wild West Kid: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2890 :{WINDOW_COLOUR_2}Vampire's Lair: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2891 :{WINDOW_COLOUR_2}Blockbuster: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2892 :{WINDOW_COLOUR_2}Airtime Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2893 :{WINDOW_COLOUR_2}Searchlight Rag: (Scott Joplin/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2894 :{WINDOW_COLOUR_2}Flight of Fantasy: (Steve Blenkinsopp) copyright {COPYRIGHT} Chris Sawyer -STR_2895 :{WINDOW_COLOUR_2}Big Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2896 :{WINDOW_COLOUR_2}Hypothermia: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2897 :{WINDOW_COLOUR_2}Last Sleigh Ride: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2898 :{WINDOW_COLOUR_2}Pipes of Glencairn: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2899 :{WINDOW_COLOUR_2}Traffic Jam: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) sans copyright +STR_2865 :{WINDOW_COLOUR_2}Heyken's Serenade : (J.Heyken) British Standard Music Coy ; GEMA, BRITICO +STR_2866 :{WINDOW_COLOUR_2}In Continental Mood : (Compositeur inconnu) Copyright +STR_2867 :{WINDOW_COLOUR_2}Wedding Journey : (Traditionnelle) +STR_2868 :{WINDOW_COLOUR_2}Les Histoires du Bois de Vienne : (Johann Strauss) sans copyright +STR_2869 :{WINDOW_COLOUR_2}Slavonic Dance : (Traditionnelle) +STR_2870 :{WINDOW_COLOUR_2}Das Alpenhorn : (Traditionnelle) +STR_2871 :{WINDOW_COLOUR_2}The Blond Sailor : (Traditionnelle) +STR_2872 :{WINDOW_COLOUR_2}Overture - Poet and Peasant : (Suppe) sans copyright +STR_2873 :{WINDOW_COLOUR_2}Waltz Medley : (Johann Strauss) sans copyright +STR_2874 :{WINDOW_COLOUR_2}Bella Bella Bimba : (Traditionnelle) +STR_2875 :{WINDOW_COLOUR_2}Enregistrements originaux (P) 1976 C.J.Mears Organisation, utilisés avec accord +STR_2876 :{WINDOW_COLOUR_2}Musique du titre RollerCoaster Tycoon 2 : (Allister Brimble) {COPYRIGHT} Chris Sawyer +STR_2877 :{WINDOW_COLOUR_2}Dodgems Beat : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2878 :{WINDOW_COLOUR_2}Mid Summer's Heat : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2879 :{WINDOW_COLOUR_2}Pharaoh's Tomb : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2880 :{WINDOW_COLOUR_2}Caesar's March : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2881 :{WINDOW_COLOUR_2}Drifting To Heaven : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2882 :{WINDOW_COLOUR_2}Invaders : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2883 :{WINDOW_COLOUR_2}Eternal Toybox : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2884 :{WINDOW_COLOUR_2}Jungle Juice : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2885 :{WINDOW_COLOUR_2}Ninja's Noodles : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2886 :{WINDOW_COLOUR_2}Voyage to Andromeda : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2887 :{WINDOW_COLOUR_2}Brimble's Beat : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2888 :{WINDOW_COLOUR_2}Atlantis : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2889 :{WINDOW_COLOUR_2}Wild West Kid : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2890 :{WINDOW_COLOUR_2}Vampire's Lair : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2891 :{WINDOW_COLOUR_2}Blockbuster : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2892 :{WINDOW_COLOUR_2}Airtime Rock : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2893 :{WINDOW_COLOUR_2}Searchlight Rag : (Scott Joplin/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2894 :{WINDOW_COLOUR_2}Flight of Fantasy : (Steve Blenkinsopp) copyright {COPYRIGHT} Chris Sawyer +STR_2895 :{WINDOW_COLOUR_2}Big Rock : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2896 :{WINDOW_COLOUR_2}Hypothermia : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2897 :{WINDOW_COLOUR_2}Last Sleigh Ride : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2898 :{WINDOW_COLOUR_2}Pipes of Glencairn : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2899 :{WINDOW_COLOUR_2}Traffic Jam : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2900 :{WINDOW_COLOUR_2} -STR_2901 :{WINDOW_COLOUR_2}(Samples courtesy of Spectrasonics {ENDQUOTES}Liquid Grooves{ENDQUOTES}) -STR_2902 :{WINDOW_COLOUR_2}Toccata: (C.M.Widor, played by Peter James Adcock) recording {COPYRIGHT} Chris Sawyer -STR_2903 :{WINDOW_COLOUR_2}Space Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2904 :{WINDOW_COLOUR_2}Manic Mechanic: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2905 :{WINDOW_COLOUR_2}Techno Torture: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2906 :{WINDOW_COLOUR_2}Sweat Dreams: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2907 :{WINDOW_COLOUR_2}What shall we do with the Drunken Sailor: (Anon/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2901 :{WINDOW_COLOUR_2}(Extraits avec l'aimable autorisation de Spectrasonics {ENDQUOTES}Liquid Grooves{ENDQUOTES}) +STR_2902 :{WINDOW_COLOUR_2}Toccata : (C.M.Widor, joué par Peter James Adcock) enregistrements {COPYRIGHT} Chris Sawyer +STR_2903 :{WINDOW_COLOUR_2}Space Rock : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2904 :{WINDOW_COLOUR_2}Manic Mechanic : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2905 :{WINDOW_COLOUR_2}Techno Torture : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2906 :{WINDOW_COLOUR_2}Sweat Dreams : (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2907 :{WINDOW_COLOUR_2}What shall we do with the Drunken Sailor : (Anon/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2908 :{WINDOW_COLOUR_2}Infogrames Interactive -STR_2909 :{WINDOW_COLOUR_2}Senior Producer: Thomas J. Zahorik -STR_2910 :{WINDOW_COLOUR_2}Executive Producer: Bill Levay -STR_2911 :{WINDOW_COLOUR_2}Senior Marketing Product Manager: Scott Triola -STR_2912 :{WINDOW_COLOUR_2}V.P. of Product Development: Scott Walker -STR_2913 :{WINDOW_COLOUR_2}General Manager: John Hurlbut -STR_2914 :{WINDOW_COLOUR_2}Director of Quality Assurance: Michael Craighead -STR_2915 :{WINDOW_COLOUR_2}Q.A. Certification Manager: Kurt Boutin -STR_2916 :{WINDOW_COLOUR_2}Q.A. Certification Lead: Mark Huggins -STR_2917 :{WINDOW_COLOUR_2}Testers: Dena Irene Fitzgerald, Scott Rollins, Christopher McPhail +STR_2909 :{WINDOW_COLOUR_2}Producteur en chef : Thomas J. Zahorik +STR_2910 :{WINDOW_COLOUR_2}Producteur exécutif : Bill Levay +STR_2911 :{WINDOW_COLOUR_2}Chef produit marketing senior : Scott Triola +STR_2912 :{WINDOW_COLOUR_2}Vice-Président développement produit : Scott Walker +STR_2913 :{WINDOW_COLOUR_2}Directeur général : John Hurlbut +STR_2914 :{WINDOW_COLOUR_2}Directeur assurance qualité : Michael Craighead +STR_2915 :{WINDOW_COLOUR_2}Directeur certification AQ : Kurt Boutin +STR_2916 :{WINDOW_COLOUR_2}Responsable certification AQ : Mark Huggins +STR_2917 :{WINDOW_COLOUR_2}Testeurs : Dena Irene Fitzgerald, Scott Rollins, Christopher McPhail STR_2918 :{WINDOW_COLOUR_2}Clif McClure, Erik Maramaldi, Erik Jeffery -STR_2919 :{WINDOW_COLOUR_2}Director of Marketing: Ann Marie Bland -STR_2920 :{WINDOW_COLOUR_2}Manager of Creative Services: Steve Martin -STR_2921 :{WINDOW_COLOUR_2}Manager of Editorial & Documentation Services: Elizabeth Mackney -STR_2922 :{WINDOW_COLOUR_2}Graphic Designer: Paul Anselmi -STR_2923 :{WINDOW_COLOUR_2}Copywriter: Kurt Carlson -STR_2924 :{WINDOW_COLOUR_2}Special Thanks to: Peter Matiss -STR_2925 :{WINDOW_COLOUR_2}Engineering Specialist: Ken Edwards -STR_2926 :{WINDOW_COLOUR_2}Engineering Services Manager: Luis Rivas -STR_2927 :{WINDOW_COLOUR_2}Lead Compatibility Analyst: Geoffrey Smith -STR_2928 :{WINDOW_COLOUR_2}Compatibility Analysts: Jason Cordero, Burke McQuinn, Kim Jardin -STR_2929 :{WINDOW_COLOUR_2}Lead Tester: Daniel Frisoli -STR_2930 :{WINDOW_COLOUR_2}Senior Tester: Matt Pantaleoni +STR_2919 :{WINDOW_COLOUR_2}Directeur marketing : Ann Marie Bland +STR_2920 :{WINDOW_COLOUR_2}Responsable services création : Steve Martin +STR_2921 :{WINDOW_COLOUR_2}Responsable services rédaction & documentation : Elizabeth Mackney +STR_2922 :{WINDOW_COLOUR_2}Infographiste : Paul Anselmi +STR_2923 :{WINDOW_COLOUR_2}Rédacteur publicitaire : Kurt Carlson +STR_2924 :{WINDOW_COLOUR_2}Remerciements à : Peter Matiss +STR_2925 :{WINDOW_COLOUR_2}Ingénieur : Ken Edwards +STR_2926 :{WINDOW_COLOUR_2}Responsable services ingénierie : Luis Rivas +STR_2927 :{WINDOW_COLOUR_2}Responsable compatibilité : Geoffrey Smith +STR_2928 :{WINDOW_COLOUR_2}Analystes compatibilité : Jason Cordero, Burke McQuinn, Kim Jardin +STR_2929 :{WINDOW_COLOUR_2}Responsable tests : Daniel Frisoli +STR_2930 :{WINDOW_COLOUR_2}Testeur senior : Matt Pantaleoni STR_2931 :{WINDOW_COLOUR_2} STR_2932 :{WINDOW_COLOUR_2} STR_2933 :{WINDOW_COLOUR_2} @@ -2978,31 +2978,31 @@ STR_2967 : STR_2968 : STR_2969 : STR_2970 : -STR_2971 :Main colour scheme -STR_2972 :Alternative colour scheme 1 -STR_2973 :Alternative colour scheme 2 -STR_2974 :Alternative colour scheme 3 -STR_2975 :{SMALLFONT}{BLACK}Select which colour scheme to change, or paint ride with -STR_2976 :{SMALLFONT}{BLACK}Paint an individual area of this ride using the selected colour scheme -STR_2977 :Staff member name -STR_2978 :Enter new name for this member of staff: -STR_2979 :Can't name staff member... -STR_2980 :Too many banners in game +STR_2971 :Palette de couleurs principale +STR_2972 :Palette de couleurs second. 1 +STR_2973 :Palette de couleurs second. 2 +STR_2974 :Palette de couleurs second. 3 +STR_2975 :{SMALLFONT}{BLACK}Choisir la palette de couleurs à modifier ou peindre l'attraction avec +STR_2976 :{SMALLFONT}{BLACK}Peindre une seule partie de l'attraction avec la palette de couleurs choisie +STR_2977 :Nom de l'employé +STR_2978 :Entrer le nouveau nom de cet employé : +STR_2979 :Impossible de renommer cet employé... +STR_2980 :Trop de bannières dans cette partie STR_2981 :{RED}Accès interdit - - -STR_2982 :Banner text -STR_2983 :Enter new text for this banner: -STR_2984 :Can't set new text for banner... -STR_2985 :Banner -STR_2986 :{SMALLFONT}{BLACK}Change text on banner -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_2992 :Sign text -STR_2993 :Enter new text for this sign: -STR_2994 :{SMALLFONT}{BLACK}Change text on sign -STR_2995 :{SMALLFONT}{BLACK}Demolish this sign +STR_2982 :Texte bannière +STR_2983 :Saisir nouveau texte pour cette bannière : +STR_2984 :Impossible de placer nouveau texte pour la bannière... +STR_2985 :Bannière +STR_2986 :{SMALLFONT}{BLACK}Modifier texte sur la bannière +STR_2987 :{SMALLFONT}{BLACK}Transformer cette bannière en panneau 'Accès interdit' +STR_2988 :{SMALLFONT}{BLACK}Démolir cette bannière +STR_2989 :{SMALLFONT}{BLACK}Choisir couleur principale +STR_2990 :{SMALLFONT}{BLACK}Choisir couleur du texte +STR_2991 :Panneau +STR_2992 :Texte du panneau +STR_2993 :Saisir nouveau texte pour ce panneau : +STR_2994 :{SMALLFONT}{BLACK}Modifier texte sur panneau +STR_2995 :{SMALLFONT}{BLACK}Démolir ce panneau STR_2996 :{BLACK}ABC STR_2997 :{GREY}ABC STR_2998 :{WHITE}ABC @@ -3017,151 +3017,151 @@ STR_3006 :{PALEGOLD}ABC STR_3007 :{LIGHTPINK}ABC STR_3008 :{PEARLAQUA}ABC STR_3009 :{PALESILVER}ABC -STR_3010 :Unable to load file... -STR_3011 :File contains invalid data -STR_3012 :Dodgems beat style -STR_3013 :Fairground organ style -STR_3014 :Roman fanfare style -STR_3015 :Oriental style -STR_3016 :Martian style -STR_3017 :Jungle drums style -STR_3018 :Egyptian style -STR_3019 :Toyland style +STR_3010 :Impossible de charger le fichier.... +STR_3011 :Le fichier contient des données non valides +STR_3012 :Auto-tamponneuse +STR_3013 :Orgue champ de foire +STR_3014 :Fanfare romaine +STR_3015 :Oriental +STR_3016 :Alien +STR_3017 :Tambours de la jungle +STR_3018 :Egyptien +STR_3019 :Jouets par milliers STR_3020 : -STR_3021 :Space style -STR_3022 :Horror style -STR_3023 :Techno style -STR_3024 :Gentle style -STR_3025 :Summer style -STR_3026 :Water style -STR_3027 :Wild west style -STR_3028 :Jurassic style -STR_3029 :Rock style -STR_3030 :Ragtime style -STR_3031 :Fantasy style -STR_3032 :Rock style 2 -STR_3033 :Ice style -STR_3034 :Snow style -STR_3035 :Custom music 1 -STR_3036 :Custom music 2 -STR_3037 :Medieval style -STR_3038 :Urban style -STR_3039 :Organ style -STR_3040 :Mechanical style -STR_3041 :Modern style -STR_3042 :Pirates style -STR_3043 :Rock style 3 -STR_3044 :Candy style -STR_3045 :{SMALLFONT}{BLACK}Select style of music to play -STR_3046 :This ride cannot be modified -STR_3047 :Local authority forbids demolition or modifications to this ride -STR_3048 :Marketing campaigns forbidden by local authority -STR_3049 :Golf hole A -STR_3050 :Golf hole B -STR_3051 :Golf hole C -STR_3052 :Golf hole D -STR_3053 :Golf hole E -STR_3054 :Loading... +STR_3021 :Espace +STR_3022 :Horreur +STR_3023 :Techno +STR_3024 :Tranquille +STR_3025 :Estival +STR_3026 :Aquatique +STR_3027 :Western +STR_3028 :Jurassique +STR_3029 :Rock +STR_3030 :Ragtime +STR_3031 :Imaginaire +STR_3032 :Rock 2 +STR_3033 :Glace +STR_3034 :Neige +STR_3035 :Musique perso 1 +STR_3036 :Musique perso 2 +STR_3037 :Médiéval +STR_3038 :Urbain +STR_3039 :Orgue +STR_3040 :Mécanique +STR_3041 :Moderne +STR_3042 :Pirates +STR_3043 :Rock 3 +STR_3044 :Bonbon-ville +STR_3045 :{SMALLFONT}{BLACK}Choisir style de musique +STR_3046 :Impossible de modifier cette attraction +STR_3047 :Les autorités locales interdisent la démolition ou modification de cette attraction +STR_3048 :Les autorités locales interdisent toute campagne marketing +STR_3049 :Trou de golf A +STR_3050 :Trou de golf B +STR_3051 :Trou de golf C +STR_3052 :Trou de golf D +STR_3053 :Trou de golf E +STR_3054 :Chargement... STR_3055 :Blanc -STR_3056 :Transparent -STR_3057 :{WINDOW_COLOUR_2}Construction Marker: -STR_3058 :Brick walls -STR_3059 :Hedges -STR_3060 :Ice blocks -STR_3061 :Wooden fences -STR_3062 :{SMALLFONT}{BLACK}Standard roller coaster track -STR_3063 :{SMALLFONT}{BLACK}Water channel (track submerged) +STR_3056 :Translucide +STR_3057 :{WINDOW_COLOUR_2}Marque construction : +STR_3058 :Mur de briques +STR_3059 :Haies +STR_3060 :Blocs de glace +STR_3061 :Clôtures en bois +STR_3062 :{SMALLFONT}{BLACK}Voie de montagne russe classique +STR_3063 :{SMALLFONT}{BLACK}Tunnel aquatique (voie engloutie) STR_3064 :Parcs débutants STR_3065 :Parcs moyens STR_3066 :Parcs experts STR_3067 :Parcs {OPENQUOTES}Réels{ENDQUOTES} STR_3068 :Autres parcs -STR_3069 :Top Section -STR_3070 :Slope to Level -STR_3071 :{WINDOW_COLOUR_2}Same price throughout park -STR_3072 :{SMALLFONT}{BLACK}Select whether this price is used throughout the entire park -STR_3073 :{RED}WARNING: Your park rating has dropped below 700 !{NEWLINE}If you haven't raised the park rating in 4 weeks, your park will be closed down -STR_3074 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have 3 weeks to raise the park rating -STR_3075 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have only 2 weeks to raise the park rating, or your park will be closed down -STR_3076 :{RED}FINAL WARNING: Your park rating is still below 700 !{NEWLINE}In just 7 days your park will be closed down unless you can raise the rating -STR_3077 :{RED}CLOSURE NOTICE: Your park has been closed down ! -STR_3078 :Plain entrance -STR_3079 :Wooden entrance -STR_3080 :Canvas tent entrance -STR_3081 :Castle entrance (grey) -STR_3082 :Castle entrance (brown) -STR_3083 :Jungle entrance -STR_3084 :Log cabin entrance -STR_3085 :Classical/Roman entrance -STR_3086 :Abstract entrance -STR_3087 :Snow/Ice entrance -STR_3088 :Pagoda entrance -STR_3089 :Space entrance -STR_3090 :{SMALLFONT}{BLACK}Select style of entrance, exit, and station -STR_3091 :You are not allowed to remove this section! -STR_3092 :You are not allowed to move or modify the station for this ride! -STR_3093 :{WINDOW_COLOUR_2}Favourite: {BLACK}{STRINGID} +STR_3069 :Section supérieure +STR_3070 :Niveau d'inclinaison +STR_3071 :{WINDOW_COLOUR_2}Même tarif dans tout le parc +STR_3072 :{SMALLFONT}{BLACK}Choisir pour appliquer ce tarif à tout le parc +STR_3073 :{RED}AVERTISSEMENT : l'évaluation de votre parc est inférieure à 700 !{NEWLINE}Si elle n'augmente pas d'ici à 4 semaines, votre parc sera fermé +STR_3074 :{RED}AVERTISSEMENT : l'évaluation de votre parc est toujours inférieure à 700 !NEWLINE}Il vous reste 3 semaines pour l'améliorer +STR_3075 :{RED}AVERTISSEMENT : l'évaluation de votre parc est toujours inférieure à 700 !{NEWLINE}Il ne vous reste plus que 2 semaines pour l'améliorer, sous peine de fermeture +STR_3076 :{RED}DERNIER AVERTISSEMENT : l'évaluation de votre parc est toujours inférieure à 700 !{NEWLINE}Si elle n'a pas augmenté dans 7 jours, votre parc sera fermé +STR_3077 :{RED}AVIS DE FERMETURE : votre parc a été fermé ! +STR_3078 :Entrée simple +STR_3079 :Entrée en bois +STR_3080 :Entrée en toile +STR_3081 :Entrée château (gris) +STR_3082 :Entrée château (marron) +STR_3083 :Entrée jungle +STR_3084 :Entrée rondins +STR_3085 :Entrée classique/romaine +STR_3086 :Entrée abstraite +STR_3087 :Entrée neige/glace +STR_3088 :Entrée pagode +STR_3089 :Entrée espace +STR_3090 :{SMALLFONT}{BLACK}Choisir style d'entrée, de sortie et de station +STR_3091 :Interdit de supprimer cette section ! +STR_3092 :Interdit de déplacer ou modifier la station de cette attraction ! +STR_3093 :{WINDOW_COLOUR_2}Préférée : {BLACK}{STRINGID} STR_3094 :N/A -STR_3095 :{WINDOW_COLOUR_2}Lift hill chain speed: +STR_3095 :{WINDOW_COLOUR_2}Vitesse remontée : STR_3096 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} -STR_3097 :{SMALLFONT}{BLACK}Select lift hill chain speed -STR_3098 :Can't change lift hill speed... -STR_3099 :{SMALLFONT}{BLACK}Select colour -STR_3100 :{SMALLFONT}{BLACK}Select second colour -STR_3101 :{SMALLFONT}{BLACK}Select third colour -STR_3102 :{SMALLFONT}{BLACK}Re-paint coloured scenery on landscape -STR_3103 :Can't re-paint this... -STR_3104 :{SMALLFONT}{BLACK}List rides -STR_3105 :{SMALLFONT}{BLACK}List shops and stalls -STR_3106 :{SMALLFONT}{BLACK}List information kiosks and other guest facilities +STR_3097 :{SMALLFONT}{BLACK}Choisir vitesse remontée +STR_3098 :Impossible de modifier la vitesse... +STR_3099 :{SMALLFONT}{BLACK}Choisir la couleur +STR_3100 :{SMALLFONT}{BLACK}Choisir la deuxième couleur +STR_3101 :{SMALLFONT}{BLACK}Choisir la troisième couleur +STR_3102 :{SMALLFONT}{BLACK}Repeindre le décor sur le paysage +STR_3103 :Impossible de repeindre ceci... +STR_3104 :{SMALLFONT}{BLACK}Liste des attractions +STR_3105 :{SMALLFONT}{BLACK}Liste des magasins et boutiques +STR_3106 :{SMALLFONT}{BLACK}Liste points info et autres services clientèle STR_3107 :Fermer STR_3108 :Tester STR_3109 :Ouvrir -STR_3110 :{WINDOW_COLOUR_2}Block Sections: {BLACK}{COMMA16} -STR_3111 :{SMALLFONT}{BLACK}Click on design to build it -STR_3112 :{SMALLFONT}{BLACK}Click on design to rename or delete it -STR_3113 :Select a different design -STR_3114 :{SMALLFONT}{BLACK}Go back to design selection window -STR_3115 :{SMALLFONT}{BLACK}Save track design -STR_3116 :{SMALLFONT}{BLACK}Save track design (Not possible until ride has been tested and statistics have been generated) -STR_3117 :{BLACK}Calling mechanic... -STR_3118 :{BLACK}{STRINGID} is heading for the ride -STR_3119 :{BLACK}{STRINGID} is fixing the ride -STR_3120 :{SMALLFONT}{BLACK}Locate nearest available mechanic, or mechanic fixing ride -STR_3121 :Unable to locate mechanic, or all nearby mechanics are busy -STR_3122 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guest -STR_3123 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guests -STR_3124 :Broken {STRINGID} -STR_3125 :{WINDOW_COLOUR_2}Excitement Factor: {BLACK}+{COMMA16}% -STR_3126 :{WINDOW_COLOUR_2}Intensity Factor: {BLACK}+{COMMA16}% -STR_3127 :{WINDOW_COLOUR_2}Nausea Factor: {BLACK}+{COMMA16}% -STR_3128 :Save Track Design -STR_3129 :Save Track Design with Scenery +STR_3110 :{WINDOW_COLOUR_2}Sections blocs : {BLACK}{COMMA16} +STR_3111 :{SMALLFONT}{BLACK}Cliquer sur une conception pour la construire +STR_3112 :{SMALLFONT}{BLACK}Cliquer sur une conception pour la renommer ou la supprimer +STR_3113 :Choisir une autre conception +STR_3114 :{SMALLFONT}{BLACK}Retour à la fenêtre de sélection de la conception +STR_3115 :{SMALLFONT}{BLACK}Sauvegarder voie +STR_3116 :{SMALLFONT}{BLACK}Sauvegarder voie (Possible seulement après test de l'attraction et génération des statistiques) +STR_3117 :{BLACK}Appelle un mécanicien... +STR_3118 :{BLACK}{STRINGID} se dirige vers l'attraction +STR_3119 :{BLACK}{STRINGID} répare l'attraction +STR_3120 :{SMALLFONT}{BLACK}Localiser le mécanicien le plus proche (disponible ou réparant l'attraction) +STR_3121 :Impossible de localiser un mécanicien ou les mécaniciens les plus proches sont tous occupés +STR_3122 :{WINDOW_COLOUR_2}Attraction préférée de {BLACK}{COMMA16} visiteur +STR_3123 :{WINDOW_COLOUR_2}Attraction préférée de {BLACK}{COMMA16} visiteurs +STR_3124 :En panne {STRINGID} +STR_3125 :{WINDOW_COLOUR_2}Indice d'excitation : {BLACK}+{COMMA16}% +STR_3126 :{WINDOW_COLOUR_2}Indice d'intensité : {BLACK}+{COMMA16}% +STR_3127 :{WINDOW_COLOUR_2}Indice de nausée : {BLACK}+{COMMA16}% +STR_3128 :Sauvegarder voie +STR_3129 :Sauvegarder voie avec décor STR_3130 :Sauvegarder STR_3131 :Annuler -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) -STR_3135 :{RED}(Vehicle design unavailable - Ride performance may be affected) -STR_3136 :Warning: This design will be built with an alternative vehicle type and may not perform as expected -STR_3137 :Select Nearby Scenery -STR_3138 :Reset Selection -STR_3139 :Cable lift unable to work in this operating mode -STR_3140 :Cable lift hill must start immediately after station -STR_3141 :Multi-circuit per ride not possible with cable lift hill -STR_3142 :{WINDOW_COLOUR_2}Capacity: {BLACK}{STRINGID} -STR_3143 :{SMALLFONT}{BLACK}Show people on map -STR_3144 :{SMALLFONT}{BLACK}Show rides and stalls on map -STR_3145 :{SMALLFONT}{BLACK}Scroll {STRINGID} left -STR_3146 :{SMALLFONT}{BLACK}Scroll {STRINGID} right -STR_3147 :{SMALLFONT}{BLACK}Scroll {STRINGID} left fast -STR_3148 :{SMALLFONT}{BLACK}Scroll {STRINGID} right fast -STR_3149 :{SMALLFONT}{BLACK}Scroll {STRINGID} left/right -STR_3150 :{SMALLFONT}{BLACK}Scroll {STRINGID} up -STR_3151 :{SMALLFONT}{BLACK}Scroll {STRINGID} down -STR_3152 :{SMALLFONT}{BLACK}Scroll {STRINGID} up fast -STR_3153 :{SMALLFONT}{BLACK}Scroll {STRINGID} down fast -STR_3154 :{SMALLFONT}{BLACK}Scroll {STRINGID} up/down +STR_3132 :{BLACK}Cliquer sur des objets de décor pour les sauvegarder avec la voie... +STR_3133 :Impossible de construire ceci sur une pente +STR_3134 :{RED}(La conception comprend un décor non disponible) +STR_3135 :{RED}(Conception véhicule non disponible - les performances de l'attraction pourraient en pâtir) +STR_3136 :Attention: cette construction sera fabriquée avec un autre type de véhicule et ses performances pourraient donc être différentes de celles prévues initialement +STR_3137 :Choisir décor proche +STR_3138 :Recomm. sélection +STR_3139 :Impossible d'appliquer une remontée au câble dans ce mode de fonctionnement +STR_3140 :La remontée au câble doit commencer immédiatement à la sortie de la station +STR_3141 :La remontée au câble n'est pas compatible avec une attraction multi-parcours +STR_3142 :{WINDOW_COLOUR_2}Capacité : {BLACK}{STRINGID} +STR_3143 :{SMALLFONT}{BLACK}Voir les personnes sur la carte +STR_3144 :{SMALLFONT}{BLACK}Voir les attractions et boutiques sur la carte +STR_3145 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} à gauche +STR_3146 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} à droite +STR_3147 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} à gauche vite +STR_3148 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} à droite vite +STR_3149 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} à gauche/à droite +STR_3150 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} en haut +STR_3151 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} en bas +STR_3152 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} en haut vite +STR_3153 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} en bas vite +STR_3154 :{SMALLFONT}{BLACK}Faire défiler {STRINGID} en haut/en bas STR_3155 : STR_3156 : STR_3157 :plan @@ -3169,28 +3169,28 @@ STR_3158 :graphique STR_3159 :liste STR_3160 : STR_3161 : -STR_3162 :Unable to allocate enough memory -STR_3163 :Installing new data: -STR_3164 :{BLACK}{COMMA16} selected (maximum {COMMA16}) +STR_3162 :Impossible d'allouer assez de mémoire +STR_3163 :Installation des nouvelles données : +STR_3164 :{BLACK}{COMMA16} sélectionné (maximum {COMMA16}) STR_3165 : STR_3166 :{BLACK}(ID: -STR_3167 :{WINDOW_COLOUR_2}Inclut: {BLACK}{COMMA16} objets -STR_3168 :{WINDOW_COLOUR_2}Texte: {BLACK}{STRINGID} -STR_3169 :Data for the following object not found: -STR_3170 :Not enough space for graphics -STR_3171 :Too many objects of this type selected -STR_3172 :The following object must be selected first: {STRING} -STR_3173 :This object is currently in use -STR_3174 :This object is required by another object -STR_3175 :This object is always required -STR_3176 :Unable to select this object -STR_3177 :Unable to de-select this object -STR_3178 :At least one path object must be selected -STR_3179 :At least one ride vehicle/attraction object must be selected -STR_3180 :Invalid selection of objects -STR_3181 :Sélection d'object - {STRINGID} -STR_3182 :Park entrance type must be selected -STR_3183 :Water type must be selected +STR_3167 :{WINDOW_COLOUR_2}Inclus : {BLACK}{COMMA16} objets +STR_3168 :{WINDOW_COLOUR_2}Texte : {BLACK}{STRINGID} +STR_3169 :Données de l'objet suivant non trouvées : +STR_3170 :Espace insuffisant pour les graphiques +STR_3171 :Trop d'objets de ce type sélectionnés +STR_3172 :L'objet suivant doit d'abord être sélectionné : {STRING} +STR_3173 :Cet objet est déjà utilisé +STR_3174 :Cet objet est requis par un autre objet +STR_3175 :Cet objet est toujours requis +STR_3176 :Impossible de sélectionner cet objet +STR_3177 :Impossible de déselectionner cet objet +STR_3178 :Au moins un objet d'allée doit être sélectionné +STR_3179 :Au moins un objet de véhicule ou d'attraction doit être sélectionné +STR_3180 :Sélection d'objets non valide +STR_3181 :Sélection d'objet - {STRINGID} +STR_3182 :Le type d'entrée de parc doit être sélectionné +STR_3183 :Le type d'étendue d'eau doit être sélectionné STR_3184 :Véhicules/Attractions STR_3185 :Petit décor STR_3186 :Grand décor @@ -3201,11 +3201,11 @@ STR_3190 :Suppléments allées STR_3191 :Groupes de décor STR_3192 :Entrée du parc STR_3193 :Etendue d'eau -STR_3194 :Scenario Description +STR_3194 :Description du scénario STR_3195 :Liste d'inventions -STR_3196 :{WINDOW_COLOUR_2}Groupe de recherche: {BLACK}{STRINGID} -STR_3197 :{WINDOW_COLOUR_2}Eléments pré-inventés au début d'une partie: -STR_3198 :{WINDOW_COLOUR_2}Eléments à inventer pendant la partie: +STR_3196 :{WINDOW_COLOUR_2}Groupe de recherche : {BLACK}{STRINGID} +STR_3197 :{WINDOW_COLOUR_2}Eléments pré-inventés au début d'une partie : +STR_3198 :{WINDOW_COLOUR_2}Eléments à inventer pendant la partie : STR_3199 :Choix aléatoire STR_3200 :{SMALLFONT}{BLACK}Définissez de manière aléatoire la liste d'éléments à inventer pendant la partie STR_3201 :Sélection des objets @@ -3214,15 +3214,15 @@ STR_3203 :Liste d'inventions STR_3204 :Sélection des options STR_3205 :Selection d'objectif STR_3206 :Sauvegarder scénario -STR_3207 :Roller Coaster Designer -STR_3208 :Track Designs Manager -STR_3209 :Retour étape précédente: -STR_3210 :Passer à l'étape suivante: -STR_3211 :{WINDOW_COLOUR_2}Taille carte: +STR_3207 :Concepteur de montagnes russes +STR_3208 :Gestionnaire de voies +STR_3209 :Retour étape précédente : +STR_3210 :Passer à l'étape suivante : +STR_3211 :{WINDOW_COLOUR_2}Taille carte : STR_3212 :{POP16}{COMMA16} x {PUSH16}{COMMA16} STR_3213 :Impossible de diminuer davantage la taille de la carte STR_3214 :Impossible d'augmenter davantage la taille de le carte -STR_3215 :Too close to edge of map +STR_3215 :Trop proche du bord de la carte STR_3216 :{SMALLFONT}{BLACK}Choisir terrain du parc etc. STR_3217 :Terrain du parc STR_3218 :Droits de constr. du parc @@ -3232,13 +3232,13 @@ STR_3221 :{SMALLFONT}{BLACK}Définir le terrain sur lequel s'étend le parc STR_3222 :{SMALLFONT}{BLACK}Définir les droits de construction exclusifs du parc STR_3223 :{SMALLFONT}{BLACK}Définir le terrain disponible à l'achat STR_3224 :{SMALLFONT}{BLACK}Définir les droits de construction disponibles à l'achat -STR_3225 :{SMALLFONT}{BLACK}Toggle on/off building a random cluster of objects around the selected position +STR_3225 :{SMALLFONT}{BLACK}Activer/Désactiver la formation aléatoire d'un ensemble d'objets autour de la position sélectionnée STR_3226 :{SMALLFONT}{BLACK}Construire entrée parc -STR_3227 :Trop d'entrée de parc +STR_3227 :Trop d'entrée de parc ! STR_3228 :{SMALLFONT}{BLACK}Définir position de départ pour les visiteurs -STR_3229 :Block Brakes cannot be used directly after station -STR_3230 :Block Brakes cannot be used directly after each other -STR_3231 :Block Brakes cannot be used directly after the top of this lift hill +STR_3229 :Les freins de blocs ne peuvent être posés directement après la station +STR_3230 :Les freins de blocs ne peuvent être posés les uns derrière les autres +STR_3231 :Les freins de blocs ne peuvent être posés directement après le sommet d'une remontée STR_3232 :Options - Finances STR_3233 :Options - Visiteurs STR_3234 :Options - Parc @@ -3247,107 +3247,107 @@ STR_3236 :{SMALLFONT}{BLACK}Voir les options des visiteurs STR_3237 :{SMALLFONT}{BLACK}Voir les options du parc STR_3238 :Pas d'argent STR_3239 :{SMALLFONT}{BLACK}Faire de ce parc un parc 'sans argent' sans restriction financière -STR_3240 :{WINDOW_COLOUR_2}Argent initial: -STR_3241 :{WINDOW_COLOUR_2}Emprunt initial: -STR_3242 :{WINDOW_COLOUR_2}Emprunt maximum: -STR_3243 :{WINDOW_COLOUR_2}Taux d'int. annuel: +STR_3240 :{WINDOW_COLOUR_2}Argent initial : +STR_3241 :{WINDOW_COLOUR_2}Emprunt initial : +STR_3242 :{WINDOW_COLOUR_2}Emprunt maximum : +STR_3243 :{WINDOW_COLOUR_2}Taux d'int. annuel : STR_3244 :Interdire campagnes marketing STR_3245 :{SMALLFONT}{BLACK}Interdire la publicité, les opérations promotionnelles et autres campagnes marketing STR_3246 :{WINDOW_COLOUR_2}{CURRENCY} STR_3247 :{WINDOW_COLOUR_2}{COMMA16}% STR_3248 :Impossible d'augmenter davantage la somme d'argent initiale ! STR_3249 :Impossible de diminuer davantage la somme d'argent initiale ! -STR_3250 :Can't increase initial loan any further! -STR_3251 :Can't reduce initial loan any further! -STR_3252 :Can't increase maximum loan size any further! -STR_3253 :Can't reduce maximum loan size any further! -STR_3254 :Can't increase interest rate any further! -STR_3255 :Can't reduce interest rate any further! -STR_3256 :Guests prefer less intense rides -STR_3257 :{SMALLFONT}{BLACK}Select whether guests should generally prefer less intense rides only -STR_3258 :Guests prefer more intense rides -STR_3259 :{SMALLFONT}{BLACK}Select whether guests should generally prefer more intense rides only -STR_3260 :{WINDOW_COLOUR_2}Argent par visiteur (moy.): -STR_3261 :{WINDOW_COLOUR_2}Bonheur initial: -STR_3262 :{WINDOW_COLOUR_2}Faim initiale: -STR_3263 :{WINDOW_COLOUR_2}Soif initiale: -STR_3264 :Impossible d'augmenter davantage! -STR_3265 :Impossible de diminuer davantage! -STR_3266 :{SMALLFONT}{BLACK}Select how this park charges for entrance and rides +STR_3250 :Impossible d'augmenter davantage l'emprunt initial ! +STR_3251 :Impossible de diminuer davantage l'emprunt initial ! +STR_3252 :Impossible d'augmenter davantage l'emprunt maximum ! +STR_3253 :Impossible de diminuer davantage l'emprunt maximum ! +STR_3254 :Impossible d'augmenter davantage le taux d'intérêts ! +STR_3255 :Impossible de diminuer davantage le taux d'intérêts ! +STR_3256 :Attr. moins dures pour visiteurs +STR_3257 :{SMALLFONT}{BLACK}Choisir si vous souhaitez que les visiteurs préfèrent des attractions moins intenses +STR_3258 :Attr. plus dures pour visiteurs +STR_3259 :{SMALLFONT}{BLACK}Choisir si vous souhaitez que les visiteurs préfèrent des attr. plus intenses +STR_3260 :{WINDOW_COLOUR_2}Argent par visiteur (moy.) : +STR_3261 :{WINDOW_COLOUR_2}Bonheur initial : +STR_3262 :{WINDOW_COLOUR_2}Faim initiale : +STR_3263 :{WINDOW_COLOUR_2}Soif initiale : +STR_3264 :Impossible d'augmenter davantage ! +STR_3265 :Impossible de diminuer davantage ! +STR_3266 :{SMALLFONT}{BLACK}Choisir le tarif d'entrée et le tarif des attractions de ce parc STR_3267 :Interdire le déracinement d'arbres -STR_3268 :{SMALLFONT}{BLACK}Forbid tall trees being removed +STR_3268 :{SMALLFONT}{BLACK}Empêcher que les grands arbres soient enlevés STR_3269 :Interdire les modifications du paysage -STR_3270 :{SMALLFONT}{BLACK}Forbid any changes to the landscape +STR_3270 :{SMALLFONT}{BLACK}Empêcher toute modification du paysage STR_3271 :Interdire les constructions hautes -STR_3272 :{SMALLFONT}{BLACK}Forbid any tall construction -STR_3273 :Niveau de difficulté supérieur pour fréquentation -STR_3274 :{SMALLFONT}{BLACK}Make the park rating value more challenging -STR_3275 :Guest generation higher difficult level -STR_3276 :{SMALLFONT}{BLACK}Make it more difficult to attract guests to the park -STR_3277 :{WINDOW_COLOUR_2}Coût d'achat de terrain: -STR_3278 :{WINDOW_COLOUR_2}Coût d'achat droits de constr.: -STR_3279 :Free park entry / Pay per ride -STR_3280 :Pay to enter park / Free rides -STR_3281 :{WINDOW_COLOUR_2}Prix d'entrée: +STR_3272 :{SMALLFONT}{BLACK}Empêcher les constructions de grande envergure +STR_3273 :Niveau de difficulté supérieur pour évaluation du parc +STR_3274 :{SMALLFONT}{BLACK}Rendre l'évaluation du parc plus ardue +STR_3275 :Niveau de difficulté supérieur pour fréquentation +STR_3276 :{SMALLFONT}{BLACK}Rendre la fréquentation du parc plus difficile +STR_3277 :{WINDOW_COLOUR_2}Coût d'achat de terrain : +STR_3278 :{WINDOW_COLOUR_2}Coût d'achat droits de constr. : +STR_3279 :Entrée gratuite/Attr. payantes +STR_3280 :Entrée payante/Attr. gratuites +STR_3281 :{WINDOW_COLOUR_2}Prix d'entrée : STR_3282 :{SMALLFONT}{BLACK}Choisir objectif et nom du parc -STR_3283 :{SMALLFONT}{BLACK}Select rides to be preserved +STR_3283 :{SMALLFONT}{BLACK}Choisir attractions à protéger STR_3284 :Sélection des objectifs -STR_3285 :Preserved Rides -STR_3286 :{SMALLFONT}{BLACK}Selecter un objectif pour ce scénario -STR_3287 :{WINDOW_COLOUR_2}Objectif: -STR_3288 :{SMALLFONT}{BLACK}Selecter climat -STR_3289 :{WINDOW_COLOUR_2}Climat: +STR_3285 :Attractions protégées +STR_3286 :{SMALLFONT}{BLACK}Selectionner un objectif pour ce scénario +STR_3287 :{WINDOW_COLOUR_2}Objectif : +STR_3288 :{SMALLFONT}{BLACK}Selectionner climat +STR_3289 :{WINDOW_COLOUR_2}Climat : STR_3290 :Frais et humide STR_3291 :Chaud STR_3292 :Chaud et sec STR_3293 :Froid STR_3294 :Modifier... -STR_3295 :{SMALLFONT}{BLACK}Change name of park -STR_3296 :{SMALLFONT}{BLACK}Change name of scenario -STR_3297 :{SMALLFONT}{BLACK}Change detail notes about park / scenario -STR_3298 :{WINDOW_COLOUR_2}Nom du parc: {BLACK}{STRINGID} -STR_3299 :{WINDOW_COLOUR_2}Park/Scenario Details: -STR_3300 :{WINDOW_COLOUR_2}Nom du scénario: {BLACK}{STRINGID} -STR_3301 :{WINDOW_COLOUR_2}Date objectif: +STR_3295 :{SMALLFONT}{BLACK}Modifier nom du parc +STR_3296 :{SMALLFONT}{BLACK}Modifier nom du scénario +STR_3297 :{SMALLFONT}{BLACK}Modifier détails sur le parc / scénario +STR_3298 :{WINDOW_COLOUR_2}Nom du parc : {BLACK}{STRINGID} +STR_3299 :{WINDOW_COLOUR_2}Détails parc/scén. : +STR_3300 :{WINDOW_COLOUR_2}Nom du scénario : {BLACK}{STRINGID} +STR_3301 :{WINDOW_COLOUR_2}Date objectif : STR_3302 :{WINDOW_COLOUR_2}{MONTHYEAR} -STR_3303 :{WINDOW_COLOUR_2}Nombre de visiteurs: -STR_3304 :{WINDOW_COLOUR_2}Valeur du parc: -STR_3305 :{WINDOW_COLOUR_2}Monthly income: -STR_3306 :{WINDOW_COLOUR_2}Bénéfice mensuel: -STR_3307 :{WINDOW_COLOUR_2}Minimum length: -STR_3308 :{WINDOW_COLOUR_2}Excitement rating: +STR_3303 :{WINDOW_COLOUR_2}Nombre de visiteurs : +STR_3304 :{WINDOW_COLOUR_2}Valeur du parc : +STR_3305 :{WINDOW_COLOUR_2}Revenu mensuel : +STR_3306 :{WINDOW_COLOUR_2}Bénéfice mensuel : +STR_3307 :{WINDOW_COLOUR_2}Longueur minimum : +STR_3308 :{WINDOW_COLOUR_2}Indice d'excitation : STR_3309 :{WINDOW_COLOUR_2}{COMMA16} STR_3310 :{WINDOW_COLOUR_2}{LENGTH} STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} -STR_3312 :{WINDOW_COLOUR_2}Rides/attractions under a preservation order: -STR_3313 :Nom du scénario: -STR_3314 :Enter name for scenario: -STR_3315 :Park/Scenario Details -STR_3316 :Décrire ce scénario: +STR_3312 :{WINDOW_COLOUR_2}Attractions protégées : +STR_3313 :Nom du scénario +STR_3314 :Saisir le nom du scénario : +STR_3315 :Détails parc/scénario +STR_3316 :Décrire ce scénario : STR_3317 :Pas de détails -STR_3318 :{SMALLFONT}{BLACK}Select which group this scenario appears in -STR_3319 :{WINDOW_COLOUR_2}Scenario Group: -STR_3320 :Unable to save scenario file... -STR_3321 :New objects installed successfully -STR_3322 :{WINDOW_COLOUR_2}Objectif: {BLACK}{STRINGID} -STR_3323 :Missing object data, ID: -STR_3324 :Requires Add-On Pack: -STR_3325 :Requires an Add-On Pack +STR_3318 :{SMALLFONT}{BLACK}Choisir le groupe de ce scénario +STR_3319 :{WINDOW_COLOUR_2}Groupe scénario : +STR_3320 :Impossible de sauvegarder le fichier de scénario... +STR_3321 :Installation nouveaux objets réussie +STR_3322 :{WINDOW_COLOUR_2}Objectif : {BLACK}{STRINGID} +STR_3323 :Données objet manquantes, ID : +STR_3324 :Requiert un add-on : +STR_3325 :Requiert un add-on STR_3326 :{WINDOW_COLOUR_2}(aucune image) -STR_3327 :Starting positions for people not set -STR_3328 :Can't advance to next editor stage... -STR_3329 :Park entrance not yet built -STR_3330 :Park must own some land -STR_3331 :Path from park entrance to map edge either not complete or too complex - Path must be single-width with as few junctions and corners as possible -STR_3332 :Park entrance is the wrong way round or has no path leading to the map edge -STR_3333 :Export plug-in objects with saved games -STR_3334 :{SMALLFONT}{BLACK}Select whether to save any additional plug-in object data required (add-in data not supplied with the main product) in saved game or scenario files, allowing them to be loaded by someone who doesn't have the additional object data -STR_3335 :Roller Coaster Designer - Select Ride Types & Vehicles -STR_3336 :Track Designs Manager - Select Ride Type +STR_3327 :Positions de départ non définies +STR_3328 :Impossible de passer à l'étape suivante de l'éditeur... +STR_3329 :Entrée du parc pas encore construite +STR_3330 :Le parc doit posséder du terrain +STR_3331 :Allée depuis l'entrée du parc jusqu'au bord de la carte incomplète ou trop complexe. Une allée doit être simple avec aussi peu d'intersections et de virages que possible +STR_3332 :L'entrée du parc est dans le mauvais sens ou ne possède pas d'allée conduisant au bord de la carte +STR_3333 :Exporter objets plug-ins avec parties sauvegardées +STR_3334 :{SMALLFONT}{BLACK}Choisir si vous souhaitez sauvegarder d'autres données requises pour objets plug-in (données supplémentaires non fournies avec ce produit) dans des fichiers de sauvegarde ou de scénario, afin qu'une personne ne disposant pas des données additionnelles puisse les charger +STR_3335 :Concepteur de montagnes russes - Choisir type d'attraction et de véhicule +STR_3336 :Gestionnaire de voies - Choisir type d'attraction STR_3337 : -STR_3338 :{BLACK}Dispositions personnalisées -STR_3339 :{BLACK}{COMMA16} design disponible, ou disposition personnalisée -STR_3340 :{BLACK}{COMMA16} designs disponibles, ou dispositions personnalisées +STR_3338 :{BLACK}Conception personnalisée +STR_3339 :{BLACK}{COMMA16} conception disponible, ou conception personnalisée +STR_3340 :{BLACK}{COMMA16} conceptions disponibles, ou conception personnalisée STR_3341 :{SMALLFONT}{BLACK}Outils STR_3342 :Editeur de scénario STR_3343 :Convertir partie sauvegardée en scénario @@ -3377,7 +3377,7 @@ STR_3366 :{BLACK}= Attraction STR_3367 :{BLACK}= Stand de nourriture STR_3368 :{BLACK}= Stand de boissons STR_3369 :{BLACK}= Stand de souvenirs -STR_3370 :{BLACK}= Kiosque aux informations +STR_3370 :{BLACK}= Kiosque d'information STR_3371 :{BLACK}= Infirmerie STR_3372 :{BLACK}= D.A.B. STR_3373 :{BLACK}= Toilettes @@ -3400,7 +3400,7 @@ STR_3389 :Impossible de choisir plus d'objets du décor... STR_3390 :Trop d'objets sélectionnés STR_3391 :{SMALLFONT}{BLACK}Voici notre parc. Voyons ça d'un peu plus près... STR_3392 :{SMALLFONT}{BLACK}Pour déplacer la vue, maintenez le bouton DROIT de la souris enfoncé puis bouger la souris... -STR_3393 :{SMALLFONT}{BLACK}Pour élargir la vue, faites un zoom arrière à l'aide de l'icone placé en haut de l'écran... +STR_3393 :{SMALLFONT}{BLACK}Pour élargir la vue, faites un zoom arrière à l'aide de l'icône placée en haut de l'écran... STR_3394 :{SMALLFONT}{BLACK}Vous pouvez aussi faire pivoter la vue par tranches de 90 degrés... STR_3395 :{SMALLFONT}{BLACK}Difficile d'entamer une construction avec une vue aussi large. Faites un zoom avant... STR_3396 :{SMALLFONT}{BLACK}Construisons d'abord une simple attraction... @@ -3418,7 +3418,7 @@ STR_3407 :{SMALLFONT}{BLACK}Tout d'abord on doit choisir le point de départ. STR_3408 :{SMALLFONT}{BLACK}La section du circuit que nous venons de construire est la 'station', cela permet aux visiteurs de monter et descendre de l'attraction... STR_3409 :{SMALLFONT}{BLACK}Nous allons étendre cette station en ajoutant quelques blocs... STR_3410 :{SMALLFONT}{BLACK}Les icônes en haut de la fenêtre de construction vous permet les différentes parties du circuit à ajouter... -STR_3411 :{SMALLFONT}{BLACK}Nous choissions une courbe vers la gauche... +STR_3411 :{SMALLFONT}{BLACK}Nous choisissons une courbe vers la gauche... STR_3412 :{SMALLFONT}{BLACK}La courbe n'est pas encore construite, mais l'image fantôme blanche indique où elle le sera. Cliquez sur l'icône 'construire ceci' pour construire le bloc... STR_3413 :{SMALLFONT}{BLACK}Maintenant nous voulons construire un tracé droit, donc on clique sur l'icône 'tracé droit'... STR_3414 :{SMALLFONT}{BLACK}Maintenant que le circuit est terminé, nous devons construire l'entrée et la sortie... @@ -3437,7 +3437,7 @@ STR_3426 :{SMALLFONT}{BLACK}La montée est terminée - Maintenant la descente STR_3427 :{SMALLFONT}{BLACK}Ces courbes sont une mauvaise idée - Les visiteurs vont être projetés sur le côté de leur siège par les forces G latérales pendant que le train tourne... STR_3428 :{SMALLFONT}{BLACK}Pencher les courbes améliorera l'attraction - Les visiteurs auront leur dos collé aux sièges plutôt que d'être projetés sur les côtés... STR_3429 :{SMALLFONT}{BLACK}Non - Ca ne fonctionnera pas ! Regardez les marques de hauteur - La deuxième montée est plus grande que la première... -STR_3430 :{SMALLFONT}{BLACK}Pour être sûr que le train réussise le circuit, chaque montée doit être légèrement plus petite que la précédente... +STR_3430 :{SMALLFONT}{BLACK}Pour être sûr que le train réussisse le circuit, chaque montée doit être légèrement plus petite que la précédente... STR_3431 :{SMALLFONT}{BLACK}C'est mieux - Notre train pourra passer cette montée ! Ajoutons des voies plus tordues... STR_3432 :{SMALLFONT}{BLACK}Nous devons freiner le train avant la courbe finale et la station, ajoutons quelques freins... STR_3433 :{SMALLFONT}{BLACK}Et finalement nous rajouterons des 'freins de blocs', cela permettra à 2 trains de parcourir le circuit en sécurité... @@ -3445,382 +3445,382 @@ STR_3434 :{SMALLFONT}{BLACK}Testons l'attraction et regardons si tout fonctio STR_3435 :{SMALLFONT}{BLACK}Génial - Tout fonctionne ! Ajoutons la zone d'attente et l'allée de sortie pour que les visiteurs puissent y accéder... STR_3436 :{SMALLFONT}{BLACK}En attendant les premiers passagers, on va personnaliser un peu l'attraction... STR_3437 :{SMALLFONT}{BLACK}Nettoyer grande zone de décor du paysage -STR_3438 :Impossible d'effacer tout le décor d'içi... +STR_3438 :Impossible d'effacer tout le décor de cette zone... STR_3439 :Effacer décor STR_3440 :Page 1 STR_3441 :Page 2 STR_3442 :Page 3 STR_3443 :Page 4 STR_3444 :Page 5 -STR_3445 :Définir Zone de Patrouille -STR_3446 :Annuler Zone de Patrouille +STR_3445 :Définir zone de Patrouille +STR_3446 :Annuler zone de Patrouille # New strings, cleaner STR_5120 :Finances -STR_5121 :Research -STR_5122 :Select rides by track type (like in RCT1) +STR_5121 :Recherche +STR_5122 :Choisir attractions selon type de voie (comme RCT1) STR_5123 :Renouveler attr. STR_5124 : -STR_5125 :All destructable -STR_5126 :Random title music -STR_5127 :{SMALLFONT}{BLACK}Disable land elevation -STR_5128 :Selection size -STR_5129 :Enter selection size between {COMMA16} and {COMMA16} -STR_5130 :Map size -STR_5131 :Enter map size between {COMMA16} and {COMMA16} -STR_5132 :Fix all rides -STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights -STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights -STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights -STR_5136 :Land rights -STR_5137 :Allow lift hill and launch speeds{NEWLINE}up to {VELOCITY} +STR_5125 :Tout destructible +STR_5126 :Musique aléatoire +STR_5127 :{SMALLFONT}{BLACK}Outil pinceau de surface{NEWLINE}Peint le terrain au lieu de changer l'élévation +STR_5128 :Taille de sélection +STR_5129 :Saisir une taille de sélection entre {COMMA16} et {COMMA16} +STR_5130 :Taille de la carte +STR_5131 :Saisir une taille de carte entre {COMMA16} et {COMMA16} +STR_5132 :Réparer attractions +STR_5133 :{SMALLFONT}{BLACK}Ajuster zone achat + petite +STR_5134 :{SMALLFONT}{BLACK}Ajuster zone achat + grande +STR_5135 :{SMALLFONT}{BLACK}Acheter du terrain et des droits de construction +STR_5136 :Achat +STR_5137 :Autoriser remontées et vitesse de {NEWLINE}lancement jusqu'à {VELOCITY} STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} -STR_5140 :Disable brakes failure -STR_5141 :Disable all breakdowns -STR_5142 :Normal Speed -STR_5143 :Quick Speed -STR_5144 :Fast Speed -STR_5145 :Turbo Speed -STR_5146 :Hyper Speed -STR_5147 :Cheats -STR_5148 :{SMALLFONT}{BLACK}Change the game speed -STR_5149 :{SMALLFONT}{BLACK}Open the cheats window -STR_5150 :Enable debugging tools +STR_5140 :Désactiver pannes de freins +STR_5141 :Désactiver toutes les pannes +STR_5142 :Vitesse Normale +STR_5143 :Vitesse Rapide +STR_5144 :Vitesse Très Rapide +STR_5145 :Vitesse Turbo +STR_5146 :Vitesse Hyper +STR_5147 :Triche +STR_5148 :{SMALLFONT}{BLACK}Changer la vitesse du jeu +STR_5149 :{SMALLFONT}{BLACK}Ouvrir la fenêtre de triche +STR_5150 :Activer les outils de débogage #Thousands separator -STR_5151 :. +STR_5151 : #Decimal separator STR_5152 :, STR_5153 :Thèmes... -STR_5154 :Hardware display -STR_5155 :Allow testing of unfinished tracks -STR_5156 :{SMALLFONT}{BLACK}Allows testing of most ride types even when the track is unfinished, does not apply to block sectioned modes -STR_5157 :Unlock all prices -STR_5158 :Quit to menu +STR_5154 :Affichage matériel +STR_5155 :Autoriser le test de circuits incomplets +STR_5156 :{SMALLFONT}{BLACK}Autorise le test de la plupart des attractions même si le circuit est incomplet. Ne s'applique pas aux modes à blocs de voie. +STR_5157 :Débloquer tous les prix +STR_5158 :Retour au menu STR_5159 :Quitter OpenRCT2 -STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, an {POP16}{COMMA16} -STR_5161 :Date Format: -STR_5162 :Day/Month/Year -STR_5163 :Month/Day/Year -STR_5164 :Twitch Channel name -STR_5165 :Name peeps after followers -STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers -STR_5167 :Track follower peeps -STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers -STR_5169 :Name peeps after people in Twitch chat -STR_5170 :{SMALLFONT}{BLACK}Will name peeps after people in Twitch chat -STR_5171 :Track chat peeps -STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants -STR_5173 :Pull Twitch chat as news -STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications -STR_5175 :Input the name of your Twitch channel -STR_5176 :Enable Twitch integration -STR_5177 :Fullscreen mode: -STR_5178 :{SMALLFONT}{BLACK}Show financial cheats -STR_5179 :{SMALLFONT}{BLACK}Show guest cheats -STR_5180 :{SMALLFONT}{BLACK}Show park cheats -STR_5181 :{SMALLFONT}{BLACK}Show ride cheats +STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, année {POP16}{COMMA16} +STR_5161 :Format de date : +STR_5162 :Jour/Mois/Année +STR_5163 :Mois/Jour/Année +STR_5164 :Nom de la chaîne Twitch +STR_5165 :Nommer les visiteurs d'après les abonnés +STR_5166 :{SMALLFONT}{BLACK}Renommera les visiteurs d'après les abonnés à la chaîne Twitch +STR_5167 :Suivre les visiteurs abonnés +STR_5168 :{SMALLFONT}{BLACK}Activera les informations de suivi pour les visiteurs nommés d'après les abonnés à la chaîne Twitch +STR_5169 :Nommer les visiteurs d'après les participants du chat +STR_5170 :{SMALLFONT}{BLACK}Renommera les visiteurs d'après les participants du chat Twitch +STR_5171 :Suivre les visiteurs du chat +STR_5172 :{SMALLFONT}{BLACK}Activera les informations de suivi pour les visiteurs nommés d'après les participants du chat Twitch +STR_5173 :Passer les messages Twitch dans les actualités +STR_5174 :{SMALLFONT}{BLACK}Utilisera les messages de chat Twitch précédés de !news pour les notifications durant le jeu +STR_5175 :Saisir le nom de votre chaîne Twitch +STR_5176 :Activer l'intégration Twitch +STR_5177 :Mode plein écran : +STR_5178 :{SMALLFONT}{BLACK}Afficher les options de triche financière +STR_5179 :{SMALLFONT}{BLACK}Afficher les options de triche des visiteurs +STR_5180 :{SMALLFONT}{BLACK}Afficher les options de triche du parc +STR_5181 :{SMALLFONT}{BLACK}Afficher les options de triche des attractions STR_5182 :{INT32} -STR_5183 :Base height -STR_5184 :Enter base height between {COMMA16} and {COMMA16} -STR_5185 :Water level -STR_5186 :Enter water level between {COMMA16} and {COMMA16} +STR_5183 :Hauteur de base +STR_5184 :Entrez une hauter de base entre {COMMA16} et {COMMA16} +STR_5185 :Niveau de l'eau +STR_5186 :Entrez un niveau d'eau entre {COMMA16} et {COMMA16} STR_5187 :Finances -STR_5188 :New Campaign -STR_5189 :Research -STR_5190 :Map -STR_5191 :Viewport -STR_5192 :Recent News -STR_5193 :Land -STR_5194 :Water -STR_5195 :Clear Scenery -STR_5196 :Land Rights -STR_5197 :Scenery -STR_5198 :Footpath -STR_5199 :Ride Construction -STR_5200 :Track Design Place -STR_5201 :New Ride -STR_5202 :Track Design Selection +STR_5188 :Nouvelle campagne +STR_5189 :Recherche +STR_5190 :Carte +STR_5191 :Vue supplémentaire +STR_5192 :Nouvelles récentes +STR_5193 :Terre +STR_5194 :Eau +STR_5195 :Nettoyer paysage +STR_5196 :Achat de terrain +STR_5197 :Décor +STR_5198 :Allées +STR_5199 :Construction d'attractions +STR_5200 :Emplacement de conception de voie +STR_5201 :Nouvelle attraction +STR_5202 :Sélection de conception de voie STR_5203 :Attraction STR_5204 :Liste des attractions STR_5205 :Visiteur STR_5206 :Liste des visiteurs STR_5207 :Personnel STR_5208 :Liste personnel -STR_5209 :Banner -STR_5210 :Object Selection -STR_5211 :Invention List -STR_5212 :Scenario Options -STR_5213 :Objective Options -STR_5214 :Map Generation -STR_5215 :Track Design Manager -STR_5216 :Track Design Manager List -STR_5217 :Cheats +STR_5209 :Bannière +STR_5210 :Sélection d'objets +STR_5211 :Liste d'inventions +STR_5212 :Options de scénario +STR_5213 :Options d'objectif +STR_5214 :Génération de carte +STR_5215 :Gestionnaire de conception de voie +STR_5216 :Liste du gestionnaire de conception de voie +STR_5217 :Triche STR_5218 :Thèmes STR_5219 :Options -STR_5220 :Keyboard Shortcuts -STR_5221 :Change Keyboard Shortcut -STR_5222 :Load/Save -STR_5223 :Save Prompt -STR_5224 :Demolish Ride Prompt -STR_5225 :Fire Staff Prompt -STR_5226 :Track Delete Prompt -STR_5227 :Save Overwrite Prompt -STR_5228 :{SMALLFONT}{BLACK}Main UI -STR_5229 :{SMALLFONT}{BLACK}Park -STR_5230 :{SMALLFONT}{BLACK}Tools -STR_5231 :{SMALLFONT}{BLACK}Rides and Peeps -STR_5232 :{SMALLFONT}{BLACK}Editors -STR_5233 :{SMALLFONT}{BLACK}Miscellaneous -STR_5234 :{SMALLFONT}{BLACK}Prompts -STR_5235 :{SMALLFONT}{BLACK}Settings -STR_5236 :Window: -STR_5237 :Palette: -STR_5238 :Current Theme: -STR_5239 :Duplicate -STR_5240 :Enter a name for the theme -STR_5241 :Can't change this theme -STR_5242 :Theme name already exists -STR_5243 :Invalid characters used +STR_5220 :Raccourcis clavier +STR_5221 :Changer raccourcis clavier +STR_5222 :Charger/Sauvegarder +STR_5223 :Sauvegarde +STR_5224 :Démolition d'attraction +STR_5225 :Renvoi de personnel +STR_5226 :Suppression de voie +STR_5227 :Ecrasement de sauvegarde +STR_5228 :{SMALLFONT}{BLACK}Interface principale +STR_5229 :{SMALLFONT}{BLACK}Parc +STR_5230 :{SMALLFONT}{BLACK}Outils +STR_5231 :{SMALLFONT}{BLACK}Attractions et visiteurs +STR_5232 :{SMALLFONT}{BLACK}Editeurs +STR_5233 :{SMALLFONT}{BLACK}Divers +STR_5234 :{SMALLFONT}{BLACK}Fenêtres de dialogue +STR_5235 :{SMALLFONT}{BLACK}Paramètres +STR_5236 :Fenêtre : +STR_5237 :Palette : +STR_5238 :Thème actuel : +STR_5239 :Dupliquer +STR_5240 :Entrez un nom pour le thème +STR_5241 :Impossible de modifier ce thème +STR_5242 :Ce nom de thème existe déjà +STR_5243 :Caractère invalide utilisé STR_5244 :Thèmes -STR_5245 :Top Toolbar -STR_5246 :Bottom Toolbar -STR_5247 :Track Editor Bottom Toolbar -STR_5248 :Scenario Editor Bottom Toolbar -STR_5249 :Title Menu Buttons -STR_5250 :Title Exit Button -STR_5251 :Title Options Button -STR_5252 :Title Scenario Selection -STR_5253 :Park Information -STR_5254 :Create -STR_5255 :{SMALLFONT}{BLACK}Create a new title sequence from scratch -STR_5256 :Create a new theme to make changes to -STR_5257 :{SMALLFONT}{BLACK}Create a new theme based on the current one -STR_5258 :{SMALLFONT}{BLACK}Delete the current theme -STR_5259 :{SMALLFONT}{BLACK}Rename the current theme -STR_5260 :Giant Screenshot -STR_5261 :Filter +STR_5245 :Barre d'outils du haut +STR_5246 :Barre d'outils du bas +STR_5247 :Barre d'outils du bas (éditeur de voies) +STR_5248 :Barre d'outils du bas (éditeur de scénarios) +STR_5249 :Boutons de l'écran titreTitle Menu Buttons +STR_5250 :Bouton Quitter de l'écran titre +STR_5251 :Bouton Options de l'écran titre +STR_5252 :Fenêtre de sélection de scénario +STR_5253 :Informations sur le parc +STR_5254 :Créer +STR_5255 :{SMALLFONT}{BLACK}Créer une nouvelle séquence titre de zéro +STR_5256 :Créer un nouveau thème à modifier +STR_5257 :{SMALLFONT}{BLACK}Créer un nouveau thème d'après l'actuel +STR_5258 :{SMALLFONT}{BLACK}Supprimer le thème actuel +STR_5259 :{SMALLFONT}{BLACK}Renommer le thème actuel +STR_5260 :Capture d'écran géante +STR_5261 :Filtrer STR_5262 :Wacky Worlds STR_5263 :Time Twister -STR_5264 :Custom -STR_5265 :{SMALLFONT}{BLACK}Select which content sources are visible -STR_5266 :{SMALLFONT}{BLACK}Display -STR_5267 :{SMALLFONT}{BLACK}Culture and Units +STR_5264 :Objets personnalisés +STR_5265 :{SMALLFONT}{BLACK}Choisir la source des objets visibles +STR_5266 :{SMALLFONT}{BLACK}Affichage +STR_5267 :{SMALLFONT}{BLACK}Langue et unités STR_5268 :{SMALLFONT}{BLACK}Audio -STR_5269 :{SMALLFONT}{BLACK}Controls and interface -STR_5270 :{SMALLFONT}{BLACK}Miscellaneous +STR_5269 :{SMALLFONT}{BLACK}Contrôles et interface +STR_5270 :{SMALLFONT}{BLACK}Divers STR_5271 :{SMALLFONT}{BLACK}Twitch -STR_5272 :{SMALLFONT}{BLACK}Small Scenery -STR_5273 :{SMALLFONT}{BLACK}Large Scenery -STR_5274 :{SMALLFONT}{BLACK}Footpaths -STR_5275 :Search for Objects -STR_5276 :Enter the name of an object to search for -STR_5277 :Clear -STR_5278 :Sandbox mode -STR_5279 :Sandbox mode off -STR_5280 :{SMALLFONT}{BLACK}Allow editing land ownership settings through the Map window and other options that are normally restricted to the Scenario Editor -STR_5281 :{SMALLFONT}{BLACK}Features -STR_5282 :RCT1 Ride Open/Close Lights -STR_5283 :RCT1 Park Open/Close Lights -STR_5284 :RCT1 Scenario Selection Font -STR_5285 :EXPLODE!!! -STR_5286 :{SMALLFONT}{BLACK}Makes some guests explode -STR_5287 :Ride is already broken down -STR_5288 :Ride is closed -STR_5289 :No breakdowns available for this ride -STR_5290 :Fix ride -STR_5291 :Can't force breakdown -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_5272 :{SMALLFONT}{BLACK}Petits décors +STR_5273 :{SMALLFONT}{BLACK}Grands décors +STR_5274 :{SMALLFONT}{BLACK}Allées +STR_5275 :Chercher des objets +STR_5276 :Entrer le nom d'un objet à rechercher +STR_5277 :Effacer +STR_5278 :Activer bac à sable +STR_5279 :Désact. bac à sable +STR_5280 :{SMALLFONT}{BLACK}Autorise la modification du terrain du parc via la fenêtre de la carte ainsi que d'autres options normalement réservées à l'éditeur de scénario +STR_5281 :{SMALLFONT}{BLACK}Fonctionnalités +STR_5282 :Ouverture/fermeture attraction comme RCT1 +STR_5283 :Ouverture/fermeture parc comme RCT1 +STR_5284 :Police de sélection de scénario comme RCT1 +STR_5285 :EXPLOSION!!! +STR_5286 :{SMALLFONT}{BLACK}Fait exploser quelques visiteurs +STR_5287 :L'attraction est déjà en panne +STR_5288 :L'attraction est fermée +STR_5289 :Pas de pannes disponibles pour cette attraction +STR_5290 :Réparer l'attraction +STR_5291 :Impossible de forcer une panne +STR_5292 :{SMALLFONT}{BLACK}Forcer une panne +STR_5293 :{SMALLFONT}{BLACK}Fermer l'attraction +STR_5294 :{SMALLFONT}{BLACK}Tester l'attraction +STR_5295 :{SMALLFONT}{BLACK}Ouvrir l'attraction +STR_5296 :{SMALLFONT}{BLACK}Fermer le parc +STR_5297 :{SMALLFONT}{BLACK}Ouvrir le parc STR_5298 :{RED}{STRINGID} STR_5299 :{LIGHTPINK}{STRINGID} -STR_5300 :{SMALLFONT}{BLACK}Quick fire staff -STR_5301 :{MEDIUMFONT}{BLACK}Clear your loan -STR_5302 :Clear loan -STR_5303 :Allow building in pause mode -STR_5304 :Title Sequence: +STR_5300 :{SMALLFONT}{BLACK}Licenciement rapide +STR_5301 :{MEDIUMFONT}{BLACK}Effacer votre emprunt +STR_5302 :Effacer emprunt +STR_5303 :Autoriser construction en mode pause +STR_5304 :Séquence titre : STR_5305 :RollerCoaster Tycoon 1 -STR_5306 :RollerCoaster Tycoon 1 (AA) -STR_5307 :RollerCoaster Tycoon 1 (AA + LL) +STR_5306 :RollerCoaster Tycoon 1 (NA) +STR_5307 :RollerCoaster Tycoon 1 (NA + LF) STR_5308 :RollerCoaster Tycoon 2 STR_5309 :OpenRCT2 -STR_5310 :Random -STR_5311 :{SMALLFONT}{BLACK}Debug tools -STR_5312 :Show console -STR_5313 :Show tile inspector -STR_5314 :Tile inspector -STR_5315 :Grass -STR_5316 :Sand -STR_5317 :Dirt -STR_5318 :Rock -STR_5319 :Martian -STR_5320 :Checkerboard -STR_5321 :Grass clumps -STR_5322 :Ice -STR_5323 :Grid (red) -STR_5324 :Grid (yellow) -STR_5325 :Grid (blue) -STR_5326 :Grid (green) -STR_5327 :Sand (dark) -STR_5328 :Sand (light) -STR_5329 :Checkerboard (inverted) -STR_5330 :Underground view -STR_5331 :Rock -STR_5332 :Wood (red) -STR_5333 :Wood (black) -STR_5334 :Ice -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_5341 :Flags +STR_5310 :Aléatoire +STR_5311 :{SMALLFONT}{BLACK}Outil de débogage +STR_5312 :Afficher la console +STR_5313 :Afficher l'inspecteur de carrés +STR_5314 :Inspecteur de carrés +STR_5315 :Herbe +STR_5316 :Sable +STR_5317 :Boue +STR_5318 :Pierre +STR_5319 :Martien +STR_5320 :Damier +STR_5321 :Touffes d'herbe +STR_5322 :Glace +STR_5323 :Grille (rouge) +STR_5324 :Grille (jaune) +STR_5325 :Grille (bleu) +STR_5326 :Grille (vert) +STR_5327 :Sable (sombre) +STR_5328 :Sable (clair) +STR_5329 :Damier (inversé) +STR_5330 :Vue souterraine +STR_5331 :Pierre +STR_5332 :Bois (rouge) +STR_5333 :Bois (noir) +STR_5334 :Glace +STR_5335 :Entrée du manège +STR_5336 :Sortie du manège +STR_5337 :Entrée du parc +STR_5338 :Type d'élément +STR_5339 :Hauteur de base +STR_5340 :Hauteur de collision +STR_5341 :Drapeaux STR_5342 :Choose a map tile -STR_5343 :Automatically place staff -STR_5344 :Changelog -STR_5345 :Financial cheats -STR_5346 :Guest cheats -STR_5347 :Park cheats -STR_5348 :Ride cheats -STR_5349 :{SMALLFONT}{BLACK}All Rides +STR_5343 :Placer employés automatiquement +STR_5344 :Historique +STR_5345 :Triche financière +STR_5346 :Triche des visiteurs +STR_5347 :Triche du parc +STR_5348 :Triche des attractions +STR_5349 :{SMALLFONT}{BLACK}Toutes les attractions STR_5350 :Max STR_5351 :Min -STR_5352 :{BLACK}Bonheur: -STR_5353 :{BLACK}Energie: -STR_5354 :{BLACK}Faim: -STR_5355 :{BLACK}Soif: -STR_5356 :{BLACK}Nausée: -STR_5357 :{BLACK}Tolérance nausée: -STR_5358 :{BLACK}Toilettes: -STR_5359 :Remove guests -STR_5360 :{SMALLFONT}{BLACK}Removes all guests from the map -STR_5361 :Give all guests: -STR_5362 :{BLACK}Set all guests' preferred ride intensity to: -STR_5363 :More than 1 -STR_5364 :Less than 15 -STR_5365 :{BLACK}Vit. de personnel: +STR_5352 :{BLACK}Bonheur : +STR_5353 :{BLACK}Energie : +STR_5354 :{BLACK}Faim : +STR_5355 :{BLACK}Soif : +STR_5356 :{BLACK}Nausée : +STR_5357 :{BLACK}Tolérance nausée : +STR_5358 :{BLACK}Toilettes : +STR_5359 :Supprimer visiteurs +STR_5360 :{SMALLFONT}{BLACK}Supprimer tous les visiteurs de la carte +STR_5361 :Donner à tous les visiteurs : +STR_5362 :{BLACK}Définir l'intensité préférée des visiteurs à : +STR_5363 :Plus de 1 +STR_5364 :Moins de 15 +STR_5365 :{BLACK}Vitesse du personnel : STR_5366 :Normal STR_5367 :Rapide -STR_5368 :Reset crash status -STR_5369 :Park parameters... -STR_5370 :{SMALLFONT}{BLACK}Click this button to modify park{NEWLINE}parameters like restrictions,{NEWLINE}guest generation and money. -STR_5371 :Object Selection -STR_5372 :Invert right mouse dragging +STR_5368 :Réinit. accidents +STR_5369 :Param. du parc... +STR_5370 :{SMALLFONT}{BLACK}Cliquez ce bouton pour modifier les paramètres du parc comme les restrictions, la génération de visiteurs et l'argent. +STR_5371 :Sélection d'objets +STR_5372 :Inverser le déplacement du clic droit STR_5373 :Nom {STRINGID} STR_5374 :Date {STRINGID} STR_5375 :{UP} STR_5376 :{DOWN} -STR_5377 :{SMALLFONT}{BLACK}Saves +STR_5377 :{SMALLFONT}{BLACK}Sauvegardes STR_5378 :{SMALLFONT}{BLACK}Script -STR_5379 :{SMALLFONT}{BLACK}Skip to next wait command -STR_5380 :{SMALLFONT}{BLACK}Start playing title sequence -STR_5381 :{SMALLFONT}{BLACK}Stop playing title sequence -STR_5382 :{SMALLFONT}{BLACK}Restart title sequence -STR_5383 :{SMALLFONT}{BLACK}Create a new title sequence based on the current one -STR_5384 :{SMALLFONT}{BLACK}Delete the current title sequence -STR_5385 :{SMALLFONT}{BLACK}Rename the current title sequence -STR_5386 :{SMALLFONT}{BLACK}Insert a new command -STR_5387 :{SMALLFONT}{BLACK}Edit the selected command -STR_5388 :{SMALLFONT}{BLACK}Delete the selected command -STR_5389 :{SMALLFONT}{BLACK}Skip to the selected command in the title sequence -STR_5390 :{SMALLFONT}{BLACK}Move the selected command down -STR_5391 :{SMALLFONT}{BLACK}Move the selected command up -STR_5392 :{SMALLFONT}{BLACK}Add a save to the title sequence -STR_5393 :{SMALLFONT}{BLACK}Remove the selected save from the title sequence -STR_5394 :{SMALLFONT}{BLACK}Rename the selected save -STR_5395 :{SMALLFONT}{BLACK}Load the selected save in game -STR_5396 :{SMALLFONT}{BLACK}Reload the title sequence if changes have been made to it outside of the game -STR_5397 :Can only be used on the title screen -STR_5398 :Cannot edit title sequence while it's playing -STR_5399 :Press the stop button to continue editing -STR_5400 :Can't change this title sequence -STR_5401 :Create a new title sequence to make changes to -STR_5402 :Failed to load title sequence -STR_5403 :There may be no Load or Wait command or a save may be invalid -STR_5404 :Name already exists -STR_5405 :Enter a name for the save -STR_5406 :Enter a name for the title sequence -STR_5407 :Add -STR_5408 :Remove -STR_5409 :Insert -STR_5410 :Edit -STR_5411 :Reload -STR_5412 :Skip to -STR_5413 :Load -STR_5414 :Load{MOVE_X}{87}Six Flags Magic Mountain.SC6 -STR_5415 :Load{MOVE_X}{87}{STRING} -STR_5416 :Load{MOVE_X}{87}No save selected -STR_5417 :Location -STR_5418 :Location{MOVE_X}{87}{COMMA16} {COMMA16} -STR_5419 :Rotate -STR_5420 :Rotate{MOVE_X}{87}{COMMA16} -STR_5421 :Zoom -STR_5422 :Zoom{MOVE_X}{87}{COMMA16} -STR_5423 :Wait -STR_5424 :Wait{MOVE_X}{87}{COMMA16} -STR_5425 :Restart -STR_5426 :End -STR_5427 :Coordinates: -STR_5428 :Anticlockwise rotations: -STR_5429 :Zoom level: -STR_5430 :Seconds to wait: -STR_5431 :Save to load: -STR_5432 :Command: -STR_5433 :Title Sequences -STR_5434 :Command Editor -STR_5435 :Rename save -STR_5436 :Edit Title Sequences... -STR_5437 :No save selected -STR_5438 :Can't make changes while command editor is open -STR_5439 :A wait command with at least 4 seconds is required with a restart command -STR_5440 :Minimise fullscreen on focus loss -STR_5441 :{SMALLFONT}{BLACK}Identifies rides by track type,{NEWLINE}so vehicles can be changed{NEWLINE}afterwards, like in RCT1. -STR_5442 :Force park rating: +STR_5379 :{SMALLFONT}{BLACK}Passer à la commande suivante +STR_5380 :{SMALLFONT}{BLACK}Démarrer séquence titre +STR_5381 :{SMALLFONT}{BLACK}Arrêter séquence titre +STR_5382 :{SMALLFONT}{BLACK}Redémarrer séquence titre +STR_5383 :{SMALLFONT}{BLACK}Créer une nouvelle séquence titre d'après l'actuelle +STR_5384 :{SMALLFONT}{BLACK}Supprimer l'actuelle séquence titre +STR_5385 :{SMALLFONT}{BLACK}Renommer l'actuelle séquence titre +STR_5386 :{SMALLFONT}{BLACK}Insérer une nouvelle commande +STR_5387 :{SMALLFONT}{BLACK}Editer la commande sélectionnée +STR_5388 :{SMALLFONT}{BLACK}Supprimer la commande sélectionée +STR_5389 :{SMALLFONT}{BLACK}Passer à la commande sélectionnée dans la séquence titre +STR_5390 :{SMALLFONT}{BLACK}Déplacer la commande sélectionnée vers le bas +STR_5391 :{SMALLFONT}{BLACK}Déplacer la commande sélectionnée vers le haut +STR_5392 :{SMALLFONT}{BLACK}Ajouter une sauvegarde à la séquence titre +STR_5393 :{SMALLFONT}{BLACK}Retirer la sauvegarde sélectionnée de la séquence titre +STR_5394 :{SMALLFONT}{BLACK}Renommer la sauvegarde sélectionnée +STR_5395 :{SMALLFONT}{BLACK}Charger la sauvegarde sélectionnée dans le jeu +STR_5396 :{SMALLFONT}{BLACK}Recharger la séquence titre si des changements ont été effectués en-dehors du jeu +STR_5397 :Peut être utilisé uniquement sur l'écran titre +STR_5398 :Impossible de modifier la séquence titre quand elle joue +STR_5399 :Appuyez sur le bouton Arrêter pour continuer les modifications +STR_5400 :Impossible de modifier cette séquence titre +STR_5401 :Créez une nouvelle séquence titre à modifier +STR_5402 :Impossible de charger la séquence titre +STR_5403 :Il n'y a peut-être pas de commande de chargement ou d'attente, ou une sauvegarde est peut-être invalide +STR_5404 :Le nom existe déjà +STR_5405 :Saisir un nom pour la sauvegarde +STR_5406 :Saisir un nom pour la séquence titre +STR_5407 :Ajouter +STR_5408 :Retirer +STR_5409 :Insérer +STR_5410 :Editer +STR_5411 :Recharger +STR_5412 :Passer à +STR_5413 :Charger +STR_5414 :Charger{MOVE_X}{87}Six Flags Magic Mountain.SC6 +STR_5415 :Charger{MOVE_X}{87}{STRING} +STR_5416 :Charger{MOVE_X}{87}Aucune sauvegarde séléctionné +STR_5417 :Emplacement +STR_5418 :Emplacement{MOVE_X}{87}{COMMA16} {COMMA16} +STR_5419 :Tourner +STR_5420 :Tourner{MOVE_X}{87}{COMMA16} +STR_5421 :Zoomer +STR_5422 :Zoomer{MOVE_X}{87}{COMMA16} +STR_5423 :Attendre +STR_5424 :Attendre{MOVE_X}{87}{COMMA16} +STR_5425 :Redémarrer +STR_5426 :Fin +STR_5427 :Coordonnées : +STR_5428 :Rotations antihoraires : +STR_5429 :Niveau de zoom : +STR_5430 :Secondes à attendre : +STR_5431 :Sauvegarde à charger : +STR_5432 :Commande : +STR_5433 :Séquences de titre +STR_5434 :Editeur de commande +STR_5435 :Renommer sauvegarde +STR_5436 :Editer séquence titre... +STR_5437 :Aucune sauvegarde sélectionnée +STR_5438 :Impossible de modifier tant que l'éditeur de commande est ouvert +STR_5439 :Une commande d'attente d'au moins 4 secondes est requise pour redémarrer +STR_5440 :Minimiser le plein écran au passage en arrière-plan +STR_5441 :{SMALLFONT}{BLACK}Identifie les attractions par type de voie, pour que les voitures puissent être changées plus tard, comme dans RCT1. +STR_5442 :Eval. du parc : STR_5443 :Vitesse{MOVE_X}{87}{STRINGID} STR_5444 :Vitesse: STR_5445 :Vitesse STR_5446 :Get STR_5447 :Type {STRINGID} -STR_5448 :Ride / Vehicle {STRINGID} -STR_5449 :Reduce game speed -STR_5450 :Increase game speed -STR_5451 :Open cheats window -STR_5452 :Toggle visibility of toolbars -STR_5453 :Select another ride -STR_5454 :Uncap FPS -STR_5455 :Enable sandbox mode -STR_5456 :Disable clearance checks -STR_5457 :Disable support limits -STR_5458 :Rotate clockwise -STR_5459 :Rotate anti-clockwise -STR_5460 :Rotate view anti-clockwise -STR_5461 :Set guests' parameters +STR_5448 :Attraction/véhicule {STRINGID} +STR_5449 :Diminuer la vitesse de jeu +STR_5450 :Augmenter la vitesse de jeu +STR_5451 :Ouvrir la fenêtre de triche +STR_5452 :Afficher/masquer les barres d'outils +STR_5453 :Choisir une autre attraction +STR_5454 :Déplafonner les FPS +STR_5455 :Activer mode bac à sable +STR_5456 :Désactiver les collisions +STR_5457 :Désactiver la limite de support +STR_5458 :Pivoter dans le sens horaire +STR_5459 :Pivoter dans le sens anti-horaire +STR_5460 :Pivoter dans le sens anti-horaire +STR_5461 :Paramètre des visiteurs STR_5462 :{CURRENCY} -STR_5463 :Goal: Have fun! -STR_5464 :General -STR_5465 :Climate +STR_5463 :But : Amusez-vous ! +STR_5464 :Général +STR_5465 :Climat STR_5466 :Personnel STR_5467 :ALT + STR_5468 :Messages récents -STR_5469 :Scroll map up -STR_5470 :Scroll map left -STR_5471 :Scroll map down -STR_5472 :Scroll map right -STR_5473 :Cycle day / night -STR_5474 :Display text on banners in upper case +STR_5469 :Défiler la carte vers le haut +STR_5470 :Défiler la carte vers la gauche +STR_5471 :Défiler la carte vers le bas +STR_5472 :Défiler la carte vers la droite +STR_5473 :Cycle jour / nuit +STR_5474 :Afficher le texte des bannières en majuscule STR_5475 :{COMMA16} semaines STR_5476 :Matériel STR_5477 :Rendu de la carte STR_5478 :Contrôles STR_5479 :Barre d'outils -STR_5480 :Show toolbar buttons for: +STR_5480 :Afficher des boutons dans la barre d'outils pour : STR_5481 :Thèmes -STR_5482 :{WINDOW_COLOUR_2}Temps écoulé depuis la dernière inspection: {BLACK}une minute +STR_5482 :{WINDOW_COLOUR_2}Temps écoulé depuis la dernière inspection : {BLACK}une minute STR_5483 :{BLACK}({COMMA16} semaines restantes) STR_5484 :{BLACK}({COMMA16} semaine restante) STR_5485 :{SMALLFONT}{STRING} @@ -3830,4 +3830,730 @@ STR_5488 :Pas d'entrée STR_5489 :{SMALLFONT}{BLACK}Afficher seulement les visiteurs surveillés STR_5490 :Couper le son lorsque la fenêtre est minimisée STR_5491 :Liste d'inventions -STR_5492 :Options scénario +STR_5492 :Options du scénario +STR_5493 :Envoyer un message +STR_5494 : +STR_5495 :Liste des joueurs +STR_5496 :Joueur : +STR_5497 :Ping : +STR_5498 :Liste des serveurs +STR_5499 :Nom du joueur : +STR_5500 :Ajouter un serveur +STR_5501 :Démarrer un serveur +STR_5502 :Multijoueur +STR_5503 :Saisir nom d'hôte ou adresse IP : +STR_5504 :{SMALLFONT}{BLACK}Afficher le statut multijoueur +STR_5505 :Impossible de se connecter au serveur +STR_5506 :Les visiteurs ignorent l'intensité +STR_5507 :Les agents d'entretien tondent la pelouse par défaut +STR_5508 :Autor. charg. de fichiers avec une empreinte incorrecte +STR_5509 :{SMALLFONT}{BLACK}Autoriser le chargement de scénarios et sauvegardes ayant une empreinte incorrecte, par exemple les scénarios de la démo ou des sauvegardes corrompues. +STR_5510 :Périphérique audio par défaut +STR_5511 :(UNKNOWN) +STR_5512 :Sauvegarder partie sous +STR_5513 :Sauvegarde rapide +STR_5514 :Désactiver le vandalisme +STR_5515 :{SMALLFONT}{BLACK}Empêche les visiteurs de vandaliser votre parc quand ils sont furieux +STR_5516 :{SMALLFONT}{BLACK}Noir +STR_5517 :{SMALLFONT}{BLACK}Gris +STR_5518 :{SMALLFONT}{BLACK}Blanc +STR_5519 :{SMALLFONT}{BLACK}Violet foncé +STR_5520 :{SMALLFONT}{BLACK}Violet clair +STR_5521 :{SMALLFONT}{BLACK}Violet vif +STR_5522 :{SMALLFONT}{BLACK}Bleu fincé +STR_5523 :{SMALLFONT}{BLACK}Bleu clair +STR_5524 :{SMALLFONT}{BLACK}Bleu vif +STR_5525 :{SMALLFONT}{BLACK}Eau foncée +STR_5526 :{SMALLFONT}{BLACK}Eau claire +STR_5527 :{SMALLFONT}{BLACK}Vert saturé +STR_5528 :{SMALLFONT}{BLACK}Vert foncé +STR_5529 :{SMALLFONT}{BLACK}Vert mousse +STR_5530 :{SMALLFONT}{BLACK}Vert clair +STR_5531 :{SMALLFONT}{BLACK}Vert olive +STR_5532 :{SMALLFONT}{BLACK}Vert olive foncé +STR_5533 :{SMALLFONT}{BLACK}Jaune clair +STR_5534 :{SMALLFONT}{BLACK}Jaune +STR_5535 :{SMALLFONT}{BLACK}Jaune foncé +STR_5536 :{SMALLFONT}{BLACK}Orange claire +STR_5537 :{SMALLFONT}{BLACK}Orange foncée +STR_5538 :{SMALLFONT}{BLACK}Brun clair +STR_5539 :{SMALLFONT}{BLACK}Brun saturé +STR_5540 :{SMALLFONT}{BLACK}Brun foncé +STR_5541 :{SMALLFONT}{BLACK}Rose saumon +STR_5542 :{SMALLFONT}{BLACK}Rouge bordeaux +STR_5543 :{SMALLFONT}{BLACK}Rouge saturé +STR_5544 :{SMALLFONT}{BLACK}Rouge clair +STR_5545 :{SMALLFONT}{BLACK}Rose foncé +STR_5546 :{SMALLFONT}{BLACK}Rose clair +STR_5547 :{SMALLFONT}{BLACK}Rose vif +STR_5548 :Afficher tous les modes d'exploitation +STR_5549 :Année/Mois/Jour +STR_5550 :{POP16}{POP16}Year {COMMA16}, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} +STR_5551 :Année/Jour/Mois +STR_5552 :{POP16}{POP16}Year {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} +STR_5553 :Mettre en pause quand l'overlay Steam est ouvert +STR_5554 :{SMALLFONT}{BLACK}Outil montagne +STR_5555 :Afficher véhicules d'autres types de voie +STR_5556 :{SMALLFONT}{BLACK}Sortir le joueur +STR_5557 :Rester connecter après désynchronisation (multij.) +STR_5558 :Redémarrez le jeu pour appliquer ce paramètre +STR_5559 :Inspections 10 min. +STR_5560 :{SMALLFONT}{BLACK}Définit l'intervalle d'inspection de toutes les attractions à toutes les 10 minutes +STR_5561 :Le chargement de la langue à échoué +STR_5562 :ATTENTION! +STR_5563 :Cette fonctionnalité est actuellement instable, faites attention. +STR_5564 :Insérer un élément corrompu +STR_5565 :{SMALLFONT}{BLACK}Insère un élément corrompu au sommet du carré. Ceci va masquer tous les éléments au-dessus de l'élément corrompu. +STR_5566 :Mot de passe : +STR_5567 :Afficher dans la liste des serveurs +STR_5568 :Mot de passe requis +STR_5569 :Ce serveur nécessite un mot de passe +STR_5570 :Rafraichir +STR_5571 :Rejoindre +STR_5572 :Ajouter aux Favoris +STR_5573 :Retirer des Favoris +STR_5574 :Nom du serveur : +STR_5575 :Joueurs max. : +STR_5576 :Port : +STR_5577 :Won Sud-Coréen (W) +STR_5578 :Rouble Russe (R) +STR_5579 :Mise à l'échelle : +STR_5580 :Couronne Tchèque (Kc) +STR_5581 :Afficher les FPS +STR_5582 :Toujours garder le curseur dans la fenêtre +STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} +STR_5584 :SI +STR_5585 :{SMALLFONT}{BLACK}Débloque les limites d'exploitation des attractions, permettant par exemple une remontée à {VELOCITY} +STR_5586 :Ouvrir les magasins et boutiques automatiquement +STR_5587 :{SMALLFONT}{BLACK}Activé, les magasins et boutiques seront automatiquement ouverts après être construits +STR_5588 :{SMALLFONT}{BLACK}Jouer avec d'autres joueurs +STR_5589 :Paramètres de notifications +STR_5590 :Prix du parc +STR_5591 :Fins des campagnes marketing +STR_5592 :Avertissements du parc +STR_5593 :Avertissements d'évaluation du parc +STR_5594 :Pannes des attractions +STR_5595 :Accidents des attractions +STR_5596 :Avertissements des attractions +STR_5597 :Nouvelles recherches +STR_5598 :Avertissements des visiteurs +STR_5599 :Visiteurs perdus +STR_5600 :Départs des visiteurs +STR_5601 :Visiteurs font la queue +STR_5602 :Visiteurs sur une attraction +STR_5603 :Visiteurs quittent une attraction +STR_5604 :Visiteurs achètent un objet +STR_5605 :Visiteurs utilisent une commodité +STR_5606 :Visiteurs décèdent +STR_5607 :{SMALLFONT}{BLACK}Forcer la suppression de l'élément sélectionné +STR_5608 :HB +STR_5609 :HC +STR_5610 :{SMALLFONT}{BLACK}Supprime l'élément sélectoonné. La suppression va être forcée, pas d'argent ne va être dépensé/gagné. A utiliser avec précaution. +STR_5611 :F +STR_5612 :{SMALLFONT}{BLACK}Drapeau {OPENQUOTES}fantôme{ENDQUOTES} +STR_5613 :C +STR_5614 :{SMALLFONT}{BLACK}Drapeau {OPENQUOTES}cassé{ENDQUOTES} +STR_5615 :D +STR_5616 :{SMALLFONT}{BLACK}Drapeau {OPENQUOTES}dernier élément sur le carré{ENDQUOTES} +STR_5617 :{SMALLFONT}{BLACK}Déplacer l'élément sélectionné vers le haut +STR_5618 :{SMALLFONT}{BLACK}Déplacer l'élément sélectionné vers le bas +STR_5619 :RollerCoaster Tycoon +STR_5620 :Nouvelles Attractions +STR_5621 :Loopings en Folie +STR_5622 :RollerCoaster Tycoon 2 +STR_5623 :Wacky Worlds +STR_5624 :Time Twister +STR_5625 :Parcs {OPENQUOTES}réels{ENDQUOTES} +STR_5626 :Autres parcs +STR_5627 :Grouper les scénarios par : +STR_5628 :Jeu d'origine +STR_5629 :Niveau de difficulté +STR_5630 :Activer le déblocage progressif des scénarios +STR_5631 :Parcs additionnels originaux +STR_5632 :Construisez votre propre parc... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Argent dépensé : {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Commandes exécutées : {BLACK}{COMMA16} +STR_5637 :Impossible... +STR_5638 :Permission refusée +STR_5639 :{SMALLFONT}{BLACK}Affiche la liste des joueurs +STR_5640 :{SMALLFONT}{BLACK}Gérer les groupes +STR_5641 :Groupe par défaut : +STR_5642 :Groupes : +STR_5643 :Ajouter groupe +STR_5644 :Suppr. groupe +STR_5645 :Chat +STR_5646 :Modifier terrain +STR_5647 :Pause +STR_5648 :Définir niveau de l'eau +STR_5649 :Créer attraction +STR_5650 :Supprimer attraction +STR_5651 :Construire attraction +STR_5652 :Options attraction +STR_5653 :Décor +STR_5654 :Allée +STR_5655 :Guest +STR_5656 :Employé +STR_5657 :Propriétés du parc +STR_5658 :Argent du parc +STR_5659 :Expulser joueur +STR_5660 :Modifier groupes +STR_5661 :Définir groupe +STR_5662 :N/A +STR_5663 :Nettoyer paysage +STR_5664 :Triche +STR_5701 :{WINDOW_COLOUR_2}Dernière action : {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Localise l'action la plus récente du joueur +STR_5703 :Imposible d'expulser l'hébergeur +STR_5704 :Dernière action : +STR_5705 :Impossible d'attribuer à ce groupe +STR_5706 :Impossible de supprimer un groupe ayant des joueurs +STR_5707 :Ce groupe ne peut pas être modifié +STR_5708 :Impossible de changer le groupe auquel l'hébergeur appartient +STR_5709 :Renom. groupe +STR_5710 :Nom du groupe +STR_5711 :Saisir un nouveau nom pour ce groupe : +STR_5712 :Impossible de modifier une permission que vous n'avez pas vous-même +STR_5713 :Expulser joueur +STR_5714 :Afficher fenêtre des options +STR_5715 :Nouvelle partie +STR_5716 :Pas autorisé en multijoueur +# For identifying client network version in server list window +STR_5717 :Version du serveur : {STRING} +STR_5718 :{SMALLFONT}{BLACK}Version du serveur : {STRING} +STR_5719 :Ensoleillé +STR_5720 :Partiellement Nuageux +STR_5721 :Nuageux +STR_5722 :Pluie +STR_5723 :Forte Pluie +STR_5724 :Orage +STR_5725 :{BLACK}Forcer la météo : +STR_5726 :{SMALLFONT}{BLACK}Défini la météo actuelle dans le parc +STR_5727 :Qual. de mise à l'échelle : +STR_5728 :Requiert l'option d'affichage matériel +STR_5729 :{SMALLFONT}{BLACK}Requiert l'option d'affichage matériel +STR_5730 :Au plus proche +STR_5731 :Linéaire +STR_5732 :Anisotropique +STR_5733 :Utilise la mise à l'échelle NN aux échelles d'entiers +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Rendu +STR_5735 :Etat du réseau +STR_5736 :Joueur +STR_5737 :Fermé, {COMMA16} visiteur toujours sur l'attraction +STR_5738 :Fermé, {COMMA16} visiteurs toujours sur l'attraction +STR_5739 :{WINDOW_COLOUR_2}Clients sur l'attraction : {BLACK}{COMMA16} +STR_5740 :Campagnes marketing permanentes +STR_5741 :{SMALLFONT}{BLACK}Les campagnes marketings ne s'arrêtent jamais +STR_5742 :Authentification... +STR_5743 :Connection... +STR_5744 :Résolution... +STR_5745 :Désynchronisation détéctée +STR_5746 :Déconnecté +STR_5747 :Déconnecté : {STRING} +STR_5748 :Expulsé +STR_5749 :Sort du serveur ! +STR_5750 :Connexion fermée +STR_5751 :Aucune Données +STR_5752 :{OUTLINE}{RED}{STRING} s'est déconnecté +STR_5753 :{OUTLINE}{RED}{STRING} s'est déconnecté ({STRING}) +STR_5754 :Mauvais pseudo +STR_5755 :Mauvaise version du programme +STR_5756 :Mauvais mot de passe +STR_5757 :Serveur plein +STR_5758 :{OUTLINE}{GREEN}{STRING} a rejoint la partie +STR_5759 :Téléchargement de la carte... ({INT32} / {INT32}) +STR_5760 :Dollars de Hong Kong (HK$) +STR_5761 :Nouveau Dollar Taïwanais (NT$) +STR_5762 :Yuan Chinois (CN{YEN}) +STR_5763 :Tous les fichiers +STR_5764 :Type d'attraction invalide +STR_5765 :Impossible d'éditer les attractions de type invalide +STR_5766 : +STR_5767 :Revenu +STR_5768 :Clients total +STR_5769 :Bénéfice total +STR_5770 :Clients par heure +STR_5771 :Coûts d'exploitation +STR_5772 :Age +STR_5773 :Clients total : {COMMA32} +STR_5774 :Bénéf. total : {CURRENCY2DP} +STR_5775 :Clients : {COMMA32} par heure +STR_5776 :Construit : cette année +STR_5777 :Construit : l'année dernière +STR_5778 :Construit : {COMMA16} ans +STR_5779 :Revenu : {CURRENCY2DP} par heure +STR_5780 :Coût d'exploitation : {CURRENCY2DP} par heure +STR_5781 :Coût d'exploitation : inconnu +STR_5782 :Vous êtes maintenant connecté. Pressez '{STRING}' pour discuter. +STR_5783 :{WINDOW_COLOUR_2}Scénario verrouillé +STR_5784 :{BLACK}Complétez les scénarios précédents pour déverrouiller ce scénario +STR_5785 :Impossible de renommer le groupe... +STR_5786 :Nom de groupe invalide +STR_5787 :{COMMA32} joueurs en ligne +STR_5788 :Délai d'insp. par défaut : +STR_5789 :Désactiver les éclairs +STR_5790 :{SMALLFONT}{BLACK}Active les prix façon RCT1 (Possibilité de définir à la fois un prix d'entrée et des prix d'attractions) +STR_5791 :{SMALLFONT}{BLACK}Règle la fiabilité de toutes les attractions à 100% et réinitialise leur date de construction +STR_5792 :{SMALLFONT}{BLACK}Répare toutes les attractions en panne +STR_5793 :{SMALLFONT}{BLACK}Réinitialise l'historique des accidents des attractions, les visiteurs ne se plaindront plus de leur fiabilité +STR_5794 :{SMALLFONT}{BLACK}Certains scénarios empêchent d'éditer des attractions déjà dans le parc, ceci annule cette interdiction +STR_5795 :{SMALLFONT}{BLACK}Les visiteurs iront sur toutes les attractions, même si l'intensité est très élevée +STR_5796 :{SMALLFONT}{BLACK}Force le parc à ouvrir ou fermer +STR_5797 :{SMALLFONT}{BLACK}Désactive les changements de météo et reste à la météo actuelle +STR_5798 :{SMALLFONT}{BLACK}Autorise la construction lorsque le jeu est en pause +STR_5799 :{SMALLFONT}{BLACK}Empêche les accidents sur les attractions en désactivant les pannes de freins +STR_5800 :{SMALLFONT}{BLACK}Empêche les attractions de tomber en panne + +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Frontières Forestières +STR_PARK :Frontières Forestières +STR_DTLS :Au coeur de la forêt, construisez un parc à thème florissant dans une grande zone ouverte. + + +STR_SCNR :Dunes Dynamite +STR_PARK :Dunes Dynamite +STR_DTLS :Construit au milieu du desert, ce parc à thème n'a qu'une seule montagne russe mais a de la place pour s'agrandir. + + +STR_SCNR :Lac Luxuriant +STR_PARK :Lac Luxuriant +STR_DTLS :En partant de rien, construisez un parc à thème autour d'un grand lac. + + +STR_SCNR :Monts Diamant +STR_PARK :Monts Diamant +STR_DTLS :Monts Diamant est déjà un parc à thème très coté avec des attractions géniales - développez-le et doublez sa valeur. + + +STR_SCNR :Jardins Verdoyants +STR_PARK :Jardins Verdoyants +STR_DTLS :Transformez les magnifiques Jardins Verdoyants en un parc à thème florissant. + + +STR_SCNR :Plage Bourdonnante +STR_PARK :Plage Bourdonnante +STR_DTLS :Transformez le petit parc d'attractions de Plage Bourdonnante en un parc à thème florissant. + + +STR_SCNR :Îles Trinité +STR_PARK :Îles Trinité +STR_DTLS :Plusieurs îles constituent la base de ce nouveau parc. + + +STR_SCNR :Monde de Katie +STR_PARK :Monde de Katie +STR_DTLS :Un petit parc à thème avec peu d'attractions et peu de place pour s'agrandir. Votre mission est de doubler la valeur du parc. + + +STR_SCNR :Parc Minus +STR_PARK :Parc Minus +STR_DTLS :Un tout petit parc d'attractions à l'étroit qui a vraiment besoin de s'agrandir. + + +STR_SCNR :Parc Eau Pure +STR_PARK :Parc Eau Pure +STR_DTLS :Un parc avec quelques attractions aquatiques géniales qui a besoin de s'agrandir. + + +STR_SCNR :Mines Millennium +STR_PARK :Mines Millennium +STR_DTLS :Transformez une grande mine abandonnée qui fait la curiosité des touristes en un parc à thèmes. + + +STR_SCNR :Karts & Grands Huit +STR_PARK :Karts & Grands Huit +STR_DTLS :Un grand parc caché dans la forêt, avec uniquement des pistes de karting et des montagnes russes en bois. + + +STR_SCNR :Monde de Mel +STR_PARK :Monde de Mel +STR_DTLS :Ce parc à thème a quelques attractions modernes bien conçues, mais plein d'espace pour son expansion. + + +STR_SCNR :Montagnes Mystiques +STR_PARK :Montagnes Mystiques +STR_DTLS :Dans les forêts vallonnées de Mystic Mountain, construisez un parc à thème en partant de rien. + + +STR_SCNR :Pyramides Pacifiques +STR_PARK :Pyramides Pacifiques +STR_DTLS :Transformez les ruines égyptiennes prisées par les touristes en un parc à thème florissant. + + +STR_SCNR :Bois Craquants +STR_PARK :Bois Craquants +STR_DTLS :Un grand parc avec des attractions bien conçues mais plutôt anciennes. Remplacez les anciennes attractions ou ajoutez-en de nouvelles pour rendre le parc plus attractif. + + +STR_SCNR :Ponton Paradis +STR_PARK :Ponton Paradis +STR_DTLS :Transformez la jetée de cette ville endormie en un parc d'attractions florissante. + + +STR_SCNR :Pics Foudroyants +STR_PARK :Pics Foudroyants +STR_DTLS :Les magnifiques Pics Foudroyants sont très prisés par les randonneurs et les touristes. Utilisez le terrain disponible pour attirer une nouvelle clientèle avide de sensations fortes. + + +STR_SCNR :Tours d'Ivoire +STR_PARK :Tours d'Ivoire +STR_DTLS :Un parc bien établi, qui a quelques petits problèmes. + + +STR_SCNR :Vallée Arc-en-ciel +STR_PARK :Vallée Arc-en-ciel +STR_DTLS :Les autorités locales de la Vallée Arc-en-ciel ne permettront aucun changement dans l'aménagement du territoire ou l'abattage de gros arbres, mais vous devez transformer la zone en un grand parc à thème. + + +STR_SCNR :Roc Fracas +STR_PARK :Roc Fracas +STR_DTLS :Roc Fracas se trouve au milieu d'un désert et attire de nombreux touristes. Utilisez l'espace disponible pour construire des attractions qui attireront encore plus de personnes. + + +STR_SCNR :Mega Parc +STR_PARK :Mega Parc +STR_DTLS :Amusez-vous ! + +## Added Attractions + +STR_SCNR :Falaises Insidieuses +STR_PARK :Falaises Insidieuses +STR_DTLS :Transformer les falaises de bord de mer en parc d'attractions à succès. + + +STR_SCNR :Parc des Trois Singes +STR_PARK :Parc des Trois Singes +STR_DTLS :Au centre de ce grand parc en construction se trouvent des montagnes russes géantes en acier à triple voie. + + +STR_SCNR :Mine Canari +STR_PARK :Mine Canari +STR_DTLS :Cette mine désaffectée est un site idéal pour la construction d'un parc d'attraction, avec ses rails miniatures et ses deux montagnes russes à chute verticale. + + +STR_SCNR :Pont Baron +STR_PARK :Pont Baron +STR_DTLS :Vous pouvez transformer un vieux pont désaffecté en parc d'attractions. + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Entourant un grand axe routier, ce parc contient plusieurs attractions déjà en fonctionnement. + + +STR_SCNR :Baie des Chimères +STR_PARK :Baie des Chimères +STR_DTLS :Les autorités locales ont accepté de vendre à ce parc côtier des terrains proches à prix bas, à condition que certaines attractions soient préservées. + + +STR_SCNR :Forteresse Frivole +STR_PARK :Forteresse Frivole +STR_DTLS :À vous de transformer ce château en parc d'attractions. + + +STR_SCNR :Monde Futur +STR_PARK :Monde Futur +STR_DTLS :L'étrange paysage de ce parc futuriste offre suffisamment d'espace pour la construction de nouvelles attractions. + + +STR_SCNR :Ruisseau Reposant +STR_PARK :Ruisseau Reposant +STR_DTLS :La population locale préfère des attractions tranquilles et relaxantes ; c'est donc à vous d'adapter ce parc à ses goûts. + + +STR_SCNR :Jungle Joviale +STR_PARK :Jungle Joviale +STR_DTLS :Dans les profondeurs de la jungle se trouve une zone de terrain qui ferait un parc d'attractions parfait. + + +STR_SCNR :Monts Lacustres +STR_PARK :Monts Lacustres +STR_DTLS :Une série de lacs en dénivelé est à la base de ce nouveau parc. + + +STR_SCNR :Parc Pétillant +STR_PARK :Parc Pétillant +STR_DTLS :Ce parc assez ancien comporte de nombreuses attractions historiques mais est très endetté. + + +STR_SCNR :Quarts Magiques +STR_PARK :Quarts Magiques +STR_DTLS :Une grande zone a été dégagée et partiellement prête pour la construction d'un parc d'attractions. + + +STR_SCNR :Ferme Fruitière +STR_PARK :Ferme Fruitière +STR_DTLS :Une grosse exploitation fruitière a construit un chemin de fer miniature pour améliorer ses revenus ; à vous de le développer en parc d'attractions à succès. + + +STR_SCNR :Barrage Papillon +STR_PARK :Barrage Papillon +STR_DTLS :La zone entourant un barrage est disponible et peut être transformée en parc d'attractions. + + +STR_SCNR :Canyon Grondant +STR_PARK :Canyon Grondant +STR_DTLS :Transformez un grand canyon en parc d'attractions. + + +STR_SCNR :Parc Orageux +STR_PARK :Parc Orageux +STR_DTLS :Le temps est si humide qu'une pyramide gréante a été construite pour que certaines attractions restent à l'abri. + + +STR_SCNR :Collines Concorde +STR_PARK :Collines Concorde +STR_DTLS :Les autorités locales refuseront toute construction qui dépasse la hauteur des arbres dans ce parc. + + +STR_SCNR :Village Romain +STR_PARK :Village Romain +STR_DTLS :Développez ce parc à thème romain en en ajoutant des attractions et des montagnes russes. + + +STR_SCNR :Crique Cloaque +STR_PARK :Crique Cloaque +STR_DTLS :Construit partiellement sur de petites îles, ce parc contient déjà deux grosses montagnes russes en attractions principales. + + +STR_SCNR :Mont Adrénaline +STR_PARK :Mont Adrénalin +STR_DTLS :Construisez un parc qui plaira à la population locale en quête de sensations fortes. + + +STR_SCNR :Utopia +STR_PARK :Utopia +STR_DTLS :Une oasis en plein coeur d'un désert constitue une idée de parc originale. + + +STR_SCNR :Monts Putrides +STR_PARK :Monts Putrides +STR_DTLS :Pouvez-vous relancer ce parc envahi par la végétation et délabré qui connut jadis son heure de gloire ? + + +STR_SCNR :Forêt Faillite +STR_PARK :Forêt Faillite +STR_DTLS :Vous disposez d'un budget très limité et de peu de temps pour réparer et améliorer ce parc équipé d'attractions mal conçues et dangereuses. + + +STR_SCNR :Parc Pétrin +STR_PARK :Parc Pétrin +STR_DTLS :Les autorités locales interdisent tout type de publicité ou promotion, vous devez donc essayer de faire marcher ce parc par le bouche à oreille uniquement. + + +STR_SCNR :Pentes Glapissantes +STR_PARK :Pentes Glapissantes +STR_DTLS :L'attraction principale de ce parc en pleine expansion est un rodéo-montagnes. + + +STR_SCNR :Parc Minéral +STR_PARK :Parc Minéral +STR_DTLS :Transformez cette carrière de pierres désaffectée en un parc qui attirera les touristes en quête de sensations fortes. + + +STR_SCNR :Loopings en Folie +STR_PARK :Loopings en Folie +STR_DTLS :Vous disposez de peu de fonds mais d'un temps illimité pour transformer cette zone montagneuse en un parc de montagnes russes géant. + + +STR_SCNR :Parc Urbain +STR_PARK :Parc Urbain +STR_DTLS :Un parc minuscule a signé un accord avec la ville voisine pour autoriser son expansion dans la ville elle-même. + + +STR_SCNR :Jardins Geoffrey +STR_PARK :Jardins Geoffrey +STR_DTLS :Un grand parc de jardins doit être transformé en parc à thème prospère. + + +## Loopy Landscapes + +STR_SCNR :Îles Iceberg +STR_PARK :Îles Iceberg +STR_DTLS :Un ensemble d'icebergs constitue l'environnement glacial de cet ambitieux parc à thème. + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :Un volcan éteint est le site de ce défi à la construction de montagnes russes. + + +STR_SCNR :Hauteurs Arides +STR_PARK :Hauteurs Arides +STR_DTLS :Vous avez carte blanche pour développer ce parc désertique en assurant la joie de ses visiteurs. + + +STR_SCNR :Rocs Rasoirs +STR_PARK :Rocs Rasoirs +STR_DTLS :Vous devez construire un vaste parc rempli de montagnes russes dans Razor Rocks. + + +STR_SCNR :Cratère Lacustre +STR_PARK :Cratère Lacustre +STR_DTLS :Ce parc a pour environnement un vaste lac dans un ancien cratère. + + +STR_SCNR :Vertigo +STR_PARK :Vertigo +STR_DTLS :Ce parc possède déjà un excellent tracé de super-montagnes russes, et vous devez en accroître massivement les profits. + + +STR_SCNR :Ponton Paradis 2 +STR_PARK :Ponton Paradis 2 +STR_DTLS :Ponton Paradis a étendu son réseau d'allées sur l'océan ; à vous d'exploiter cet espace en agrandissant le parc. + + +STR_SCNR :Crique du Dragon +STR_PARK :Crique du Dragon +STR_DTLS :Ce défi à la construction de montagnes russes a pour site une crique sur la côte. + + +STR_SCNR :Parc du Bon Chevalier +STR_PARK :Parc du Bon Chevalier +STR_DTLS :Vous devez développer ce château doté de deux montagnes russes en un vaste parc à thème. + + +STR_SCNR :Taupes Toquées +STR_PARK :Taupes Toquées +STR_DTLS :Un parc dont une bonne part des allées et des montagnes russes sont souterraines. + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :Il vous appartient de développer une vallée abritant un glacier en parc à thème. + + +STR_SCNR :Cratères Fumants +STR_PARK :Cratères Fumants +STR_DTLS :Vous devez construire, sur une planète éloignée où l'argent ne compte pas, un centre assurant le bonheur de la population. + + +STR_SCNR :Désert Sableux +STR_PARK :Désert Sableux +STR_DTLS :Cinq montagnes russes doivent être achevée dans ce parc désertique. + + +STR_SCNR :Parc Vermoulu +STR_PARK :Parc Vermoulu +STR_DTLS :Ce parc historique ne peut accueillir que des attractions de style ancien. + + +STR_SCNR :Parc Icarus +STR_PARK :Parc Icarus +STR_DTLS :Développez ce parc extraterrestre afin d'en maximiser les profits. + + +STR_SCNR :Marais Radieux +STR_PARK :Marais Radieux +STR_DTLS :Ce parc à thème bien choisi possède déjà quelques attractions, mais aussi une grande surface à exploiter. + + +STR_SCNR :Monts Epouvante +STR_PARK :Monts Epouvante +STR_DTLS :Un parc d'horreur dont le clou est un circuit de montagnes russes géant. + + +STR_SCNR :Rocs Fracas +STR_PARK :Rocs Fracas +STR_DTLS :Deux rochers émergeant du sable supportent les premiers éléments d'un parc à thème. + + +STR_SCNR :Parc Octogone +STR_PARK :Parc Octogone +STR_DTLS :Vous devez concevoir et construire dix montagnes russes dans ce vaste parc. + + +STR_SCNR :Îles Délices +STR_PARK :Îles Délices +STR_DTLS :Un vrai défi : implanter une sélection de montagnes russes sur une île longue et étroite. + + +STR_SCNR :Mondes Gelés +STR_PARK :Mondes Gelés +STR_DTLS :Vous devez transformer ce paysage glacé en parc à thème prospère. + + +STR_SCNR :Sable Austral +STR_PARK :Sable Austral +STR_DTLS :Vous devez étendre un parc désertique possédant déjà quelques montagnes russes intelligemment conçues. + + +STR_SCNR :Tours Ténues +STR_PARK :Tours Ténues +STR_DTLS :Vous devez achever la construction des cinq montagnes russes de ce tout petit parc. + + +STR_SCNR :Parc Nevermore +STR_PARK :Parc Nevermore +STR_DTLS :Un vaste parc entouré d'un nouveau mode de transport. + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :Développez un parc d'amusement sur cette grande île. + + +STR_SCNR :Jungle Urbaine +STR_PARK :Jungle Urbaine +STR_DTLS :Un gratte-ciel géant à l'abandon : une occasion unique pour un concepteur de parc à thème. + + +STR_SCNR :Faubourg du Frisson +STR_PARK :Faubourg du Frisson +STR_DTLS :Développez un parc d'amusement dans cette zone urbaine. + + +STR_SCNR :Parc Mégagiga +STR_PARK :Parc Mégagiga +STR_DTLS :Un parc géant déjà rempli d'attractions exige des améliorations. + + +STR_SCNR :Mare Veneris +STR_PARK :Mare Veneris +STR_DTLS :Vous devez aménager en parc à thème ce terrain situé sur une planète lointaine. + + +STR_SCNR :Micro Parc +STR_PARK :Micro Parc +STR_DTLS :Essayez de créer le plus petit parc bénéficiaire du monde. + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronisme +STR_PARK :Fort Anachronisme +STR_DTLS : + +##################### +# Rides/attractions # +##################### + +#WW +[CONDORRD] +STR_NAME :Le condor +STR_DESC :Les passagers sont couchés à plat ventre dans une voiture en forme de condor se déplaçant sur un monorail et se balançant d'un côté à l'autre dans les virages +STR_CPTY :4 passagers par voiture diff --git a/data/language/german.txt b/data/language/german.txt index 0a20a28754..a9d98de25d 100644 --- a/data/language/german.txt +++ b/data/language/german.txt @@ -848,7 +848,7 @@ STR_0843 : STR_0844 : STR_0845 : STR_0846 : -STR_0847 :Infos zu `OpenRCT2' +STR_0847 :Über `OpenRCT2' STR_0848 :RollerCoaster Tycoon 2 STR_0849 :{WINDOW_COLOUR_2}Version 2.01.032 STR_0850 :{WINDOW_COLOUR_2}Copyright {COPYRIGHT} 2002 Chris Sawyer, alle Rechte vorbehalten @@ -1197,7 +1197,7 @@ STR_1192 :{OUTLINE}{RED}{STRINGID} STR_1193 :{WINDOW_COLOUR_2}{STRINGID} STR_1194 :Geschlossen STR_1195 :Testlauf -STR_1196 :Offen +STR_1196 :Geöffnet STR_1197 :Defekt STR_1198 :Verunglückt! STR_1199 :{COMMA16} Person auf Fahrt @@ -1657,7 +1657,7 @@ STR_1652 :{SMALLFONT}{OPENQUOTES}Ich bin ja so aufgeregt - eine Bahn von Inta STR_1653 :{SMALLFONT}{OPENQUOTES}...und hier sind wir bei d. {STRINGID}!{ENDQUOTES} STR_1654 :{WINDOW_COLOUR_2}Aktuelle Gedanken: STR_1655 :{SMALLFONT}{BLACK}Fußweg auf Gelände anlegen -STR_1656 :{SMALLFONT}{BLACK}Brücke bauen oder Tunnelfußweg anlegen +STR_1656 :{SMALLFONT}{BLACK}Brücke bauen oder Tunnel anlegen STR_1657 :{WINDOW_COLOUR_2}Bevorzugte Bahn- STR_1658 :{WINDOW_COLOUR_2}intensität: {BLACK}weniger als {COMMA16} STR_1659 :{WINDOW_COLOUR_2}intensität: {BLACK}zwischen {COMMA16} und {COMMA16} @@ -1713,8 +1713,8 @@ STR_1708 :{SMALLFONT}{BLACK}Patrouillenbereich für diesen{NEWLINE}Mitarbeite STR_1709 :Mitarbeiter entlassen STR_1710 :Ja STR_1711 :{WINDOW_COLOUR_1}Möchten Sie {STRINGID} wirklich entlassen? -STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Fußwege kehren -STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Beete wässern +STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Fußwege fegen +STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Beete bewässern STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Mülleimer leeren STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Gras mähen STR_1716 :Ungültiger Name für Park @@ -1778,7 +1778,7 @@ STR_1773 :Nur ein Fahrtfoto-Bereich pro Bahn erlaubt STR_1774 :Nur ein Kabellifthügel pro Bahn erlaubt STR_1775 :Aus STR_1776 :Ein -STR_1777 :{WINDOW_COLOUR_2}Musik +STR_1777 :{WINDOW_COLOUR_2}Attraktionsmusik STR_1778 :{STRINGID} - - STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Pandakostüm STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tigerkostüm @@ -1793,7 +1793,7 @@ STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Sheriffkostüm STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Piratenkostüm STR_1790 :{SMALLFONT}{BLACK}Uniformfarbe für diesen{NEWLINE}Mitarbeiter auswählen STR_1791 :{WINDOW_COLOUR_2}Uniformfarbe: -STR_1792 :Antwortet auf Störung von {STRINGID} +STR_1792 :Unterwegs zur Reparatur von {STRINGID} STR_1793 :Unterwegs zur Inspektion von {STRINGID} STR_1794 :Repariert {STRINGID} STR_1795 :Beantwortet einen Funkspruch @@ -1877,8 +1877,8 @@ STR_1872 :{COMMA16} STR_1873 :{WINDOW_COLOUR_2}Einkünfte: {BLACK}{CURRENCY2DP} pro Stunde STR_1874 :{WINDOW_COLOUR_2}Gewinn: {BLACK}{CURRENCY2DP} pro Stunde STR_1875 :{BLACK} {SPRITE}{BLACK} {STRINGID} -STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Bahnen inspizieren -STR_1877 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{252}{19}{00}{00}Bahnen reparieren +STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Attraktionen inspizieren +STR_1877 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{252}{19}{00}{00}Attraktionen reparieren STR_1878 :{WINDOW_COLOUR_2}Inspektion: STR_1879 :Alle 10 Minuten STR_1880 :Alle 20 Minuten @@ -1887,7 +1887,7 @@ STR_1882 :Alle 45 Minuten STR_1883 :Jede Stunde STR_1884 :Alle 2 Stunden STR_1885 :Nie -STR_1886 :Inspektion bei {STRINGID} +STR_1886 :Inspiziert {STRINGID} STR_1887 :{WINDOW_COLOUR_2}Letzte Inspektion vor: {BLACK}{COMMA16} Minuten STR_1888 :{WINDOW_COLOUR_2}Letzte Inspektion vor: {BLACK}mehr als 4 Stunden STR_1889 :{WINDOW_COLOUR_2}Ausfallzeit: {MOVE_X}{255}{BLACK}{COMMA16}% @@ -1939,8 +1939,8 @@ STR_1934 :{STRINGID} hat {STRINGID} verlassen STR_1935 :{STRINGID} hat den Park verlassen STR_1936 :{STRINGID} hat {STRINGID} gekauft STR_1937 :{SMALLFONT}{BLACK}Informationen zum Thema dieser{NEWLINE}Nachricht anzeigen -STR_1938 :{SMALLFONT}{BLACK}Ansicht des Besuchers anzeigen -STR_1939 :{SMALLFONT}{BLACK}Ansicht des Mitarbeiters anzeigen +STR_1938 :{SMALLFONT}{BLACK}Ansicht des Besuchers +STR_1939 :{SMALLFONT}{BLACK}Ansicht des Mitarbeiters STR_1940 :{SMALLFONT}{BLACK}Vergnügen, Energie, Hunger, usw.{NEWLINE}dieses Besuchers anzeigen STR_1941 :{SMALLFONT}{BLACK}Gefahrene Bahnen dieses Besuchers anzeigen STR_1942 :{SMALLFONT}{BLACK}Finanzinformationen zu diesem{NEWLINE}Besucher anzeigen @@ -2225,8 +2225,8 @@ STR_2220 :{WINDOW_COLOUR_2}Parkbewertung: {BLACK}{COMMA16} STR_2221 :{SMALLFONT}{BLACK}Parkbewertung: {COMMA16} STR_2222 :{SMALLFONT}{BLACK}{STRINGID} STR_2223 :{WINDOW_COLOUR_2}Besucher im Park: {BLACK}{COMMA16} -STR_2224 :{WINDOW_COLOUR_2}Geld: {BLACK}{CURRENCY2DP} -STR_2225 :{WINDOW_COLOUR_2}Geld: {RED}{CURRENCY2DP} +STR_2224 :{WINDOW_COLOUR_2}Kontostand: {BLACK}{CURRENCY2DP} +STR_2225 :{WINDOW_COLOUR_2}Kontostand: {RED}{CURRENCY2DP} STR_2226 :{WINDOW_COLOUR_2}Verkehrswert: {BLACK}{CURRENCY} STR_2227 :{WINDOW_COLOUR_2}Firmenwert: {BLACK}{CURRENCY} STR_2228 :{WINDOW_COLOUR_2}Gewinne des letzten Monats aus Speisen/Getränke und {NEWLINE}-Werbeartikeln: {BLACK}{CURRENCY} @@ -2351,17 +2351,17 @@ STR_2346 :Anzeigen STR_2347 :{RED}{STRINGID} ist ertrunken! STR_2348 :{SMALLFONT}{BLACK}Statistiken für diesen Mitarbeiter anzeigen STR_2349 :{WINDOW_COLOUR_2}Lohn: {BLACK}{CURRENCY} pro Monat -STR_2350 :{WINDOW_COLOUR_2}Angestellt: {BLACK}{MONTHYEAR} -STR_2351 :{WINDOW_COLOUR_2}Gemähte Rasen: {BLACK}{COMMA16} +STR_2350 :{WINDOW_COLOUR_2}Angestellt seit: {BLACK}{MONTHYEAR} +STR_2351 :{WINDOW_COLOUR_2}Gemähte Rasenflächen: {BLACK}{COMMA16} STR_2352 :{WINDOW_COLOUR_2}Bewässerte Beete: {BLACK}{COMMA16} -STR_2353 :{WINDOW_COLOUR_2}Beseitigter Abfall: {BLACK}{COMMA16} +STR_2353 :{WINDOW_COLOUR_2}Gefegte Fußwege: {BLACK}{COMMA16} STR_2354 :{WINDOW_COLOUR_2}Geleerte Mülleimer: {BLACK}{COMMA16} -STR_2355 :{WINDOW_COLOUR_2}Reparierte Bahnen: {BLACK}{COMMA16} -STR_2356 :{WINDOW_COLOUR_2}Inspizierte Bahnen: {BLACK}{COMMA16} +STR_2355 :{WINDOW_COLOUR_2}Reparierte Attraktionen: {BLACK}{COMMA16} +STR_2356 :{WINDOW_COLOUR_2}Inspizierte Attraktionen: {BLACK}{COMMA16} STR_2357 :Haus STR_2358 :Einheiten STR_2359 :Echte Werte -STR_2360 :{WINDOW_COLOUR_2}Bildschirmauflösung: +STR_2360 :Bildschirmauflösung: STR_2361 :Landschaftsglättung STR_2362 :{SMALLFONT}{BLACK}Kantenglättung des Landschaftsquadrats ein-/ausschalten STR_2363 :Gitterlinien auf Landschaft @@ -2453,17 +2453,17 @@ STR_2448 :{YELLOW}Ihre Marketingkampagne für einen halben Parkeintrittspreis STR_2449 :{YELLOW}Ihre Marketingkampange für Gratis-{STRINGID} ist zu Ende STR_2450 :{YELLOW}Ihre Werbekampagne für den Park ist zu Ende STR_2451 :{YELLOW}Ihre Werbekampagne für d. {STRINGID} ist zu Ende -STR_2452 :{WINDOW_COLOUR_2}Geld (abzüglich Darlehen): {BLACK}{CURRENCY2DP} -STR_2453 :{WINDOW_COLOUR_2}Geld (abzüglich Darlehen): {RED}{CURRENCY2DP} +STR_2452 :{WINDOW_COLOUR_2}Kontostand (abzüglich Darlehen): {BLACK}{CURRENCY2DP} +STR_2453 :{WINDOW_COLOUR_2}Kontostand (abzüglich Darlehen): {RED}{CURRENCY2DP} STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - STR_2455 :{SMALLFONT}{BLACK}+{CURRENCY2DP} - STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} - STR_2457 :{SMALLFONT}{BLACK}Finanzkonten anzeigen -STR_2458 :{SMALLFONT}{BLACK}Gelddiagramm (abzüglich Darlehen){NEWLINE}im Zeitverlauf anzeigen +STR_2458 :{SMALLFONT}{BLACK}Kontostand (abzüglich Darlehen){NEWLINE}im Zeitverlauf anzeigen STR_2459 :{SMALLFONT}{BLACK}Verkehrswertdiagramm im{NEWLINE}Zeitverlauf anzeigen -STR_2460 :{SMALLFONT}{BLACK}Diagramm zu Wochengewinn anzeigen +STR_2460 :{SMALLFONT}{BLACK}Diagramm zum Wochengewinn anzeigen STR_2461 :{SMALLFONT}{BLACK}Marketingkampagnen anzeigen -STR_2462 :{SMALLFONT}{BLACK}Ansicht von Parkeingang anzeigen +STR_2462 :{SMALLFONT}{BLACK}Ansicht des Parkeingangs STR_2463 :{SMALLFONT}{BLACK}Parkbewertungsdiagramm{NEWLINE}im Zeitverlauf anzeigen STR_2464 :{SMALLFONT}{BLACK}Besucherzahlendiagramm{NEWLINE}im Zeitverlauf anzeigen STR_2465 :{SMALLFONT}{BLACK}Parkeintrittspreis und -informationen anzeigen @@ -2684,7 +2684,7 @@ STR_2677 :??? STR_2678 :??? STR_2679 :??? STR_2680 :Alle Forschungen beendet -STR_2681 :{MEDIUMFONT}{BLACK}Erhöht Ihr Geld um {CURRENCY} +STR_2681 :{MEDIUMFONT}{BLACK}Erhöht Ihren Kontostand um {CURRENCY} STR_2682 :{MEDIUMFONT}{BLACK}Zw. freiem und kostenpfl. Eintritt umsch. STR_2683 :{MEDIUMFONT}{BLACK}Erhöht das Vergnügen der Besucher maximal STR_2684 :{SMALLFONT}{BLACK}Eine große Gruppe von Besuchern tritt ein @@ -2754,15 +2754,15 @@ STR_2747 :{ENDQUOTES} STR_2748 :Leiste STR_2749 :Mein neues Szenario # New strings used in the cheats window previously these were ??? -STR_2750 :Alle Gegenstände nach oben bewegen -STR_2751 :Alle Gegenstände nach unten bewegen +STR_2750 :Alle Objekte nach oben bewegen +STR_2751 :Alle Objekte nach unten bewegen STR_2752 :Gras beseitigen STR_2753 :Rasen mähen STR_2754 :Pflanzen gießen STR_2755 :Vandalismus bes. STR_2756 :Müll beseitigen -STR_2757 :Schönes Wetter -STR_2758 :Gewitter +STR_2757 : +STR_2758 : STR_2759 :Höhen auf Null STR_2760 :+{CURRENCY} STR_2761 :Bezahlen für Eintritt @@ -2779,7 +2779,7 @@ STR_2771 :Zeit langsamer STR_2772 :Zeit schneller STR_2773 :Fenstermodus STR_2774 :Vollbild -STR_2775 :Vollbild (Desktop) +STR_2775 :Vollbild (Randlos) STR_2776 :Sprache: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} @@ -2805,7 +2805,7 @@ STR_2796 :{SMALLFONT}{BLACK}Sortieren Sie die Bahnliste in die richtige Reihe STR_2797 :Ansicht rollen, wenn Zeiger am Bildschirmrand ist STR_2798 :{SMALLFONT}{BLACK}Wählen Sie aus, ob die Ansicht gerollt werden soll, wenn sich der Mauszeiger am Bildschirmrand befindet STR_2799 :{SMALLFONT}{BLACK}Tastenkürzel anzeigen oder ändern -STR_2800 :{WINDOW_COLOUR_2}Besucher gesammt: {BLACK}{COMMA32} +STR_2800 :{WINDOW_COLOUR_2}Besucher gesamt: {BLACK}{COMMA32} STR_2801 :{WINDOW_COLOUR_2}Einkünfte d. Eintrittskarten: {BLACK}{CURRENCY2DP} STR_2802 :Karte STR_2803 :{SMALLFONT}{BLACK}Diese Besucher auf Karte hervorheben @@ -3233,7 +3233,7 @@ STR_3224 :{SMALLFONT}{BLACK}Legen Sie die Baurechte fest, die vom{NEWLINE}Par STR_3225 :{SMALLFONT}{BLACK}Bau einer zufälligen Objektgruppe{NEWLINE}um ausgewählte Position herum ein-/ausschalten STR_3226 :{SMALLFONT}{BLACK}Parkeingang bauen STR_3227 :Zu viele Parkeingänge! -STR_3228 :{SMALLFONT}{BLACK}Legen Sie die Startpositionen{NEWLINE}für Personen fest +STR_3228 :{SMALLFONT}{BLACK}Legen Sie die Startpositionen{NEWLINE}der Besucher fest STR_3229 :Blockbremsen können nicht unmittelbar nach der Station eingesetzt werden STR_3230 :Blockbremsen können nicht unmittelbar hintereinander eingesetzt werden STR_3231 :Blockbremsen können nicht unmittelbar nach der Anstiegsspitze eingesetzt werden @@ -3245,32 +3245,32 @@ STR_3236 :{SMALLFONT}{BLACK}Besucheroptionen anzeigen STR_3237 :{SMALLFONT}{BLACK}Parkoptionen anzeigen STR_3238 :Kein Geld STR_3239 :{SMALLFONT}{BLACK}Machen Sie diesen Park zu einem Park, bei dem keine finanziellen Einschränkungen gelten -STR_3240 :{WINDOW_COLOUR_2}Anfangsgeldstand: -STR_3241 :{WINDOW_COLOUR_2}Anfangsdarlehen: -STR_3242 :{WINDOW_COLOUR_2}Max. Darlehensgröße: +STR_3240 :{WINDOW_COLOUR_2}Kontostand zu Beginn: +STR_3241 :{WINDOW_COLOUR_2}Darlehen zu Beginn: +STR_3242 :{WINDOW_COLOUR_2}Maximales Darlehen: STR_3243 :{WINDOW_COLOUR_2}Jährliche Zinsrate: STR_3244 :Marketingkampagnen verbieten STR_3245 :{SMALLFONT}{BLACK}Werbung, Werbeschemas und sonstige Marketingkampagnen verbieten STR_3246 :{WINDOW_COLOUR_2}{CURRENCY} STR_3247 :{WINDOW_COLOUR_2}{COMMA16}% -STR_3248 :Anfangsgeldstand kann nicht weiter erhöht werden! -STR_3249 :Anfangsgeldstand kann nicht weiter reduziert werden! -STR_3250 :Anfangsdarlehen kann nicht weiter erhöht werden! -STR_3251 :Anfangsdarlehen kann nicht weiter reduziert werden! -STR_3252 :Max. Darlehensgröße kann nicht weiter erhöht werden! -STR_3253 :Max. Darlehensgröße kann nicht weiter reduziert werden! -STR_3254 :Zinsrate kann nicht weiter erhöht werden! -STR_3255 :Zinsrate kann nicht weiter reduziert werden! -STR_3256 :Weniger aufregendere Bahnen bevorzugt +STR_3248 :Anfangskontostand kann nicht{NEWLINE}weiter erhöht werden! +STR_3249 :Anfangskontostand kann nicht{NEWLINE}weiter reduziert werden! +STR_3250 :Anfangsdarlehen kann nicht{NEWLINE}weiter erhöht werden! +STR_3251 :Anfangsdarlehen kann nicht{NEWLINE}weiter reduziert werden! +STR_3252 :Maximales Darlehen kann nicht{NEWLINE}weiter erhöht werden! +STR_3253 :Maximales Darlehen kann nicht{NEWLINE}weiter reduziert werden! +STR_3254 :Zinsrate kann nicht weiter{NEWLINE}erhöht werden! +STR_3255 :Zinsrate kann nicht weiter{NEWLINE}reduziert werden! +STR_3256 :Weniger aufregende Bahnen bevorzugt STR_3257 :{SMALLFONT}{BLACK}Wählen Sie aus, ob die Besucher im Allgemeinen weniger aufregende{NEWLINE}Bahnen vorziehen STR_3258 :Aufregendere Bahnen bevorzugt STR_3259 :{SMALLFONT}{BLACK}Wählen Sie aus, ob die Besucher im Allgemeinen aufregendere{NEWLINE}Bahnen vorziehen STR_3260 :{WINDOW_COLOUR_2}Durchschnittliches Geld pro Besucher: -STR_3261 :{WINDOW_COLOUR_2}Anfangsvergnügen der Besucher: -STR_3262 :{WINDOW_COLOUR_2}Anfangshunger der Besucher: -STR_3263 :{WINDOW_COLOUR_2}Anfangsdurst der Besucher: -STR_3264 :Dies kann nicht weiter erhöht werden! -STR_3265 :Dies kann nicht weiter reduziert werden! +STR_3261 :{WINDOW_COLOUR_2}Vergnügen der Besucher zu Beginn: +STR_3262 :{WINDOW_COLOUR_2}Hunger der Besucher zu Beginn: +STR_3263 :{WINDOW_COLOUR_2}Durst der Besucher zu Beginn: +STR_3264 :Dies kann nicht weiter{NEWLINE}erhöht werden! +STR_3265 :Dies kann nicht weiter{NEWLINE}reduziert werden! STR_3266 :{SMALLFONT}{BLACK}Wählen Sie aus, was der Park für{NEWLINE}Eintritt und Fahrten verlangt STR_3267 :Entfernen von Bäumen verbieten STR_3268 :{SMALLFONT}{BLACK}Entfernen von hohen Bäumen verbieten @@ -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öherer Schwierigkeitsgrad für Parkbewertung STR_3274 :{SMALLFONT}{BLACK}Machen Sie die Parkbewertung schwieriger -STR_3275 :Höhere Schwierigkeitsstufe für Besuchergewinnung +STR_3275 :Höherer 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: @@ -3319,7 +3319,7 @@ STR_3310 :{WINDOW_COLOUR_2}{LENGTH} STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} STR_3312 :{WINDOW_COLOUR_2}Attraktionen unter Beibehaltungsauftrag: STR_3313 :Szenarioname -STR_3314 :Namen für Szenario eingeben: +STR_3314 :Namen für dieses Szenario eingeben: STR_3315 :Park-/Szenariodetails STR_3316 :Beschreibung für dieses Szenario eingeben: STR_3317 :Noch keine Details @@ -3329,7 +3329,7 @@ STR_3320 :Szenariodatei kann nicht gespeichert werden... STR_3321 :Neue Objekte erfolgreich installiert STR_3322 :{WINDOW_COLOUR_2}Ziel: {BLACK}{STRINGID} STR_3323 :Fehlende Objektdaten, ID: -STR_3324 :Erfordert Add-On-Pack: +STR_3324 :Erfordert Add-On-Pack: {STRINGID} STR_3325 :Erfordert ein Add-On-Pack STR_3326 :{WINDOW_COLOUR_2}(kein Bild) STR_3327 :Startpositionen für Personen nicht eingestellt @@ -3343,9 +3343,9 @@ STR_3334 :{SMALLFONT}{BLACK}Wählen Sie aus, ob zusätzliche Plugin-Objektdat STR_3335 :Achterbahn-Designer - Bahnarten & Fahrzeuge auswählen STR_3336 :Streckenentwurf-Manager - Bahnart auswählen STR_3337 :Six Flags-Park -STR_3338 :{BLACK}Eigenes Layout -STR_3339 :{BLACK}{COMMA16} Entwurf verfügbar oder eigenes Layout -STR_3340 :{BLACK}{COMMA16} Entwürfe verfügbar oder eigenes Layout +STR_3338 :{BLACK}Eigenes Layout entwerfen +STR_3339 :{BLACK}{COMMA16} Entwurf verfügbar oder eigenes Layout entwerfen +STR_3340 :{BLACK}{COMMA16} Entwürfe verfügbar oder eigenes Layout entwerfen STR_3341 :{SMALLFONT}{BLACK}Spielwerkzeuge STR_3342 :Szenario-Editor STR_3343 :Gespeichertes Spiel in Szenario umwandeln @@ -3460,7 +3460,7 @@ STR_5123 :Bahnen erneuern STR_5124 :Keine Six Flags STR_5125 :Alles zerstörbar STR_5126 :Zufällige Titelmusik -STR_5127 :{SMALLFONT}{BLACK}Höhenanpassung deaktivieren +STR_5127 :{SMALLFONT}{BLACK}Während dem Ziehen wird die Landschaft angemalt, ohne die Höhe zu verändern STR_5128 :Auswahlgröße STR_5129 :Auswahlgröße zwischen {COMMA16} und {COMMA16} eingeben: STR_5130 :Kartengröße @@ -3470,7 +3470,7 @@ STR_5133 :{SMALLFONT}{BLACK}Kleineren Landbereich anpassen STR_5134 :{SMALLFONT}{BLACK}Größeren Landbereich anpassen STR_5135 :{SMALLFONT}{BLACK}Kaufe Land- und Baurechte STR_5136 :Landrechte -STR_5137 :Erlaube Lifthügel- und Antriebsgeschw.{NEWLINE}bis zu {VELOCITY} +STR_5137 :Betriebsbeschränkungen aufheben STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} STR_5140 :Deaktiviere Bremsenfehlfunktion @@ -3510,7 +3510,7 @@ STR_5173 :Erhalte Twitch-Chat als Spielnachrichten STR_5174 :{SMALLFONT}{BLACK}Benutzt Twitch-Chatnachrichten, welchen !news vorangestellt ist, für Spielbenachrichtigungen STR_5175 :Namen Ihres Twitch-Kanals eingeben: STR_5176 :Twitch-Integration aktivieren -STR_5177 :Vollbildmodus: +STR_5177 :Bildschirmmodus: STR_5178 :{SMALLFONT}{BLACK}Cheats für Finanzen anzeigen STR_5179 :{SMALLFONT}{BLACK}Cheats für Parkbesucher anzeigen STR_5180 :{SMALLFONT}{BLACK}Cheats für Park anzeigen @@ -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 @@ -3889,7 +3889,7 @@ STR_5552 :{POP16}{POP16}Jahr {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {M STR_5553 :Spiel bei geöffnetem Steam Overlay pausieren STR_5554 :{SMALLFONT}{BLACK}Gebirgswerkzeug aktivieren STR_5555 :Fahrzeuge anderer Streckentyp. anzeigen -STR_5556 :Spieler entfernen +STR_5556 :{SMALLFONT}{BLACK}Spieler entfernen STR_5557 :Nach Desync. verbunden bleiben (Mehrspieler) STR_5558 :Damit diese Einstellung wirksam wird, ist ein Neustart erforderlich STR_5559 :10 Min. Inspektionen @@ -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 @@ -3914,6 +3914,633 @@ STR_5577 :Südkoreanischer Won (W) STR_5578 :Russischer Rubel (R) STR_5579 :Skalierungsfaktor: STR_5580 :Tschechische Krone (Kc) +STR_5581 :FPS anzeigen +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... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Geld ausgegeben: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Befehle ausgeführt: {BLACK}{COMMA16} +STR_5637 :Nicht möglich... +STR_5638 :Keine Berechtigung +STR_5639 :{SMALLFONT}{BLACK}Spielerliste anzeigen +STR_5640 :{SMALLFONT}{BLACK}Gruppen verwalten +STR_5641 :Standardgruppe: +STR_5642 :Gruppe: +STR_5643 :Gruppe hinzuf. +STR_5644 :Gruppe entf. +STR_5645 :Chat +STR_5646 :Landschaft anpassen +STR_5647 :Spiel pausieren/fortsetzen +STR_5648 :Wasserniveau festlegen +STR_5649 :Attraktion entwerfen +STR_5650 :Attraktion abreißen +STR_5651 :Attraktion bauen +STR_5652 :Attraktionseigenschaften +STR_5653 :Szenerie +STR_5654 :Fußwege +STR_5655 :Besucher +STR_5656 :Mitarbeiter +STR_5657 :Parkeigenschaften +STR_5658 :Parkfinanzierung +STR_5659 :Spieler entfernen +STR_5660 :Gruppen anpassen +STR_5661 :Spielergruppe festlegen +STR_5662 :N/A +STR_5663 :Landschaft leeren +STR_5664 :Cheats +STR_5665 :Bau Szenerie-Objektgruppe ein-/ausschalten +STR_5701 :{WINDOW_COLOUR_2}Letzte Aktion: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Lokalisiert die letzte Aktion des Spielers +STR_5703 :Host kann nicht entfernt werden +STR_5704 :Letzte Aktion: +STR_5705 :Diese Gruppe kann nicht{NEWLINE}eingestellt werden +STR_5706 :Diese Gruppe kann nicht entfernt werden, solange ihr Spieler angehören +STR_5707 :Diese Gruppe kann nicht{NEWLINE}angepasst werden +STR_5708 :Die Gruppe des Hosts kann{NEWLINE}nicht geändert werden +STR_5709 :Gruppe umbenen. +STR_5710 :Gruppenname +STR_5711 :Neuen Namen für diese Gruppe eingeben: +STR_5712 :Berechtigung kann nicht bearbeitet werden, da Sie diese selbst nicht besitzen +STR_5713 :Spieler entfernen +STR_5714 :Optionen anzeigen +STR_5715 :Neues Spiel +STR_5716 :Im Mehrspielermodus nicht erlaubt +STR_5717 :Netzwerkversion: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Netzwerkversion: {STRING} +STR_5719 :Sonnig +STR_5720 :Teilweise bewölkt +STR_5721 :Bewölkt +STR_5722 :Regen +STR_5723 :Starker Regen +STR_5724 :Gewitter +STR_5725 :{BLACK}Wetter erzwingen: +STR_5726 :{SMALLFONT}{BLACK}Stellt das aktuelle Wetter im Park ein +STR_5727 :Skalierungsmethode: +STR_5728 :Setzt Anzeige durch Hardware voraus +STR_5729 :{SMALLFONT}{BLACK}Setzt Anzeige durch Hardware voraus +STR_5730 :Pixelwiederholung +STR_5731 :Linear +STR_5732 :Anisotrop +STR_5733 :Pixelwdh. bei ganzzahligem Skalierungsfaktor +STR_5734 :{SMALLFONT}{BLACK}Darstellung +STR_5735 :Netzwerkstatus +STR_5736 :Spieler +STR_5737 :Geschlossen, noch {COMMA16} Person auf Fahrt +STR_5738 :Geschlossen, noch {COMMA16} Personen auf Fahrt +STR_5739 :{WINDOW_COLOUR_2}Besucher auf Fahrt: {BLACK}{COMMA16} +STR_5740 :Dauerhafte Marketingkampagnen +STR_5741 :{SMALLFONT}{BLACK}Marketingkampagnen sind dauerhaft +STR_5742 :Authentifizieren ... +STR_5743 :Verbinden ... +STR_5744 :Auflösen ... +STR_5745 :Netzwerkdesynchronisation entdeckt +STR_5746 :Getrennt +STR_5747 :Getrennt: {STRING} +STR_5748 :Gekickt +STR_5749 :Verschwinde vom Server! +STR_5750 :Verbindung geschlossen +STR_5751 :Keine Daten +STR_5752 :{OUTLINE}{RED}{STRING} hat das Spiel verlassen +STR_5753 :{OUTLINE}{RED}{STRING} hat das Spiel verlassen ({STRING}) +STR_5754 :Unzulässiger Spielername +STR_5755 :Inkompatible Softwareversion +STR_5756 :Falsches Passwort +STR_5757 :Server voll +STR_5758 :{OUTLINE}{GREEN}{STRING} hat das Spiel betreten +STR_5759 :Karte herunterladen ... ({INT32} / {INT32}) +STR_5760 :Hongkong-Dollar (HK$) +STR_5761 :Neuer Taiwan-Dollar (NT$) +STR_5762 :Chinesischer Yuan (CN{YEN}) +STR_5763 :Alle Dateien +STR_5764 :Ungültiger Bahntyp +STR_5765 :Kann Bahnen eines ungültigen Typs nicht bearbeiten +STR_5766 : +STR_5767 :Einkünfte +STR_5768 :Besucher gesamt +STR_5769 :Gesamtgewinn +STR_5770 :Besucher pro Stunde +STR_5771 :Betriebskosten +STR_5772 :Alter +STR_5773 :Besucher gesamt: {COMMA32} +STR_5774 :Gesamtgewinn: {CURRENCY2DP} +STR_5775 :Besucher: {COMMA32} pro Stunde +STR_5776 :Erbaut: Dieses Jahr +STR_5777 :Erbaut: Letztes Jahr +STR_5778 :Erbaut: Vor {COMMA16} Jahren +STR_5779 :Einkünfte: {CURRENCY2DP} pro Stunde +STR_5780 :Betriebskosten: {CURRENCY2DP} pro Stunde +STR_5781 :Betriebskosten: Unbekannt +STR_5782 :Sie sind jetzt verbunden. Drücken Sie '{STRING}' um zu chatten. +STR_5783 :{WINDOW_COLOUR_2}Szenario gesperrt +STR_5784 :{BLACK}Vorhergehende Szenarios abschließen, um dieses Szenario freizuschalten. +STR_5785 :Gruppe kann nicht umbenannt werden... +STR_5786 :Ungültiger Gruppenname +STR_5787 :{COMMA32} Spieler online +STR_5788 :Standardinspektionszeit: +STR_5789 :Blitzeffekt deaktivieren +STR_5790 :{SMALLFONT}{BLACK}(De-)Aktiviert die RCT1-Preisgestaltung{NEWLINE}(z.B. Fahrtpreis und Parkeintrittspreis festlegen) +STR_5791 :{SMALLFONT}{BLACK}Setzt die Zuverlässigkeit aller Attraktionen auf 100% und setzt ihr Baujahr auf "Dieses Jahr" zurück +STR_5792 :{SMALLFONT}{BLACK}Repariert alle defekten Attraktionen +STR_5793 :{SMALLFONT}{BLACK}Setzt die Unfallhistorie zurück, sodass sich Besucher nicht länger über unsichere Attraktionen beschweren +STR_5794 :{SMALLFONT}{BLACK}Einige Szenarien verbieten das Bearbeiten einiger bereits gebauten Attraktionen. Dieser Cheat hebt diese{NEWLINE}Beschränkung auf +STR_5795 :{SMALLFONT}{BLACK}Besucher fahren mit jeder Attraktion, auch wenn die Intensität extrem hoch ist +STR_5796 :{SMALLFONT}{BLACK}Zwingt den Park zu schließen/öffnen +STR_5797 :{SMALLFONT}{BLACK}Deaktiviert Wetterveränderungen und{NEWLINE}friert das ausgewählte Wetter ein +STR_5798 :{SMALLFONT}{BLACK}Erlaubt das Bauen im Pausenmodus +STR_5799 :{SMALLFONT}{BLACK}Verhindert einen Defekt oder Unfall, einer Attraktion, durch fehlerhafte Bremsen +STR_5800 :{SMALLFONT}{BLACK}Verhindert, dass Attraktionen ausfallen + +############# +# Scenarios # +################ +# RCT Original # +################ + +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. + + +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. + + +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. + + +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. + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Wandeln Sie die schönen Evergreen Gardens in einen gut besuchten Freizeitpark um. + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Machen Sie aus dem kleinen Vergnügungspark Bumbly Beach einen florierenden Freizeitpark. + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Mehrere Inseln bilden den Ausgangspunkt für diesen neuen Park. + + +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. + + +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. + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :Dieser Park mit verschiedenen hervorragenden Wasser-Attraktionen hat einen Ausbau nötig. + + +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. + + +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. + + +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. + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :Bauen Sie in den bergigen Wäldern der Mystic Mountains einen neuen Freizeitpark. + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Verwandeln Sie die Touristenattraktion mit ägyptischen Ruinen in einen erfolgreichen Freizeitpark. + + +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. + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :Verwandeln Sie die Anlegestelle dieser verschlafenen Stadt in einen wohlbekannten und gutgehenden Anziehungspunkt. + + +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. + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :Ein gut geführter Park, der jedoch ein paar Probleme hat. + + +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. + + +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. + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Nur zum Spaß! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Lassen Sie in diesen Klippen am Meer einen florierenden Vergnügungspark entstehen. + + +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. + + +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. + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :Wandeln Sie eine alte, nicht mehr benutzte Brücke in einen attraktiven Park um. + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :In diesem Park zu beiden Seiten einer Autobahn sind bereits verschiedene Attraktionen in Betrieb. + + +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. + + +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. + + +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. + + +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. + + +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. + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :Eine Reihe terrassenförmig angeordneter Seen sind der Ausgangsort für den neuen Park. + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :Dieser ältere Park besitzt viele historisch interessante Attraktionen, ist aber hoch verschuldet. + + +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. + + +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. + + +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. + + +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. + + +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. + + +STR_SCNR :Harmonic Hills +STR_PARK :Harmonic Hills +STR_DTLS :Die Baubehörde dieser Gegend erlaubt in diesem Park keine Konstruktionen über Baumhöhe. + + +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. + + +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. + + +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. + + +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. + + +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? + + +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. + + +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. + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :Eine vierspurige Bahn mit Renncharakter ist das Herzstück dieses aufstrebenden Parks. + + +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. + + +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. + + +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. + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :Eine große gepflegte Parkanlage soll in einen erfolgreichen Themenpark umgestaltet werden. + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :Eine Anzahl Eisberge bilden die kalte Umgebung dieses anspruchsvollen Parkprojekts. + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :Ein untätiger Vulkan fordert geradezu heraus, an ihm eine Achterbahnanlage zu bauen. + + +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. + + +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. + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :Ein großer See in einem alten Krater ist Ausgangspunkt für diesen Park. + + +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. + + +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. + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :Eine Meeresbucht ist der Rahmen für dieses anspruchsvolle Achterbahn-Bauvorhaben. + + +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. + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :Ein Park, dessen Gehwege und Achterbahnen größtenteils unterirdisch angelegt sind. + + +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. + + +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. + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Fünf Achterbahnen müssen in diesem Wüstenpark fertiggestellt werden. + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :In diesem historischen Park dürfen nur Attraktionen im altmodischen Stil gebaut werden. + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Verbessern Sie diesen außerirdischen Park, damit höchste Erträge erzielt werden. + + +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. + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :Ein Gruselpark mit einer Riesenachterbahn als Herzstück. + + +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. + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In diesem weitläufigen Park sollen Sie zehn große Achterbahnen entwerfen und konstruieren. + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :Diese lange, schmale Insel ist Anreiz genug, eine Auswahl an Achterbahnen zu errichten. + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :Eine Eislandschaft soll in einen florierenden Vergnügungspark verwandelt werden. + + +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. + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In diesem winzigen Park sollten Sie die fünf angefangenen Achterbahnen fertigstellen. + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :Ein großer Park mit einem neuartigen Transportsystem, das durch die Randbereiche führt. + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :Diese große Insel steht zu Ihrer Verfügung, machen Sie einen Vergnügungspark daraus. + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :Ein gigantischer, verlassener Wolkenkratzer ist eine einmalige Gelegenheit für einen Vergnügungsparkbetreiber. + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :Aus diesem Stadtgebiet können Sie einen Vergnügungspark zaubern. + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :Ein ausgedehnter Park, der bereits mit Attraktionen vollgepackt ist, bedarf der Verbesserung. + + +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. + + +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 + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : ####################### # Bahnen/Attraktionen # diff --git a/data/language/japanese.txt b/data/language/japanese.txt new file mode 100644 index 0000000000..82e72edd34 --- /dev/null +++ b/data/language/japanese.txt @@ -0,0 +1,3931 @@ +# STR_XXXX part is read and XXXX becomes the string id number. +# Everything after the colon and before the new line will be saved as the string. +# Use # at the beginning of a line to leave a comment. +STR_0000 : +STR_0001 :{STRINGID} {COMMA16} +STR_0002 :スパイラルコースター +STR_0003 :スタンディングコースター +STR_0004 :揺れるサスペンデッドコースター +STR_0005 :インバーテッドコースター +STR_0006 :ジュニアジェットコースター +STR_0007 :ミニ列車 +STR_0008 :モノレール +STR_0009 :ミニサスペンデッドコースター +STR_0010 :船乗り +STR_0011 :木製ワイルドマウス +STR_0012 :ジャンプレース +STR_0013 :ドライブ +STR_0014 :打ち上げフリーフォール +STR_0015 :ボブスレーコースター +STR_0016 :展望塔 +STR_0017 :ループコースター +STR_0018 :ゴムボート滑り台 +STR_0019 :暴走トロッコ +STR_0020 :スキーリフト +STR_0021 :コルクスクリューコースター +STR_0022 :迷路 +STR_0023 :スパイラル滑り台 +STR_0024 :ゴーカート +STR_0025 :ログ・フリューム +STR_0026 :川の急流 +STR_0027 :バンパーカー +STR_0028 :海賊船 +STR_0029 :揺れるインバータバイキング +STR_0030 :食べ物の屋台 +STR_0031 :Unknown Stall (1D) +STR_0032 :飲み物の屋台 +STR_0033 :Unknown Stall (1F) +STR_0034 :ショップ +STR_0035 :メリーゴーラウンド +STR_0036 :Unknown Stall (22) +STR_0037 :案内所 +STR_0038 :トイレ +STR_0039 :観覧車 +STR_0040 :モーションシミュレーター +STR_0041 :3Dシネマ +STR_0042 :トップスピン +STR_0043 :スペースリング +STR_0044 :リバースフリーフォールコースター +STR_0045 :エレベーター +STR_0046 :バーティカルドロップジェットコースター +STR_0047 :ATM +STR_0048 :ツイスト +STR_0049 :お化け屋敷 +STR_0050 :救護所 +STR_0051 :サーカス +STR_0052 :幻の列車 +STR_0053 :鋼鉄ツイスタージェットコースター +STR_0054 :木製ジェットコースター +STR_0055 :サイドフリクションジェットコースター +STR_0056 :ワイルドマウス +STR_0057 :多次元ジェットコースター +STR_0058 :Unknown Ride (38) +STR_0059 :フライングジェットコースター +STR_0060 :Unknown Ride (3A) +STR_0061 :バージニア・リール +STR_0062 :スプラッシュ・ボート +STR_0063 :ミニヘリコプター +STR_0064 :Lay-down Roller Coaster +STR_0065 :サスペンデッドモノレール +STR_0066 :Unknown Ride (40) +STR_0067 :リバーサージェットコースター +STR_0068 :ハートラインツイスターコースター +STR_0069 :ミニチュアゴルフ +STR_0070 :ギガコースター +STR_0071 :ロトドロップ +STR_0072 :空飛ぶ円盤 +STR_0073 :ねじれた家 +STR_0074 :Monorail Cycles +STR_0075 :コンパクト倒立コースター +STR_0076 :ウォーターコースター +STR_0077 :エアパワード垂直コースター +STR_0078 :倒立ヘアピンコースター +STR_0079 :魔法のじゅうたん +STR_0080 :潜水艦ライド +STR_0081 :River Rafts +STR_0082 :Unknown Ride (50) +STR_0083 :エンタープライズ +STR_0084 :Unknown Ride (52) +STR_0085 :Unknown Ride (53) +STR_0086 :Unknown Ride (54) +STR_0087 :Unknown Ride (55) +STR_0088 :倒立インパルスコースター +STR_0089 :ミニジェットコースター +STR_0090 :Mine Ride +STR_0091 :Unknown Ride (59) +STR_0092 :LIM Launched Roller Coaster +STR_0093 : +STR_0094 : +STR_0095 : +STR_0096 : +STR_0097 : +STR_0098 : +STR_0099 : +STR_0100 : +STR_0101 : +STR_0102 : +STR_0103 : +STR_0104 : +STR_0105 : +STR_0106 : +STR_0107 : +STR_0108 : +STR_0109 : +STR_0110 : +STR_0111 : +STR_0112 : +STR_0113 : +STR_0114 : +STR_0115 : +STR_0116 : +STR_0117 : +STR_0118 : +STR_0119 : +STR_0120 : +STR_0121 : +STR_0122 : +STR_0123 : +STR_0124 : +STR_0125 : +STR_0126 : +STR_0127 : +STR_0128 : +STR_0129 : +STR_0130 : +STR_0131 : +STR_0132 : +STR_0133 : +STR_0134 : +STR_0135 : +STR_0136 : +STR_0137 : +STR_0138 : +STR_0139 : +STR_0140 : +STR_0141 : +STR_0142 : +STR_0143 : +STR_0144 : +STR_0145 : +STR_0146 : +STR_0147 : +STR_0148 : +STR_0149 : +STR_0150 : +STR_0151 : +STR_0152 : +STR_0153 : +STR_0154 : +STR_0155 : +STR_0156 : +STR_0157 : +STR_0158 : +STR_0159 : +STR_0160 : +STR_0161 : +STR_0162 : +STR_0163 : +STR_0164 : +STR_0165 : +STR_0166 : +STR_0167 : +STR_0168 : +STR_0169 : +STR_0170 : +STR_0171 : +STR_0172 : +STR_0173 : +STR_0174 : +STR_0175 : +STR_0176 : +STR_0177 : +STR_0178 : +STR_0179 : +STR_0180 : +STR_0181 : +STR_0182 : +STR_0183 : +STR_0184 : +STR_0185 : +STR_0186 : +STR_0187 : +STR_0188 : +STR_0189 : +STR_0190 : +STR_0191 : +STR_0192 : +STR_0193 : +STR_0194 : +STR_0195 : +STR_0196 : +STR_0197 : +STR_0198 : +STR_0199 : +STR_0200 : +STR_0201 : +STR_0202 : +STR_0203 : +STR_0204 : +STR_0205 : +STR_0206 : +STR_0207 : +STR_0208 : +STR_0209 : +STR_0210 : +STR_0211 : +STR_0212 : +STR_0213 : +STR_0214 : +STR_0215 : +STR_0216 : +STR_0217 : +STR_0218 : +STR_0219 : +STR_0220 : +STR_0221 : +STR_0222 : +STR_0223 : +STR_0224 : +STR_0225 : +STR_0226 : +STR_0227 : +STR_0228 : +STR_0229 : +STR_0230 : +STR_0231 : +STR_0232 : +STR_0233 : +STR_0234 : +STR_0235 : +STR_0236 : +STR_0237 : +STR_0238 : +STR_0239 : +STR_0240 : +STR_0241 : +STR_0242 : +STR_0243 : +STR_0244 : +STR_0245 : +STR_0246 : +STR_0247 : +STR_0248 : +STR_0249 : +STR_0250 : +STR_0251 : +STR_0252 : +STR_0253 : +STR_0254 : +STR_0255 : +STR_0256 : +STR_0257 : +STR_0258 : +STR_0259 : +STR_0260 : +STR_0261 : +STR_0262 : +STR_0263 : +STR_0264 : +STR_0265 : +STR_0266 : +STR_0267 : +STR_0268 : +STR_0269 : +STR_0270 : +STR_0271 : +STR_0272 : +STR_0273 : +STR_0274 : +STR_0275 : +STR_0276 : +STR_0277 : +STR_0278 : +STR_0279 : +STR_0280 : +STR_0281 : +STR_0282 : +STR_0283 : +STR_0284 : +STR_0285 : +STR_0286 : +STR_0287 : +STR_0288 : +STR_0289 : +STR_0290 : +STR_0291 : +STR_0292 : +STR_0293 : +STR_0294 : +STR_0295 : +STR_0296 : +STR_0297 : +STR_0298 : +STR_0299 : +STR_0300 : +STR_0301 : +STR_0302 : +STR_0303 : +STR_0304 : +STR_0305 : +STR_0306 : +STR_0307 : +STR_0308 : +STR_0309 : +STR_0310 : +STR_0311 : +STR_0312 : +STR_0313 : +STR_0314 : +STR_0315 : +STR_0316 : +STR_0317 : +STR_0318 : +STR_0319 : +STR_0320 : +STR_0321 : +STR_0322 : +STR_0323 : +STR_0324 : +STR_0325 : +STR_0326 : +STR_0327 : +STR_0328 : +STR_0329 : +STR_0330 : +STR_0331 : +STR_0332 : +STR_0333 : +STR_0334 : +STR_0335 : +STR_0336 : +STR_0337 : +STR_0338 : +STR_0339 : +STR_0340 : +STR_0341 : +STR_0342 : +STR_0343 : +STR_0344 : +STR_0345 : +STR_0346 : +STR_0347 : +STR_0348 : +STR_0349 : +STR_0350 : +STR_0351 : +STR_0352 : +STR_0353 : +STR_0354 : +STR_0355 : +STR_0356 : +STR_0357 : +STR_0358 : +STR_0359 : +STR_0360 : +STR_0361 : +STR_0362 : +STR_0363 : +STR_0364 : +STR_0365 : +STR_0366 : +STR_0367 : +STR_0368 : +STR_0369 : +STR_0370 : +STR_0371 : +STR_0372 : +STR_0373 : +STR_0374 : +STR_0375 : +STR_0376 : +STR_0377 : +STR_0378 : +STR_0379 : +STR_0380 : +STR_0381 : +STR_0382 : +STR_0383 : +STR_0384 : +STR_0385 : +STR_0386 : +STR_0387 : +STR_0388 : +STR_0389 : +STR_0390 : +STR_0391 : +STR_0392 : +STR_0393 : +STR_0394 : +STR_0395 : +STR_0396 : +STR_0397 : +STR_0398 : +STR_0399 : +STR_0400 : +STR_0401 : +STR_0402 : +STR_0403 : +STR_0404 : +STR_0405 : +STR_0406 : +STR_0407 : +STR_0408 : +STR_0409 : +STR_0410 : +STR_0411 : +STR_0412 : +STR_0413 : +STR_0414 : +STR_0415 : +STR_0416 : +STR_0417 : +STR_0418 : +STR_0419 : +STR_0420 : +STR_0421 : +STR_0422 : +STR_0423 : +STR_0424 : +STR_0425 : +STR_0426 : +STR_0427 : +STR_0428 : +STR_0429 : +STR_0430 : +STR_0431 : +STR_0432 : +STR_0433 : +STR_0434 : +STR_0435 : +STR_0436 : +STR_0437 : +STR_0438 : +STR_0439 : +STR_0440 : +STR_0441 : +STR_0442 : +STR_0443 : +STR_0444 : +STR_0445 : +STR_0446 : +STR_0447 : +STR_0448 : +STR_0449 : +STR_0450 : +STR_0451 : +STR_0452 : +STR_0453 : +STR_0454 : +STR_0455 : +STR_0456 : +STR_0457 : +STR_0458 : +STR_0459 : +STR_0460 : +STR_0461 : +STR_0462 : +STR_0463 : +STR_0464 : +STR_0465 : +STR_0466 : +STR_0467 : +STR_0468 : +STR_0469 : +STR_0470 : +STR_0471 : +STR_0472 : +STR_0473 : +STR_0474 : +STR_0475 : +STR_0476 : +STR_0477 : +STR_0478 : +STR_0479 : +STR_0480 : +STR_0481 : +STR_0482 : +STR_0483 : +STR_0484 : +STR_0485 : +STR_0486 : +STR_0487 : +STR_0488 : +STR_0489 : +STR_0490 : +STR_0491 : +STR_0492 : +STR_0493 : +STR_0494 : +STR_0495 : +STR_0496 : +STR_0497 : +STR_0498 : +STR_0499 : +STR_0500 : +STR_0501 : +STR_0502 : +STR_0503 : +STR_0504 : +STR_0505 : +STR_0506 : +STR_0507 : +STR_0508 : +STR_0509 : +STR_0510 : +STR_0511 : +STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. +STR_0513 :A looping roller coaster where the riders ride in a standing position +STR_0514 :Trains suspended beneath the roller coaster track swing out to the side around corners +STR_0515 :A steel roller coaster with trains that are held beneath the track, with many complex and twisting track elements +STR_0516 :A gentle roller coaster for people who haven't yet got the courage to face the larger rides +STR_0517 :Passengers ride in miniature trains along a narrow-gauge railway track +STR_0518 :Passengers travel in electric trains along a monorail track +STR_0519 :Passengers ride in small cars hanging beneath the single-rail track, swinging freely from side to side around corners +STR_0520 :A dock platform where guests can drive/row personal watercraft on a body of water +STR_0521 :A fast and twisting roller coaster with tight turns and steep drops. Intensity is bound to be high. +STR_0522 :A smaller roller coaster where the riders sit above the track with no car around them +STR_0523 :Riders travel slowly in powered vehicles along a track-based route +STR_0524 :Freefall car is pneumatically launched up a tall steel tower and then allowed to freefall down +STR_0525 :Riders career down a twisting track guided only by the curvature and banking of the semi-circular track +STR_0526 :Passengers travel in a rotating observation cabin which travels up a tall tower +STR_0527 :A smooth steel-tracked roller coaster capable of vertical loops +STR_0528 :Riders travel in inflatable dinghies down a twisting semi-circular or completely enclosed tube track +STR_0529 :Mine train themed roller coaster trains career along steel roller coaster track made to look like old railway track +STR_0530 :Cars hang from a steel cable which runs continuously from one end of the ride to the other and back again +STR_0531 :A compact steel-tracked roller coaster where the train travels through corkscrews and loops +STR_0532 : +STR_0533 : +STR_0534 :Self-drive petrol-engined go karts +STR_0535 :Log-shaped boats travel along a water channel, splashing down steep slopes to soak the riders +STR_0536 :Circular boats meander along a wide water channel, splashing through waterfalls and thrilling riders through foaming rapids +STR_0537 : +STR_0538 : +STR_0539 : +STR_0540 : +STR_0541 : +STR_0542 : +STR_0543 : +STR_0544 : +STR_0545 : +STR_0546 : +STR_0547 : +STR_0548 : +STR_0549 : +STR_0550 : +STR_0551 : +STR_0552 : +STR_0553 : +STR_0554 :The car is accelerated out of the station along a long level track using Linear Induction Motors, then heads straight up a vertical spike of track, freefalling back down to return to the station +STR_0555 :Guests ride in an elevator up or down a vertical tower to get from one level to another +STR_0556 :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_0557 : +STR_0558 : +STR_0559 : +STR_0560 : +STR_0561 : +STR_0562 :Powered cars travel along a multi-level track past spooky scenery and special effects +STR_0563 :Sitting in comfortable trains with only simple lap restraints riders enjoy giant smooth drops and twisting track as well as plenty of 'air time' over the hills +STR_0564 :Running on wooden track, this coaster is fast, rough, noisy, and gives an 'out of control' riding experience with plenty of 'air time' +STR_0565 :A simple wooden roller coaster capable of only gentle slopes and turns, where the cars are only kept on the track by side friction wheels and gravity +STR_0566 :Individual roller coaster cars zip around a tight zig-zag layout of track with sharp corners and short sharp drops +STR_0567 :Sitting in seats suspended either side of the track, riders are pitched head-over-heels while they plunge down steep drops and travel through various inversions +STR_0568 : +STR_0569 :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air +STR_0570 : +STR_0571 :Circular cars spin around as they travel along the zig-zagging wooden track +STR_0572 :Large capacity boats travel along a wide water channel, propelled up slopes by a conveyer belt, accelerating down steep slopes to soak the riders with a gaint splash +STR_0573 :Powered helicoper shaped cars running on a steel track, controlled by the pedalling of the riders +STR_0574 :Riders are held in special harnesses in a lying-down position, travlling through twisted track and inversions either on their backs or facing the ground +STR_0575 :Powered trains hanging from a single rail transport people around the park +STR_0576 : +STR_0577 :Bogied cars run on wooden tracks, turning around on special reversing sections +STR_0578 :Cars run along track enclosed by circular hoops, traversing steep drops and heartline twists +STR_0579 : +STR_0580 :A giant steel roller coaster capable of smooth drops and hills of over 300ft +STR_0581 :A ring of seats is pulled to the top of a tall tower while gently rotating, then allowed to free-fall down, stopping gently at the bottom using magnetic brakes +STR_0582 : +STR_0583 : +STR_0584 :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders +STR_0585 :Riders sit in pairs of seats suspended beneath the track as they loop and twist through tight inversions +STR_0586 :Boat shaped cars run on roller coaster track to allow twisting curves and steep drops, splashing down into sections of water for gentle river sections +STR_0587 :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station +STR_0588 :Individual cars run beneath a zig-zagging track with hairpin turns and sharp drops +STR_0589 : +STR_0590 :Riders ride in a submerged submarine through an underwater course +STR_0591 :Raft-shaped boats gently meander around a river track +STR_0592 : +STR_0593 : +STR_0594 : +STR_0595 : +STR_0596 : +STR_0597 : +STR_0598 :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track +STR_0599 :A compact roller coaster with individual cars and smooth twisting drops +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 :来客{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 :修理工 {INT32} +STR_0770 :警備員 {INT32} +STR_0771 :Entertainer {INT32} +STR_0772 :Unnamed park{POP16}{POP16} +STR_0773 :Unnamed park{POP16}{POP16} +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 :バナー +STR_0779 :1日 +STR_0780 :2日 +STR_0781 :3日 +STR_0782 :4日 +STR_0783 :5日 +STR_0784 :6日 +STR_0785 :7日 +STR_0786 :8日 +STR_0787 :9日 +STR_0788 :10日 +STR_0789 :11日 +STR_0790 :12日 +STR_0791 :13日 +STR_0792 :14日 +STR_0793 :15日 +STR_0794 :16日 +STR_0795 :17日 +STR_0796 :18日 +STR_0797 :19日 +STR_0798 :20日 +STR_0799 :21日 +STR_0800 :22日 +STR_0801 :23日 +STR_0802 :24日 +STR_0803 :25日 +STR_0804 :26日 +STR_0805 :27日 +STR_0806 :28日 +STR_0807 :29日 +STR_0808 :30日 +STR_0809 :31日 +STR_0810 :1月 +STR_0811 :2月 +STR_0812 :3月 +STR_0813 :4月 +STR_0814 :5月 +STR_0815 :6月 +STR_0816 :7月 +STR_0817 :8月 +STR_0818 :9月 +STR_0819 :10月 +STR_0820 :11月 +STR_0821 :12月 +STR_0822 :Unable to access graphic data file +STR_0823 :Missing or inaccessible data file +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}ウィンドウを閉める +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 +STR_0837 :Unable to initialise graphics system +STR_0838 : +STR_0839 :{UINT16} x {UINT16} +STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16} +# The following six strings were used for display resolutions, but have been replaced. +STR_0841 : +STR_0842 : +STR_0843 : +STR_0844 : +STR_0845 : +STR_0846 : +STR_0847 :OpenRCT2について +STR_0848 :RollerCoaster Tycoon 2 +STR_0849 :{WINDOW_COLOUR_2}Version 2.01.028 +STR_0850 :{WINDOW_COLOUR_2}Copyright {COPYRIGHT} 2002 Chris Sawyer, all rights reserved +STR_0851 :{WINDOW_COLOUR_2}Designed and programmed by Chris Sawyer +STR_0852 :{WINDOW_COLOUR_2}Graphics by Simon Foster +STR_0853 :{WINDOW_COLOUR_2}Sound and music by Allister Brimble +STR_0854 :{WINDOW_COLOUR_2}Additional sounds recorded by David Ellis +STR_0855 :{WINDOW_COLOUR_2}Representation by Jacqui Lyons at Marjacq Ltd. +STR_0856 :{WINDOW_COLOUR_2}Thanks to: +STR_0857 :{WINDOW_COLOUR_2}Peter James Adcock, Joe Booth, and John Wardley +STR_0858 :{WINDOW_COLOUR_2} +STR_0859 :{WINDOW_COLOUR_2} +STR_0860 :{WINDOW_COLOUR_2} +STR_0861 : +STR_0862 : +STR_0863 : +STR_0864 : +STR_0865 :{STRINGID} +STR_0866 :{POP16}{STRINGID} +STR_0867 :{POP16}{POP16}{STRINGID} +STR_0868 :{POP16}{POP16}{POP16}{STRINGID} +STR_0869 :{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_0870 :{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_0871 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_0872 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_0873 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_0874 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_0875 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_0876 :{BLACK}{DOWN} +STR_0877 :低すぎる! +STR_0878 :高すぎる! +STR_0879 :Can't lower land here... +STR_0880 :Can't raise land here... +STR_0881 :Object in the way +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 :スクリーンショット +STR_0892 :Screenshot saved to disk as '{STRINGID}' +STR_0893 :Screenshot failed ! +STR_0894 :Landscape data area full ! +STR_0895 :Can't build partly above and partly below ground +STR_0896 :{POP16}{POP16}{STRINGID} Construction +STR_0897 :Direction +STR_0898 :{SMALLFONT}{BLACK}Left-hand curve +STR_0899 :{SMALLFONT}{BLACK}Right-hand curve +STR_0900 :{SMALLFONT}{BLACK}Left-hand curve (small radius) +STR_0901 :{SMALLFONT}{BLACK}Right-hand curve (small radius) +STR_0902 :{SMALLFONT}{BLACK}Left-hand curve (very small radius) +STR_0903 :{SMALLFONT}{BLACK}Right-hand curve (very small radius) +STR_0904 :{SMALLFONT}{BLACK}Left-hand curve (large radius) +STR_0905 :{SMALLFONT}{BLACK}Right-hand curve (large radius) +STR_0906 :{SMALLFONT}{BLACK}Straight +STR_0907 :Slope +STR_0908 :Roll/Banking +STR_0909 :Seat Rot. +STR_0910 :{SMALLFONT}{BLACK}Roll for left-hand curve +STR_0911 :{SMALLFONT}{BLACK}Roll for right-hand curve +STR_0912 :{SMALLFONT}{BLACK}No roll +STR_0913 :{SMALLFONT}{BLACK}Move to previous section +STR_0914 :{SMALLFONT}{BLACK}Move to next section +STR_0915 :{SMALLFONT}{BLACK}Construct the selected section +STR_0916 :{SMALLFONT}{BLACK}Remove the highlighted section +STR_0917 :{SMALLFONT}{BLACK}Vertical drop +STR_0918 :{SMALLFONT}{BLACK}Steep slope down +STR_0919 :{SMALLFONT}{BLACK}Slope down +STR_0920 :{SMALLFONT}{BLACK}Level +STR_0921 :{SMALLFONT}{BLACK}Slope up +STR_0922 :{SMALLFONT}{BLACK}Steep slope up +STR_0923 :{SMALLFONT}{BLACK}Vertical rise +STR_0924 :{SMALLFONT}{BLACK}Helix down +STR_0925 :{SMALLFONT}{BLACK}Helix up +STR_0926 :Can't remove this... +STR_0927 :Can't construct this here... +STR_0928 :{SMALLFONT}{BLACK}Chain lift, to pull cars up slopes +STR_0929 :'S' Bend (left) +STR_0930 :'S' Bend (right) +STR_0931 :Vertical Loop (left) +STR_0932 :Vertical Loop (right) +STR_0933 :Raise or lower land first +STR_0934 :Ride entrance in the way +STR_0935 :Ride exit in the way +STR_0936 :Park entrance in the way +STR_0937 :{SMALLFONT}{BLACK}View options +STR_0938 :{SMALLFONT}{BLACK}Adjust land height and slope +STR_0939 :Underground/Inside View +STR_0940 :Remove Base Land +STR_0941 :Remove Vertical Faces +STR_0942 :See-Through Rides +STR_0943 :See-Through Scenery +STR_0944 :保存する +STR_0945 :保存しない +STR_0946 :キャンセル +STR_0947 :ロードする前に保存しますか? +STR_0948 :終了する前に保存しますか? +STR_0949 :終了する前に保存しますか? +STR_0950 :ゲームをリロードする +STR_0951 :ゲームを閉じる +STR_0952 :ゲームを閉じる +STR_0953 :Load Landscape +STR_0954 : +STR_0955 :{SMALLFONT}{BLACK}Select seat rotation angle for this track section +STR_0956 :-180{DEGREE} +STR_0957 :-135{DEGREE} +STR_0958 :-90{DEGREE} +STR_0959 :-45{DEGREE} +STR_0960 :0{DEGREE} +STR_0961 :+45{DEGREE} +STR_0962 :+90{DEGREE} +STR_0963 :+135{DEGREE} +STR_0964 :+180{DEGREE} +STR_0965 :+225{DEGREE} +STR_0966 :+270{DEGREE} +STR_0967 :+315{DEGREE} +STR_0968 :+360{DEGREE} +STR_0969 :+405{DEGREE} +STR_0970 :+450{DEGREE} +STR_0971 :+495{DEGREE} +STR_0972 :キャンセル +STR_0973 :OK +STR_0974 :乗り物 +STR_0975 :Shops and Stalls +STR_0976 :トイレと案内所 +STR_0977 :New Transport Rides +STR_0978 :New Gentle Rides +STR_0979 :New Roller Coasters +STR_0980 :New Thrill Rides +STR_0981 :New Water Rides +STR_0982 :New Shops & Stalls +STR_0983 :Research & Development +STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP} +STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP} +STR_0986 :{BLACK}{CURRENCY2DP} +STR_0987 :Too many rides/attractions +STR_0988 :Can't create new ride/attraction... +STR_0989 :{STRINGID} +STR_0990 :{SMALLFONT}{BLACK}Construction +STR_0991 :Station platform +STR_0992 :{SMALLFONT}{BLACK}Demolish entire ride/attraction +STR_0993 :Demolish ride/attraction +STR_0994 :Demolish +STR_0995 :{WINDOW_COLOUR_1}Are you sure you want to completely demolish {STRINGID}? +STR_0996 :Overall view +STR_0997 :{SMALLFONT}{BLACK}View selection +STR_0998 :No more stations allowed on this ride +STR_0999 :Requires a station platform +STR_1000 :Track is not a complete circuit +STR_1001 :Track unsuitable for type of train +STR_1002 :Can't open {POP16}{POP16}{POP16}{STRINGID}... +STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID}... +STR_1004 :Can't close {POP16}{POP16}{POP16}{STRINGID}... +STR_1005 :Can't start construction on {POP16}{POP16}{POP16}{STRINGID}... +STR_1006 :Must be closed first +STR_1007 :Unable to create enough vehicles +STR_1008 :{SMALLFONT}{BLACK}Open, close, or test ride/attraction +STR_1009 :{SMALLFONT}{BLACK}Open or close all rides/attractions +STR_1010 :{SMALLFONT}{BLACK}Open or close park +STR_1011 :Close all +STR_1012 :Open all +STR_1013 :Close park +STR_1014 :Open park +STR_1015 :Unable to operate with more than one station platform in this mode +STR_1016 :Unable to operate with less than two stations in this mode +STR_1017 :Can't change operating mode... +STR_1018 :Can't make changes... +STR_1019 :Can't make changes... +STR_1020 :Can't make changes... +STR_1021 :{POP16}{POP16}{POP16}{POP16}{STRINGID} +STR_1022 :{POP16}{POP16}{POP16}{COMMA16} car per train +STR_1023 :{POP16}{POP16}{POP16}{COMMA16} cars per train +STR_1024 :{COMMA16} car per train +STR_1025 :{COMMA16} cars per train +STR_1026 :Station platform too long! +STR_1027 :{SMALLFONT}{BLACK}Locate this on Main View +STR_1028 :Off edge of map! +STR_1029 :Cannot build partly above and partly below water! +STR_1030 :Can only build this underwater! +STR_1031 :Can't build this underwater! +STR_1032 :Can only build this on water! +STR_1033 :Can only build this above ground! +STR_1034 :Can only build this on land! +STR_1035 :Local authority won't allow construction above tree-height! +STR_1036 :Load Game +STR_1037 :Load Landscape +STR_1038 :Convert saved game to scenario +STR_1039 :Install new track design +STR_1040 :Save Game +STR_1041 :Save Scenario +STR_1042 :Save Landscape +STR_1043 :OpenRCT2 Saved Game +STR_1044 :OpenRCT2 Scenario File +STR_1045 :OpenRCT2 Landscape File +STR_1046 :OpenRCT2 Track Design File +STR_1047 :Game save failed! +STR_1048 :Scenario save failed! +STR_1049 :Landscape save failed! +STR_1050 :Failed to load...{NEWLINE}File contains invalid data! +STR_1051 :Invisible Supports +STR_1052 :Invisible People +STR_1053 :{SMALLFONT}{BLACK}Rides/attractions in park +STR_1054 :{SMALLFONT}{BLACK}Name ride/attraction +STR_1055 :{SMALLFONT}{BLACK}Name person +STR_1056 :{SMALLFONT}{BLACK}Name staff member +STR_1057 :Ride/attraction name +STR_1058 :Enter new name for this ride/attraction: +STR_1059 :Can't rename ride/attraction... +STR_1060 :Invalid ride/attraction name +STR_1061 :Normal mode +STR_1062 :Continuous circuit mode +STR_1063 :Reverse-Incline launched shuttle mode +STR_1064 :Powered launch (passing station) +STR_1065 :Shuttle mode +STR_1066 :Boat hire mode +STR_1067 :Upward launch +STR_1068 :Rotating lift mode +STR_1069 :Station to station mode +STR_1070 :Single ride per admission +STR_1071 :Unlimited rides per admission +STR_1072 :Maze mode +STR_1073 :Race mode +STR_1074 :Bumper-car mode +STR_1075 :Swing mode +STR_1076 :Shop stall mode +STR_1077 :Rotation mode +STR_1078 :Forward rotation +STR_1079 :Backward rotation +STR_1080 :Film: {ENDQUOTES}Avenging aviators{ENDQUOTES} +STR_1081 :3D film: {ENDQUOTES}Mouse tails{ENDQUOTES} +STR_1082 :Space rings mode +STR_1083 :Beginners mode +STR_1084 :LIM-powered launch +STR_1085 :Film: {ENDQUOTES}Thrill riders{ENDQUOTES} +STR_1086 :3D film: {ENDQUOTES}Storm chasers{ENDQUOTES} +STR_1087 :3D film: {ENDQUOTES}Space raiders{ENDQUOTES} +STR_1088 :Intense mode +STR_1089 :Berserk mode +STR_1090 :Haunted house mode +STR_1091 :Circus show mode +STR_1092 :Downward launch +STR_1093 :Crooked house mode +STR_1094 :Freefall drop mode +STR_1095 :Continuous circuit block sectioned mode +STR_1096 :Powered launch (without passing station) +STR_1097 :Powered launch block sectioned mode +STR_1098 :Moving to end of {POP16}{STRINGID} +STR_1099 :Waiting for passengers at {POP16}{STRINGID} +STR_1100 :Waiting to depart {POP16}{STRINGID} +STR_1101 :Departing {POP16}{STRINGID} +STR_1102 :Travelling at {VELOCITY} +STR_1103 :Arriving at {POP16}{STRINGID} +STR_1104 :Unloading passengers at {POP16}{STRINGID} +STR_1105 :Travelling at {VELOCITY} +STR_1106 :Crashing! +STR_1107 :Crashed! +STR_1108 :Travelling at {VELOCITY} +STR_1109 :Swinging +STR_1110 :回転中 +STR_1111 :回転中 +STR_1112 :Operating +STR_1113 :上映中 +STR_1114 :回転中 +STR_1115 :Operating +STR_1116 :Operating +STR_1117 :Doing circus show +STR_1118 :Operating +STR_1119 :Waiting for cable lift +STR_1120 :Travelling at {VELOCITY} +STR_1121 :Stopping +STR_1122 :Waiting for passengers +STR_1123 :Waiting to start +STR_1124 :Starting +STR_1125 :Operating +STR_1126 :Stopping +STR_1127 :Unloading passengers +STR_1128 :Stopped by block brakes +STR_1129 :All vehicles in same colours +STR_1130 :Different colours per {STRINGID} +STR_1131 :Different colours per vehicle +STR_1132 :Vehicle {POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1133 :Vehicle {POP16}{COMMA16} +STR_1134 :{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} {COMMA16} +STR_1135 :{STRINGID} {COMMA16} +STR_1136 :{SMALLFONT}{BLACK}Select main colour +STR_1137 :{SMALLFONT}{BLACK}Select additional colour 1 +STR_1138 :{SMALLFONT}{BLACK}Select additional colour 2 +STR_1139 :{SMALLFONT}{BLACK}Select support structure colour +STR_1140 :{SMALLFONT}{BLACK}Select vehicle colour scheme option +STR_1141 :{SMALLFONT}{BLACK}Select which vehicle/train to modify +STR_1142 :{MOVE_X}{SMALLFONT}{STRINGID} +STR_1143 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRINGID} +STR_1144 :Can't build/move entrance for this ride/attraction... +STR_1145 :Can't build/move exit for this ride/attraction... +STR_1146 :Entrance not yet built +STR_1147 :Exit not yet built +STR_1148 :Quarter load +STR_1149 :Half load +STR_1150 :Three-quarter load +STR_1151 :Full load +STR_1152 :Any load +STR_1153 :Height Marks on Ride Tracks +STR_1154 :Height Marks on Land +STR_1155 :Height Marks on Paths +STR_1156 :{MOVE_X}{SMALLFONT}{STRINGID} +STR_1157 :{TICK}{MOVE_X}{SMALLFONT}{STRINGID} +STR_1158 :Can't remove this... +STR_1159 :{SMALLFONT}{BLACK}Place scenery, gardens, and other accessories +STR_1160 :{SMALLFONT}{BLACK}Create/adjust lakes & water +STR_1161 :Can't position this here... +STR_1162 :{OUTLINE}{TOPAZ}{STRINGID} +STR_1163 :{STRINGID}{NEWLINE}(Right-Click to Modify) +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 :設定 +STR_1169 :(None) +STR_1170 :{STRING} +STR_1171 :{RED}Closed - - +STR_1172 :{YELLOW}{STRINGID} - - +STR_1173 :{SMALLFONT}{BLACK}Build footpaths and queue lines +STR_1174 :Banner sign in the way +STR_1175 :Can't build this on sloped footpath +STR_1176 :Can't build footpath here... +STR_1177 :Can't remove footpath from here... +STR_1178 :Land slope unsuitable +STR_1179 :Footpath in the way +STR_1180 :Can't build this underwater! +STR_1181 :Footpaths +STR_1182 :Type +STR_1183 :Direction +STR_1184 :Slope +STR_1185 :{SMALLFONT}{BLACK}Direction +STR_1186 :{SMALLFONT}{BLACK}Slope down +STR_1187 :{SMALLFONT}{BLACK}Level +STR_1188 :{SMALLFONT}{BLACK}Slope up +STR_1189 :{SMALLFONT}{BLACK}Construct the selected footpath section +STR_1190 :{SMALLFONT}{BLACK}Remove previous footpath section +STR_1191 :{BLACK}{STRINGID} +STR_1192 :{OUTLINE}{RED}{STRINGID} +STR_1193 :{WINDOW_COLOUR_2}{STRINGID} +STR_1194 :Closed +STR_1195 :Test Run +STR_1196 :Open +STR_1197 :Broken Down +STR_1198 :Crashed! +STR_1199 :{COMMA16} person on ride +STR_1200 :{COMMA16} people on ride +STR_1201 :Nobody in queue line +STR_1202 :1 person in queue line +STR_1203 :{COMMA16} people in queue line +STR_1204 :{COMMA16} minute queue time +STR_1205 :{COMMA16} minutes queue time +STR_1206 :{WINDOW_COLOUR_2}Wait for: +STR_1207 :{WINDOW_COLOUR_2}Leave if another train arrives at station +STR_1208 :{WINDOW_COLOUR_2}Leave if another boat arrives at station +STR_1209 :{SMALLFONT}{BLACK}Select whether should wait for passengers before departing +STR_1210 :{SMALLFONT}{BLACK}Select whether should leave if another vehicle arrives at the same station +STR_1211 :{WINDOW_COLOUR_2}Minimum waiting time: +STR_1212 :{WINDOW_COLOUR_2}Maximum waiting time: +STR_1213 :{SMALLFONT}{BLACK}Select minimum length of time to wait before departing +STR_1214 :{SMALLFONT}{BLACK}Select maximum length of time to wait before departing +STR_1215 :{WINDOW_COLOUR_2}Synchronise with adjacent stations +STR_1216 :{SMALLFONT}{BLACK}Select whether to synchronise departure with all adjacent stations (for 'racing') +STR_1217 :{COMMA16} seconds +STR_1218 :{BLACK}{SMALLUP} +STR_1219 :{BLACK}{SMALLDOWN} +STR_1220 :Exit only +STR_1221 :No entrance +STR_1222 :No exit +STR_1223 :{SMALLFONT}{BLACK}Transport rides +STR_1224 :{SMALLFONT}{BLACK}Gentle rides +STR_1225 :{SMALLFONT}{BLACK}Roller coasters +STR_1226 :{SMALLFONT}{BLACK}Thrill rides +STR_1227 :{SMALLFONT}{BLACK}Water rides +STR_1228 :{SMALLFONT}{BLACK}Shops & stalls +STR_1229 :train +STR_1230 :trains +STR_1231 :Train +STR_1232 :Trains +STR_1233 :{COMMA16} train +STR_1234 :{COMMA16} trains +STR_1235 :Train {COMMA16} +STR_1236 :boat +STR_1237 :boats +STR_1238 :Boat +STR_1239 :Boats +STR_1240 :{COMMA16} boat +STR_1241 :{COMMA16} boats +STR_1242 :Boat {COMMA16} +STR_1243 :track +STR_1244 :tracks +STR_1245 :Track +STR_1246 :Tracks +STR_1247 :{COMMA16} track +STR_1248 :{COMMA16} tracks +STR_1249 :Track {COMMA16} +STR_1250 :docking platform +STR_1251 :docking platforms +STR_1252 :Docking platform +STR_1253 :Docking platforms +STR_1254 :{COMMA16} docking platform +STR_1255 :{COMMA16} docking platforms +STR_1256 :Docking platform {COMMA16} +STR_1257 :station +STR_1258 :stations +STR_1259 :Station +STR_1260 :Stations +STR_1261 :{COMMA16} station +STR_1262 :{COMMA16} stations +STR_1263 :Station {COMMA16} +STR_1264 :car +STR_1265 :cars +STR_1266 :Car +STR_1267 :Cars +STR_1268 :{COMMA16} car +STR_1269 :{COMMA16} cars +STR_1270 :Car {COMMA16} +STR_1271 :building +STR_1272 :buildings +STR_1273 :Building +STR_1274 :Buildings +STR_1275 :{COMMA16} building +STR_1276 :{COMMA16} buildings +STR_1277 :Building {COMMA16} +STR_1278 :structure +STR_1279 :structures +STR_1280 :Structure +STR_1281 :Structures +STR_1282 :{COMMA16} structure +STR_1283 :{COMMA16} structures +STR_1284 :Structure {COMMA16} +STR_1285 :ship +STR_1286 :ships +STR_1287 :Ship +STR_1288 :Ships +STR_1289 :{COMMA16} ship +STR_1290 :{COMMA16} ships +STR_1291 :Ship {COMMA16} +STR_1292 :cabin +STR_1293 :cabins +STR_1294 :Cabin +STR_1295 :Cabins +STR_1296 :{COMMA16} cabin +STR_1297 :{COMMA16} cabins +STR_1298 :Cabin {COMMA16} +STR_1299 :wheel +STR_1300 :wheels +STR_1301 :Wheel +STR_1302 :Wheels +STR_1303 :{COMMA16} wheel +STR_1304 :{COMMA16} wheels +STR_1305 :Wheel {COMMA16} +STR_1306 :ring +STR_1307 :rings +STR_1308 :Ring +STR_1309 :Rings +STR_1310 :{COMMA16} ring +STR_1311 :{COMMA16} rings +STR_1312 :Ring {COMMA16} +STR_1313 :player +STR_1314 :players +STR_1315 :Player +STR_1316 :Players +STR_1317 :{COMMA16} player +STR_1318 :{COMMA16} players +STR_1319 :Player {COMMA16} +STR_1320 :course +STR_1321 :courses +STR_1322 :Course +STR_1323 :Courses +STR_1324 :{COMMA16} course +STR_1325 :{COMMA16} courses +STR_1326 :Course {COMMA16} +STR_1327 :{SMALLFONT}{BLACK}Rotate objects by 90{DEGREE} +STR_1328 :Level land required +STR_1329 :{WINDOW_COLOUR_2}Launch speed: +STR_1330 :{SMALLFONT}{BLACK}Maximum speed when leaving station +STR_1331 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} +STR_1332 :{VELOCITY} +STR_1333 :{STRINGID} - {STRINGID}{POP16} +STR_1334 :{STRINGID} - {STRINGID} {COMMA16} +STR_1335 :{STRINGID} - Entrance{POP16}{POP16} +STR_1336 :{STRINGID} - Station {POP16}{COMMA16} Entrance +STR_1337 :{STRINGID} - Exit{POP16}{POP16} +STR_1338 :{STRINGID} - Station {POP16}{COMMA16} Exit +STR_1339 :{BLACK}No test results yet... +STR_1340 :{WINDOW_COLOUR_2}Max. speed: {BLACK}{VELOCITY} +STR_1341 :{WINDOW_COLOUR_2}Ride time: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1342 :{DURATION} +STR_1343 :{DURATION} / +STR_1344 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1345 :{LENGTH} +STR_1346 :{LENGTH} / +STR_1347 :{WINDOW_COLOUR_2}Average speed: {BLACK}{VELOCITY} +STR_1348 :{WINDOW_COLOUR_2}Max. positive vertical G's: {BLACK}{COMMA2DP32}g +STR_1349 :{WINDOW_COLOUR_2}Max. positive vertical G's: {OUTLINE}{RED}{COMMA2DP32}g +STR_1350 :{WINDOW_COLOUR_2}Max. negative vertical G's: {BLACK}{COMMA2DP32}g +STR_1351 :{WINDOW_COLOUR_2}Max. negative vertical G's: {OUTLINE}{RED}{COMMA2DP32}g +STR_1352 :{WINDOW_COLOUR_2}Max. lateral G's: {BLACK}{COMMA2DP32}g +STR_1353 :{WINDOW_COLOUR_2}Max. lateral G's: {OUTLINE}{RED}{COMMA2DP32}g +STR_1354 :{WINDOW_COLOUR_2}Highest drop height: {BLACK}{LENGTH} +STR_1355 :{WINDOW_COLOUR_2}Drops: {BLACK}{COMMA16} +STR_1356 :{WINDOW_COLOUR_2}Inversions: {BLACK}{COMMA16} +STR_1357 :{WINDOW_COLOUR_2}Holes: {BLACK}{COMMA16} +STR_1358 :{WINDOW_COLOUR_2}Total 'air' time: {BLACK}{COMMA2DP32}secs +STR_1359 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minute +STR_1360 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minutes +STR_1361 :Can't change speed... +STR_1362 :Can't change launch speed... +STR_1363 :Too high for supports! +STR_1364 :Supports for track above can't be extended any further! +STR_1365 :In-line Twist (left) +STR_1366 :In-line Twist (right) +STR_1367 :Half Loop +STR_1368 :Half Corkscrew (left) +STR_1369 :Half Corkscrew (right) +STR_1370 :Barrel Roll (left) +STR_1371 :Barrel Roll (right) +STR_1372 :Launched Lift Hill +STR_1373 :Large Half Loop (left) +STR_1374 :Large Half Loop (right) +STR_1375 :Upper Transfer +STR_1376 :Lower Transfer +STR_1377 :Heartline Roll (left) +STR_1378 :Heartline Roll (right) +STR_1379 :Reverser (left) +STR_1380 :Reverser (right) +STR_1381 :Curved Lift Hill (left) +STR_1382 :Curved Lift Hill (right) +STR_1383 :Quarter Loop +STR_1384 :{YELLOW}{STRINGID} +STR_1385 :{SMALLFONT}{BLACK}Other track configurations +STR_1386 :Special... +STR_1387 :Can't change land type... +STR_1388 :{OUTLINE}{GREEN}+ {CURRENCY} +STR_1389 :{OUTLINE}{RED}- {CURRENCY} +STR_1390 :{CURRENCY2DP} +STR_1391 :{RED}{CURRENCY2DP} +STR_1392 :{SMALLFONT}{BLACK}View of ride/attraction +STR_1393 :{SMALLFONT}{BLACK}Vehicle details and options +STR_1394 :{SMALLFONT}{BLACK}Operating options +STR_1395 :{SMALLFONT}{BLACK}Maintenance options +STR_1396 :{SMALLFONT}{BLACK}Colour scheme options +STR_1397 :{SMALLFONT}{BLACK}Sound & music options +STR_1398 :{SMALLFONT}{BLACK}Measurements and test data +STR_1399 :{SMALLFONT}{BLACK}Graphs +STR_1400 :Entrance +STR_1401 :Exit +STR_1402 :{SMALLFONT}{BLACK}Build or move entrance to ride/attraction +STR_1403 :{SMALLFONT}{BLACK}Build or move exit from ride/attraction +STR_1404 :{SMALLFONT}{BLACK}Rotate 90{DEGREE} +STR_1405 :{SMALLFONT}{BLACK}Mirror image +STR_1406 :{SMALLFONT}{BLACK}Toggle scenery on/off (if available for this design) +STR_1407 :{WINDOW_COLOUR_2}Build this... +STR_1408 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY} +STR_1409 :Entry/Exit Platform +STR_1410 :Vertical Tower +STR_1411 :{STRINGID} in the way +STR_1412 :{WINDOW_COLOUR_3}Data logging not available for this type of ride +STR_1413 :{WINDOW_COLOUR_3}Data logging will start when next {STRINGID} leaves {STRINGID} +STR_1414 :{SMALLFONT}{BLACK}{DURATION} +STR_1415 :{WINDOW_COLOUR_2}Velocity +STR_1416 :{WINDOW_COLOUR_2}Altitude +STR_1417 :{WINDOW_COLOUR_2}Vert.G's +STR_1418 :{WINDOW_COLOUR_2}Lat.G's +STR_1419 :{SMALLFONT}{BLACK}{VELOCITY} +STR_1420 :{SMALLFONT}{BLACK}{LENGTH} +STR_1421 :{SMALLFONT}{BLACK}{COMMA16}g +STR_1422 :{SMALLFONT}{BLACK}Logging data from {POP16}{STRINGID} +STR_1423 :{SMALLFONT}{BLACK}Queue line path +STR_1424 :{SMALLFONT}{BLACK}Footpath +STR_1425 :Footpath +STR_1426 :Queue Line +STR_1427 :{WINDOW_COLOUR_2}Customers: {BLACK}{COMMA32} per hour +STR_1428 :{WINDOW_COLOUR_2}Admission price: +STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} +STR_1430 :無料 +STR_1431 :Walking +STR_1432 :Heading for {STRINGID} +STR_1433 :Queuing for {STRINGID} +STR_1434 :Drowning +STR_1435 :On {STRINGID} +STR_1436 :In {STRINGID} +STR_1437 :At {STRINGID} +STR_1438 :Sitting +STR_1439 :(select location) +STR_1440 :Mowing grass +STR_1441 :Sweeping footpath +STR_1442 :Emptying litter bin +STR_1443 :Watering gardens +STR_1444 :Watching {STRINGID} +STR_1445 :Watching construction of {STRINGID} +STR_1446 :Looking at scenery +STR_1447 :Leaving the park +STR_1448 :Watching new ride being constructed +STR_1449 :{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) +STR_1450 :{INLINE_SPRITE}{09}{20}{00}{00}{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) +STR_1451 :{STRINGID}{NEWLINE}({STRINGID}) +STR_1452 :Guest's name +STR_1453 :Enter name for this guest: +STR_1454 :Can't name guest... +STR_1455 :Invalid name for guest +STR_1456 :{WINDOW_COLOUR_2}Cash spent: {BLACK}{CURRENCY2DP} +STR_1457 :{WINDOW_COLOUR_2}Cash in pocket: {BLACK}{CURRENCY2DP} +STR_1458 :{WINDOW_COLOUR_2}Time in park: {BLACK}{REALTIME} +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 :来客 +STR_1464 :Helix up (small) +STR_1465 :Helix up (large) +STR_1466 :Helix down (small) +STR_1467 :Helix down (large) +STR_1468 :Staff +STR_1469 :Ride must start and end with stations +STR_1470 :Station not long enough +STR_1471 :{WINDOW_COLOUR_2}Speed: +STR_1472 :{SMALLFONT}{BLACK}Speed of this ride +STR_1473 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1474 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}Not yet available +STR_1475 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1476 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}Not yet available +STR_1477 :{WINDOW_COLOUR_2}Intensity rating: {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) +STR_1478 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1479 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}Not yet available +STR_1480 :{SMALLFONT}{OPENQUOTES}I can't afford {STRINGID}{ENDQUOTES} +STR_1481 :{SMALLFONT}{OPENQUOTES}I've spent all my money{ENDQUOTES} +STR_1482 :{SMALLFONT}{OPENQUOTES}I feel sick{ENDQUOTES} +STR_1483 :{SMALLFONT}{OPENQUOTES}I feel very sick{ENDQUOTES} +STR_1484 :{SMALLFONT}{OPENQUOTES}I want to go on something more thrilling than {STRINGID}{ENDQUOTES} +STR_1485 :{SMALLFONT}{OPENQUOTES}{STRINGID} looks too intense for me{ENDQUOTES} +STR_1486 :{SMALLFONT}{OPENQUOTES}I haven't finished my {STRINGID} yet{ENDQUOTES} +STR_1487 :{SMALLFONT}{OPENQUOTES}Just looking at {STRINGID} makes me feel sick{ENDQUOTES} +STR_1488 :{SMALLFONT}{OPENQUOTES}I'm not paying that much to go on {STRINGID}{ENDQUOTES} +STR_1489 :{SMALLFONT}{OPENQUOTES}I want to go home{ENDQUOTES} +STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} is really good value{ENDQUOTES} +STR_1491 :{SMALLFONT}{OPENQUOTES}I've already got {STRINGID}{ENDQUOTES} +STR_1492 :{SMALLFONT}{OPENQUOTES}I can't afford {STRINGID}{ENDQUOTES} +STR_1493 :{SMALLFONT}{OPENQUOTES}I'm not hungry{ENDQUOTES} +STR_1494 :{SMALLFONT}{OPENQUOTES}I'm not thirsty{ENDQUOTES} +STR_1495 :{SMALLFONT}{OPENQUOTES}Help! I'm drowning!{ENDQUOTES} +STR_1496 :{SMALLFONT}{OPENQUOTES}I'm lost!{ENDQUOTES} +STR_1497 :{SMALLFONT}{OPENQUOTES}{STRINGID} was great{ENDQUOTES} +STR_1498 :{SMALLFONT}{OPENQUOTES}I've been queuing for {STRINGID} for ages{ENDQUOTES} +STR_1499 :{SMALLFONT}{OPENQUOTES}I'm tired{ENDQUOTES} +STR_1500 :{SMALLFONT}{OPENQUOTES}I'm hungry{ENDQUOTES} +STR_1501 :{SMALLFONT}{OPENQUOTES}I'm thirsty{ENDQUOTES} +STR_1502 :{SMALLFONT}{OPENQUOTES}I need to go to the bathroom{ENDQUOTES} +STR_1503 :{SMALLFONT}{OPENQUOTES}I can't find {STRINGID}{ENDQUOTES} +STR_1504 :{SMALLFONT}{OPENQUOTES}I'm not paying that much to use {STRINGID}{ENDQUOTES} +STR_1505 :{SMALLFONT}{OPENQUOTES}I'm not going on {STRINGID} while it's raining{ENDQUOTES} +STR_1506 :{SMALLFONT}{OPENQUOTES}The litter here is really bad{ENDQUOTES} +STR_1507 :{SMALLFONT}{OPENQUOTES}I can't find the park exit{ENDQUOTES} +STR_1508 :{SMALLFONT}{OPENQUOTES}I want to get off {STRINGID}{ENDQUOTES} +STR_1509 :{SMALLFONT}{OPENQUOTES}I want to get out of {STRINGID}{ENDQUOTES} +STR_1510 :{SMALLFONT}{OPENQUOTES}I'm not going on {STRINGID} - It isn't safe{ENDQUOTES} +STR_1511 :{SMALLFONT}{OPENQUOTES}This path is disgusting{ENDQUOTES} +STR_1512 :{SMALLFONT}{OPENQUOTES}It's too crowded here{ENDQUOTES} +STR_1513 :{SMALLFONT}{OPENQUOTES}The vandalism here is really bad{ENDQUOTES} +STR_1514 :{SMALLFONT}{OPENQUOTES}Great scenery!{ENDQUOTES} +STR_1515 :{SMALLFONT}{OPENQUOTES}This park is really clean and tidy{ENDQUOTES} +STR_1516 :{SMALLFONT}{OPENQUOTES}The jumping fountains are great{ENDQUOTES} +STR_1517 :{SMALLFONT}{OPENQUOTES}The music is nice here{ENDQUOTES} +STR_1518 :{SMALLFONT}{OPENQUOTES}This balloon from {STRINGID} is really good value{ENDQUOTES} +STR_1519 :{SMALLFONT}{OPENQUOTES}This cuddly toy from {STRINGID} is really good value{ENDQUOTES} +STR_1520 :{SMALLFONT}{OPENQUOTES}This park map from {STRINGID} is really good value{ENDQUOTES} +STR_1521 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} +STR_1522 :{SMALLFONT}{OPENQUOTES}This umbrella from {STRINGID} is really good value{ENDQUOTES} +STR_1523 :{SMALLFONT}{OPENQUOTES}This drink from {STRINGID} is really good value{ENDQUOTES} +STR_1524 :{SMALLFONT}{OPENQUOTES}This burger from {STRINGID} is really good value{ENDQUOTES} +STR_1525 :{SMALLFONT}{OPENQUOTES}These chips from {STRINGID} are really good value{ENDQUOTES} +STR_1526 :{SMALLFONT}{OPENQUOTES}This ice cream from {STRINGID} is really good value{ENDQUOTES} +STR_1527 :{SMALLFONT}{OPENQUOTES}This candyfloss from {STRINGID} is really good value{ENDQUOTES} +STR_1528 : +STR_1529 : +STR_1530 : +STR_1531 :{SMALLFONT}{OPENQUOTES}This pizza from {STRINGID} is really good value{ENDQUOTES} +STR_1532 : +STR_1533 :{SMALLFONT}{OPENQUOTES}This popcorn from {STRINGID} is really good value{ENDQUOTES} +STR_1534 :{SMALLFONT}{OPENQUOTES}This hot dog from {STRINGID} is really good value{ENDQUOTES} +STR_1535 :{SMALLFONT}{OPENQUOTES}This tentacle from {STRINGID} is really good value{ENDQUOTES} +STR_1536 :{SMALLFONT}{OPENQUOTES}This hat from {STRINGID} is really good value{ENDQUOTES} +STR_1537 :{SMALLFONT}{OPENQUOTES}This toffee apple from {STRINGID} is really good value{ENDQUOTES} +STR_1538 :{SMALLFONT}{OPENQUOTES}This T-shirt from {STRINGID} is really good value{ENDQUOTES} +STR_1539 :{SMALLFONT}{OPENQUOTES}This doughnut from {STRINGID} is really good value{ENDQUOTES} +STR_1540 :{SMALLFONT}{OPENQUOTES}This coffee from {STRINGID} is really good value{ENDQUOTES} +STR_1541 : +STR_1542 :{SMALLFONT}{OPENQUOTES}This fried chicken from {STRINGID} is really good value{ENDQUOTES} +STR_1543 :{SMALLFONT}{OPENQUOTES}This lemonade from {STRINGID} is really good value{ENDQUOTES} +STR_1544 : +STR_1545 : +STR_1546 : +STR_1547 : +STR_1548 : +STR_1549 : +STR_1550 :{SMALLFONT}{OPENQUOTES}Wow!{ENDQUOTES} +STR_1551 :{SMALLFONT}{OPENQUOTES}I have the strangest feeling someone is watching me{ENDQUOTES} +STR_1552 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a balloon from {STRINGID}{ENDQUOTES} +STR_1553 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a cuddly toy from {STRINGID}{ENDQUOTES} +STR_1554 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a park map from {STRINGID}{ENDQUOTES} +STR_1555 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} +STR_1556 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an umbrella from {STRINGID}{ENDQUOTES} +STR_1557 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a drink from {STRINGID}{ENDQUOTES} +STR_1558 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a burger from {STRINGID}{ENDQUOTES} +STR_1559 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for chips from {STRINGID}{ENDQUOTES} +STR_1560 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an ice cream from {STRINGID}{ENDQUOTES} +STR_1561 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for candyfloss from {STRINGID}{ENDQUOTES} +STR_1562 : +STR_1563 : +STR_1564 : +STR_1565 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for pizza from {STRINGID}{ENDQUOTES} +STR_1566 : +STR_1567 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for popcorn from {STRINGID}{ENDQUOTES} +STR_1568 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a hot dog from {STRINGID}{ENDQUOTES} +STR_1569 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for tentacle from {STRINGID}{ENDQUOTES} +STR_1570 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a hat from {STRINGID}{ENDQUOTES} +STR_1571 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a toffee apple from {STRINGID}{ENDQUOTES} +STR_1572 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a T-shirt from {STRINGID}{ENDQUOTES} +STR_1573 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a doughnut from {STRINGID}{ENDQUOTES} +STR_1574 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for coffee from {STRINGID}{ENDQUOTES} +STR_1575 : +STR_1576 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fried chicken from {STRINGID}{ENDQUOTES} +STR_1577 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for lemonade from {STRINGID}{ENDQUOTES} +STR_1578 : +STR_1579 : +STR_1580 : +STR_1581 : +STR_1582 : +STR_1583 : +STR_1584 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} +STR_1585 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} +STR_1586 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} +STR_1587 :{SMALLFONT}{OPENQUOTES}This pretzel from {STRINGID} is really good value{ENDQUOTES} +STR_1588 :{SMALLFONT}{OPENQUOTES}This hot chocolate from {STRINGID} is really good value{ENDQUOTES} +STR_1589 :{SMALLFONT}{OPENQUOTES}This iced tea from {STRINGID} is really good value{ENDQUOTES} +STR_1590 :{SMALLFONT}{OPENQUOTES}This funnel cake from {STRINGID} is really good value{ENDQUOTES} +STR_1591 :{SMALLFONT}{OPENQUOTES}These sunglasses from {STRINGID} are really good value{ENDQUOTES} +STR_1592 :{SMALLFONT}{OPENQUOTES}These beef noodles from {STRINGID} are really good value{ENDQUOTES} +STR_1593 :{SMALLFONT}{OPENQUOTES}These fried rice noodles from {STRINGID} are really good value{ENDQUOTES} +STR_1594 :{SMALLFONT}{OPENQUOTES}This wonton soup from {STRINGID} is really good value{ENDQUOTES} +STR_1595 :{SMALLFONT}{OPENQUOTES}This meatball soup from {STRINGID} is really good value{ENDQUOTES} +STR_1596 :{SMALLFONT}{OPENQUOTES}This fruit juice from {STRINGID} is really good value{ENDQUOTES} +STR_1597 :{SMALLFONT}{OPENQUOTES}This soybean milk from {STRINGID} is really good value{ENDQUOTES} +STR_1598 :{SMALLFONT}{OPENQUOTES}This sujongkwa from {STRINGID} is really good value{ENDQUOTES} +STR_1599 :{SMALLFONT}{OPENQUOTES}This sub sandwich from {STRINGID} is really good value{ENDQUOTES} +STR_1600 :{SMALLFONT}{OPENQUOTES}This cookie from {STRINGID} is really good value{ENDQUOTES} +STR_1601 : +STR_1602 : +STR_1603 : +STR_1604 :{SMALLFONT}{OPENQUOTES}This roast sausage from {STRINGID} are really good value{ENDQUOTES} +STR_1605 : +STR_1606 : +STR_1607 : +STR_1608 : +STR_1609 : +STR_1610 : +STR_1611 : +STR_1612 : +STR_1613 : +STR_1614 : +STR_1615 : +STR_1616 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} +STR_1617 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} +STR_1618 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} +STR_1619 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a pretzel from {STRINGID}{ENDQUOTES} +STR_1620 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for hot chocolate from {STRINGID}{ENDQUOTES} +STR_1621 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for iced tea from {STRINGID}{ENDQUOTES} +STR_1622 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a funnel cake from {STRINGID}{ENDQUOTES} +STR_1623 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sunglasses from {STRINGID}{ENDQUOTES} +STR_1624 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for beef noodles from {STRINGID}{ENDQUOTES} +STR_1625 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fried rice noodles from {STRINGID}{ENDQUOTES} +STR_1626 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for wonton soup from {STRINGID}{ENDQUOTES} +STR_1627 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for meatball soup from {STRINGID}{ENDQUOTES} +STR_1628 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fruit juice from {STRINGID}{ENDQUOTES} +STR_1629 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for soybean milk from {STRINGID}{ENDQUOTES} +STR_1630 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sujongkwa from {STRINGID}{ENDQUOTES} +STR_1631 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a sub sandwich from {STRINGID}{ENDQUOTES} +STR_1632 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a cookie from {STRINGID}{ENDQUOTES} +STR_1633 : +STR_1634 : +STR_1635 : +STR_1636 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a roast sausage from {STRINGID}{ENDQUOTES} +STR_1637 : +STR_1638 : +STR_1639 : +STR_1640 : +STR_1641 : +STR_1642 : +STR_1643 : +STR_1644 : +STR_1645 : +STR_1646 : +STR_1647 : +STR_1648 :{SMALLFONT}{OPENQUOTES}Help! Put me down!{ENDQUOTES} +STR_1649 :{SMALLFONT}{OPENQUOTES}I'm running out of cash!{ENDQUOTES} +STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! A new ride being built!{ENDQUOTES} +STR_1651 :{SMALLFONT}{OPENQUOTES}Nice ride! But not as good as the Phoenix...{ENDQUOTES} +STR_1652 :{SMALLFONT}{OPENQUOTES}I'm so excited - It's an Intamin ride!{ENDQUOTES} +STR_1653 :{SMALLFONT}{OPENQUOTES}...and here we are on {STRINGID}!{ENDQUOTES} +STR_1654 :{WINDOW_COLOUR_2}Recent thoughts: +STR_1655 :{SMALLFONT}{BLACK}Construct footpath on land +STR_1656 :{SMALLFONT}{BLACK}Construct bridge or tunnel footpath +STR_1657 :{WINDOW_COLOUR_2}Preferred ride +STR_1658 :{WINDOW_COLOUR_2}intensity: {BLACK}less than {COMMA16} +STR_1659 :{WINDOW_COLOUR_2}intensity: {BLACK}between {COMMA16} and {COMMA16} +STR_1660 :{WINDOW_COLOUR_2}intensity: {BLACK}more than {COMMA16} +STR_1661 :{WINDOW_COLOUR_2}Nausea tolerance: {BLACK}{STRINGID} +STR_1662 :{WINDOW_COLOUR_2}Happiness: +STR_1663 :{WINDOW_COLOUR_2}Nausea: +STR_1664 :{WINDOW_COLOUR_2}Energy: +STR_1665 :{WINDOW_COLOUR_2}Hunger: +STR_1666 :{WINDOW_COLOUR_2}Thirst: +STR_1667 :{WINDOW_COLOUR_2}Bathroom: +STR_1668 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}Unknown +STR_1669 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}{COMMA16}% +STR_1670 :{WINDOW_COLOUR_2}Total customers: {BLACK}{COMMA32} +STR_1671 :{WINDOW_COLOUR_2}Total profit: {BLACK}{CURRENCY2DP} +STR_1672 :Brakes +STR_1673 :Spinning Control Toggle Track +STR_1674 :Brake speed +STR_1675 :{POP16}{VELOCITY} +STR_1676 :{SMALLFONT}{BLACK}Set speed limit for brakes +STR_1677 :{WINDOW_COLOUR_2}Popularity: {BLACK}Unknown +STR_1678 :{WINDOW_COLOUR_2}Popularity: {BLACK}{COMMA16}% +STR_1679 :Helix up (left) +STR_1680 :Helix up (right) +STR_1681 :Helix down (left) +STR_1682 :Helix down (right) +STR_1683 :Base size 2 x 2 +STR_1684 :Base size 4 x 4 +STR_1685 :Base size 2 x 4 +STR_1686 :Base size 5 x 1 +STR_1687 :Water splash +STR_1688 :Base size 4 x 1 +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}来客 +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 :便利屋を雇います +STR_1701 :Hire new 修理工 +STR_1702 :Hire new Security Guard +STR_1703 :Hire new Entertainer +STR_1704 :Can't hire new staff... +STR_1705 :{SMALLFONT}{BLACK}Sack this staff member +STR_1706 :{SMALLFONT}{BLACK}Move this person to a new location +STR_1707 :Too many staff in game +STR_1708 :{SMALLFONT}{BLACK}Set patrol area for this staff member +STR_1709 :Sack staff +STR_1710 :はい +STR_1711 :{WINDOW_COLOUR_1}Are you sure you want to sack {STRINGID}? +STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Sweep footpaths +STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Water gardens +STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Empty litter bins +STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Mow grass +STR_1716 :Invalid name for park +STR_1717 :Can't rename park... +STR_1718 :Park Name +STR_1719 :Enter name for park: +STR_1720 :{SMALLFONT}{BLACK}Name park +STR_1721 :Park closed +STR_1722 :Park open +STR_1723 :Can't open park... +STR_1724 :Can't close park... +STR_1725 :Can't buy land... +STR_1726 :Land not for sale! +STR_1727 :Construction rights not for sale! +STR_1728 :Can't buy construction rights here... +STR_1729 :Land not owned by park! +STR_1730 :{RED}Closed - - +STR_1731 :{WHITE}{STRINGID} - - +STR_1732 :Build +STR_1733 :モード +STR_1734 :{WINDOW_COLOUR_2}Number of laps: +STR_1735 :{SMALLFONT}{BLACK}Number of laps of circuit +STR_1736 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1737 :{COMMA16} +STR_1738 :Can't change number of laps... +STR_1739 :Race won by guest {INT32} +STR_1740 :Race won by {STRINGID} +STR_1741 :Not yet constructed ! +STR_1742 :{WINDOW_COLOUR_2}Max. people on ride: +STR_1743 :{SMALLFONT}{BLACK}Maximum number of people allowed on this ride at one time +STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1745 :{COMMA16} +STR_1746 :Can't change this... +STR_1747 :{WINDOW_COLOUR_2}Time limit: +STR_1748 :{SMALLFONT}{BLACK}Time limit for ride +STR_1749 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{DURATION} +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} 来客 +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 +STR_1759 :{SMALLFONT}{BLACK}Move mode +STR_1760 :{SMALLFONT}{BLACK}Fill-in mode +STR_1761 :{SMALLFONT}{BLACK}Build maze in this direction +STR_1762 :Waterfalls +STR_1763 :Rapids +STR_1764 :Log Bumps +STR_1765 :On-ride photo section +STR_1766 :Reverser turntable +STR_1767 :Spinning tunnel +STR_1768 :Can't change number of swings... +STR_1769 :{WINDOW_COLOUR_2}Number of swings: +STR_1770 :{SMALLFONT}{BLACK}Number of complete swings +STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1772 :{COMMA16} +STR_1773 :Only one on-ride photo section allowed per ride +STR_1774 :Only one cable lift hill allowed per ride +STR_1775 :Off +STR_1776 :On +STR_1777 :{WINDOW_COLOUR_2}音楽 +STR_1778 :{STRINGID} - - +STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Panda costume +STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tiger costume +STR_1781 :{INLINE_SPRITE}{00}{20}{00}{00} Elephant costume +STR_1782 :{INLINE_SPRITE}{01}{20}{00}{00} Roman costume +STR_1783 :{INLINE_SPRITE}{02}{20}{00}{00} Gorilla costume +STR_1784 :{INLINE_SPRITE}{03}{20}{00}{00} Snowman costume +STR_1785 :{INLINE_SPRITE}{04}{20}{00}{00} Knight costume +STR_1786 :{INLINE_SPRITE}{05}{20}{00}{00} Astronaut costume +STR_1787 :{INLINE_SPRITE}{06}{20}{00}{00} Bandit costume +STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Sheriff costume +STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Pirate costume +STR_1790 :{SMALLFONT}{BLACK}Select uniform colour for this type of staff +STR_1791 :{WINDOW_COLOUR_2}Uniform colour: +STR_1792 :Responding to {STRINGID} breakdown call +STR_1793 :Heading to {STRINGID} for an inspection +STR_1794 :Fixing {STRINGID} +STR_1795 :Answering radio call +STR_1796 :Has broken down and requires fixing +STR_1797 :This option cannot be changed for this ride +STR_1798 :Whirlpool +STR_1799 :{POP16}{POP16}{POP16}{POP16}{POP16}{CURRENCY2DP} +STR_1800 :Safety cut-out +STR_1801 :Restraints stuck closed +STR_1802 :Restraints stuck open +STR_1803 :Doors stuck closed +STR_1804 :Doors stuck open +STR_1805 :Vehicle malfunction +STR_1806 :Brakes failure +STR_1807 :Control failure +STR_1808 :{WINDOW_COLOUR_2}Last breakdown: {BLACK}{STRINGID} +STR_1809 :{WINDOW_COLOUR_2}Current breakdown: {OUTLINE}{RED}{STRINGID} +STR_1810 :{WINDOW_COLOUR_2}Carrying: +STR_1811 :Can't build this here... +STR_1812 :{SMALLFONT}{BLACK}{STRINGID} +STR_1813 :Miscellaneous Objects +STR_1814 :Actions +STR_1815 :Thoughts +STR_1816 :{SMALLFONT}{BLACK}Select information type to show in guest list +STR_1817 :({COMMA16}) +STR_1818 :{WINDOW_COLOUR_2}All guests +STR_1819 :{WINDOW_COLOUR_2}All guests (summarised) +STR_1820 :{WINDOW_COLOUR_2}Guests {STRINGID} +STR_1821 :{WINDOW_COLOUR_2}Guests thinking {STRINGID} +STR_1822 :{WINDOW_COLOUR_2}Guests thinking about {POP16}{STRINGID} +STR_1823 :{SMALLFONT}{BLACK}Show guests' thoughts about this ride/attraction +STR_1824 :{SMALLFONT}{BLACK}Show guests on this ride/attraction +STR_1825 :{SMALLFONT}{BLACK}Show guests queuing for this ride/attraction +STR_1826 :Status +STR_1827 :人気度 +STR_1828 :満足度 +STR_1829 :利益 +STR_1830 :列の長さ +STR_1831 :待ち時間 +STR_1832 :信頼度 +STR_1833 :停車時間 +STR_1834 :来客のお気に入り +STR_1835 :人気度: 未知 +STR_1836 :人気度: {COMMA16}% +STR_1837 :満足度: 未知 +STR_1838 :満足度: {COMMA16}% +STR_1839 :信頼度: {COMMA16}% +STR_1840 :ダウンタイム: {COMMA16}% +STR_1841 :利益: {CURRENCY2DP}/時間 +STR_1842 :{COMMA16}人の来客のお気に入り +STR_1843 :{COMMA16}人の来客のお気に入り +STR_1844 :{SMALLFONT}{BLACK}Select information type to show in ride/attraction list +STR_1845 :{MONTHYEAR} +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 +STR_1852 :{WINDOW_COLOUR_2}Running cost: {BLACK}Unknown +STR_1853 :{WINDOW_COLOUR_2}Built: {BLACK}This Year +STR_1854 :{WINDOW_COLOUR_2}Built: {BLACK}Last Year +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 :便利屋 +STR_1860 :修理工 +STR_1861 :警備員 +STR_1862 :Entertainers +STR_1863 :便利屋 +STR_1864 :修理工 +STR_1865 :警備員 +STR_1866 :Entertainer +STR_1867 :{BLACK}{COMMA16} {STRINGID} +STR_1868 :回転数が変更できない... +STR_1869 :{WINDOW_COLOUR_2}回転数: +STR_1870 :{SMALLFONT}{BLACK}Number of complete rotations +STR_1871 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1872 :{COMMA16} +STR_1873 :{WINDOW_COLOUR_2}Income: {BLACK}{CURRENCY2DP} per hour +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}改めるの: +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}% +STR_1890 :{SMALLFONT}{BLACK}Select how often a mechanic should check this ride +STR_1891 :No {STRINGID} in park yet! +# The following two strings were used to display an error when the disc was missing. +# This has been replaced in OpenRCT2. +STR_1892 : +STR_1893 : +STR_1894 :{WINDOW_COLOUR_2}{STRINGID} sold: {BLACK}{COMMA32} +STR_1895 :{SMALLFONT}{BLACK}Build new ride/attraction +STR_1896 :{WINDOW_COLOUR_2}Expenditure/Income +STR_1897 :{WINDOW_COLOUR_2}Ride construction +STR_1898 :{WINDOW_COLOUR_2}Ride running costs +STR_1899 :{WINDOW_COLOUR_2}Land purchase +STR_1900 :{WINDOW_COLOUR_2}Landscaping +STR_1901 :{WINDOW_COLOUR_2}Park entrance tickets +STR_1902 :{WINDOW_COLOUR_2}Ride tickets +STR_1903 :{WINDOW_COLOUR_2}Shop sales +STR_1904 :{WINDOW_COLOUR_2}Shop stock +STR_1905 :{WINDOW_COLOUR_2}Food/drink sales +STR_1906 :{WINDOW_COLOUR_2}Food/drink stock +STR_1907 :{WINDOW_COLOUR_2}Staff wages +STR_1908 :{WINDOW_COLOUR_2}Marketing +STR_1909 :{WINDOW_COLOUR_2}Research +STR_1910 :{WINDOW_COLOUR_2}Loan interest +STR_1911 :{BLACK} at {COMMA16}% per year +STR_1912 :{MONTH} +STR_1913 :{BLACK}+{CURRENCY2DP} +STR_1914 :{BLACK}{CURRENCY2DP} +STR_1915 :{RED}{CURRENCY2DP} +STR_1916 :{WINDOW_COLOUR_2}Loan: +STR_1917 :{POP16}{POP16}{POP16}{CURRENCY} +STR_1918 :Can't borrow any more money! +STR_1919 :Not enough cash available! +STR_1920 :Can't pay back loan! +STR_1921 :{SMALLFONT}{BLACK}Start a new game +STR_1922 :{SMALLFONT}{BLACK}Continue playing a saved game +STR_1923 :{SMALLFONT}{BLACK}Show tutorial +STR_1924 :{SMALLFONT}{BLACK}終了 +STR_1925 :ここに人を置けない... +STR_1926 :{SMALLFONT} +STR_1927 :{YELLOW}{STRINGID} has broken down +STR_1928 :{RED}{STRINGID} has crashed! +STR_1929 :{RED}{STRINGID} still hasn't been fixed{NEWLINE}Check where your mechanics are and consider organizing them better +STR_1930 :{SMALLFONT}{BLACK}Turn on/off tracking information for this guest - (If tracking is on, guest's movements will be reported in the message area) +STR_1931 :{STRINGID} has joined the queue line for {STRINGID} +STR_1932 :{STRINGID} is on {STRINGID} +STR_1933 :{STRINGID} is in {STRINGID} +STR_1934 :{STRINGID} has left {STRINGID} +STR_1935 :{STRINGID} has left the park +STR_1936 :{STRINGID} has bought {STRINGID} +STR_1937 :{SMALLFONT}{BLACK}Show information about the subject of this message +STR_1938 :{SMALLFONT}{BLACK}Show view of guest +STR_1939 :{SMALLFONT}{BLACK}Show view of staff member +STR_1940 :{SMALLFONT}{BLACK}Show happiness, energy, hunger etc. for this guest +STR_1941 :{SMALLFONT}{BLACK}Show which rides this guest has been on +STR_1942 :{SMALLFONT}{BLACK}Show financial information about this guest +STR_1943 :{SMALLFONT}{BLACK}Show guest's recent thoughts +STR_1944 :{SMALLFONT}{BLACK}Show items guest is carrying +STR_1945 :{SMALLFONT}{BLACK}Show orders and options for this staff member +STR_1946 :{SMALLFONT}{BLACK}Select costume for this entertainer +STR_1947 :{SMALLFONT}{BLACK}Show areas patrolled by selected staff type, and locate the nearest staff member +STR_1948 :{SMALLFONT}{BLACK}Hire a new staff member of the selected type +STR_1949 :Financial Summary +STR_1950 :Financial Graph +STR_1951 :Park Value Graph +STR_1952 :Profit Graph +STR_1953 :Marketing +STR_1954 :Research Funding +STR_1955 :{WINDOW_COLOUR_2}Number of circuits: +STR_1956 :{SMALLFONT}{BLACK}Number of circuits of track per ride +STR_1957 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1958 :{COMMA16} +STR_1959 :Can't change number of circuits... +STR_1960 :{WINDOW_COLOUR_2}Balloon price: +STR_1961 :{WINDOW_COLOUR_2}Cuddly Toy price: +STR_1962 :{WINDOW_COLOUR_2}Park Map price: +STR_1963 :{WINDOW_COLOUR_2}On-Ride Photo price: +STR_1964 :{WINDOW_COLOUR_2}Umbrella price: +STR_1965 :{WINDOW_COLOUR_2}Drink price: +STR_1966 :{WINDOW_COLOUR_2}Burger price: +STR_1967 :{WINDOW_COLOUR_2}Chips price: +STR_1968 :{WINDOW_COLOUR_2}Ice Cream price: +STR_1969 :{WINDOW_COLOUR_2}Candyfloss price: +STR_1970 :{WINDOW_COLOUR_2} +STR_1971 :{WINDOW_COLOUR_2} +STR_1972 :{WINDOW_COLOUR_2} +STR_1973 :{WINDOW_COLOUR_2}Pizza price: +STR_1974 :{WINDOW_COLOUR_2} +STR_1975 :{WINDOW_COLOUR_2}Popcorn price: +STR_1976 :{WINDOW_COLOUR_2}Hot Dog price: +STR_1977 :{WINDOW_COLOUR_2}Tentacle price: +STR_1978 :{WINDOW_COLOUR_2}Hat price: +STR_1979 :{WINDOW_COLOUR_2}Toffee Apple price: +STR_1980 :{WINDOW_COLOUR_2}T-Shirt price: +STR_1981 :{WINDOW_COLOUR_2}Doughnut price: +STR_1982 :{WINDOW_COLOUR_2}Coffee price: +STR_1983 :{WINDOW_COLOUR_2} +STR_1984 :{WINDOW_COLOUR_2}Fried Chicken price: +STR_1985 :{WINDOW_COLOUR_2}Lemonade price: +STR_1986 :{WINDOW_COLOUR_2} +STR_1987 :{WINDOW_COLOUR_2} +STR_1988 :風船 +STR_1989 :Cuddly Toy +STR_1990 :地図 +STR_1991 :On-Ride Photo +STR_1992 :傘 +STR_1993 :飲み物 +STR_1994 :ハンバーガー +STR_1995 :フライドポテト +STR_1996 :ソフトクリーム +STR_1997 :綿菓子 +STR_1998 :空き缶 +STR_1999 :ゴミ +STR_2000 :Empty Burger Box +STR_2001 :ピザ +STR_2002 :Voucher +STR_2003 :ポップコーン +STR_2004 :ホットドッグ +STR_2005 :Tentacle +STR_2006 :帽子 +STR_2007 :Toffee Apple +STR_2008 :Tシャツ +STR_2009 :ドーナツ +STR_2010 :コーヒー +STR_2011 :空のカップ +STR_2012 :フライドチキン +STR_2013 :レモネード +STR_2014 :空の箱 +STR_2015 :空き瓶 +STR_2016 :風船 +STR_2017 :Cuddly Toys +STR_2018 :地図 +STR_2019 :On-Ride Photos +STR_2020 :傘 +STR_2021 :ドリンク +STR_2022 :バーガー +STR_2023 :フライ +STR_2024 :ソフトクリーム +STR_2025 :綿菓子 +STR_2026 :空き缶 +STR_2027 :ごみ +STR_2028 :Empty Burger Boxes +STR_2029 :ピザ +STR_2030 :無料券 +STR_2031 :ポップコーン +STR_2032 :ホットドッグ +STR_2033 :Tentacles +STR_2034 :帽子 +STR_2035 :Toffee Apples +STR_2036 :ティーシャツ +STR_2037 :ドーナツ +STR_2038 :コーヒー +STR_2039 :Empty Cups +STR_2040 :フライドチキン +STR_2041 :レモネード +STR_2042 :Empty Boxes +STR_2043 :空き瓶 +STR_2044 :a Balloon +STR_2045 :a Cuddly Toy +STR_2046 :a Park Map +STR_2047 :an On-Ride Photo +STR_2048 :an Umbrella +STR_2049 :a Drink +STR_2050 :a Burger +STR_2051 :some Chips +STR_2052 :an Ice Cream +STR_2053 :some Candyfloss +STR_2054 :an Empty Can +STR_2055 :some Rubbish +STR_2056 :an Empty Burger Box +STR_2057 :a Pizza +STR_2058 :a Voucher +STR_2059 :some Popcorn +STR_2060 :a Hot Dog +STR_2061 :a Tentacle +STR_2062 :a Hat +STR_2063 :a Toffee Apple +STR_2064 :a T-Shirt +STR_2065 :a Doughnut +STR_2066 :a Coffee +STR_2067 :an Empty Cup +STR_2068 :some Fried Chicken +STR_2069 :some Lemonade +STR_2070 :an Empty Box +STR_2071 :an Empty Bottle +STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Balloon +STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Cuddly Toy +STR_2074 :{STRINGID}の地図 +STR_2075 :On-Ride Photo of {STRINGID} +STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Umbrella +STR_2077 :飲み物 +STR_2078 :ハンバーガー +STR_2079 :フライドポテト +STR_2080 :ソフトクリーム +STR_2081 :綿菓子 +STR_2082 :空き缶 +STR_2083 :ゴミ +STR_2084 :Empty Burger Box +STR_2085 :ピザ +STR_2086 :{STRINGID}の無料券 +STR_2087 :ポップコーン +STR_2088 :ホットドッグ +STR_2089 :Tentacle +STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Hat +STR_2091 :Toffee Apple +STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} T-Shirt +STR_2093 :ドーナツ +STR_2094 :コーヒー +STR_2095 :空のカップ +STR_2096 :フライドチキン +STR_2097 :レモネード +STR_2098 :空の箱 +STR_2099 :空き瓶 +STR_2100 :{WINDOW_COLOUR_2}On-Ride Photo price: +STR_2101 :{WINDOW_COLOUR_2}On-Ride Photo price: +STR_2102 :{WINDOW_COLOUR_2}On-Ride Photo price: +STR_2103 :{WINDOW_COLOUR_2}Pretzel price: +STR_2104 :{WINDOW_COLOUR_2}Hot Chocolate price: +STR_2105 :{WINDOW_COLOUR_2}Iced Tea price: +STR_2106 :{WINDOW_COLOUR_2}Funnel Cake price: +STR_2107 :{WINDOW_COLOUR_2}Sunglasses price: +STR_2108 :{WINDOW_COLOUR_2}Beef Noodles price: +STR_2109 :{WINDOW_COLOUR_2}Fried Rice Noodles price: +STR_2110 :{WINDOW_COLOUR_2}Wonton Soup price: +STR_2111 :{WINDOW_COLOUR_2}Meatball Soup price: +STR_2112 :{WINDOW_COLOUR_2}Fruit Juice price: +STR_2113 :{WINDOW_COLOUR_2}Soybean Milk price: +STR_2114 :{WINDOW_COLOUR_2}Sujongkwa price: +STR_2115 :{WINDOW_COLOUR_2}Sub Sandwich price: +STR_2116 :{WINDOW_COLOUR_2}Cookie price: +STR_2117 :{WINDOW_COLOUR_2} +STR_2118 :{WINDOW_COLOUR_2} +STR_2119 :{WINDOW_COLOUR_2} +STR_2120 :{WINDOW_COLOUR_2}Roast Sausage price: +STR_2121 :{WINDOW_COLOUR_2} +STR_2122 :On-Ride Photo +STR_2123 :On-Ride Photo +STR_2124 :On-Ride Photo +STR_2125 :プレッツェル +STR_2126 :ホットココア +STR_2127 :アイスティー +STR_2128 :Funnel Cake +STR_2129 :サングラス +STR_2130 :Beef Noodles +STR_2131 :Fried Rice Noodles +STR_2132 :Wonton Soup +STR_2133 :Meatball Soup +STR_2134 :フルーツジュース +STR_2135 :豆乳 +STR_2136 :Sujongkwa +STR_2137 :Sub Sandwich +STR_2138 :クッキー +STR_2139 :Empty Bowl +STR_2140 :Empty Drink Carton +STR_2141 :Empty Juice Cup +STR_2142 :Roast Sausage +STR_2143 :Empty Bowl +STR_2144 :On-Ride Photos +STR_2145 :On-Ride Photos +STR_2146 :On-Ride Photos +STR_2147 :Pretzels +STR_2148 :Hot Chocolates +STR_2149 :Iced Teas +STR_2150 :Funnel Cakes +STR_2151 :Sunglasses +STR_2152 :Beef Noodles +STR_2153 :Fried Rice Noodles +STR_2154 :Wonton Soups +STR_2155 :Meatball Soups +STR_2156 :Fruit Juices +STR_2157 :Soybean Milks +STR_2158 :Sujongkwa +STR_2159 :Sub Sandwiches +STR_2160 :Cookies +STR_2161 :Empty Bowls +STR_2162 :Empty Drink Cartons +STR_2163 :Empty Juice cups +STR_2164 :Roast Sausages +STR_2165 :Empty Bowls +STR_2166 :an On-Ride Photo +STR_2167 :an On-Ride Photo +STR_2168 :an On-Ride Photo +STR_2169 :a Pretzel +STR_2170 :a Hot Chocolate +STR_2171 :an Iced Tea +STR_2172 :a Funnel Cake +STR_2173 :a pair of Sunglasses +STR_2174 :some Beef Noodles +STR_2175 :some Fried Rice Noodles +STR_2176 :some Wonton Soup +STR_2177 :some Meatball Soup +STR_2178 :a Fruit Juice +STR_2179 :some Soybean Milk +STR_2180 :some Sujongkwa +STR_2181 :a Sub Sandwich +STR_2182 :a Cookie +STR_2183 :an Empty Bowl +STR_2184 :an Empty Drink Carton +STR_2185 :an Empty Juice Cup +STR_2186 :a Roast Sausage +STR_2187 :an Empty Bowl +STR_2188 :On-Ride Photo of {STRINGID} +STR_2189 :On-Ride Photo of {STRINGID} +STR_2190 :On-Ride Photo of {STRINGID} +STR_2191 :プレッツェル +STR_2192 :ホットココア +STR_2193 :アイスティー +STR_2194 :Funnel Cake +STR_2195 :Sunglasses +STR_2196 :Beef Noodles +STR_2197 :Fried Rice Noodles +STR_2198 :Wonton Soup +STR_2199 :Meatball Soup +STR_2200 :フルーツジュース +STR_2201 :豆乳 +STR_2202 :Sujongkwa +STR_2203 :Sub Sandwich +STR_2204 :クッキー +STR_2205 :Empty Bowl +STR_2206 :Empty Drink Carton +STR_2207 :Empty Juice Cup +STR_2208 :Roast Sausage +STR_2209 :Empty Bowl +STR_2210 :{SMALLFONT}{BLACK}Show list of handymen in park +STR_2211 :{SMALLFONT}{BLACK}Show list of mechanics in park +STR_2212 :{SMALLFONT}{BLACK}Show list of security guards in park +STR_2213 :{SMALLFONT}{BLACK}Show list of entertainers in park +STR_2214 :Construction not possible while game is paused! +STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) +STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C +STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F +STR_2218 :{RED}{STRINGID} on {STRINGID} hasn't returned to the {STRINGID} yet!{NEWLINE}Check whether it is stuck or has stalled +STR_2219 :{RED}{COMMA16} people have died in an accident on {STRINGID} +STR_2220 :{WINDOW_COLOUR_2}Park Rating: {BLACK}{COMMA16} +STR_2221 :{SMALLFONT}{BLACK}Park Rating: {COMMA16} +STR_2222 :{SMALLFONT}{BLACK}{STRINGID} +STR_2223 :{WINDOW_COLOUR_2}Guests in park: {BLACK}{COMMA16} +STR_2224 :{WINDOW_COLOUR_2}Cash: {BLACK}{CURRENCY2DP} +STR_2225 :{WINDOW_COLOUR_2}Cash: {RED}{CURRENCY2DP} +STR_2226 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} +STR_2227 :{WINDOW_COLOUR_2}Company value: {BLACK}{CURRENCY} +STR_2228 :{WINDOW_COLOUR_2}Last month's profit from food/drink and{NEWLINE}merchandise sales: {BLACK}{CURRENCY} +STR_2229 :Slope up to vertical +STR_2230 :Vertical track +STR_2231 :Holding brake for drop +STR_2232 :Cable lift hill +STR_2233 :{SMALLFONT}{BLACK}Park information +STR_2234 :Recent Messages +STR_2235 :{SMALLFONT}{STRINGID} {STRINGID} +STR_2236 :1月 +STR_2237 :2月 +STR_2238 :3月 +STR_2239 :4月 +STR_2240 :5月 +STR_2241 :6月 +STR_2242 :7月 +STR_2243 :8月 +STR_2244 :9月 +STR_2245 :10月 +STR_2246 :11月 +STR_2247 :12月 +STR_2248 :Can't demolish ride/attraction... +STR_2249 :{BABYBLUE}New ride/attraction now available:{NEWLINE}{STRINGID} +STR_2250 :{BABYBLUE}New scenery/themeing now available:{NEWLINE}{STRINGID} +STR_2251 :Can only be built on paths! +STR_2252 :Can only be built across paths! +STR_2253 :トランスポートライド +STR_2254 :ジェントルライド +STR_2255 :ジェットコースター +STR_2256 :Thrill Rides +STR_2257 :Water Rides +STR_2258 :Shops & Stalls +STR_2259 :Scenery & Themeing +STR_2260 :No funding +STR_2261 :Minimum funding +STR_2262 :Normal funding +STR_2263 :Maximum funding +STR_2264 :Research funding +STR_2265 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY} per month +STR_2266 :Research priorities +STR_2267 :Currently in development +STR_2268 :Last development +STR_2269 :{WINDOW_COLOUR_2}Type: {BLACK}{STRINGID} +STR_2270 :{WINDOW_COLOUR_2}Progress: {BLACK}{STRINGID} +STR_2271 :{WINDOW_COLOUR_2}Expected: {BLACK}{STRINGID} +STR_2272 :{WINDOW_COLOUR_2}Ride/attraction:{NEWLINE}{BLACK}{STRINGID} +STR_2273 :{WINDOW_COLOUR_2}Scenery/themeing:{NEWLINE}{BLACK}{STRINGID} +STR_2274 :{SMALLFONT}{BLACK}Show details of this invention or development +STR_2275 :{SMALLFONT}{BLACK}Show funding and options for research & development +STR_2276 :{SMALLFONT}{BLACK}Show research & development status +STR_2277 :Unknown +STR_2278 :Transport Ride +STR_2279 :Gentle Ride +STR_2280 :Roller Coaster +STR_2281 :Thrill Ride +STR_2282 :Water Ride +STR_2283 :Shop/Stall +STR_2284 :Scenery/Themeing +STR_2285 :Initial research +STR_2286 :Designing +STR_2287 :Completing design +STR_2288 :Unknown +STR_2289 :{STRINGID} {STRINGID} +STR_2290 : +STR_2291 :Select scenario for new game +STR_2292 :{WINDOW_COLOUR_2}Rides been on: +STR_2293 :{BLACK} Nothing +STR_2294 :{SMALLFONT}{BLACK}Change base land style +STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} paid to enter park +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} ride +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} rides +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} item of food +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} items of food +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drink +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drinks +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenir +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenirs +STR_2305 :Track design files +STR_2306 :Save track design +STR_2307 :Select {STRINGID} design +STR_2308 :{STRINGID} Track Designs +STR_2309 :Install New Track Design +STR_2310 :Build custom design +STR_2311 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} (approx.) +STR_2312 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} (approx.) +STR_2313 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} (approx.) +STR_2314 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID} +STR_2315 :{WINDOW_COLOUR_2}Cost: {BLACK}around {CURRENCY} +STR_2316 :{WINDOW_COLOUR_2}Space required: {BLACK}{COMMA16} x {COMMA16} blocks +STR_2317 : +STR_2318 : +STR_2319 : +STR_2320 : +STR_2321 :{WINDOW_COLOUR_2}Number of rides/attractions: {BLACK}{COMMA16} +STR_2322 :{WINDOW_COLOUR_2}Staff: {BLACK}{COMMA16} +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 :設定 +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) +STR_2337 :ドイツマルク (DM) +STR_2338 :円 ({YEN}) +STR_2339 :ペセタ (Pts) +STR_2340 :リラ (L) +STR_2341 :フローリン (fl.) +STR_2342 :クローナ (kr) +STR_2343 :ユーロ ({EURO}) +STR_2344 :Imperial +STR_2345 :Metric +STR_2346 :Display +STR_2347 :{RED}{STRINGID} has drowned! +STR_2348 :{SMALLFONT}{BLACK}Show statistics for this staff member +STR_2349 :{WINDOW_COLOUR_2}Wages: {BLACK}{CURRENCY} per month +STR_2350 :{WINDOW_COLOUR_2}Employed: {BLACK}{MONTHYEAR} +STR_2351 :{WINDOW_COLOUR_2}Lawns mown: {BLACK}{COMMA16} +STR_2352 :{WINDOW_COLOUR_2}Gardens watered: {BLACK}{COMMA16} +STR_2353 :{WINDOW_COLOUR_2}Litter swept: {BLACK}{COMMA16} +STR_2354 :{WINDOW_COLOUR_2}Bins emptied: {BLACK}{COMMA16} +STR_2355 :{WINDOW_COLOUR_2}Rides fixed: {BLACK}{COMMA16} +STR_2356 :{WINDOW_COLOUR_2}Rides inspected: {BLACK}{COMMA16} +STR_2357 :House +STR_2358 :Units +STR_2359 :Real Values +STR_2360 :{WINDOW_COLOUR_2}Display Resolution: +STR_2361 :Landscape Smoothing +STR_2362 :{SMALLFONT}{BLACK}Toggle landscape tile edge smoothing on/off +STR_2363 :Gridlines on Landscape +STR_2364 :{SMALLFONT}{BLACK}Toggle gridlines on landscape on/off +STR_2365 :The bank refuses to increase your loan! +STR_2366 :Celsius ({DEGREE}C) +STR_2367 :Fahrenheit ({DEGREE}F) +STR_2368 :None +STR_2369 :低い +STR_2370 :平均的 +STR_2371 :高い +STR_2372 :低い +STR_2373 :普通 +STR_2374 :高い +STR_2375 :非常に高い +STR_2376 :最高 +STR_2377 :Ultra-Extreme +STR_2378 :{SMALLFONT}{BLACK}Adjust smaller area of land +STR_2379 :{SMALLFONT}{BLACK}Adjust larger area of land +STR_2380 :{SMALLFONT}{BLACK}Adjust smaller area of water +STR_2381 :{SMALLFONT}{BLACK}Adjust larger area of water +STR_2382 :Land +STR_2383 :Water +STR_2384 :{WINDOW_COLOUR_2}あなたの目標: +STR_2385 :{BLACK}なし +STR_2386 :{BLACK}To have at least {COMMA16} guests in your park at the end of {MONTHYEAR}, with a park rating of at least 600 +STR_2387 :{BLACK}To achieve a park value of at least {POP16}{POP16}{CURRENCY} at the end of {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} +STR_2388 :{BLACK}Have Fun! +STR_2389 :{BLACK}Build the best {STRINGID} you can! +STR_2390 :{BLACK}To have 10 different types of roller coasters operating in your park, each with an excitement value of at least 6.00 +STR_2391 :{BLACK}To have at least {COMMA16} guests in your park. You must not let the park rating drop below 700 at any time! +STR_2392 :{BLACK}To achieve a monthly income from ride tickets of at least {POP16}{POP16}{CURRENCY} +STR_2393 :{BLACK}To have 10 different types of roller coasters operating in your park, each with a minimum length of {LENGTH}, and an excitement rating of at least 7.00 +STR_2394 :{BLACK}To finish building all 5 of the partially built roller coasters in this park, designing them to achieve excitement ratings of at least {POP16}{POP16}{COMMA2DP32} each +STR_2395 :{BLACK}To repay your loan and achieve a park value of at least {POP16}{POP16}{CURRENCY} +STR_2396 :{BLACK}To achieve a monthly profit from food, drink and merchandise sales of at least {POP16}{POP16}{CURRENCY} +STR_2397 :None +STR_2398 :Number of guests at a given date +STR_2399 :Park value at a given date +STR_2400 :Have fun +STR_2401 :Build the best ride you can +STR_2402 :Build 10 roller coasters +STR_2403 :Number of guests in park +STR_2404 :Monthly income from ride tickets +STR_2405 :Build 10 roller coasters of a given length +STR_2406 :Finish building 5 roller coasters +STR_2407 :Repay loan and achieve a given park value +STR_2408 :Monthly profit from food/merchandise +STR_2409 :{WINDOW_COLOUR_2}Marketing campaigns in operation +STR_2410 :{BLACK}None +STR_2411 :{WINDOW_COLOUR_2}Marketing campaigns available +STR_2412 :{SMALLFONT}{BLACK}Start this marketing campaign +STR_2413 :{BLACK}({CURRENCY2DP} per week) +STR_2414 :(Not Selected) +STR_2415 :{WINDOW_COLOUR_2}Ride: +STR_2416 :{WINDOW_COLOUR_2}Item: +STR_2417 :{WINDOW_COLOUR_2}Length of time: +STR_2418 :Free entry to {STRINGID} +STR_2419 :Free ride on {STRINGID} +STR_2420 :Half-price entry to {STRINGID} +STR_2421 :Free {STRINGID} +STR_2422 :Advertising campaign for {STRINGID} +STR_2423 :Advertising campaign for {STRINGID} +STR_2424 :{WINDOW_COLOUR_2}Vouchers for free entry to the park +STR_2425 :{WINDOW_COLOUR_2}Vouchers for free rides on a particular ride +STR_2426 :{WINDOW_COLOUR_2}Vouchers for half-price entry to the park +STR_2427 :{WINDOW_COLOUR_2}Vouchers for free food or drink +STR_2428 :{WINDOW_COLOUR_2}Advertising campaign for the park +STR_2429 :{WINDOW_COLOUR_2}Advertising campaign for a particular ride +STR_2430 :{BLACK}Vouchers for free entry to {STRINGID} +STR_2431 :{BLACK}Vouchers for free ride on {STRINGID} +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週間 +STR_2437 : +STR_2438 : +STR_2439 : +STR_2440 : +STR_2441 : +STR_2442 : +STR_2443 :{WINDOW_COLOUR_2}Cost per week: {BLACK}{CURRENCY2DP} +STR_2444 :{WINDOW_COLOUR_2}Total cost: {BLACK}{CURRENCY2DP} +STR_2445 :Start this marketing campaign +STR_2446 :{YELLOW}Your marketing campaign for free entry to the park has finished +STR_2447 :{YELLOW}Your marketing campaign for free rides on {STRINGID} has finished +STR_2448 :{YELLOW}Your marketing campaign for half-price entry to the park has finished +STR_2449 :{YELLOW}Your marketing campaign for free {STRINGID} has finished +STR_2450 :{YELLOW}Your advertising campaign for the park has finished +STR_2451 :{YELLOW}Your advertising campaign for {STRINGID} has finished +STR_2452 :{WINDOW_COLOUR_2}Cash (less loan): {BLACK}{CURRENCY2DP} +STR_2453 :{WINDOW_COLOUR_2}Cash (less loan): {RED}{CURRENCY2DP} +STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - +STR_2455 :{SMALLFONT}{BLACK}+{CURRENCY2DP} - +STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} - +STR_2457 :{SMALLFONT}{BLACK}Show financial accounts +STR_2458 :{SMALLFONT}{BLACK}Show graph of cash (less loan) over time +STR_2459 :{SMALLFONT}{BLACK}Show graph of park value over time +STR_2460 :{SMALLFONT}{BLACK}Show graph of weekly profit +STR_2461 :{SMALLFONT}{BLACK}Show marketing campaigns +STR_2462 :{SMALLFONT}{BLACK}Show view of park entrance +STR_2463 :{SMALLFONT}{BLACK}Show graph of park ratings over time +STR_2464 :{SMALLFONT}{BLACK}Show graph of guest numbers over time +STR_2465 :{SMALLFONT}{BLACK}Show park entrance price and information +STR_2466 :{SMALLFONT}{BLACK}Show park statistics +STR_2467 :{SMALLFONT}{BLACK}Show objectives for this game +STR_2468 :{SMALLFONT}{BLACK}Show recent awards this park has received +STR_2469 :{SMALLFONT}{BLACK}Select level of research & development +STR_2470 :{SMALLFONT}{BLACK}Research new transport rides +STR_2471 :{SMALLFONT}{BLACK}Research new gentle rides +STR_2472 :{SMALLFONT}{BLACK}Research new roller coasters +STR_2473 :{SMALLFONT}{BLACK}Research new thrill rides +STR_2474 :{SMALLFONT}{BLACK}Research new water rides +STR_2475 :{SMALLFONT}{BLACK}Research new shops and stalls +STR_2476 :{SMALLFONT}{BLACK}Research new scenery and themeing +STR_2477 :{SMALLFONT}{BLACK}Select operating mode for this ride/attraction +STR_2478 :{SMALLFONT}{BLACK}Show graph of velocity against time +STR_2479 :{SMALLFONT}{BLACK}Show graph of altitude against time +STR_2480 :{SMALLFONT}{BLACK}Show graph of vertical acceleration against time +STR_2481 :{SMALLFONT}{BLACK}Show graph of lateral acceleration against time +STR_2482 :{SMALLFONT}{BLACK}Profit: {CURRENCY} per week, Park Value: {CURRENCY} +STR_2483 :{WINDOW_COLOUR_2}Weekly profit: {BLACK}+{CURRENCY2DP} +STR_2484 :{WINDOW_COLOUR_2}Weekly profit: {RED}{CURRENCY2DP} +STR_2485 :Controls +STR_2486 :General +STR_2487 :Show 'real' names of guests +STR_2488 :{SMALLFONT}{BLACK}Toggle between showing 'real' names of guests and guest numbers +STR_2489 :Shortcut keys... +STR_2490 :Keyboard shortcuts +STR_2491 :Reset keys +STR_2492 :{SMALLFONT}{BLACK}Set all keyboard shortcuts back to default settings +STR_2493 :Close top-most window +STR_2494 :Close all floating windows +STR_2495 :Cancel construction mode +STR_2496 :Pause game +STR_2497 :Zoom view out +STR_2498 :Zoom view in +STR_2499 :Rotate view clockwise +STR_2500 :Rotate construction object +STR_2501 :Underground view toggle +STR_2502 :Remove base land toggle +STR_2503 :Remove vertical land toggle +STR_2504 :See-through rides toggle +STR_2505 :See-through scenery toggle +STR_2506 :Invisible supports toggle +STR_2507 :Invisible people toggle +STR_2508 :Height marks on land toggle +STR_2509 :Height marks on ride tracks toggle +STR_2510 :Height marks on paths toggle +STR_2511 :Adjust land +STR_2512 :Adjust water +STR_2513 :Build scenery +STR_2514 :Build paths +STR_2515 :Build new ride +STR_2516 :Show financial information +STR_2517 :Show research information +STR_2518 :Show rides list +STR_2519 :Show park information +STR_2520 :Show guest list +STR_2521 :Show staff list +STR_2522 :Show recent messages +STR_2523 :Show map +STR_2524 :Screenshot +### The following need to be reordered to match SDL_keycode layout. +STR_2525 :??? +STR_2526 :??? +STR_2527 :??? +STR_2528 :??? +STR_2529 :??? +STR_2530 :??? +STR_2531 :??? +STR_2532 :??? +STR_2533 :Backspace +STR_2534 :Tab +STR_2535 :??? +STR_2536 :??? +STR_2537 :Clear +STR_2538 :Return +STR_2539 :??? +STR_2540 :??? +STR_2541 :??? +STR_2542 :??? +STR_2543 :Alt/Menu +STR_2544 :Pause +STR_2545 :Caps +STR_2546 :??? +STR_2547 :??? +STR_2548 :??? +STR_2549 :??? +STR_2550 :??? +STR_2551 :??? +STR_2552 :Escape +STR_2553 :??? +STR_2554 :??? +STR_2555 :??? +STR_2556 :??? +STR_2557 :Spacebar +STR_2558 :PgUp +STR_2559 :PgDn +STR_2560 :End +STR_2561 :Home +STR_2562 :Left +STR_2563 :Up +STR_2564 :Right +STR_2565 :Down +STR_2566 :Select +STR_2567 :Print +STR_2568 :Execute +STR_2569 :Snapshot +STR_2570 :Insert +STR_2571 :Delete +STR_2572 :ヘルプ +STR_2573 :0 +STR_2574 :1 +STR_2575 :2 +STR_2576 :3 +STR_2577 :4 +STR_2578 :5 +STR_2579 :6 +STR_2580 :7 +STR_2581 :8 +STR_2582 :9 +STR_2583 :??? +STR_2584 :??? +STR_2585 :??? +STR_2586 :??? +STR_2587 :??? +STR_2588 :??? +STR_2589 :??? +STR_2590 :A +STR_2591 :B +STR_2592 :C +STR_2593 :D +STR_2594 :E +STR_2595 :F +STR_2596 :G +STR_2597 :H +STR_2598 :I +STR_2599 :J +STR_2600 :K +STR_2601 :L +STR_2602 :M +STR_2603 :N +STR_2604 :O +STR_2605 :P +STR_2606 :Q +STR_2607 :R +STR_2608 :S +STR_2609 :T +STR_2610 :U +STR_2611 :V +STR_2612 :W +STR_2613 :X +STR_2614 :Y +STR_2615 :Z +STR_2616 :??? +STR_2617 :??? +STR_2618 :Menu +STR_2619 :??? +STR_2620 :??? +STR_2621 :NumPad 0 +STR_2622 :NumPad 1 +STR_2623 :NumPad 2 +STR_2624 :NumPad 3 +STR_2625 :NumPad 4 +STR_2626 :NumPad 5 +STR_2627 :NumPad 6 +STR_2628 :NumPad 7 +STR_2629 :NumPad 8 +STR_2630 :NumPad 9 +STR_2631 :NumPad * +STR_2632 :NumPad + +STR_2633 :??? +STR_2634 :NumPad - +STR_2635 :NumPad . +STR_2636 :NumPad / +STR_2637 :F1 +STR_2638 :F2 +STR_2639 :F3 +STR_2640 :F4 +STR_2641 :F5 +STR_2642 :F6 +STR_2643 :F7 +STR_2644 :F8 +STR_2645 :F9 +STR_2646 :F10 +STR_2647 :F11 +STR_2648 :F12 +STR_2649 :F13 +STR_2650 :F14 +STR_2651 :F15 +STR_2652 :F16 +STR_2653 :F17 +STR_2654 :F18 +STR_2655 :F19 +STR_2656 :F20 +STR_2657 :F21 +STR_2658 :F22 +STR_2659 :F23 +STR_2660 :F24 +STR_2661 :??? +STR_2662 :??? +STR_2663 :??? +STR_2664 :??? +STR_2665 :??? +STR_2666 :??? +STR_2667 :??? +STR_2668 :??? +STR_2669 :NumLock +STR_2670 :Scroll +STR_2671 :??? +STR_2672 :??? +STR_2673 :??? +STR_2674 :??? +STR_2675 :??? +STR_2676 :??? +STR_2677 :??? +STR_2678 :??? +STR_2679 :??? +STR_2680 :All research complete +STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} +STR_2682 : +STR_2683 : +STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive +STR_2685 :Simplex Noise Parameters +STR_2686 :{WINDOW_COLOUR_2}Low: +STR_2687 :{WINDOW_COLOUR_2}High: +STR_2688 :{WINDOW_COLOUR_2}Base Frequency: +STR_2689 :{WINDOW_COLOUR_2}Octaves: +STR_2690 :Map Generation +STR_2691 :{WINDOW_COLOUR_2}Base height: +STR_2692 :{WINDOW_COLOUR_2}Water level: +STR_2693 :{WINDOW_COLOUR_2}Terrain: +STR_2694 :Generate +STR_2695 :Random terrain +STR_2696 :Place trees +STR_2697 :??? +STR_2698 :??? +STR_2699 :??? +STR_2700 :Autosave frequency: +STR_2701 :Every minute +STR_2702 :Every 5 minutes +STR_2703 :Every 15 minutes +STR_2704 :Every 30 minutes +STR_2705 :Every hour +STR_2706 :Never +STR_2707 :Use system dialog window +STR_2708 :{WINDOW_COLOUR_1}Are you sure you want to overwrite {STRINGID}? +STR_2709 :Overwrite +STR_2710 :Type the name of the file. +STR_2711 :; +STR_2712 := +STR_2713 :, +STR_2714 :- +STR_2715 :. +STR_2716 :/ +STR_2717 :' +STR_2718 :Up +STR_2719 :New file +STR_2720 :{UINT16}秒 +STR_2721 :{UINT16}秒 +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}分 +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_2738 :Title screen music: +STR_2739 :None +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 :[ +STR_2745 :\ +STR_2746 :] +STR_2747 :{ENDQUOTES} +STR_2748 :Bar +STR_2749 :My new scenario +# New strings used in the cheats window previously these were ??? +STR_2750 :Move all items to top +STR_2751 :Move all items to bottom +STR_2752 :Clear grass +STR_2753 :Mowed grass +STR_2754 :Water plants +STR_2755 :Fix vandalism +STR_2756 :Remove litter +STR_2757 :Force Sun +STR_2758 :Force Thunder +STR_2759 :Zero Clearance +STR_2760 :+{CURRENCY} +STR_2761 : +STR_2762 : +STR_2763 :??? +STR_2764 : +STR_2765 :Large Tram +STR_2766 :Win scenario +STR_2767 :Freeze Climate +STR_2768 :Unfreeze Climate +STR_2769 :Open Park +STR_2770 :Close Park +STR_2771 :Slower Gamespeed +STR_2772 :Faster Gamespeed +STR_2773 :Windowed +STR_2774 :Fullscreen +STR_2775 :Fullscreen (desktop) +STR_2776 :言語: +STR_2777 :{MOVE_X}{SMALLFONT}{STRING} +STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} +STR_2779 :Viewport #{COMMA16} +STR_2780 :Extra viewport +# End of new strings +STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} +STR_2782 :SHIFT + +STR_2783 :CTRL + +STR_2784 :Change keyboard shortcut +STR_2785 :{WINDOW_COLOUR_2}Press new shortcut key for:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2786 :{SMALLFONT}{BLACK}Click on shortcut description to select new key +STR_2787 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} +STR_2788 :{WINDOW_COLOUR_2}Congratulations !{NEWLINE}{BLACK}You achieved your objective with a company value of {CURRENCY} ! +STR_2789 :{WINDOW_COLOUR_2}You have failed your objective ! +STR_2790 :Enter name into scenario chart +STR_2791 :Enter name +STR_2792 :Please enter your name for the scenario chart: +STR_2793 :{SMALLFONT}(Completed by {STRINGID}) +STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY} +STR_2795 :Sort +STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed +STR_2797 :Scroll view when pointer at screen edge +STR_2798 :{SMALLFONT}{BLACK}Select whether to scroll the view when the mouse pointer is at the screen edge +STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments +STR_2800 :{WINDOW_COLOUR_2}Total admissions: {BLACK}{COMMA32} +STR_2801 :{WINDOW_COLOUR_2}Income from admissions: {BLACK}{CURRENCY2DP} +STR_2802 :Map +STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map +STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map +STR_2805 :{SMALLFONT}{BLACK}Show map of park +STR_2806 :{RED}Guests are complaining about the disgusting state of the paths in your park{NEWLINE}Check where your handymen are and consider organising them better +STR_2807 :{RED}Guests are complaining about the amount of litter in your park{NEWLINE}Check where your handymen are and consider organising them better +STR_2808 :{RED}Guests are complaining about the vandalism in your park{NEWLINE}Check where your security guards are and consider organising them better +STR_2809 :{RED}Guests are hungry and can't find anywhere to buy food +STR_2810 :{RED}Guests are thirsty and can't find anywhere to buy drinks +STR_2811 :{RED}Guests are complaining because they can't find the toilets in your park +STR_2812 :{RED}Guests are getting lost or stuck{NEWLINE}Check whether the layout of your footpaths needs improving to help the guests find their way around +STR_2813 :{RED}Your park entrance fee is too high!{NEWLINE}Reduce your entrance fee or improve the value of the park to attract more guests +STR_2814 :{WINDOW_COLOUR_2}Most untidy park award +STR_2815 :{WINDOW_COLOUR_2}Tidiest park award +STR_2816 :{WINDOW_COLOUR_2}Award for the park with the best roller coasters +STR_2817 :{WINDOW_COLOUR_2}Best value park award +STR_2818 :{WINDOW_COLOUR_2}Most beautiful park award +STR_2819 :{WINDOW_COLOUR_2}Worst value park award +STR_2820 :{WINDOW_COLOUR_2}Safest park award +STR_2821 :{WINDOW_COLOUR_2}Best staff award +STR_2822 :{WINDOW_COLOUR_2}Best park food award +STR_2823 :{WINDOW_COLOUR_2}Worst park food award +STR_2824 :{WINDOW_COLOUR_2}Best park toilets award +STR_2825 :{WINDOW_COLOUR_2}Most disappointing park award +STR_2826 :{WINDOW_COLOUR_2}Best water rides award +STR_2827 :{WINDOW_COLOUR_2}Best custom-designed rides award +STR_2828 :{WINDOW_COLOUR_2}Most dazzling ride colour schemes award +STR_2829 :{WINDOW_COLOUR_2}Most confusing park layout award +STR_2830 :{WINDOW_COLOUR_2}Best gentle ride award +STR_2831 :{TOPAZ}Your park has received an award for being 'The most untidy park in the country'! +STR_2832 :{TOPAZ}Your park has received an award for being 'The tidiest park in the country'! +STR_2833 :{TOPAZ}Your park has received an award for being 'The park with the best roller coasters'! +STR_2834 :{TOPAZ}Your park has received an award for being 'The best value park in the country'! +STR_2835 :{TOPAZ}Your park has received an award for being 'The most beautiful park in the country'! +STR_2836 :{TOPAZ}Your park has received an award for being 'The worst value park in the country'! +STR_2837 :{TOPAZ}Your park has received an award for being 'The safest park in the country'! +STR_2838 :{TOPAZ}Your park has received an award for being 'The park with the best staff'! +STR_2839 :{TOPAZ}Your park has received an award for being 'The park with the best food in the country'! +STR_2840 :{TOPAZ}Your park has received an award for being 'The park with the worst food in the country'! +STR_2841 :{TOPAZ}Your park has received an award for being 'The park with the best toilet facilities in the country'! +STR_2842 :{TOPAZ}Your park has received an award for being 'The most disappointing park in the country'! +STR_2843 :{TOPAZ}Your park has received an award for being 'The park with the best water rides in the country'! +STR_2844 :{TOPAZ}Your park has received an award for being 'The park with the best custom-designed rides'! +STR_2845 :{TOPAZ}Your park has received an award for being 'The park with the most dazzling choice of colour schemes'! +STR_2846 :{TOPAZ}Your park has received an award for being 'The park with the most confusing layout'! +STR_2847 :{TOPAZ}Your park has received an award for being 'The park with the best gentle rides'! +STR_2848 :{WINDOW_COLOUR_2}No recent awards +STR_2849 :New scenario installed successfully +STR_2850 :New track design installed successfully +STR_2851 :Scenario already installed +STR_2852 :Track design already installed +STR_2853 :Forbidden by the local authority! +STR_2854 :{RED}Guests can't get to the entrance of {STRINGID} !{NEWLINE}Construct a path to the entrance +STR_2855 :{RED}{STRINGID} has no path leading from its exit !{NEWLINE}Construct a path from the ride exit +STR_2856 :{WINDOW_COLOUR_2}Tutorial +STR_2857 :{WINDOW_COLOUR_2}(Press a key or mouse button to take control) +STR_2858 :Can't start marketing campaign... +STR_2859 :Another instance of OpenRCT2 is already running +STR_2860 :Infogrames Interactive credits... +STR_2861 :{WINDOW_COLOUR_2}Licensed to Infogrames Interactive Inc. +STR_2862 :Music acknowledgements... +STR_2863 :Music acknowledgements +STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) non copyright +STR_2865 :{WINDOW_COLOUR_2}Heyken's Serenade: (J.Heyken) British Standard Music Coy; GEMA, BRITICO +STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Composer unknown) Copyright Control +STR_2867 :{WINDOW_COLOUR_2}Wedding Journey: (Traditional) +STR_2868 :{WINDOW_COLOUR_2}Tales from the Vienna Woods: (Johann Strauss) non copyright +STR_2869 :{WINDOW_COLOUR_2}Slavonic Dance: (Traditional) +STR_2870 :{WINDOW_COLOUR_2}Das Alpenhorn: (Traditional) +STR_2871 :{WINDOW_COLOUR_2}The Blond Sailor: (Traditional) +STR_2872 :{WINDOW_COLOUR_2}Overture - Poet and Peasant: (Suppe) non copyright +STR_2873 :{WINDOW_COLOUR_2}Waltz Medley: (Johann Strauss) non copyright +STR_2874 :{WINDOW_COLOUR_2}Bella Bella Bimba: (Traditional) +STR_2875 :{WINDOW_COLOUR_2}Original recordings (P) 1976 C.J.Mears Organization, used with consent +STR_2876 :{WINDOW_COLOUR_2}RollerCoaster Tycoon 2 Title Music: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2877 :{WINDOW_COLOUR_2}Dodgems Beat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2878 :{WINDOW_COLOUR_2}Mid Summer's Heat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2879 :{WINDOW_COLOUR_2}Pharaoh's Tomb: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2880 :{WINDOW_COLOUR_2}Caesar's March: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2881 :{WINDOW_COLOUR_2}Drifting To Heaven: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2882 :{WINDOW_COLOUR_2}Invaders: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2883 :{WINDOW_COLOUR_2}Eternal Toybox: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2884 :{WINDOW_COLOUR_2}Jungle Juice: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2885 :{WINDOW_COLOUR_2}Ninja's Noodles: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2886 :{WINDOW_COLOUR_2}Voyage to Andromeda: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2887 :{WINDOW_COLOUR_2}Brimble's Beat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2888 :{WINDOW_COLOUR_2}Atlantis: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2889 :{WINDOW_COLOUR_2}Wild West Kid: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2890 :{WINDOW_COLOUR_2}Vampire's Lair: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2891 :{WINDOW_COLOUR_2}Blockbuster: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2892 :{WINDOW_COLOUR_2}Airtime Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2893 :{WINDOW_COLOUR_2}Searchlight Rag: (Scott Joplin/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2894 :{WINDOW_COLOUR_2}Flight of Fantasy: (Steve Blenkinsopp) copyright {COPYRIGHT} Chris Sawyer +STR_2895 :{WINDOW_COLOUR_2}Big Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2896 :{WINDOW_COLOUR_2}Hypothermia: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2897 :{WINDOW_COLOUR_2}Last Sleigh Ride: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2898 :{WINDOW_COLOUR_2}Pipes of Glencairn: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2899 :{WINDOW_COLOUR_2}Traffic Jam: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2900 :{WINDOW_COLOUR_2} +STR_2901 :{WINDOW_COLOUR_2}(Samples courtesy of Spectrasonics {ENDQUOTES}Liquid Grooves{ENDQUOTES}) +STR_2902 :{WINDOW_COLOUR_2}Toccata: (C.M.Widor, played by Peter James Adcock) recording {COPYRIGHT} Chris Sawyer +STR_2903 :{WINDOW_COLOUR_2}Space Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2904 :{WINDOW_COLOUR_2}Manic Mechanic: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2905 :{WINDOW_COLOUR_2}Techno Torture: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2906 :{WINDOW_COLOUR_2}Sweat Dreams: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2907 :{WINDOW_COLOUR_2}What shall we do with the Drunken Sailor: (Anon/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2908 :{WINDOW_COLOUR_2}Infogrames Interactive +STR_2909 :{WINDOW_COLOUR_2}Senior Producer: Thomas J. Zahorik +STR_2910 :{WINDOW_COLOUR_2}Executive Producer: Bill Levay +STR_2911 :{WINDOW_COLOUR_2}Senior Marketing Product Manager: Scott Triola +STR_2912 :{WINDOW_COLOUR_2}V.P. of Product Development: Scott Walker +STR_2913 :{WINDOW_COLOUR_2}General Manager: John Hurlbut +STR_2914 :{WINDOW_COLOUR_2}Director of Quality Assurance: Michael Craighead +STR_2915 :{WINDOW_COLOUR_2}Q.A. Certification Manager: Kurt Boutin +STR_2916 :{WINDOW_COLOUR_2}Q.A. Certification Lead: Mark Huggins +STR_2917 :{WINDOW_COLOUR_2}Testers: Dena Irene Fitzgerald, Scott Rollins, Christopher McPhail +STR_2918 :{WINDOW_COLOUR_2}Clif McClure, Erik Maramaldi, Erik Jeffery +STR_2919 :{WINDOW_COLOUR_2}Director of Marketing: Ann Marie Bland +STR_2920 :{WINDOW_COLOUR_2}Manager of Creative Services: Steve Martin +STR_2921 :{WINDOW_COLOUR_2}Manager of Editorial & Documentation Services: Elizabeth Mackney +STR_2922 :{WINDOW_COLOUR_2}Graphic Designer: Paul Anselmi +STR_2923 :{WINDOW_COLOUR_2}Copywriter: Kurt Carlson +STR_2924 :{WINDOW_COLOUR_2}Special Thanks to: Peter Matiss +STR_2925 :{WINDOW_COLOUR_2}Engineering Specialist: Ken Edwards +STR_2926 :{WINDOW_COLOUR_2}Engineering Services Manager: Luis Rivas +STR_2927 :{WINDOW_COLOUR_2}Lead Compatibility Analyst: Geoffrey Smith +STR_2928 :{WINDOW_COLOUR_2}Compatibility Analysts: Jason Cordero, Burke McQuinn, Kim Jardin +STR_2929 :{WINDOW_COLOUR_2}Lead Tester: Daniel Frisoli +STR_2930 :{WINDOW_COLOUR_2}Senior Tester: Matt Pantaleoni +STR_2931 :{WINDOW_COLOUR_2} +STR_2932 :{WINDOW_COLOUR_2} +STR_2933 :{WINDOW_COLOUR_2} +STR_2934 :{WINDOW_COLOUR_2} +STR_2935 :{WINDOW_COLOUR_2} +STR_2936 :{WINDOW_COLOUR_2} +STR_2937 :{WINDOW_COLOUR_2} +STR_2938 :{WINDOW_COLOUR_2} +STR_2939 :{WINDOW_COLOUR_2} +STR_2940 :{WINDOW_COLOUR_2} +STR_2941 :{WINDOW_COLOUR_2} +STR_2942 :{WINDOW_COLOUR_2} +STR_2943 :{WINDOW_COLOUR_2} +STR_2944 :{WINDOW_COLOUR_2} +STR_2945 :{WINDOW_COLOUR_2} +STR_2946 :{WINDOW_COLOUR_2} +STR_2947 :{WINDOW_COLOUR_2} +STR_2948 :{WINDOW_COLOUR_2} +STR_2949 :{WINDOW_COLOUR_2} +STR_2950 :{WINDOW_COLOUR_2} +STR_2951 :{WINDOW_COLOUR_2} +STR_2952 :{WINDOW_COLOUR_2} +STR_2953 :{WINDOW_COLOUR_2} +STR_2954 :{WINDOW_COLOUR_2} +STR_2955 :{WINDOW_COLOUR_2} +STR_2956 :{WINDOW_COLOUR_2} +STR_2957 :{WINDOW_COLOUR_2} +STR_2958 :{WINDOW_COLOUR_2} +STR_2959 :{WINDOW_COLOUR_2} +STR_2960 :{WINDOW_COLOUR_2} +STR_2961 :{WINDOW_COLOUR_2} +STR_2962 :{WINDOW_COLOUR_2} +STR_2963 :{WINDOW_COLOUR_2} +STR_2964 :{WINDOW_COLOUR_2} +STR_2965 :{WINDOW_COLOUR_2} +STR_2966 : +STR_2967 : +STR_2968 : +STR_2969 : +STR_2970 : +STR_2971 :Main colour scheme +STR_2972 :Alternative colour scheme 1 +STR_2973 :Alternative colour scheme 2 +STR_2974 :Alternative colour scheme 3 +STR_2975 :{SMALLFONT}{BLACK}Select which colour scheme to change, or paint ride with +STR_2976 :{SMALLFONT}{BLACK}Paint an individual area of this ride using the selected colour scheme +STR_2977 :Staff member name +STR_2978 :Enter new name for this member of staff: +STR_2979 :Can't name staff member... +STR_2980 :Too many banners in game +STR_2981 :{RED}No entry - - +STR_2982 :Banner text +STR_2983 :Enter new text for this banner: +STR_2984 :Can't set new text for banner... +STR_2985 :Banner +STR_2986 :{SMALLFONT}{BLACK}Change text on banner +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 :バナー +STR_2992 :Sign text +STR_2993 :Enter new text for this sign: +STR_2994 :{SMALLFONT}{BLACK}Change text on sign +STR_2995 :{SMALLFONT}{BLACK}Demolish this sign +STR_2996 :{BLACK}ABC +STR_2997 :{GREY}ABC +STR_2998 :{WHITE}ABC +STR_2999 :{RED}ABC +STR_3000 :{GREEN}ABC +STR_3001 :{YELLOW}ABC +STR_3002 :{TOPAZ}ABC +STR_3003 :{CELADON}ABC +STR_3004 :{BABYBLUE}ABC +STR_3005 :{PALELAVENDER}ABC +STR_3006 :{PALEGOLD}ABC +STR_3007 :{LIGHTPINK}ABC +STR_3008 :{PEARLAQUA}ABC +STR_3009 :{PALESILVER}ABC +STR_3010 :Unable to load file... +STR_3011 :File contains invalid data +STR_3012 :Dodgems beat style +STR_3013 :Fairground organ style +STR_3014 :Roman fanfare style +STR_3015 :Oriental style +STR_3016 :Martian style +STR_3017 :Jungle drums style +STR_3018 :Egyptian style +STR_3019 :Toyland style +STR_3020 : +STR_3021 :Space style +STR_3022 :Horror style +STR_3023 :Techno style +STR_3024 :Gentle style +STR_3025 :Summer style +STR_3026 :Water style +STR_3027 :Wild west style +STR_3028 :Jurassic style +STR_3029 :Rock style +STR_3030 :Ragtime style +STR_3031 :Fantasy style +STR_3032 :Rock style 2 +STR_3033 :Ice style +STR_3034 :Snow style +STR_3035 :Custom music 1 +STR_3036 :Custom music 2 +STR_3037 :Medieval style +STR_3038 :Urban style +STR_3039 :Organ style +STR_3040 :Mechanical style +STR_3041 :Modern style +STR_3042 :Pirates style +STR_3043 :Rock style 3 +STR_3044 :Candy style +STR_3045 :{SMALLFONT}{BLACK}Select style of music to play +STR_3046 :This ride cannot be modified +STR_3047 :Local authority forbids demolition or modifications to this ride +STR_3048 :Marketing campaigns forbidden by local authority +STR_3049 :Golf hole A +STR_3050 :Golf hole B +STR_3051 :Golf hole C +STR_3052 :Golf hole D +STR_3053 :Golf hole E +STR_3054 :Loading... +STR_3055 :白 +STR_3056 :Translucent +STR_3057 :{WINDOW_COLOUR_2}Construction Marker: +STR_3058 :Brick walls +STR_3059 :Hedges +STR_3060 :Ice blocks +STR_3061 :Wooden fences +STR_3062 :{SMALLFONT}{BLACK}Standard roller coaster track +STR_3063 :{SMALLFONT}{BLACK}Water channel (track submerged) +STR_3064 :Beginner Parks +STR_3065 :Challenging Parks +STR_3066 :Expert Parks +STR_3067 :{OPENQUOTES}Real{ENDQUOTES} Parks +STR_3068 :Other Parks +STR_3069 :Top Section +STR_3070 :Slope to Level +STR_3071 :{WINDOW_COLOUR_2}Same price throughout park +STR_3072 :{SMALLFONT}{BLACK}Select whether this price is used throughout the entire park +STR_3073 :{RED}WARNING: Your park rating has dropped below 700 !{NEWLINE}If you haven't raised the park rating in 4 weeks, your park will be closed down +STR_3074 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have 3 weeks to raise the park rating +STR_3075 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have only 2 weeks to raise the park rating, or your park will be closed down +STR_3076 :{RED}FINAL WARNING: Your park rating is still below 700 !{NEWLINE}In just 7 days your park will be closed down unless you can raise the rating +STR_3077 :{RED}CLOSURE NOTICE: Your park has been closed down ! +STR_3078 :Plain entrance +STR_3079 :Wooden entrance +STR_3080 :Canvas tent entrance +STR_3081 :Castle entrance (grey) +STR_3082 :Castle entrance (brown) +STR_3083 :Jungle entrance +STR_3084 :Log cabin entrance +STR_3085 :Classical/Roman entrance +STR_3086 :Abstract entrance +STR_3087 :Snow/Ice entrance +STR_3088 :Pagoda entrance +STR_3089 :Space entrance +STR_3090 :{SMALLFONT}{BLACK}Select style of entrance, exit, and station +STR_3091 :You are not allowed to remove this section! +STR_3092 :You are not allowed to move or modify the station for this ride! +STR_3093 :{WINDOW_COLOUR_2}Favourite: {BLACK}{STRINGID} +STR_3094 :N/A +STR_3095 :{WINDOW_COLOUR_2}Lift hill chain speed: +STR_3096 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} +STR_3097 :{SMALLFONT}{BLACK}Select lift hill chain speed +STR_3098 :Can't change lift hill speed... +STR_3099 :{SMALLFONT}{BLACK}Select colour +STR_3100 :{SMALLFONT}{BLACK}Select second colour +STR_3101 :{SMALLFONT}{BLACK}Select third colour +STR_3102 :{SMALLFONT}{BLACK}Re-paint coloured scenery on landscape +STR_3103 :Can't re-paint this... +STR_3104 :{SMALLFONT}{BLACK}List rides +STR_3105 :{SMALLFONT}{BLACK}List shops and stalls +STR_3106 :{SMALLFONT}{BLACK}List information kiosks and other guest facilities +STR_3107 :閉鎖 +STR_3108 :テスト +STR_3109 :オープン +STR_3110 :{WINDOW_COLOUR_2}Block Sections: {BLACK}{COMMA16} +STR_3111 :{SMALLFONT}{BLACK}Click on design to build it +STR_3112 :{SMALLFONT}{BLACK}Click on design to rename or delete it +STR_3113 :Select a different design +STR_3114 :{SMALLFONT}{BLACK}Go back to design selection window +STR_3115 :{SMALLFONT}{BLACK}Save track design +STR_3116 :{SMALLFONT}{BLACK}Save track design (Not possible until ride has been tested and statistics have been generated) +STR_3117 :{BLACK}Calling mechanic... +STR_3118 :{BLACK}{STRINGID} is heading for the ride +STR_3119 :{BLACK}{STRINGID} is fixing the ride +STR_3120 :{SMALLFONT}{BLACK}Locate nearest available mechanic, or mechanic fixing ride +STR_3121 :Unable to locate mechanic, or all nearby mechanics are busy +STR_3122 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guest +STR_3123 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guests +STR_3124 :Broken {STRINGID} +STR_3125 :{WINDOW_COLOUR_2}Excitement Factor: {BLACK}+{COMMA16}% +STR_3126 :{WINDOW_COLOUR_2}Intensity Factor: {BLACK}+{COMMA16}% +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 :キャンセル +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) +STR_3135 :{RED}(Vehicle design unavailable - Ride performance may be affected) +STR_3136 :Warning: This design will be built with an alternative vehicle type and may not perform as expected +STR_3137 :Select Nearby Scenery +STR_3138 :Reset Selection +STR_3139 :Cable lift unable to work in this operating mode +STR_3140 :Cable lift hill must start immediately after station +STR_3141 :Multi-circuit per ride not possible with cable lift hill +STR_3142 :{WINDOW_COLOUR_2}Capacity: {BLACK}{STRINGID} +STR_3143 :{SMALLFONT}{BLACK}Show people on map +STR_3144 :{SMALLFONT}{BLACK}Show rides and stalls on map +STR_3145 :{SMALLFONT}{BLACK}Scroll {STRINGID} left +STR_3146 :{SMALLFONT}{BLACK}Scroll {STRINGID} right +STR_3147 :{SMALLFONT}{BLACK}Scroll {STRINGID} left fast +STR_3148 :{SMALLFONT}{BLACK}Scroll {STRINGID} right fast +STR_3149 :{SMALLFONT}{BLACK}Scroll {STRINGID} left/right +STR_3150 :{SMALLFONT}{BLACK}Scroll {STRINGID} up +STR_3151 :{SMALLFONT}{BLACK}Scroll {STRINGID} down +STR_3152 :{SMALLFONT}{BLACK}Scroll {STRINGID} up fast +STR_3153 :{SMALLFONT}{BLACK}Scroll {STRINGID} down fast +STR_3154 :{SMALLFONT}{BLACK}Scroll {STRINGID} up/down +STR_3155 : +STR_3156 : +STR_3157 :map +STR_3158 :graph +STR_3159 :list +STR_3160 : +STR_3161 : +STR_3162 :Unable to allocate enough memory +STR_3163 :Installing new data: +STR_3164 :{BLACK}{COMMA16} selected (maximum {COMMA16}) +STR_3165 : +STR_3166 :{BLACK}(ID: +STR_3167 :{WINDOW_COLOUR_2}Includes: {BLACK}{COMMA16} objects +STR_3168 :{WINDOW_COLOUR_2}Text: {BLACK}{STRINGID} +STR_3169 :Data for the following object not found: +STR_3170 :Not enough space for graphics +STR_3171 :Too many objects of this type selected +STR_3172 :The following object must be selected first: {STRING} +STR_3173 :This object is currently in use +STR_3174 :This object is required by another object +STR_3175 :This object is always required +STR_3176 :Unable to select this object +STR_3177 :Unable to de-select this object +STR_3178 :At least one path object must be selected +STR_3179 :At least one ride vehicle/attraction object must be selected +STR_3180 :Invalid selection of objects +STR_3181 :Object Selection - {STRINGID} +STR_3182 :Park entrance type must be selected +STR_3183 :Water type must be selected +STR_3184 :Ride Vehicles/Attractions +STR_3185 :Small Scenery +STR_3186 :Large Scenery +STR_3187 :Walls/Fences +STR_3188 :Path Signs +STR_3189 :Footpaths +STR_3190 :Path Extras +STR_3191 :Scenery Groups +STR_3192 :Park Entrance +STR_3193 :Water +STR_3194 :Scenario Description +STR_3195 :Invention List +STR_3196 :{WINDOW_COLOUR_2}Research Group: {BLACK}{STRINGID} +STR_3197 :{WINDOW_COLOUR_2}Items pre-invented at start of game: +STR_3198 :{WINDOW_COLOUR_2}Items to invent during game: +STR_3199 :Random Shuffle +STR_3200 :{SMALLFONT}{BLACK}Randomly shuffle the list of items to invent during the game +STR_3201 :Object Selection +STR_3202 :Landscape Editor +STR_3203 :Invention List Set Up +STR_3204 :Options Selection +STR_3205 :Objective Selection +STR_3206 :Save Scenario +STR_3207 :Roller Coaster Designer +STR_3208 :Track Designs Manager +STR_3209 :Back to Previous Step: +STR_3210 :Forward to Next Step: +STR_3211 :{WINDOW_COLOUR_2}Map size: +STR_3212 :{POP16}{COMMA16} x {PUSH16}{COMMA16} +STR_3213 :Can't decrease map size any further +STR_3214 :Can't increase map size any further +STR_3215 :Too close to edge of map +STR_3216 :{SMALLFONT}{BLACK}Select park-owned land etc. +STR_3217 :Land Owned +STR_3218 :Construction Rights Owned +STR_3219 :Land For Sale +STR_3220 :Construction Rights For Sale +STR_3221 :{SMALLFONT}{BLACK}Set land to be owned by the park +STR_3222 :{SMALLFONT}{BLACK}Set construction rights only to be owned by the park +STR_3223 :{SMALLFONT}{BLACK}Set land to be available to purchase by the park +STR_3224 :{SMALLFONT}{BLACK}Set construction rights to be available to purchase by the park +STR_3225 :{SMALLFONT}{BLACK}Toggle on/off building a random cluster of objects around the selected position +STR_3226 :{SMALLFONT}{BLACK}Build park entrance +STR_3227 :Too many park entrances! +STR_3228 :{SMALLFONT}{BLACK}Set starting positions for people +STR_3229 :Block Brakes cannot be used directly after station +STR_3230 :Block Brakes cannot be used directly after each other +STR_3231 :Block Brakes cannot be used directly after the top of this lift hill +STR_3232 :Options - Financial +STR_3233 :Options - Guests +STR_3234 :Options - Park +STR_3235 :{SMALLFONT}{BLACK}Show financial options +STR_3236 :{SMALLFONT}{BLACK}Show guest options +STR_3237 :{SMALLFONT}{BLACK}Show park options +STR_3238 :No Money +STR_3239 :{SMALLFONT}{BLACK}Make this park a 'no money' park with no financial restrictions +STR_3240 :{WINDOW_COLOUR_2}Initial cash: +STR_3241 :{WINDOW_COLOUR_2}Initial loan: +STR_3242 :{WINDOW_COLOUR_2}Maximum loan size: +STR_3243 :{WINDOW_COLOUR_2}Annual interest rate: +STR_3244 :Forbid marketing campaigns +STR_3245 :{SMALLFONT}{BLACK}Forbid advertising, promotional schemes, and other marketing campaigns +STR_3246 :{WINDOW_COLOUR_2}{CURRENCY} +STR_3247 :{WINDOW_COLOUR_2}{COMMA16}% +STR_3248 :Can't increase initial cash any further! +STR_3249 :Can't reduce initial cash any further! +STR_3250 :Can't increase initial loan any further! +STR_3251 :Can't reduce initial loan any further! +STR_3252 :Can't increase maximum loan size any further! +STR_3253 :Can't reduce maximum loan size any further! +STR_3254 :Can't increase interest rate any further! +STR_3255 :Can't reduce interest rate any further! +STR_3256 :Guests prefer less intense rides +STR_3257 :{SMALLFONT}{BLACK}Select whether guests should generally prefer less intense rides only +STR_3258 :Guests prefer more intense rides +STR_3259 :{SMALLFONT}{BLACK}Select whether guests should generally prefer more intense rides only +STR_3260 :{WINDOW_COLOUR_2}Cash per guest (average): +STR_3261 :{WINDOW_COLOUR_2}Guests initial happiness: +STR_3262 :{WINDOW_COLOUR_2}Guests initial hunger: +STR_3263 :{WINDOW_COLOUR_2}Guests initial thirst: +STR_3264 :Can't increase this any further! +STR_3265 :Can't reduce this any further! +STR_3266 :{SMALLFONT}{BLACK}Select how this park charges for entrance and rides +STR_3267 :Forbid tree removal +STR_3268 :{SMALLFONT}{BLACK}Forbid tall trees being removed +STR_3269 :Forbid landscape changes +STR_3270 :{SMALLFONT}{BLACK}Forbid any changes to the landscape +STR_3271 :Forbid high construction +STR_3272 :{SMALLFONT}{BLACK}Forbid any tall construction +STR_3273 :Park rating higher difficult level +STR_3274 :{SMALLFONT}{BLACK}Make the park rating value more challenging +STR_3275 :Guest generation higher difficult level +STR_3276 :{SMALLFONT}{BLACK}Make it more difficult to attract guests to the park +STR_3277 :{WINDOW_COLOUR_2}Cost to buy land: +STR_3278 :{WINDOW_COLOUR_2}Cost to buy construction rights: +STR_3279 :Free park entry / Pay per ride +STR_3280 :Pay to enter park / Free rides +STR_3281 :{WINDOW_COLOUR_2}Entry price: +STR_3282 :{SMALLFONT}{BLACK}Select objective and park name +STR_3283 :{SMALLFONT}{BLACK}Select rides to be preserved +STR_3284 :Objective Selection +STR_3285 :Preserved Rides +STR_3286 :{SMALLFONT}{BLACK}Select objective for this scenario +STR_3287 :{WINDOW_COLOUR_2}Objective: +STR_3288 :{SMALLFONT}{BLACK}Select climate +STR_3289 :{WINDOW_COLOUR_2}Climate: +STR_3290 :Cool and wet +STR_3291 :Warm +STR_3292 :Hot and dry +STR_3293 :Cold +STR_3294 :Change... +STR_3295 :{SMALLFONT}{BLACK}Change name of park +STR_3296 :{SMALLFONT}{BLACK}Change name of scenario +STR_3297 :{SMALLFONT}{BLACK}Change detail notes about park / scenario +STR_3298 :{WINDOW_COLOUR_2}Park Name: {BLACK}{STRINGID} +STR_3299 :{WINDOW_COLOUR_2}Park/Scenario Details: +STR_3300 :{WINDOW_COLOUR_2}Scenario Name: {BLACK}{STRINGID} +STR_3301 :{WINDOW_COLOUR_2}Objective Date: +STR_3302 :{WINDOW_COLOUR_2}{MONTHYEAR} +STR_3303 :{WINDOW_COLOUR_2}Number of guests: +STR_3304 :{WINDOW_COLOUR_2}Park value: +STR_3305 :{WINDOW_COLOUR_2}Monthly income: +STR_3306 :{WINDOW_COLOUR_2}Monthly profit: +STR_3307 :{WINDOW_COLOUR_2}Minimum length: +STR_3308 :{WINDOW_COLOUR_2}Excitement rating: +STR_3309 :{WINDOW_COLOUR_2}{COMMA16} +STR_3310 :{WINDOW_COLOUR_2}{LENGTH} +STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} +STR_3312 :{WINDOW_COLOUR_2}Rides/attractions under a preservation order: +STR_3313 :Scenario Name +STR_3314 :Enter name for scenario: +STR_3315 :Park/Scenario Details +STR_3316 :Enter description of this scenario: +STR_3317 :No details yet +STR_3318 :{SMALLFONT}{BLACK}Select which group this scenario appears in +STR_3319 :{WINDOW_COLOUR_2}Scenario Group: +STR_3320 :Unable to save scenario file... +STR_3321 :New objects installed successfully +STR_3322 :{WINDOW_COLOUR_2}Objective: {BLACK}{STRINGID} +STR_3323 :Missing object data, ID: +STR_3324 :Requires Add-On Pack: +STR_3325 :Requires an Add-On Pack +STR_3326 :{WINDOW_COLOUR_2}(no image) +STR_3327 :Starting positions for people not set +STR_3328 :Can't advance to next editor stage... +STR_3329 :Park entrance not yet built +STR_3330 :Park must own some land +STR_3331 :Path from park entrance to map edge either not complete or too complex - Path must be single-width with as few junctions and corners as possible +STR_3332 :Park entrance is the wrong way round or has no path leading to the map edge +STR_3333 :Export plug-in objects with saved games +STR_3334 :{SMALLFONT}{BLACK}Select whether to save any additional plug-in object data required (add-in data not supplied with the main product) in saved game or scenario files, allowing them to be loaded by someone who doesn't have the additional object data +STR_3335 :Roller Coaster Designer - Select Ride Types & Vehicles +STR_3336 :Track Designs Manager - Select Ride Type +STR_3337 : +STR_3338 :{BLACK}Custom-designed layout +STR_3339 :{BLACK}{COMMA16} design available, or custom-designed layout +STR_3340 :{BLACK}{COMMA16} designs available, or custom-designed layout +STR_3341 :{SMALLFONT}{BLACK}Game tools +STR_3342 :Scenario Editor +STR_3343 :Convert Saved Game to Scenario +STR_3344 :Roller Coaster Designer +STR_3345 :Track Designs Manager +STR_3346 :Can't save track design... +STR_3347 :Ride is too large, contains too many elements, or scenery is too spread out +STR_3348 :Rename +STR_3349 :Delete +STR_3350 :Track design name +STR_3351 :Enter new name for this track design: +STR_3352 :Can't rename track design... +STR_3353 :New name contains invalid characters +STR_3354 :Another file exists with this name, or file is write-protected +STR_3355 :File is write-protected or locked +STR_3356 :Delete File +STR_3357 :{WINDOW_COLOUR_2}Are you sure you want to permanently delete {STRINGID} ? +STR_3358 :Can't delete track design... +STR_3359 :{BLACK}No track designs of this type +STR_3360 :Warning! +STR_3361 :Too many track designs of this type - Some will not be listed. +STR_3362 : +STR_3363 : +STR_3364 :Advanced +STR_3365 :{SMALLFONT}{BLACK}Allow selection of individual items of scenery in addition to scenery groups +STR_3366 :{BLACK}= Ride +STR_3367 :{BLACK}= Food Stall +STR_3368 :{BLACK}= Drink Stall +STR_3369 :{BLACK}= Souvenir Stall +STR_3370 :{BLACK}= Info. Kiosk +STR_3371 :{BLACK}= First Aid +STR_3372 :{BLACK}= Cash Machine +STR_3373 :{BLACK}= Toilet +STR_3374 :Warning: Too many objects selected! +STR_3375 :Not all objects in this scenery group could be selected +STR_3376 :Install new track design... +STR_3377 :{SMALLFONT}{BLACK}Install a new track design file +STR_3378 :Install +STR_3379 :Cancel +STR_3380 :Unable to install this track design... +STR_3381 :File is not compatible or contains invalid data +STR_3382 :File copy failed +STR_3383 :Select new name for track design +STR_3384 :An existing track design already has this name - Please select a new name for this design: +STR_3385 :Beginners Tutorial +STR_3386 :Custom Rides Tutorial +STR_3387 :Roller Coaster Building Tutorial +STR_3388 :Unable to switch to selected mode +STR_3389 :Unable to select additional item of scenery... +STR_3390 :Too many items selected +# Start of tutorial strings. Not used at the moment, so not necessary to translate. +STR_3391 :{SMALLFONT}{BLACK}Here is our park - Let's have a quick look around... +STR_3392 :{SMALLFONT}{BLACK}Holding down the RIGHT mouse button and moving the mouse is the quickest way to move the view... +STR_3393 :{SMALLFONT}{BLACK}To view more of the park, you can zoom the view out using the icon at the top of the screen... +STR_3394 :{SMALLFONT}{BLACK}You can also rotate the view in 90 degree steps... +STR_3395 :{SMALLFONT}{BLACK}Building anything at this scale is a bit difficult, so let's zoom the view back in again... +STR_3396 :{SMALLFONT}{BLACK}Let's build a simple ride to get the park started... +STR_3397 :{SMALLFONT}{BLACK}The white 'ghost' image shows where the ride will be built. We'll move the pointer to select the position then click to build it... +STR_3398 :{SMALLFONT}{BLACK}Rides need an entrance and an exit. We'll move the pointer to a square on the edge of the ride and then click to build first the entrance and then the exit... +STR_3399 :{SMALLFONT}{BLACK}We need to build footpaths to allow guests to reach our new ride... +STR_3400 :{SMALLFONT}{BLACK}For the path to the ride entrance we'll use a special 'queue line' path... +STR_3401 :{SMALLFONT}{BLACK}For the exit path, just an 'ordinary' path will do... +STR_3402 :{SMALLFONT}{BLACK}Right, lets open the ride! To open the ride we click the flag icon on the ride window and select 'open'... +STR_3403 :{SMALLFONT}{BLACK}But where are the guests? +STR_3404 :{SMALLFONT}{BLACK}Oh - The park is still closed! Right - Let's open it... +STR_3405 :{SMALLFONT}{BLACK}While we're waiting for our first guests, let's build some scenery... +STR_3406 :{SMALLFONT}{BLACK}Here's our empty park. We're going to build a simple custom-designed ride... +STR_3407 :{SMALLFONT}{BLACK}First we need to choose a starting position... +STR_3408 :{SMALLFONT}{BLACK}The section of track we've just built is a 'station platform', to allow guests to get on and off the ride... +STR_3409 :{SMALLFONT}{BLACK}We'll extend the platform a bit by adding a couple more station platform sections... +STR_3410 :{SMALLFONT}{BLACK}The icons at the top of the construction window let you choose different track pieces to add... +STR_3411 :{SMALLFONT}{BLACK}We'll select a left-hand curve... +STR_3412 :{SMALLFONT}{BLACK}The curve hasn't been built yet, but the white ghost image shows where it will be built. Clicking the large 'build this' icon actually builds the track... +STR_3413 :{SMALLFONT}{BLACK}Now we want to build straight track, so we click the straight track icon... +STR_3414 :{SMALLFONT}{BLACK}Now that the circuit is complete, we need to build the ride entrance and exit... +STR_3415 :{SMALLFONT}{BLACK}Let's test our ride to check it works... +STR_3416 :{SMALLFONT}{BLACK}White it's being tested, we'll build the queue line and exit path... +STR_3417 :{SMALLFONT}{BLACK}OK - Let's open the park and the ride... +STR_3418 :{SMALLFONT}{BLACK}Our new ride isn't very exciting - Perhaps we should add some scenery? +STR_3419 :{SMALLFONT}{BLACK}To build scenery above other scenery or in mid-air, hold down the SHIFT key and move the mouse to select the height... +STR_3420 :{SMALLFONT}{BLACK}Some types of scenery can be re-painted after it's built... +STR_3421 :{SMALLFONT}{BLACK}Let's add some music to the ride... +STR_3422 :{SMALLFONT}{BLACK}Let's build a roller coaster ! +STR_3423 :{SMALLFONT}{BLACK}There are loads of pre-designed coasters, but we're going to build our own custom design... +STR_3424 :{SMALLFONT}{BLACK}That's the station platform built. Now we need a lift hill... +STR_3425 :{SMALLFONT}{BLACK}Roller coaster trains aren't powered, so a 'chain lift' is needed to pull the train up the first hill... +STR_3426 :{SMALLFONT}{BLACK}That's the lift hill complete - Now for the first drop... +STR_3427 :{SMALLFONT}{BLACK}Those curves are a bad idea - The riders will be flung to the sides by the lateral G forces as the train hurtles around... +STR_3428 :{SMALLFONT}{BLACK}Banking the curves will improve the ride - Riders will be pushed down into their seats instead of flung to the sides... +STR_3429 :{SMALLFONT}{BLACK}No - That won't work! Look at the height marks - The second hill is taller than the lift hill... +STR_3430 :{SMALLFONT}{BLACK}To ensure the train makes it around, each hill should be slightly smaller than the previous one... +STR_3431 :{SMALLFONT}{BLACK}That's better - Our train should make it up that hill now! Let's try some more twisted track... +STR_3432 :{SMALLFONT}{BLACK}We need to slow the train before the final curve and station, so let's add some brakes... +STR_3433 :{SMALLFONT}{BLACK}And finally we'll add 'block brakes', which allow two trains to operate more safely on the circuit... +STR_3434 :{SMALLFONT}{BLACK}Let's test the ride and see if it works! +STR_3435 :{SMALLFONT}{BLACK}Great - It worked! Let's add the footpaths and let guests onto our new roller coaster... +STR_3436 :{SMALLFONT}{BLACK}While waiting for our first riders, we could customise the ride a bit... +# End of tutorial strings +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 :1ページ目 +STR_3441 :2ページ目 +STR_3442 :3ページ目 +STR_3443 :4ページ目 +STR_3444 :5ページ目 +STR_3445 :Set Patrol Area +STR_3446 :Cancel Patrol Area + +# New strings, cleaner +STR_5120 :Finances +STR_5121 :Research +STR_5122 :Select rides by track type (like in RCT1) +STR_5123 :Renew rides +STR_5124 : +STR_5125 :All destructable +STR_5126 :Random title music +STR_5127 :{SMALLFONT}{BLACK}Disable land elevation +STR_5128 :Selection size +STR_5129 :Enter selection size between {COMMA16} and {COMMA16} +STR_5130 :Map size +STR_5131 :Enter map size between {COMMA16} and {COMMA16} +STR_5132 :Fix all rides +STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights +STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights +STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights +STR_5136 :Land rights +STR_5137 :Allow lift hill and launch speeds{NEWLINE}up to {VELOCITY} +STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} +STR_5139 :{WHITE}{STRINGID} +STR_5140 :Disable brakes failure +STR_5141 :Disable all breakdowns +STR_5142 :Normal Speed +STR_5143 :Quick Speed +STR_5144 :Fast Speed +STR_5145 :Turbo Speed +STR_5146 :Hyper Speed +STR_5147 :Cheats +STR_5148 :{SMALLFONT}{BLACK}Change the game speed +STR_5149 :{SMALLFONT}{BLACK}Show cheat options +STR_5150 :Enable debugging tools +STR_5151 :, +STR_5152 :. +STR_5153 :Edit Themes... +STR_5154 :Hardware display +STR_5155 :Allow testing of unfinished tracks +STR_5156 :{SMALLFONT}{BLACK}Allows testing of most ride types even when the track is unfinished, does not apply to block sectioned modes +STR_5157 :Unlock all prices +STR_5158 :Quit to menu +STR_5159 :Exit OpenRCT2 +STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID} {POP16}{COMMA16}年 +STR_5161 :Date Format: +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 +STR_5167 :Track follower peeps +STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers +STR_5169 :Name peeps after people in Twitch chat +STR_5170 :{SMALLFONT}{BLACK}Will name peeps after people in Twitch chat +STR_5171 :Track chat peeps +STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants +STR_5173 :Pull Twitch chat as news +STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications +STR_5175 :Input the name of your Twitch channel +STR_5176 :Enable Twitch integration +STR_5177 :Fullscreen mode: +STR_5178 :{SMALLFONT}{BLACK}Show financial cheats +STR_5179 :{SMALLFONT}{BLACK}Show guest cheats +STR_5180 :{SMALLFONT}{BLACK}Show park cheats +STR_5181 :{SMALLFONT}{BLACK}Show ride cheats +STR_5182 :{INT32} +STR_5183 :Base height +STR_5184 :Enter base height between {COMMA16} and {COMMA16} +STR_5185 :Water level +STR_5186 :Enter water level between {COMMA16} and {COMMA16} +STR_5187 :Finances +STR_5188 :New Campaign +STR_5189 :Research +STR_5190 :Map +STR_5191 :Viewport +STR_5192 :Recent News +STR_5193 :Land +STR_5194 :Water +STR_5195 :Clear Scenery +STR_5196 :Land Rights +STR_5197 :Scenery +STR_5198 :Footpath +STR_5199 :Ride Construction +STR_5200 :Track Design Place +STR_5201 :New Ride +STR_5202 :Track Design Selection +STR_5203 :Ride +STR_5204 :Ride List +STR_5205 :Guest +STR_5206 :Guest List +STR_5207 :Staff +STR_5208 :Staff List +STR_5209 :Banner +STR_5210 :Object Selection +STR_5211 :Invention List +STR_5212 :Scenario Options +STR_5213 :Objective Options +STR_5214 :Map Generation +STR_5215 :Track Design Manager +STR_5216 :Track Design Manager List +STR_5217 :Cheats +STR_5218 :Themes +STR_5219 :Options +STR_5220 :Keyboard Shortcuts +STR_5221 :Change Keyboard Shortcut +STR_5222 :Load/Save +STR_5223 :Save Prompt +STR_5224 :Demolish Ride Prompt +STR_5225 :Fire Staff Prompt +STR_5226 :Track Delete Prompt +STR_5227 :Save Overwrite Prompt +STR_5228 :{SMALLFONT}{BLACK}Main UI +STR_5229 :{SMALLFONT}{BLACK}Park +STR_5230 :{SMALLFONT}{BLACK}Tools +STR_5231 :{SMALLFONT}{BLACK}Rides and Peeps +STR_5232 :{SMALLFONT}{BLACK}Editors +STR_5233 :{SMALLFONT}{BLACK}Miscellaneous +STR_5234 :{SMALLFONT}{BLACK}Prompts +STR_5235 :{SMALLFONT}{BLACK}Settings +STR_5236 :Window: +STR_5237 :Palette: +STR_5238 :Current Theme: +STR_5239 :Duplicate +STR_5240 :Enter a name for the theme +STR_5241 :Can't change this theme +STR_5242 :Theme name already exists +STR_5243 :Invalid characters used +STR_5244 :Themes +STR_5245 :Top Toolbar +STR_5246 :Bottom Toolbar +STR_5247 :Track Editor Bottom Toolbar +STR_5248 :Scenario Editor Bottom Toolbar +STR_5249 :Title Menu Buttons +STR_5250 :Title Exit Button +STR_5251 :Title Options Button +STR_5252 :Title Scenario Selection +STR_5253 :Park Information +STR_5254 :Create +STR_5255 :{SMALLFONT}{BLACK}Create a new title sequence from scratch +STR_5256 :Create a new theme to make changes to +STR_5257 :{SMALLFONT}{BLACK}Create a new theme based on the current one +STR_5258 :{SMALLFONT}{BLACK}Delete the current theme +STR_5259 :{SMALLFONT}{BLACK}Rename the current theme +STR_5260 :Giant Screenshot +STR_5261 :Filter +STR_5262 :Wacky Worlds +STR_5263 :Time Twister +STR_5264 :Custom +STR_5265 :{SMALLFONT}{BLACK}Select which content sources are visible +STR_5266 :{SMALLFONT}{BLACK}Display +STR_5267 :{SMALLFONT}{BLACK}Culture and Units +STR_5268 :{SMALLFONT}{BLACK}Audio +STR_5269 :{SMALLFONT}{BLACK}Controls and interface +STR_5270 :{SMALLFONT}{BLACK}Miscellaneous +STR_5271 :{SMALLFONT}{BLACK}Twitch +STR_5272 :{SMALLFONT}{BLACK}Small Scenery +STR_5273 :{SMALLFONT}{BLACK}Large Scenery +STR_5274 :{SMALLFONT}{BLACK}Footpath +STR_5275 :Search for Objects +STR_5276 :Enter the name of an object to search for +STR_5277 :Clear +STR_5278 :Sandbox mode +STR_5279 :Sandbox mode off +STR_5280 :{SMALLFONT}{BLACK}Allow editing land ownership settings through the Map window and other options that are normally restricted to the Scenario Editor +STR_5281 :{SMALLFONT}{BLACK}Features +STR_5282 :RCT1 Ride Open/Close Lights +STR_5283 :RCT1 Park Open/Close Lights +STR_5284 :RCT1 Scenario Selection Font +STR_5285 :EXPLODE!!! +STR_5286 :{SMALLFONT}{BLACK}Makes some guests explode +STR_5287 :Ride is already broken down +STR_5288 :Ride is closed +STR_5289 :No breakdowns available for this ride +STR_5290 :Fix ride +STR_5291 :Can't force breakdown +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}遊園地を閉める +STR_5297 :{SMALLFONT}{BLACK}遊園地を開ける +STR_5298 :{RED}{STRINGID} +STR_5299 :{LIGHTPINK}{STRINGID} +STR_5300 :{SMALLFONT}{BLACK}Quick fire staff +STR_5301 :{MEDIUMFONT}{BLACK}Clear your loan +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_5308 :RollerCoaster Tycoon 2 +STR_5309 :OpenRCT2 +STR_5310 :ランダム +STR_5311 :{SMALLFONT}{BLACK}デバグツール +STR_5312 :Show console +STR_5313 :Show tile inspector +STR_5314 :Tile inspector +STR_5315 :草 +STR_5316 :砂 +STR_5317 :土 +STR_5318 :石 +STR_5319 :火星 +STR_5320 :市松 +STR_5321 :Grass clumps +STR_5322 :氷 +STR_5323 :Grid (red) +STR_5324 :Grid (yellow) +STR_5325 :Grid (blue) +STR_5326 :Grid (green) +STR_5327 :Sand (dark) +STR_5328 :Sand (light) +STR_5329 :Checkerboard (inverted) +STR_5330 :Underground view +STR_5331 :Rock +STR_5332 :Wood (red) +STR_5333 :Wood (black) +STR_5334 :氷 +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_5341 :Flags +STR_5342 :Choose a map tile +STR_5343 :Automatically place staff +STR_5344 :Changelog +STR_5345 :Financial cheats +STR_5346 :Guest cheats +STR_5347 :Park cheats +STR_5348 :Ride cheats +STR_5349 :{SMALLFONT}{BLACK}All Rides +STR_5350 :Max +STR_5351 :Min +STR_5352 :{BLACK}Happiness: +STR_5353 :{BLACK}Energy: +STR_5354 :{BLACK}Hunger: +STR_5355 :{BLACK}Thirst: +STR_5356 :{BLACK}Nausea: +STR_5357 :{BLACK}Nausea tolerance: +STR_5358 :{BLACK}Bathroom: +STR_5359 :Remove guests +STR_5360 :{SMALLFONT}{BLACK}Removes all guests from the map +STR_5361 :Give all guests: +STR_5362 :{BLACK}Set all guests' preferred ride intensity to: +STR_5363 :More than 1 +STR_5364 :Less than 15 +STR_5365 :{BLACK}Staff speed: +STR_5366 :普通 +STR_5367 :速い +STR_5368 :Reset crash status +STR_5369 :Park parameters... +STR_5370 :{SMALLFONT}{BLACK}Click this button to modify park{NEWLINE}parameters like restrictions,{NEWLINE}guest generation and money. +STR_5371 :Object Selection +STR_5372 :Invert right mouse dragging +STR_5373 :Name {STRINGID} +STR_5374 :Date {STRINGID} +STR_5375 :{UP} +STR_5376 :{DOWN} +STR_5377 :{SMALLFONT}{BLACK}Saves +STR_5378 :{SMALLFONT}{BLACK}Script +STR_5379 :{SMALLFONT}{BLACK}Skip to next wait command +STR_5380 :{SMALLFONT}{BLACK}Start playing title sequence +STR_5381 :{SMALLFONT}{BLACK}Stop playing title sequence +STR_5382 :{SMALLFONT}{BLACK}Restart title sequence +STR_5383 :{SMALLFONT}{BLACK}Create a new title sequence based on the current one +STR_5384 :{SMALLFONT}{BLACK}Delete the current title sequence +STR_5385 :{SMALLFONT}{BLACK}Rename the current title sequence +STR_5386 :{SMALLFONT}{BLACK}Insert a new command +STR_5387 :{SMALLFONT}{BLACK}Edit the selected command +STR_5388 :{SMALLFONT}{BLACK}Delete the selected command +STR_5389 :{SMALLFONT}{BLACK}Skip to the selected command in the title sequence +STR_5390 :{SMALLFONT}{BLACK}Move the selected command down +STR_5391 :{SMALLFONT}{BLACK}Move the selected command up +STR_5392 :{SMALLFONT}{BLACK}Add a save to the title sequence +STR_5393 :{SMALLFONT}{BLACK}Remove the selected save from the title sequence +STR_5394 :{SMALLFONT}{BLACK}Rename the selected save +STR_5395 :{SMALLFONT}{BLACK}Load the selected save in game +STR_5396 :{SMALLFONT}{BLACK}Reload the title sequence if changes have been made to it outside of the game +STR_5397 :Can only be used on the title screen +STR_5398 :Cannot edit title sequence while it's playing +STR_5399 :Press the stop button to continue editing +STR_5400 :Can't change this title sequence +STR_5401 :Create a new title sequence to make changes to +STR_5402 :Failed to load title sequence +STR_5403 :There may be no Load or Wait command or a save may be invalid +STR_5404 :Name already exists +STR_5405 :Enter a name for the save +STR_5406 :Enter a name for the title sequence +STR_5407 :追加 +STR_5408 :削除 +STR_5409 :挿入 +STR_5410 :編集 +STR_5411 :リロード +STR_5412 :Skip to +STR_5413 :ロード +STR_5414 :Load{MOVE_X}{87}Six Flags Magic Mountain.SC6 +STR_5415 :Load{MOVE_X}{87}{STRING} +STR_5416 :Load{MOVE_X}{87}No save selected +STR_5417 :Location +STR_5418 :Location{MOVE_X}{87}{COMMA16} {COMMA16} +STR_5419 :Rotate +STR_5420 :Rotate{MOVE_X}{87}{COMMA16} +STR_5421 :Zoom +STR_5422 :Zoom{MOVE_X}{87}{COMMA16} +STR_5423 :Wait +STR_5424 :Wait{MOVE_X}{87}{COMMA16} +STR_5425 :Restart +STR_5426 :End +STR_5427 :Coordinates: +STR_5428 :Anticlockwise rotations: +STR_5429 :Zoom level: +STR_5430 :Seconds to wait: +STR_5431 :Save to load: +STR_5432 :Command: +STR_5433 :Title Sequences +STR_5434 :Command Editor +STR_5435 :Rename save +STR_5436 :Edit Title Sequences... +STR_5437 :No save selected +STR_5438 :Can't make changes while command editor is open +STR_5439 :A wait command with at least 4 seconds is required with a restart command +STR_5440 :Minimise fullscreen on focus loss +STR_5441 :{SMALLFONT}{BLACK}Identifies rides by track type,{NEWLINE}so vehicles can be changed{NEWLINE}afterwards, like in RCT1. +STR_5442 :Force park rating: +STR_5443 :Speed{MOVE_X}{87}{STRINGID} +STR_5444 :Speed: +STR_5445 :Speed +STR_5446 :Get +STR_5447 :Type {STRINGID} +STR_5448 :Ride / Vehicle {STRINGID} +STR_5449 :Reduce game speed +STR_5450 :Increase game speed +STR_5451 :Open cheats window +STR_5452 :Toggle visibility of toolbars +STR_5453 :Select another ride +STR_5454 :Uncap FPS +STR_5455 :Enable sandbox mode +STR_5456 :Disable clearance checks +STR_5457 :Disable support limits +STR_5458 :Rotate clockwise +STR_5459 :Rotate anti-clockwise +STR_5460 :Rotate view anti-clockwise +STR_5461 :Set guests' parameters +STR_5462 :{CURRENCY} +STR_5463 :Goal: Have fun! +STR_5464 :General +STR_5465 :Climate +STR_5466 :Staff +STR_5467 :ALT + +STR_5468 :Recent messages +STR_5469 :Scroll map up +STR_5470 :Scroll map left +STR_5471 :Scroll map down +STR_5472 :Scroll map right +STR_5473 :Cycle day / night +STR_5474 :Display text on banners in upper case +STR_5475 :{COMMA16} weeks +STR_5476 :Hardware +STR_5477 :Map rendering +STR_5478 :Controls +STR_5479 :Toolbar +STR_5480 :Show toolbar buttons for: +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) +STR_5485 :{SMALLFONT}{STRING} +STR_5486 :{BLACK}{COMMA16} +STR_5487 :{SMALLFONT}{BLACK}Show recent messages +STR_5488 :No entrance (OpenRCT2 only!) +STR_5489 :{SMALLFONT}{BLACK}Show only tracked guests +STR_5490 :Disable audio on focus loss +STR_5491 :Inventions list +STR_5492 :Scenario options +STR_5493 :Send Message +STR_5494 : +STR_5495 :Player List +STR_5496 :Player: +STR_5497 :Ping: +STR_5498 :Server List +STR_5499 :Player Name: +STR_5500 :Add Server +STR_5501 :Start Server +STR_5502 :Multiplayer +STR_5503 :ホスト名またはIPアドレスを入力してください: +STR_5504 :{SMALLFONT}{BLACK}Show multiplayer status +STR_5505 :サーバーに接続できない +STR_5506 :Guests ignore intensities +STR_5507 :Handymen mow grass by default +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 :名前を保存 +STR_5513 :(Quick) save game +STR_5514 :Disable vandalism +STR_5515 :{SMALLFONT}{BLACK}Stops guests from vandalising your park when they're angry +STR_5516 :{SMALLFONT}{BLACK}黒 +STR_5517 :{SMALLFONT}{BLACK}灰色 +STR_5518 :{SMALLFONT}{BLACK}白 +STR_5519 :{SMALLFONT}{BLACK}Dark purple +STR_5520 :{SMALLFONT}{BLACK}Light purple +STR_5521 :{SMALLFONT}{BLACK}Bright purple +STR_5522 :{SMALLFONT}{BLACK}紺色 +STR_5523 :{SMALLFONT}{BLACK}水色 +STR_5524 :{SMALLFONT}{BLACK}Icy blue +STR_5525 :{SMALLFONT}{BLACK}Dark water +STR_5526 :{SMALLFONT}{BLACK}Light water +STR_5527 :{SMALLFONT}{BLACK}Saturated green +STR_5528 :{SMALLFONT}{BLACK}Dark green +STR_5529 :{SMALLFONT}{BLACK}Moss green +STR_5530 :{SMALLFONT}{BLACK}Bright green +STR_5531 :{SMALLFONT}{BLACK}Olive green +STR_5532 :{SMALLFONT}{BLACK}Dark olive green +STR_5533 :{SMALLFONT}{BLACK}Bright yellow +STR_5534 :{SMALLFONT}{BLACK}黄色 +STR_5535 :{SMALLFONT}{BLACK}Dark yellow +STR_5536 :{SMALLFONT}{BLACK}Light orange +STR_5537 :{SMALLFONT}{BLACK}Dark orange +STR_5538 :{SMALLFONT}{BLACK}Light brown +STR_5539 :{SMALLFONT}{BLACK}Saturated brown +STR_5540 :{SMALLFONT}{BLACK}Dark brown +STR_5541 :{SMALLFONT}{BLACK}Salmon pink +STR_5542 :{SMALLFONT}{BLACK}Bordeaux red +STR_5543 :{SMALLFONT}{BLACK}Saturated red +STR_5544 :{SMALLFONT}{BLACK}Bright red +STR_5545 :{SMALLFONT}{BLACK}Dark pink +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 :年日月 +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 +STR_5556 :Kick Player +STR_5557 :Stay connected after desynchronisation (Multiplayer) +STR_5558 :A restart is required for this setting to take effect +STR_5559 :10 min. inspections +STR_5560 :{SMALLFONT}{BLACK}Sets the inspection time to 'Every 10 minutes' on all rides +STR_5561 :Failed to load language +STR_5562 :注意! +STR_5563 :This feature is currently unstable, take extra caution. +STR_5564 :Insert Corrupt Element +STR_5565 :{SMALLFONT}{BLACK}Inserts a corrupt map element at top of tile. This will hide any element above the corrupt element. +STR_5566 :パスワード: +STR_5567 :Advertise +STR_5568 :パスワードが必要 +STR_5569 :このサーバーはパスワードが必要 +STR_5570 :Fetch Servers +STR_5571 :Join Game +STR_5572 :Add To Favourites +STR_5573 :Remove From Favourites +STR_5574 :Server Name: +STR_5575 :Max Players: +STR_5576 :Port: +STR_5577 :South Korean Won (W) +STR_5578 :Russian Rouble (R) +STR_5579 :Window scale factor: +STR_5580 :Czech koruna (Kc) + +##################### +# Rides/attractions # +##################### + +#WW +[CONDORRD] +STR_NAME :Condor Ride +STR_DESC :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air in Condor-shaped trains +STR_CPTY :4 passengers per car diff --git a/data/language/korean.txt b/data/language/korean.txt index 33e23a30ee..ed1e276eff 100644 --- a/data/language/korean.txt +++ b/data/language/korean.txt @@ -8,7 +8,7 @@ STR_0003 :스탠드업 롤러코스터 STR_0004 :서스펜디드 스윙잉 코스터 STR_0005 :인버티드 롤러코스터 STR_0006 :주니어 롤러코스터 -STR_0007 :미니어처 레일웨이 +STR_0007 :모형 기차 STR_0008 :모노레일 STR_0009 :미니 서스펜디드 롤러코스터 STR_0010 :보트 라이드 @@ -19,10 +19,10 @@ STR_0014 :런치드 프리폴 STR_0015 :봅슬레이 코스터 STR_0016 :전망탑 STR_0017 :루핑 롤러코스터 -STR_0018 :디니 슬라이드 +STR_0018 :미니 슬라이드 STR_0019 :마인 트레인 코스터 -STR_0020 :체어리프트 -STR_0021 :코르크스크류 롤러코스터 +STR_0020 :체어 리프트 +STR_0021 :나선 롤러코스터 STR_0022 :미로 STR_0023 :나선 미끄럼틀 STR_0024 :고 카트 @@ -45,9 +45,9 @@ STR_0040 :모션 시뮬레이터 STR_0041 :3D 영화관 STR_0042 :톱 스핀 STR_0043 :스페이스 링 -STR_0044 :리버스 프리폴 코스터 +STR_0044 :역방향 자유낙하 코스터 STR_0045 :리프트 -STR_0046 :버티컬 드롭 롤러코스터 +STR_0046 :수직 낙하 롤러코스터 STR_0047 :현금 지급기 STR_0048 :트위스트 STR_0049 :귀신의 집 @@ -73,14 +73,14 @@ STR_0068 :하트라인 트위스터 코스터 STR_0069 :미니 골프 STR_0070 :기가 코스터 STR_0071 :자이로드롭 -STR_0072 :플라잉 사우서 +STR_0072 :비행 접시 STR_0073 :이상한 집 STR_0074 :모노레일 사이클 STR_0075 :컴팩트 인버티드 코스터 STR_0076 :워터 코스터 STR_0077 :에어 파워드 버티컬 코스터 STR_0078 :인버티드 헤어핀 코스터 -STR_0079 :마술 양탄자 +STR_0079 :마법의 양탄자 STR_0080 :서브마린 라이드 STR_0081 :리버 래프트 STR_0082 :알 수 없는 놀이기구 (50) @@ -89,11 +89,11 @@ STR_0084 :알 수 없는 놀이기구 (52) STR_0085 :알 수 없는 놀이기구 (53) STR_0086 :알 수 없는 놀이기구 (54) STR_0087 :알 수 없는 놀이기구 (55) -STR_0088 :인버티트 임펄스 코스터 +STR_0088 :인버티드 임펄스 코스터 STR_0089 :미니 롤러코스터 STR_0090 :마인 라이드 STR_0091 :알 수 없는 놀이기구 (59) -STR_0092 :LIM 런치드 롤러코스터 +STR_0092 :LIM 발진 롤러코스터 STR_0093 : STR_0094 : STR_0095 : @@ -514,30 +514,30 @@ STR_0509 : STR_0510 : STR_0511 : STR_0512 :나선형 리프트 힐과 부드럽게 꼬인 낙하를 가진 알찬 구성의 롤러코스터입니다. -STR_0513 :손님들이 일어선 자세로 탑승하는 루핑 롤러코스터입니다 -STR_0514 :코너를 돌 때 롤러코스터 트랙 아래에 달린 차량이 흔들리는 열차입니다 -STR_0515 :복잡하고 꼬인 트랙 요소를 가진 트랙 아래를 달리는 스틸 롤러코스터 차량입니다 -STR_0516 :큰 놀이기구를 탈 용기가 없는 사람들을 위한 얌전한 롤러코스터입니다 -STR_0517 :손님들은 협궤 선로를 따라 달리는 미니어처 열차에 탑승합니다 -STR_0518 :손님들은 모노렝리 트랙을 따라 달리는 전기 차량에 탑승합니다 -STR_0519 :손님들은 코너를 돌 때마다 좌우로 흔들리는, 단선 트랙 아래에 달린 작은 차량에 탑승합니다 -STR_0520 :손님들이 물 위를 다니는 배를 운전하거나 또는 저을 수 있는 선착장입니다 -STR_0521 :급커브와 급하강을 가진 빠르게 꼬인 롤러코스터입니다. 격렬도가 높게 나올 것입니다 -STR_0522 :탑승객이 차량 없이 트랙 위에 앉는 작은 롤러코스터입니다 -STR_0523 :정해진 트랙을 따라 천천히 움직이는 차량입니다 -STR_0524 :자유낙하 차량은 공기 압축 방식으로 높은 철제 탑을 향해 차량을 쏘아올려 자유낙하하는 차량입니다 -STR_0525 :탑승객은 오직 반원형으로 휘어있고 꼬여있는 트랙을 따라 이동합니다 -STR_0526 :탑승객은 높은 곳으로 올라가면서 회전하는 관망대 캐빈에 탑승합니다 -STR_0527 :버티컬 루프를 사용할 수 있는 부드러운 철제 트랙의 롤러코스터입니다 -STR_0528 :탑승객은 공기를 넣은 고무 보트를 타고 반원이나 원형의 튜브 트랙을 따라 이동합니다 +STR_0513 :손님들이 일어선 자세로 탑승하는 루핑 롤러코스터입니다. +STR_0514 :코너를 돌 때 롤러코스터 트랙 아래에 달린 차량이 흔들리는 열차입니다. +STR_0515 :복잡하고 꼬인 트랙 요소를 가진 트랙 아래를 달리는 스틸 롤러코스터 차량입니다. +STR_0516 :큰 놀이기구를 탈 용기가 없는 사람들을 위한 얌전한 롤러코스터입니다. +STR_0517 :손님들이 협궤 선로를 따라 달리는 모형 열차에 탑승하는 놀이기구입니다. +STR_0518 :손님들이 모노레일 트랙을 따라 달리는 전기 차량에 탑승하는 놀이기구입니다. +STR_0519 :손님들이 단선 트랙 아래에 달려서 코너를 돌 때마다 좌우로 흔들리는 작은 차량에 탑승하는 놀이기구입니다. +STR_0520 :손님들이 물 위를 다니는 배를 운전하거나 또는 저을 수 있는 선착장입니다. +STR_0521 :급커브와 급하강을 가진 빠르게 꼬인 롤러코스터입니다. 격렬도가 높게 나올 것입니다. +STR_0522 :탑승객이 차량 없이 트랙 위에 앉는 작은 롤러코스터입니다. +STR_0523 :정해진 트랙을 따라 천천히 움직이는 놀이기구입니다. +STR_0524 :자유낙하 차량은 공기 압축 방식으로 높은 철제 탑을 향해 차량을 쏘아올려 자유낙하하는 차량입니다. +STR_0525 :손님들이 반원형으로 휘어있고 꼬여있는 트랙을 따라 이동합니다. +STR_0526 :손님들이 높은 곳으로 회전하면서 올라가는 관망대 캐빈에 탑승하는 놀이기구입니다. +STR_0527 :수직 루프를 사용할 수 있는 부드러운 철제 트랙의 롤러코스터입니다. +STR_0528 :손님들이 공기를 넣은 고무 보트를 타고 반원이나 원형의 튜브 트랙을 따라 이동하는 놀이기구입니다. STR_0529 :오래된 기차 선로처럼 보이게 만든 철제 트랙을 따라 움직이는 탄광 열차 테마를 한 롤러코스터 차량입니다. -STR_0530 :철제 케이블에 달린 차량이 연속적으로 놀이기구의 한쪽 끝에서 다른쪽 끝을 왕복 운행합니다 -STR_0531 :차량이 코크스크류와 루프를 통과하는 알찬 구성의 철제 트랙 롤러코스터입니다 +STR_0530 :철제 케이블에 달린 차량이 연속적으로 놀이기구의 한쪽 끝에서 다른쪽 끝을 왕복 운행합니다. +STR_0531 :차량이 코크스크류와 루프를 통과하는 알찬 구성의 철제 트랙 롤러코스터입니다. STR_0532 : STR_0533 : -STR_0534 :패트롤 엔진으로 움직이는 고 카트입니다 -STR_0535 :통나무 모양의 보트가 수로를 따라 이동하며, 떨어지면서 탑승객을 물에 젖게 만듭니다 -STR_0536 :원형의 보트가 수로를 따라 요동치며, 폭포를 통과하며 물을 튀기고 탑승객들에게 거품 소용돌이를 통과하며 스릴을 선사합니다 +STR_0534 :패트롤 엔진으로 움직이는 고 카트입니다. +STR_0535 :통나무 모양의 보트가 수로를 따라 이동하고 낙하하면서 탑승객을 쫄딱 젖게 만듭니다. +STR_0536 :원형의 보트가 수로를 따라 요동치며, 폭포를 통과하며 물을 튀기고 탑승객들에게 거품 소용돌이를 통과하며 스릴을 선사합니다. STR_0537 : STR_0538 : STR_0539 : @@ -555,7 +555,7 @@ STR_0550 : STR_0551 : STR_0552 : STR_0553 : -STR_0554 :차량이 선형 유도 모터에 의해 긴 평지 트랙을 따라 가속된 뒤, 수직 상승 트랙에 의해 위로 상승한 뒤 다시 뒤로 자유낙하여 탑승장에 돌아옵니다 +STR_0554 :차량이 선형 유도 모터에 의해 긴 평지 트랙을 따라 가속된 뒤, 수직 상승 트랙에 의해 위로 상승한 뒤 다시 뒤로 자유낙하하여 탑승장에 돌아옵니다 STR_0555 :손님은 엘리베이터에 탑승하여 한쪽에서 다른쪽으로 이동할 수 있습니다 STR_0556 :폭이 넓은 차량이 수직으로 기울어진 트랙을 따라 내려오면서 극강의 자유 낙하 롤러코스터를 경험하게 해줍니다 STR_0557 : @@ -579,7 +579,7 @@ STR_0574 :탑승객은 특수한 마차에 누운 자세로 매달려, 이리 STR_0575 :공원 여기 저기로 사람들을 실어나르는, 단선 레일에 매달린 전동 열차입니다 STR_0576 : STR_0577 :특수한 반전 섹션에서 앞뒤가 바뀌는 목재 트랙을 달리는 보우기 차입니다 -STR_0578 :원형 고리로 둘러싸여 급강하와 하트라인 트위트스를 횡단하는 트랙을 달리는 차량입니다. +STR_0578 :원형 고리로 둘러싸여 급강하와 하트라인 트위스트를 횡단하는 트랙을 달리는 차량입니다. STR_0579 : STR_0580 :90m 이상의 언덕을 부드럽게 오르내리는 거대한 철제 롤러코스터입니다 STR_0581 :원형 모양의 좌석이 맨 위까지 끌어올려진 다음, 자유 낙하하며, 자기장에 의해 부드럽게 바닥에 정지합니다 @@ -588,7 +588,7 @@ STR_0583 : STR_0584 :탑승객이 스스로 페달을 밟아 이동해야 하는, 특별한 철제 모노레일 트랙 위를 이동하는 자전거입니다 STR_0585 :탑승객은 트랙 밑에 매달린 좌석 한 쌍에 앉아 루프와 트위스트를 급격히 통과합니다 STR_0586 :보트 모양의 차량이 꼬인 커브와 급강하가 가능한 롤러코스터 트랙을 달리며, 강 섹션의 물에서는 물보라를 일으키며 감속합니다 -STR_0587 :아주 짜릿한 공기 압축 방식으로 발진하여 차량이 수직 트랙을 향해 속력을 높인 뒤, 꼭대기에 다다르면 다시 수직으로 하강하며 다른 탑승장에 도착합니다 +STR_0587 :아주 짜릿한 공기 압축 방식으로 발진하여 차량이 수직 트랙을 향해 속력을 높인 뒤, 꼭대기에 다다르면 다시 수직으로 하강하며 다시 탑승장에 도착합니다 STR_0588 :개별적인 차량이 헤이펀 커브와 급강하를 포함한 지그재그 모양의 트랙 아래를 이동합니다 STR_0589 : STR_0590 :탑승객들은 잠수가 가능한 잠수함을 타고 수중 코스를 돕니다 @@ -830,10 +830,10 @@ STR_0825 :이미 사용 중인 이름입니다 STR_0826 :이름이 너무 많이 지정되었습니다 STR_0827 :돈이 부족합니다 - {CURRENCY2DP} 만큼의 돈이 더 필요합니다 STR_0828 :{SMALLFONT}{BLACK}창 닫기 -STR_0829 :{SMALLFONT}{BLACK}창 제목 - 창을 움직이려면 여기를 드래그하세요 +STR_0829 :{SMALLFONT}{BLACK}창 제목 - 창을 움직이려면 드래그하세요 STR_0830 :{SMALLFONT}{BLACK}화면 확대하기 STR_0831 :{SMALLFONT}{BLACK}화면 축소하기 -STR_0832 :{SMALLFONT}{BLACK}화면을 시계 방향으로 90{DEGREE}도 회전하기 +STR_0832 :{SMALLFONT}{BLACK}게임 화면을 시계방향으로 90{DEGREE} 회전하기 STR_0833 :{SMALLFONT}{BLACK}게임 일시정지 STR_0834 :{SMALLFONT}{BLACK}디스크 및 게임 옵션 STR_0835 :게임 초기화 실패 @@ -933,14 +933,14 @@ STR_0927 :여기에 건설할 수 없습니다... STR_0928 :{SMALLFONT}{BLACK}경사를 오르기 위한 체인 리프트 STR_0929 :S자 트랙 (왼쪽) STR_0930 :S자 트랙 (오른쪽) -STR_0931 :버티컬 루프 (왼쪽) -STR_0932 :버티컬 루프 (오른쪽) +STR_0931 :수직 루프 (왼쪽) +STR_0932 :수직 루프 (오른쪽) STR_0933 :땅을 먼저 올리거나 내리세요 STR_0934 :놀이기구 입구가 있습니다 STR_0935 :놀이기구 출구가 있습니다 STR_0936 :공원 입구가 있습니다 STR_0937 :{SMALLFONT}{BLACK}보기 설정 -STR_0938 :{SMALLFONT}{BLACK}지형 높이와 경사를 보여줌 +STR_0938 :{SMALLFONT}{BLACK}지형의 높이나 경사를 조정합니다. STR_0939 :지하/내부 시야 STR_0940 :땅 안 보이기 STR_0941 :절벽 안 보이기 @@ -1004,14 +1004,14 @@ STR_0998 :탑승장이 너무 많습니다 STR_0999 :탑승장이 필요합니다 STR_1000 :트랙이 완성되지 않았습니다 STR_1001 :트랙이 열차 종류와 맞지 않습니다 -STR_1002 :{POP16}{POP16}{POP16}{STRINGID}(을)를 운행할 수 없습니다... -STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID}(을)를 테스트할 수 없습니다... -STR_1004 :{POP16}{POP16}{POP16}{STRINGID}(을)를 닫을 수 없습니다... +STR_1002 :{POP16}{POP16}{POP16}{STRINGID} - 운행할 수 없습니다... +STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID} - 테스트할 수 없습니다... +STR_1004 :{POP16}{POP16}{POP16}{STRINGID} - 닫을 수 없습니다... STR_1005 :{POP16}{POP16}{POP16}{STRINGID}의 건설을 시작할 수 없습니다... STR_1006 :먼저 닫아야 합니다 STR_1007 :차량을 충분히 만들 수 없습니다 -STR_1008 :{SMALLFONT}{BLACK}놀이기구나 시설을 열거나, 닫거나 테스트합니다 -STR_1009 :{SMALLFONT}{BLACK}모든 놀이기구나 시설을 열거나 닫습니다 +STR_1008 :{SMALLFONT}{BLACK}놀이기구/시설을 개장/폐장/테스트합니다 +STR_1009 :{SMALLFONT}{BLACK}모든 놀이기구/시설을 개장/폐장합니다 STR_1010 :{SMALLFONT}{BLACK}공원을 열거나 닫습니다 STR_1011 :모두 닫기 STR_1012 :모두 열기 @@ -1029,7 +1029,7 @@ STR_1023 :1대당 {POP16}{POP16}{POP16}{COMMA16}량의 차량 STR_1024 :1대당 {COMMA16}량의 차량 STR_1025 :1대당 {COMMA16}량의 차량 STR_1026 :탑승장이 너무 깁니다! -STR_1027 :{SMALLFONT}{BLACK}여기로 이동 +STR_1027 :{SMALLFONT}{BLACK}여기로 이동합니다 STR_1028 :지도 끝을 벗어납니다! STR_1029 :일부분만 수면 위로 나오도록 건설할 수 없습니다! STR_1030 :수중에만 건설할 수 있습니다! @@ -1212,13 +1212,13 @@ STR_1206 :{WINDOW_COLOUR_2}출발: STR_1207 :{WINDOW_COLOUR_2}다른 열차가 탑승장에 도착하면 열차를 출발시킴 STR_1208 :{WINDOW_COLOUR_2}다른 보트가 탑승장에 도착하면 보트를 출발시킴 STR_1209 :{SMALLFONT}{BLACK}출발하기 전에 승객을 기다릴지 여부를 선택하세요 -STR_1210 :{SMALLFONT}{BLACK}다른 차량이 같은 탑승장에 도착하면 열차를 출발시킬지 여부를 선택하세요 +STR_1210 :{SMALLFONT}{BLACK}체크하면 다른 차량이 탑승장에 도착하면 열차를 출발시킵니다 STR_1211 :{WINDOW_COLOUR_2}최소 대기 시간: STR_1212 :{WINDOW_COLOUR_2}최대 대기 시간: -STR_1213 :{SMALLFONT}{BLACK}출발하기 전에 최소한으로 기다릴 시간 길이를 선택하세요 -STR_1214 :{SMALLFONT}{BLACK}출발하기 전에 최대한으로 기다릴 시간 길이를 선택하세요 +STR_1213 :{SMALLFONT}{BLACK}출발하기 전에 반드시 기다릴 시간 +STR_1214 :{SMALLFONT}{BLACK}출발하기 전에 최대한 기다릴 시간 STR_1215 :{WINDOW_COLOUR_2}인접한 탑승장과 같이 출발시킴 -STR_1216 :{SMALLFONT}{BLACK}모든 인접한 탑승장과 차량을 동시에 출발시킬지 여부를 선택하세요 +STR_1216 :{SMALLFONT}{BLACK}체크하면 모든 인접한 탑승장의 차량을 동시에 출발시킵니다 STR_1217 :{COMMA16}초 STR_1218 :{BLACK}{SMALLUP} STR_1219 :{BLACK}{SMALLDOWN} @@ -1357,8 +1357,8 @@ STR_1351 :{WINDOW_COLOUR_2}최대 음수 수직 중력값: {OUTLINE}{RED}{COM STR_1352 :{WINDOW_COLOUR_2}최대 측면 중력값: {BLACK}{COMMA2DP32}g STR_1353 :{WINDOW_COLOUR_2}최대 측면 중력값: {OUTLINE}{RED}{COMMA2DP32}g STR_1354 :{WINDOW_COLOUR_2}최고 낙하 높이: {BLACK}{LENGTH} -STR_1355 :{WINDOW_COLOUR_2}낙하 회수: {BLACK}{COMMA16} -STR_1356 :{WINDOW_COLOUR_2}뒤집어진 회수: {BLACK}{COMMA16} +STR_1355 :{WINDOW_COLOUR_2}낙하 횟수: {BLACK}{COMMA16} +STR_1356 :{WINDOW_COLOUR_2}뒤집어진 횟수: {BLACK}{COMMA16} STR_1357 :{WINDOW_COLOUR_2}홀 개수: {BLACK}{COMMA16} STR_1358 :{WINDOW_COLOUR_2}총 '무중력' 시간: {BLACK}{COMMA2DP32}초 STR_1359 :{WINDOW_COLOUR_2}대기 시간: {BLACK}{COMMA16}분 @@ -1369,9 +1369,9 @@ STR_1363 :지지대가 버틸 수 있는 최대 높이입니다! STR_1364 :위 트랙의 지지대를 더 이상 늘릴 수 없습니다! STR_1365 :인라인 트위스트 (왼쪽) STR_1366 :인라인 트위스트 (오른쪽) -STR_1367 :하프 루프 -STR_1368 :하프 코르크스크류 (왼쪽) -STR_1369 :하프 코르크스크류 (오른쪽) +STR_1367 :1/2 루프 +STR_1368 :1/2 나선 (왼쪽) +STR_1369 :1/2 나선 (오른쪽) STR_1370 :바렐 롤 (왼쪽) STR_1371 :바렐 롤 (오른쪽) STR_1372 :런치드 리프트 힐 @@ -1424,7 +1424,7 @@ STR_1418 :{WINDOW_COLOUR_2}측면 중력 STR_1419 :{SMALLFONT}{BLACK}{VELOCITY} STR_1420 :{SMALLFONT}{BLACK}{LENGTH} STR_1421 :{SMALLFONT}{BLACK}{COMMA16}g -STR_1422 :{SMALLFONT}{BLACK}{POP16}{STRINGID}로부터 데이터 기록 중 +STR_1422 :{SMALLFONT}{BLACK}{POP16}{STRINGID}을 기준으로 데이터 기록 중 STR_1423 :{SMALLFONT}{BLACK}대기줄 STR_1424 :{SMALLFONT}{BLACK}보도 STR_1425 :보도 @@ -1434,10 +1434,10 @@ STR_1428 :{WINDOW_COLOUR_2}입장료: STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} STR_1430 :무료 STR_1431 :걷는 중 -STR_1432 :{STRINGID}(으)로 향하는 중 -STR_1433 :{STRINGID}(에)서 대기 중 +STR_1432 :목적지 : {STRINGID} +STR_1433 :{STRINGID} 대기 중 STR_1434 :물에 빠짐 -STR_1435 :{STRINGID} 위에 +STR_1435 :{STRINGID} 탑승중 STR_1436 :{STRINGID} 안에 STR_1437 :{STRINGID}에 STR_1438 :앉음 @@ -1446,7 +1446,7 @@ STR_1440 :잔디 깎는 중 STR_1441 :보도 청소 중 STR_1442 :쓰레기통 비우는 중 STR_1443 :정원에 물을 주는 중 -STR_1444 :{STRINGID}(을)를 보는 중 +STR_1444 :{STRINGID} 구경 중 STR_1445 :{STRINGID}의 건설 장면을 보는 중 STR_1446 :풍경을 보는 중 STR_1447 :공원을 떠나는 중 @@ -1713,7 +1713,7 @@ STR_1707 :게임에 직원이 너무 많습니다 STR_1708 :{SMALLFONT}{BLACK}이 직원이 순찰할 영역을 지정합니다 STR_1709 :직원 해고 STR_1710 :예 -STR_1711 :{WINDOW_COLOUR_1}{STRINGID}(을)를 정말 해고하시겠습니까? +STR_1711 :{WINDOW_COLOUR_1}{STRINGID} - 정말 해고하시겠습니까? STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}보도 청소 STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}정원에 물 주기 STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}쓰레기통 비우기 @@ -1766,20 +1766,20 @@ STR_1760 :{SMALLFONT}{BLACK}채우기 모드 STR_1761 :{SMALLFONT}{BLACK}이 방향으로 미로 건설 STR_1762 :폭포 STR_1763 :급류 -STR_1764 :Log Bumps +STR_1764 :통나무 장애물 STR_1765 :탑승 사진 섹션 STR_1766 :역방향 턴테이블 STR_1767 :회전 터널 -STR_1768 :스윙 회수를 변경할 수 없습니다... -STR_1769 :{WINDOW_COLOUR_2}스윙 회수: -STR_1770 :{SMALLFONT}{BLACK}가장 높은 스윙의 회수를 지정합니다 +STR_1768 :스윙 횟수를 변경할 수 없습니다... +STR_1769 :{WINDOW_COLOUR_2}스윙 횟수: +STR_1770 :{SMALLFONT}{BLACK}가장 높은 스윙의 횟수를 지정합니다 STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1772 :{COMMA16} STR_1773 :한 놀이기구에는 하나의 탑승 사진 섹션만 만들 수 있습니다 STR_1774 :한 놀이기구에는 하나의 케이블 리프트만 만들 수 있습니다 STR_1775 :끄기 STR_1776 :켜기 -STR_1777 :{WINDOW_COLOUR_2}음악 +STR_1777 :{WINDOW_COLOUR_2}놀이기구 음악 STR_1778 :{STRINGID} - - STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} 팬더 복장 STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} 호랑이 복장 @@ -1797,10 +1797,10 @@ STR_1791 :{WINDOW_COLOUR_2}유니폼 색상: STR_1792 :{STRINGID} 고장 연락을 받음 STR_1793 :점검을 위해 {STRINGID}(으)로 이동 중 STR_1794 :{STRINGID} 수리 중 -STR_1795 :라디오 연락에 응답 중 +STR_1795 :무전기 연락에 응답 중 STR_1796 :고장이 나서 수리가 필요함 STR_1797 :이 놀이기구에서는 변경할 수 없는 설정입니다 -STR_1798 :쇼용돌이 +STR_1798 :소용돌이 STR_1799 :{POP16}{POP16}{POP16}{POP16}{POP16}{CURRENCY2DP} STR_1800 :안전 차단 STR_1801 :안전 벨트가 닫힌 채로 안 열림 @@ -1836,7 +1836,7 @@ STR_1830 :대기 길이 STR_1831 :대기 시간 STR_1832 :신뢰도 STR_1833 :고장률 -STR_1834 :이 놀이기구를 좋아하는 손님 수 +STR_1834 :좋아하는 손님 수 STR_1835 :인기도 : 알 수 없음 STR_1836 :인기도: {COMMA16}% STR_1837 :만족도: 알 수 없움 @@ -1892,7 +1892,7 @@ STR_1886 :{STRINGID} 점검 중 STR_1887 :{WINDOW_COLOUR_2}지난 점검 이후 지난 시간: {BLACK}{COMMA16}분 STR_1888 :{WINDOW_COLOUR_2}지난 점검 이후 지난 시간: {BLACK}4시간 이상 STR_1889 :{WINDOW_COLOUR_2}고장률: {MOVE_X}{255}{BLACK}{COMMA16}% -STR_1890 :{SMALLFONT}{BLACK}정비기술자가 이 놀이기구를 얼마나 자주 점검할 지 선택합니다 +STR_1890 :{SMALLFONT}{BLACK}정비기술자가 놀이기구를 얼마나 자주 점검할 지 선택하세요 STR_1891 :공원에 아직 {STRINGID}(이)가 없습니다! # The following two strings were used to display an error when the disc was missing. # This has been replaced in OpenRCT2. @@ -1934,7 +1934,7 @@ STR_1926 :{SMALLFONT} STR_1927 :{YELLOW}{STRINGID} 고장 발생 STR_1928 :{RED}{STRINGID} 충돌! STR_1929 :{RED}{STRINGID} - 아직 수리되지 않음{NEWLINE}정비기술자의 위치와 업무 효율을 점검하세요 -STR_1930 :{SMALLFONT}{BLACK}이 손님의 행동을 추적합니다. (이 설정을 켜면 이 손님의 모든 행동을 메시지 창으로 알려줍니다) +STR_1930 :{SMALLFONT}{BLACK}이 손님의 행동을 추적합니다.{NEWLINE}(이 설정을 켜면 이 손님의 모든 행동을 메시지 창으로 알려줍니다) STR_1931 :{STRINGID} - {STRINGID}(을)를 타기 위해 대기줄에 섰습니다 STR_1932 :{STRINGID} - {STRINGID}(을)를 탔습니다 STR_1933 :{STRINGID} - {STRINGID} 안에 있습니다 @@ -1944,12 +1944,12 @@ STR_1936 :{STRINGID} - {STRINGID}(을)를 샀습니다 STR_1937 :{SMALLFONT}{BLACK}이 메시지의 주제에 대한 정보를 보여줍니다 STR_1938 :{SMALLFONT}{BLACK}손님 주변으로 화면을 이동합니다 STR_1939 :{SMALLFONT}{BLACK}직원 주변으로 화면을 이동합니다 -STR_1940 :{SMALLFONT}{BLACK}이 손님의 행복도, 에너지, 배고픔 등의 수치를 보여줍니다 -STR_1941 :{SMALLFONT}{BLACK}이 손님이 이용한 놀이기구를 보여줍니다 -STR_1942 :{SMALLFONT}{BLACK}이 손님의 재정 상황을 보여줍니다 -STR_1943 :{SMALLFONT}{BLACK}손님의 최근 생각을 보여줍니다 -STR_1944 :{SMALLFONT}{BLACK}손님이 가지고 있는 물건을 보여줍니다 -STR_1945 :{SMALLFONT}{BLACK}이 직원이 할 일이나 설정을 보여줍니다 +STR_1940 :{SMALLFONT}{BLACK}행복도/에너지/배고픔 등의 수치를 보여줍니다 +STR_1941 :{SMALLFONT}{BLACK}이용한 놀이기구를 보여줍니다 +STR_1942 :{SMALLFONT}{BLACK}재정 상황을 보여줍니다 +STR_1943 :{SMALLFONT}{BLACK}최근 생각을 보여줍니다 +STR_1944 :{SMALLFONT}{BLACK}가지고 있는 물건을 보여줍니다 +STR_1945 :{SMALLFONT}{BLACK}이 직원의 업무나 역할을 설정합니다 STR_1946 :{SMALLFONT}{BLACK}이 엔터테이너의 복장을 선택합니다 STR_1947 :{SMALLFONT}{BLACK}선택한 직원의 행동 영역을 보여주고 가까운 직원을 거기로 이동시킵니다 STR_1948 :{SMALLFONT}{BLACK}선택한 종류의 직원을 새로 고용합니다 @@ -2214,15 +2214,15 @@ STR_2206 :빈 음료수 통 STR_2207 :빈 주스 컵 STR_2208 :구운 소시지 STR_2209 :빈 사발 -STR_2210 :{SMALLFONT}{BLACK}공원의 미화원 목록을 보여줍니다 -STR_2211 :{SMALLFONT}{BLACK}공원의 정비기술자 목록을 보여줍니다 -STR_2212 :{SMALLFONT}{BLACK}공원의 경비원 목록을 보여줍니다 -STR_2213 :{SMALLFONT}{BLACK}공원의 엔터테이너 목록을 보여줍니다 +STR_2210 :{SMALLFONT}{BLACK}미화원 목록을 보여줍니다 +STR_2211 :{SMALLFONT}{BLACK}정비기술자 목록을 보여줍니다 +STR_2212 :{SMALLFONT}{BLACK}경비원 목록을 보여줍니다 +STR_2213 :{SMALLFONT}{BLACK}엔터테이너 목록을 보여줍니다 STR_2214 :게임 일시정지 중에는 건설할 수 없습니다! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F -STR_2218 :{RED}{STRINGID}(놀이기구: {STRINGID})(이)가 {STRINGID}(으)로 아직 돌아오지 않았습니다!{NEWLINE}놀이기구가 멈춰있거나 Check whether it is stuck or has 상점ed +STR_2218 :{RED}{POP16}{POP16}{STRINGID}의 {PUSH16}{PUSH16}{PUSH16}{PUSH16}{PUSH16}{STRINGID}(이)가 {POP16}{POP16}{POP16}{STRINGID}으로 아직 돌아오지 않았습니다!{NEWLINE}놀이기구가 멈춰있거나 오도가도 못하고 있는지 확인하세요. STR_2219 :{RED}{COMMA16}명의 손님이 {STRINGID} 사고로 사망하였습니다! STR_2220 :{WINDOW_COLOUR_2}공원 등급: {BLACK}{COMMA16} STR_2221 :{SMALLFONT}{BLACK}공원 등급: {COMMA16} @@ -2232,7 +2232,7 @@ STR_2224 :{WINDOW_COLOUR_2}재정: {BLACK}{CURRENCY2DP} STR_2225 :{WINDOW_COLOUR_2}재정: {RED}{CURRENCY2DP} STR_2226 :{WINDOW_COLOUR_2}공원 가치: {BLACK}{CURRENCY} STR_2227 :{WINDOW_COLOUR_2}회사 가치: {BLACK}{CURRENCY} -STR_2228 :{WINDOW_COLOUR_2}음식/음료수 또는 물건으로 벌어들인{NEWLINE}지난달 수익: {BLACK}{CURRENCY} +STR_2228 :{WINDOW_COLOUR_2}음식/음료수 또는 물건으로 벌어들인 지난달 수익: {BLACK}{CURRENCY} STR_2229 :수직으로 상승 STR_2230 :수직 트랙 STR_2231 :낙하 브레이크 @@ -2276,7 +2276,7 @@ STR_2268 :최근에 개발한 항목 STR_2269 :{WINDOW_COLOUR_2}유형: {BLACK}{STRINGID} STR_2270 :{WINDOW_COLOUR_2}진행: {BLACK}{STRINGID} STR_2271 :{WINDOW_COLOUR_2}예상: {BLACK}{STRINGID} -STR_2272 :{WINDOW_COLOUR_2}놀이기구/시술:{NEWLINE}{BLACK}{STRINGID} +STR_2272 :{WINDOW_COLOUR_2}놀이기구/시설:{NEWLINE}{BLACK}{STRINGID} STR_2273 :{WINDOW_COLOUR_2}풍경/테마:{NEWLINE}{BLACK}{STRINGID} STR_2274 :{SMALLFONT}{BLACK}이 개발에 대한 상세 내역을 보여줍니다 STR_2275 :{SMALLFONT}{BLACK}연구 & 개발을 위한 투자 설정 창을 보여줍니다 @@ -2300,15 +2300,15 @@ STR_2292 :{WINDOW_COLOUR_2}Rides been on: STR_2293 :{BLACK} 없음 STR_2294 :{SMALLFONT}{BLACK}땅 표면 모양을 변경합니다 STR_2295 :{SMALLFONT}{BLACK}땅의 벽 모양을 변경합니다 -STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 공원 입장료로 썼습니다 -STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 {BLACK}{COMMA16} 놀이기구에 썼습니다 -STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 {BLACK}{COMMA16} 놀이기구에 썼습니다 -STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음식 {BLACK}{COMMA16}종류에 썼습니다 -STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음식 {BLACK}{COMMA16}종류에 썼습니다 -STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음료수 {BLACK}{COMMA16}종류에 썼습니다 -STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 음료수 {BLACK}{COMMA16}종류에 썼습니다 -STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 기념품 {BLACK}{COMMA16}종류에 썼습니다 -STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}(을)를 기념품 {BLACK}{COMMA16}종류에 썼습니다 +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 공원 입장료로 썼습니다 +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 {BLACK}{COMMA16} 놀이기구에 썼습니다 +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 {BLACK}{COMMA16} 놀이기구에 썼습니다 +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음식 {BLACK}{COMMA16}종류에 썼습니다 +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음식 {BLACK}{COMMA16}종류에 썼습니다 +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음료수 {BLACK}{COMMA16}종류에 썼습니다 +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 음료수 {BLACK}{COMMA16}종류에 썼습니다 +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 기념품 {BLACK}{COMMA16}종류에 썼습니다 +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2}을 기념품 {BLACK}{COMMA16}종류에 썼습니다 STR_2305 :트랙 디자인 파일 STR_2306 :트랙 디자인 저장 STR_2307 :{STRINGID} 디자인 선택 @@ -2364,9 +2364,9 @@ STR_2356 :{WINDOW_COLOUR_2}점검한 놀이기구: {BLACK}{COMMA16}개 STR_2357 :집 STR_2358 :유닛 STR_2359 :실제 값 -STR_2360 :{WINDOW_COLOUR_2}해상도: +STR_2360 :해상도: STR_2361 :땅 테두리를 부드럽게 -STR_2362 :{SMALLFONT}{BLACK}땅의 테두리를 부드럽게 보입니다 +STR_2362 :{SMALLFONT}{BLACK}땅의 테두리를 부드럽게 표시합니다. STR_2363 :땅에 격자선 보이기 STR_2364 :{SMALLFONT}{BLACK}땅에 격자선을 보여줍니다 STR_2365 :은행이 대출을 증가시키는 것을 거절했습니다! @@ -2481,7 +2481,7 @@ STR_2473 :{SMALLFONT}{BLACK}새 스릴있는 놀이기구를 개발합니다 STR_2474 :{SMALLFONT}{BLACK}새 물 놀이기구를 개발합니다 STR_2475 :{SMALLFONT}{BLACK}새 상점/매점을 개발합니다 STR_2476 :{SMALLFONT}{BLACK}새 풍경/테마를 개발합니다 -STR_2477 :{SMALLFONT}{BLACK}이 놀이기구/시설의 운영 모드를 선택합니다 +STR_2477 :{SMALLFONT}{BLACK}이 놀이기구/시설의 운영 모드 선택 STR_2478 :{SMALLFONT}{BLACK}시간에 따른 속력 그래프를 보여줍니다 STR_2479 :{SMALLFONT}{BLACK}시간에 따른 고도 그래프를 보여줍니다 STR_2480 :{SMALLFONT}{BLACK}시간에 따른 수직 가속도 그래프를 보여줍니다 @@ -2503,7 +2503,7 @@ STR_2495 :건설 모드 취소 STR_2496 :게임 일시정지 STR_2497 :화면 축소 STR_2498 :화면 확대 -STR_2499 :게임 화면 시계 방향으로 회전 +STR_2499 :게임 화면을 시계방향으로 회전 STR_2500 :건설 대상 회전 STR_2501 :지하 시야 토글 STR_2502 :땅 표면 제거 @@ -2763,8 +2763,8 @@ STR_2753 :잔디 깎기 STR_2754 :물 주기 STR_2755 :파괴된 시설물 수리 STR_2756 :쓰레기통 비우기 -STR_2757 :항상 맑음 -STR_2758 :항상 비 +STR_2757 :(더 이상 사용 안 함) +STR_2758 :(더 이상 사용 안 함) STR_2759 :보도 청소 STR_2760 :+{CURRENCY} STR_2761 :<더 이상 사용하지 않음> @@ -2773,15 +2773,15 @@ STR_2763 :??? STR_2764 :<더 이상 사용하지 않음> STR_2765 :손님 많이 부르기 STR_2766 :시나리오 클리어 -STR_2767 :기후 고정 -STR_2768 :기후 고정 해제 +STR_2767 :날씨 고정 +STR_2768 :날씨 고정 해제 STR_2769 :공원 열기 STR_2770 :공원 닫기 STR_2771 :게임 속도 느리게 STR_2772 :게임 속도 빠르게 STR_2773 :창 모드 -STR_2774 :풀 스크린 -STR_2775 :풀 스크린 (데스크탑) +STR_2774 :전체 화면 +STR_2775 :전체 화면 (창 모드) STR_2776 :언어: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} @@ -2810,8 +2810,8 @@ STR_2799 :{SMALLFONT}{BLACK}지정되어 있는 조작 키를 확인하거나 STR_2800 :{WINDOW_COLOUR_2}총 입장료: {BLACK}{COMMA32} STR_2801 :{WINDOW_COLOUR_2}입장료로 벌어들인 수익: {BLACK}{CURRENCY2DP} STR_2802 :지도 -STR_2803 :{SMALLFONT}{BLACK}이 손님들을 지도에 하이라이트하여 표시합니다 -STR_2804 :{SMALLFONT}{BLACK}이 직원들을 지도에 하이라이트하여 표시합니다 +STR_2803 :{SMALLFONT}{BLACK}이 손님들을 지도에 표시합니다 +STR_2804 :{SMALLFONT}{BLACK}이 직원들을 지도에 표시합니다 STR_2805 :{SMALLFONT}{BLACK}공원의 지도를 표시합니다 STR_2806 :{RED}손님들이 공원의 더러운 보도 청소 상태에 대해 불평하고 있습니다{NEWLINE}미화원을 더 고용하거나 미화원의 업무 효율성을 점검하세요 STR_2807 :{RED}손님들이 공원에 널린 쓰레기에 대해 불평하고 있습니다{NEWLINE}미화원을 더 고용하거나 미화원의 업무 효율성을 점검하세요 @@ -2861,7 +2861,7 @@ STR_2850 :새 트랙 디자인 설치가 성공적으로 완료되었습니 STR_2851 :시나리오가 이미 설치되어 있습니다 STR_2852 :트랙 디자인이 이미 설치되어 있습니다 STR_2853 :지역 당국에 의해 금지된 행위입니다! -STR_2854 :{RED}손님들이 {STRINGID}의 입구로 갈 수 없습니다 !{NEWLINE}입구로 가는 길을 만드세요 +STR_2854 :{RED}{STRINGID}의 입구로 가는 길이 없습니다 !{NEWLINE}입구로 가는 길을 만드세요 STR_2855 :{RED}{STRINGID}의 출구에서 나오는 길이 없습니다 !{NEWLINE}출구로 가는 길을 만드세요 STR_2856 :{WINDOW_COLOUR_2}튜토리얼 STR_2857 :{WINDOW_COLOUR_2}(조작하려면 마우스나 키보드 키를 누르세요) @@ -2898,7 +2898,7 @@ STR_2887 :{WINDOW_COLOUR_2}Brimble's Beat: (Allister Brimble) copyright {CO STR_2888 :{WINDOW_COLOUR_2}Atlantis: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2889 :{WINDOW_COLOUR_2}Wild West Kid: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2890 :{WINDOW_COLOUR_2}Vampire's Lair: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2891 :{WINDOW_COLOUR_2}Blockbuster: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2891 :{WINDOW_COLOUR_2}블록buster: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2892 :{WINDOW_COLOUR_2}Airtime Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2893 :{WINDOW_COLOUR_2}Searchlight Rag: (Scott Joplin/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2894 :{WINDOW_COLOUR_2}Flight of Fantasy: (Steve Blenkinsopp) copyright {COPYRIGHT} Chris Sawyer @@ -3232,7 +3232,7 @@ STR_3221 :{SMALLFONT}{BLACK}공원이 이미 소유하고 있는 땅을 선 STR_3222 :{SMALLFONT}{BLACK}공원이 이미 소유하고 있는 건설권을 선택합니다 STR_3223 :{SMALLFONT}{BLACK}공원이 향후 구입할 수 있는 땅을 선택합니다 STR_3224 :{SMALLFONT}{BLACK}공원이 향후 구입할 수 있는 건설권을 선택합니다 -STR_3225 :{SMALLFONT}{BLACK}선택한 위치에 오브젝트 숲 건설(무작위 건설) 모드를 켜거나 끕니다 +STR_3225 :{SMALLFONT}{BLACK}선택한 위치 주변에 오브젝트를 임의로 무리지어 설치하는 모드를 켜거나 끕니다 STR_3226 :{SMALLFONT}{BLACK}공원 입구 건설 STR_3227 :공원 입구가 너무 많습니다! STR_3228 :{SMALLFONT}{BLACK}손님이 나타나는 장소를 선택합니다 @@ -3331,7 +3331,7 @@ STR_3320 :시나리오 파일을 저장할 수 없습니다... STR_3321 :새 오브젝트가 성공적으로 설치되었습니다 STR_3322 :{WINDOW_COLOUR_2}목표: {BLACK}{STRINGID} STR_3323 :오브젝트 데이터가 존재하지 않음, ID: -STR_3324 :확장팩이 필요합니다: +STR_3324 :확장팩이 필요합니다: {STRINGID} STR_3325 :확장팩이 필요합니다 STR_3326 :{WINDOW_COLOUR_2}(이미지 없음) STR_3327 :손님이 나타나는 위치가 지정되지 않았습니다 @@ -3341,7 +3341,7 @@ STR_3330 :공원이 소유한 땅이 하나도 없습니다 STR_3331 :공원 입구에서 지도 가장자리로 이어지는 길이 이어지지 않았거나 너무 복잡합니다. 1칸 너비의 길을 코너나 교차로가 최대한 없도록 하여 만들어야 합니다. STR_3332 :공원 입구가 잘못된 방향을 향하고 있거나 지도 가장자리로 가는 길이 없습니다 STR_3333 :게임 저장시 사용한 오브젝트를 같이 포함하여 저장 -STR_3334 :{SMALLFONT}{BLACK}필요한 경우 플러그 인 오브젝트(기본적으로 지원하지 않고 사용자가 추가된 오브젝트)를 저장된 게임 파일이나 시나리오 파일과 함께 저장합니다. 이러면 그 추가 오브젝트를 갖고 있지 않은 다른 사람이 이 파일을 불러올 때 자동으로 그 오브젝트를 설치하게 되지만 파일 용량이 늘어납니다 +STR_3334 :{SMALLFONT}{BLACK}필요한 경우 내장된 오브젝트(기본 오브젝트가 아닌 사용자가 추가한 오브젝트)를 게임 저장 파일이나 시나리오 파일 내부에 함께 저장합니다. 이러면 그 추가 오브젝트를 갖고 있지 않은 다른 사람이 이 파일을 불러올 때 자동으로 그 오브젝트를 설치하게 됩니다. 다만 게임 저장 파일 용량이 늘어납니다 STR_3335 :롤러코스터 디자이너 - 놀이기구 종류 & 차량을 선택하세요 STR_3336 :트랙 디자인 매니저 - 놀이기구 종류를 선택하세요 STR_3337 :<더 이상 사용하지 않음> @@ -3387,7 +3387,7 @@ STR_3376 :새 트랙 디자인 설치... STR_3377 :{SMALLFONT}{BLACK}새 트랙 디자인 파일 설치 STR_3378 :설치 STR_3379 :취소 -STR_3380 :U이 트랙 디자인 파일을 설치할 수 없습니다... +STR_3380 :이 트랙 디자인 파일을 설치할 수 없습니다... STR_3381 :파일이 적합하지 않거나 유효하지 않은 데이터를 포함하고 있습니다 STR_3382 :파일 복사에 실패하였습니다 STR_3383 :트랙 디자인에 지정할 새 이름을 선택하세요 @@ -3463,9 +3463,9 @@ STR_5123 :놀이기구 새 걸로 STR_5124 :<더 이상 사용하지 않음> STR_5125 :모두 파괴 가능 STR_5126 :무작위 타이틀 음악 -STR_5127 :{SMALLFONT}{BLACK}땅을 올리거나 내리지 않음 +STR_5127 :{SMALLFONT}{BLACK}땅을 올리거나 내리지 않고 지형을 편집합니다 STR_5128 :선택 도구 크기 -STR_5129 :선택 도구 크기를 {COMMA16}에서 {COMMA16} 사이의 값으로 입력하세요 +STR_5129 :{COMMA16}에서 {COMMA16} 사이의 값을 입력하세요 STR_5130 :지도 크기 STR_5131 :지도 크기를 {COMMA16}에서 {COMMA16} 사이의 값으로 입력하세요 STR_5132 :모든 놀이기구 수리 @@ -3473,7 +3473,7 @@ STR_5133 :{SMALLFONT}{BLACK}땅 구입 도구 크기 줄이기 STR_5134 :{SMALLFONT}{BLACK}땅 구입 도구 크기 늘이기 STR_5135 :{SMALLFONT}{BLACK}땅 소유권과 건설권 구입하기 STR_5136 :땅 소유권 -STR_5137 :체인/발사 속력을 {VELOCITY}까지 허용 +STR_5137 :놀이기구 운영 제한 없애기 STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} STR_5140 :브레이크 고장 안 나게 @@ -3492,7 +3492,7 @@ STR_5152 :. STR_5153 :테마 수정... STR_5154 :하드웨어 디스플레이 STR_5155 :완성되지 않은 트랙의 테스트 허용 -STR_5156 :{SMALLFONT}{BLACK}대부분의 놀이기구 종류에서 트랙이 완성되지 않아도 테스트를 할 수 있도록 허용합니다. 블록 섹션 모드에는 적용되지 않습니다 +STR_5156 :{SMALLFONT}{BLACK}대부분의 놀이기구 종류에서 트랙을 완성하지 않아도 테스트를 할 수 있도록 허용합니다. 블록 섹션 모드에는 적용되지 않습니다 STR_5157 :모든 가격 잠금 해제 STR_5158 :종료하고 메뉴로 STR_5159 :OpenRCT2 종료 @@ -3513,7 +3513,7 @@ STR_5173 :트위치 채팅 내용을 뉴스로 전송 STR_5174 :{SMALLFONT}{BLACK}트위치의 채팅 메시지를 !news를 이용하여 게임 메시지로 알려줍니다 STR_5175 :트위치 채널 이름 입력 STR_5176 :트위치 통합 허용 -STR_5177 :풀 스크린 모드: +STR_5177 :전체 화면 모드: STR_5178 :{SMALLFONT}{BLACK}재정 치트를 보여줍니다 STR_5179 :{SMALLFONT}{BLACK}손님 치트를 보여줍니다 STR_5180 :{SMALLFONT}{BLACK}공원 치트를 보여줍니다 @@ -3636,7 +3636,7 @@ STR_5296 :{SMALLFONT}{BLACK}공원을 닫습니다 STR_5297 :{SMALLFONT}{BLACK}공원을 엽니다 STR_5298 :{RED}{STRINGID} STR_5299 :{LIGHTPINK}{STRINGID} -STR_5300 :{SMALLFONT}{BLACK}빠른 직원 해고 +STR_5300 :{SMALLFONT}{BLACK}직원 간편 해고 STR_5301 :{MEDIUMFONT}{BLACK}대출금을 모두 갚습니다 STR_5302 :대출금 모두 갚기 STR_5303 :일시정지 모드에서 건설 허용 @@ -3706,7 +3706,7 @@ STR_5366 :보통 STR_5367 :빠름 STR_5368 :충돌 이력 제거 STR_5369 :공원 설정... -STR_5370 :{SMALLFONT}{BLACK}제한, 손님 생성, 돈 등의{NEWLINE}공원과 관련된 설정을 수정하려면{NEWLINE}이 버튼을 클릭하세요. +STR_5370 :{SMALLFONT}{BLACK}제한, 손님 생성, 돈 등의 공원과 관련된 설정을 수정하려면 이 버튼을 클릭하세요. STR_5371 :오브젝트 선택 STR_5372 :마우스 오른쪽 드래그시 좌우 반전 STR_5373 :이름 {STRINGID} @@ -3764,7 +3764,7 @@ STR_5424 :{MOVE_X}{87}{COMMA16} 동안 기다림 STR_5425 :재시작 STR_5426 :끝 STR_5427 :좌표: -STR_5428 :반시계 방향 회전: +STR_5428 :반시계방향 회전: STR_5429 :확대 수준: STR_5430 :기다릴 시간: STR_5431 :불러올 세이브 파일: @@ -3796,12 +3796,12 @@ STR_5456 :겹쳐짓기 모드 STR_5457 :지지대 제한 없애기 STR_5458 :시계방향으로 회전 STR_5459 :반시계방향으로 회전 -STR_5460 :화면을 반시계방향으로 회전 +STR_5460 :게임 화면을 반시계방향으로 회전 STR_5461 :손님 매개변수 설정 STR_5462 :{CURRENCY} STR_5463 :목표: 즐기세요! STR_5464 :일반 -STR_5465 :기후 +STR_5465 :날씨 STR_5466 :직원 STR_5467 :ALT + STR_5468 :최근 메시지 @@ -3838,18 +3838,18 @@ STR_5498 :서버 목록 STR_5499 :플레이어 이름: STR_5500 :서버 추가 STR_5501 :서버 열기 -STR_5502 :멀티플레이 +STR_5502 :접속자 목록 STR_5503 :호스트네임이나 IP 주소를 입력하세요: -STR_5504 :{SMALLFONT}{BLACK}멀티플레이 창을 엽니다 +STR_5504 :{SMALLFONT}{BLACK}접속자 목록 창을 엽니다 STR_5505 :서버에 접속할 수 없습니다 STR_5506 :손님이 격렬도를 무시하고 탐 STR_5507 :미화원이 기본적으로 잔디를 깎음 -STR_5508 :올바르지 않은 체크합을 가진 파일 불러오기 허용 -STR_5509 :{SMALLFONT}{BLACK}데모에서 저장한 시나리오나 손상된 저장 파일과 같이 올바르지 않은 체크합을 가진 시나리오나 저장 파일을 불러오는 것을 허용합니다. +STR_5508 :올바르지 않은 검사합을 가진 파일 불러오기 허용 +STR_5509 :{SMALLFONT}{BLACK}데모에서 저장한 시나리오나 손상된 저장 파일과 같이 올바르지 않은 검사합을 가진 시나리오나 저장 파일을 불러오는 것을 허용합니다. STR_5510 :기본 사운드 장치 STR_5511 :(알 수 없음) STR_5512 :다른 이름으로 저장 -STR_5513 :(간편) 게임 저장 +STR_5513 :게임 간편 저장 STR_5514 :기물을 파손하지 않게 하기 STR_5515 :{SMALLFONT}{BLACK}손님이 화가 났을 때 기물을 파손하지 않도록 설정합니다 STR_5516 :{SMALLFONT}{BLACK}검은색 @@ -3916,13 +3916,7579 @@ STR_5576 :포트: STR_5577 :대한민국 원 (₩) STR_5578 :러시아 루블 (R) STR_5579 :창 크기 조절 배수: +STR_5580 :체코 코루나 (Kc) +STR_5581 :FPS 보기 +STR_5582 :마우스 커서를 창 밖으로 나가지 못하게 +STR_5583 :{COMMA1DP16}m/s +STR_5584 :국제단위(SI)법 +STR_5585 :{SMALLFONT}{BLACK}체인/발사 속력을 {VELOCITY}으로 만드는 등, 일부 놀이기구 운행 제한을 없애줍니다 +STR_5586 :상점이나 가게를 자동으로 엶 +STR_5587 :{SMALLFONT}{BLACK}이 설정을 켜면 상점이나 가게를 건설한 뒤에 자동으로 열도록 만들어 줍니다. +STR_5588 :{SMALLFONT}{BLACK}다른 참가자와 함께 플레이합니다. +STR_5589 :알림 설정 +STR_5590 :공원 수상 내역 +STR_5591 :광고 종료 +STR_5592 :공원에 대한 경고 +STR_5593 :공원 등급 경고 +STR_5594 :놀이기구 고장 +STR_5595 :놀이기구 충돌 +STR_5596 :놀이기구에 대한 경고 +STR_5597 :놀이기구 / 풍경 연구 완료 +STR_5598 :손님에 대한 경고 +STR_5599 :손님의 길 잃음 +STR_5600 :손님의 공원 퇴장 +STR_5601 :손님의 놀이기구 대기줄 진입 +STR_5602 :손님의 놀이기구 탑승 +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}유령 플래그 +STR_5613 :B +STR_5614 :{SMALLFONT}{BLACK}깨짐 플래그 +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}타일 플래그의 마지막 요소 +STR_5617 :{SMALLFONT}{BLACK}선택한 요소를 위로 이동합니다. +STR_5618 :{SMALLFONT}{BLACK}선택한 요소를 아래로 이동합니다. +STR_5619 :롤러코스터 타이쿤 +STR_5620 :애디드 어트랙션 +STR_5621 :루피 랜드스케이프 +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 :직접 만들기... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}쓴 돈: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}실행한 명령: {BLACK}{COMMA16} +STR_5637 :할 수 없습니다... +STR_5638 :권한 없음 +STR_5639 :{SMALLFONT}{BLACK}플레이어 목록을 보여줍니다 +STR_5640 :{SMALLFONT}{BLACK}그룹 관리 +STR_5641 :기본 그룹: +STR_5642 :그룹: +STR_5643 :그룹 추가 +STR_5644 :그룹 제거 +STR_5645 :대화 +STR_5646 :지형 편집 +STR_5647 :일시정지/해제 +STR_5648 :수면 높이 설정 +STR_5649 :놀이기구 생성 +STR_5650 :놀이기구 제거 +STR_5651 :놀이기구 짓기 +STR_5652 :놀이기구 속성 +STR_5653 :풍경 +STR_5654 :보도 +STR_5655 :손님 +STR_5656 :직원 +STR_5657 :공원 속성 +STR_5658 :공원 기금 +STR_5659 :플레이어 추방 +STR_5660 :그룹 수정 +STR_5661 :플레이어 그룹 설정 +STR_5662 :없음 +STR_5663 :지형 초기화 +STR_5664 :치트 +STR_5665 :오브젝트 무더기 설치 모드 사용 +STR_5701 :{WINDOW_COLOUR_2}마지막 행동: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}플레이어의 가장 최근 행동 장소로 이동 +STR_5703 :서버를 추방할 수 없습니다 +STR_5704 :마지막 행동: +STR_5705 :이 그룹으로 설정할 수 없습니다 +STR_5706 :플레이어가 있는 그룹을 제거할 수 없습니다 +STR_5707 :이 그룹을 수정할 수 없습니다 +STR_5708 :서버가 속한 그룹을 변경할 수 없습니다 +STR_5709 :그룹 이름 변경 +STR_5710 :그룹 이름 +STR_5711 :이 그룹의 이름을 입력하세요: +STR_5712 :본인에게 없는 권한은 수정할 수 업습니다 +STR_5713 :플레이어 추방 +STR_5714 :설정 창 보기 +STR_5715 :새로운 게임 +STR_5716 :멀티플레이 모드에서 사용할 수 없는 기능입니다 +# For identifying client network version in server list window +STR_5717 :네트워크 버전: {STRING} +STR_5718 :{SMALLFONT}{BLACK}네트워크 버전: {STRING} +STR_5719 :맑음 +STR_5720 :다소 흐림 +STR_5721 :흐림 +STR_5722 :비 +STR_5723 :폭우 +STR_5724 :천둥번개 +STR_5725 :{BLACK}날씨 고정: +STR_5726 :{SMALLFONT}{BLACK}공원의 현재 날씨를 설정합니다. +STR_5727 :크기 조절 방식 +STR_5728 :하드웨어 디스플레이 설정 필요 +STR_5729 :{SMALLFONT}{BLACK}하드웨어 디스플레이를 설정해야 합니다. +STR_5730 :최근접 인접 픽셀 사용 +STR_5731 :선형으로 +STR_5732 :비등방성으로 +STR_5733 :정수배 확대시 NN 스케일링 사용 +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}렌더링 +STR_5735 :네트워크 상태 +STR_5736 :플레이어 +STR_5737 :닫힘, {COMMA16}명의 손님이 아직 놀이기구에 있음 +STR_5738 :닫힘, {COMMA16}명의 손님이 아직 놀이기구에 있음 +STR_5739 :{WINDOW_COLOUR_2}놀이기구를 타고 있는 손님: {BLACK}{COMMA16}명 +STR_5740 :광고 기간 무제한으로 +STR_5741 :{SMALLFONT}{BLACK}광고의 기간을 무제한으로 바꿉니다 +STR_5742 :인증하는 중 ... +STR_5743 :접속 중 ... +STR_5744 :분석 중 ... +STR_5745 :네트워크 비동기화 감지 +STR_5746 :접속이 끊어짐 +STR_5747 :접속이 끊어짐: {STRING} +STR_5748 :추방 +STR_5749 :서버에서 추방당하셨습니다! +STR_5750 :접속 종료 +STR_5751 :데이터 없음 +STR_5752 :{OUTLINE}{RED}{STRING} 님 퇴장 +STR_5753 :{OUTLINE}{RED}{STRING} 님 퇴장 ({STRING}) +STR_5754 :올바르지 않은 플레이어 이름 +STR_5755 :소프트웨어 버전이 맞지 않습니다 +STR_5756 :비밀번호가 맞지 않습니다 +STR_5757 :서버 제한 인원이 꽉 찼습니다 +STR_5758 :{OUTLINE}{GREEN}{STRING} 님 입장 +STR_5759 :맵 다운로드 중 ... ({INT32} / {INT32}) +STR_5760 :홍콩 달러 (HK$) +STR_5761 :신 대만 달러 (NT$) +STR_5762 :중국 위안 (CN{YEN}) +STR_5763 :모든 파일 +STR_5764 :잘못된 놀이기구 종류 +STR_5765 :놀이기구를 유효하지 않은 종류로 수정할 수 없습니다 +STR_5766 :<사용 가능한 문자열 아이디> +STR_5767 :수익 +STR_5768 :총 고객 수 +STR_5769 :총 수익 +STR_5770 :시간당 고객 수 +STR_5771 :유지비 +STR_5772 :연식 +STR_5773 :총 고객 수: {COMMA32}명 +STR_5774 :총 수익: {CURRENCY2DP} +STR_5775 :고객 수: 시간당 {COMMA32}명 +STR_5776 :건설: 올해 +STR_5777 :건설: 작년 +STR_5778 :건설: {COMMA16}년 전 +STR_5779 :수익: 시간당 {CURRENCY2DP} +STR_5780 :유지비: 시간당 {CURRENCY2DP} +STR_5781 :유지비: 알 수 없음 +STR_5782 :접속이 완료되었습니다. 대화를 시작하시려면 '{STRING}'를 누르세요. +STR_5783 :{WINDOW_COLOUR_2}시나리오 잠김 +STR_5784 :{BLACK}이 시나리오를 플레이하려면 이전 시나리오의 목표를 먼저 완료하세요. +STR_5785 :그룹 이름을 바꿀 수 없습니다... +STR_5786 :유효하지 않은 그룹 이름 +STR_5787 :{COMMA32}명의 플레이어 접속 중 +STR_5788 :기본 점검 간격: +STR_5789 :번개 번쩍임 없애기 +STR_5790 :{SMALLFONT}{BLACK}RCT1식으로 돈을 받습니다.{NEWLINE}(예: 놀이기구 탑승료와 공원 입장료를 같이 받기) +STR_5791 :{SMALLFONT}{BLACK}모든 놀이기구의 신뢰도를 100%로 설정하고{NEWLINE}건설 시점을 "올해"로 바꿉니다. +STR_5792 :{SMALLFONT}{BLACK}고장난 놀이기구를 모두 고칩니다. +STR_5793 :{SMALLFONT}{BLACK}놀이기구의 충돌 이력을 제거하여,{NEWLINE}손님들이 안전하지 않다고 불평하지 않게 만듭니다. +STR_5794 :{SMALLFONT}{BLACK}일부 시나리오에서 공원에 이미 존재하는 놀이기구를 수정할 수 없게 해놓은 것을 해제해줍니다. +STR_5795 :{SMALLFONT}{BLACK}손님들이 놀이기구의 격렬도가 아무리 높아도 그 놀이기구에 타도록 만듭니다. +STR_5796 :{SMALLFONT}{BLACK}공원의 문을 강제로 열거나 닫습니다. +STR_5797 :{SMALLFONT}{BLACK}날씨를 선택한 날씨로 고정하고 바뀌지 않게 만듭니다. +STR_5798 :{SMALLFONT}{BLACK}일시정지 상태에서 건설을 허용합니다. +STR_5799 :{SMALLFONT}{BLACK}브레이크 실패로 인한 고장과 충돌이 일어나지 않게 만듭니다. +STR_5800 :{SMALLFONT}{BLACK}놀이기구가 고장나지 않게 만듭니다. -##################### -# Rides/attractions # -##################### +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :미개척된 숲 +STR_DTLS :깊은 숲 속 넓은 공터에 번창한 놀이공원을 건설하세요. + + +STR_SCNR :Dynamite Dunes +STR_PARK :다이너마이트 모래언덕 +STR_DTLS :사막 한가운데 건설된 이 놀이공원에는 롤러코스터 한 대만이 있지만 확장할 수 있는 곳이 많습니다. + + +STR_SCNR :Leafy Lake +STR_PARK :나뭇잎 호수 +STR_DTLS :처음부터 시작하여 큰 호수 주변에 놀이공원을 건설하세요. + + +STR_SCNR :Diamond Heights +STR_PARK :다이아몬드 언덕 +STR_DTLS :다이아몬드 언덕은 멋진 놀이기구를 통해 이미 성공한 놀이공원입니다. 공원의 가치를 두 배로 늘려 보세요. + + +STR_SCNR :Evergreen Gardens +STR_PARK :상록수 정원 +STR_DTLS :아름다운 상록수 정원을 번창한 놀이공원으로 바꿔보세요. + + +STR_SCNR :Bumbly Beach +STR_PARK :범블리 해변 +STR_DTLS :범블리 해변의 작은 놀이공원을 번창한 놀이공원으로 발전시키세요. + + +STR_SCNR :Trinity Islands +STR_PARK :삼위일체 섬 +STR_DTLS :몇 개의 섬이 이 새로운 공원의 기반입니다. + + +STR_SCNR :Katie's Dreamland +STR_PARK :케이티의 드림랜드 +STR_DTLS :몇 개의 놀이기구와 확장할 공간이 있는 작은 놀이공원으로, 여러분의 목표는 공원 가치를 두 배로 늘리는 것입니다. + + +STR_SCNR :Pokey Park +STR_PARK :비좁은 공원 +STR_DTLS :대대적인 확장을 해야하는 비좁은 놀이공원 + + +STR_SCNR :White Water Park +STR_PARK :맑은 물 공원 +STR_DTLS :훌륭한 물 놀이기구를 몇 개 갖고있지만 확장이 필요한 공원 + + +STR_SCNR :Millennium Mines +STR_PARK :밀레니엄 광산 +STR_DTLS :버려져있는 커다란 탄광을 관광시설에서 놀이공원으로 바꿔보세요. + + +STR_SCNR :Karts & Coasters +STR_PARK :카트 & 코스터 +STR_DTLS :몇 개의 고 카트 트랙과 우든 롤러코스터만이 숲 속에 숨겨져 있는 대형 놀이공원 + + +STR_SCNR :Mel's World +STR_PARK :멜의 세계 +STR_DTLS :이 놀이공원에는 잘 디자인된 현대식 놀이기구가 있지만 아직도 확장해야 할 곳이 많습니다. + + +STR_SCNR :Mystic Mountain +STR_PARK :신비한 산 +STR_DTLS :비밀스런 숲 속 언덕에 처음부터 놀이공원을 건설하세요. + + +STR_SCNR :Pacific Pyramids +STR_PARK :평화로운 피라미드 +STR_DTLS :이집트 유적 관광지를 번창한 놀이공원으로 바꿔 보세요. + + +STR_SCNR :Crumbly Woods +STR_PARK :부서지기 쉬운 숲 +STR_DTLS :잘 디자인되었지만 다소 낡은 놀이기구를 가진 대형 공원입니다. 오래된 놀이기구를 교체하거나 새로운 놀이기구를 추가하여 보다 인기있는 공원을 만들어보세요. + + +STR_SCNR :Paradise Pier +STR_PARK :파라다이스 부두 +STR_DTLS :이 조용한 마을의 부두를 번창한 놀이공원으로 바꿔보세요. + + +STR_SCNR :Lightning Peaks +STR_PARK :번개치는 산꼭대기 +STR_DTLS :번개치는 산꼭대기의 아름다운 산은 경치를 즐기며 산책을 즐기는 사람들에게 인기가 높습니다. 사용 가능한 땅을 이용해서 스릴을 찾는 새로운 고객을 유혹해보세요. + + +STR_SCNR :Ivory Towers +STR_PARK :상아 탑 +STR_DTLS :문제가 몇 가지 있지만 잘 구성된 공원 + + +STR_SCNR :Rainbow Valley +STR_PARK :무지개 계곡 +STR_DTLS :무지개 계곡의 지역 당국은 풍경을 바꾸거나 큰 나무를 제거할 수 없게 했지만, 이 지역을 개발하여 대형 놀이공원으로 바꿔야만 합니다. + + +STR_SCNR :Thunder Rock +STR_PARK :천둥 바위 +STR_DTLS :천둥 바위는 사막 한가운데에서 많은 관광객을 끌어 모으고 있습니다. 사용 가능한 공간을 이용해 놀이기구를 건설해서 더 많은 사람들을 끌어 보세요. + + +STR_SCNR :Mega Park +STR_PARK :대공원 +STR_DTLS :그냥 즐기세요! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :속삭이는 절벽 +STR_DTLS :해변의 절벽을 인기있는 놀이공원으로 발전시키세요. + + +STR_SCNR :Three Monkeys Park +STR_PARK :세 원숭이 공원 +STR_DTLS :개발 중인 이 거대한 공원의 한 가운데에는 동시에 경주하는 거대한 세 쌍둥이 스틸 롤러코스터가 있습니다. + + +STR_SCNR :Canary Mines +STR_PARK :카나리아 광산 +STR_DTLS :이 버려진 탄광은 모형 기차와 수직 낙하 롤러코스터로 이미 관광객의 인기를 끌고 있습니다. + + +STR_SCNR :Barony Bridge +STR_PARK :남작의 다리 +STR_DTLS :필요없는 오래된 다리를 놀이공원으로 개발할 수 있습니다. + + +STR_SCNR :Funtopia +STR_PARK :펀토피아 +STR_DTLS :고속도로 양쪽을 잘 활용한 이 공원은 이미 몇 가지 놀이기구를 운영하고 있습니다. + + +STR_SCNR :Haunted Harbour +STR_PARK :유령 항구 +STR_DTLS :지역 당국은 특정 놀이기구는 파괴할 수 없다는 조건을 걸고 이 작은 해변 공원 근처의 땅을 저렴하게 팔기로 합의했습니다. + + +STR_SCNR :Fun Fortress +STR_PARK :즐거운 요새 +STR_DTLS :이 성은 놀이공원으로 탈바꿈하기 위해 온전히 당신의 소유가 되었습니다. + + +STR_SCNR :Future World +STR_PARK :미래 세계 +STR_DTLS :이 미래지향적인 공원에는 새로운 놀이기구를 그 외계 지형 위에 지을 많은 공간이 있습니다. + + +STR_SCNR :Gentle Glen +STR_PARK :얌전한 골짜기 +STR_DTLS :이 지역의 주민들은 격렬하지 않고 얌전한 놀이기구를 선호하기 때문에 이 공원을 그들의 취향에 맞게 확장하는 것이 여러분의 임무입니다. + + +STR_SCNR :Jolly Jungle +STR_PARK :즐거운 정글 +STR_DTLS :정글 속 깊은 곳에 놀이공원으로 탈바꿈할 수 있는 넓은 대지가 있습니다. + + +STR_SCNR :Hydro Hills +STR_PARK :하이드로 언덕 +STR_DTLS :몇 개의 호수를 기반으로 새로운 공원을 건설할 수 있습니다. + + +STR_SCNR :Sprightly Park +STR_PARK :활기 넘치는 공원 +STR_DTLS :이 오래된 공원에는 아주 역사적인 놀이기구가 많이 있지만 심각한 적자에 시달리고 있습니다. + + +STR_SCNR :Magic Quarters +STR_PARK :매직 쿼터 +STR_DTLS :비어있는 넓은 지역의 일부분을 아름다운 풍경의 테마파크로 개발될 준비가 되었습니다. + + +STR_SCNR :Fruit Farm +STR_PARK :과일 농장 +STR_DTLS :무성한 과일 농장에 모형 기차를 건설해서 수익을 극대화하고 있습니다. 여러분의 임무는 이 농장을 최고의 놀이공원으로 만드는 것입니다. + + +STR_SCNR :Butterfly Dam +STR_PARK :나비 댐 +STR_DTLS :댐 주변 지역을 놀이공원으로 개발할 수 있습니다. + + +STR_SCNR :Coaster Canyon +STR_PARK :코스터 협곡 +STR_DTLS :광대한 협곡을 테마파크로 개발할 수 있습니다. + + +STR_SCNR :Thunderstorm Park +STR_PARK :폭풍우 공원 +STR_DTLS :날씨가 너무 습해서 거대한 피라미드를 짓고 몇몇 놀이기구를 그 밑에 두기로 했습니다. + + +STR_SCNR :Harmonic Hills +STR_PARK :조화로운 언덕 +STR_DTLS :지역 당국은 이 공원에서 나무 높이 이상의 건설을 허용하지 않습니다. + + +STR_SCNR :Roman Village +STR_PARK :로마의 마을 +STR_DTLS :이 로마 스타일의 테마파크에 놀이기구와 롤러코스터를 추가해서 더욱 발전시켜보세요. + + +STR_SCNR :Swamp Cove +STR_PARK :습지 골짜기 +STR_DTLS :몇 개의 작은 섬에 부분 부분 건설된 이 공원에는 이미 중앙에 한 쌍의 거대한 롤러코스터가 있습니다. + + +STR_SCNR :Adrenaline Heights +STR_PARK :아드레날린 언덕 +STR_DTLS :격렬한 스릴을 즐기는 사람들을 위한 공원을 건설하세요. + + +STR_SCNR :Utopia Park +STR_PARK :유토피아 공원 +STR_DTLS :사막 한가운데의 오아시스에 놀이공원을 건설해보세요. + + +STR_SCNR :Rotting Heights +STR_PARK :썩어버린 언덕 +STR_DTLS :지나치게 성장해서 황폐화되어버린 이 곳을 다시 멋진 공원으로 바꿀 수 있습니까? + + +STR_SCNR :Fiasco Forest +STR_PARK :실패한 숲 +STR_DTLS :위험하고 잘못 설계된 놀이기구가 많이 있습니다. 공원을 둘러보고 문제를 수정할 시간과 예산이 매우 부족합니다. + + +STR_SCNR :Pickle Park +STR_PARK :피클 공원 +STR_DTLS :지역 당국에서는 광고나 홍보를 허용하지 않으므로 이 공원은 사람들의 입을 통해서만 알릴 수 있습니다. + + +STR_SCNR :Giggle Downs +STR_PARK :웃기는 구릉 지대 +STR_DTLS :이 넓은 공원의 중앙에는 네 쌍둥이 스티플체이스 놀이기구가 있습니다. + + +STR_SCNR :Mineral Park +STR_PARK :광물 공원 +STR_DTLS :이 버려진 채석장을 스릴을 찾는 사람들을 유혹할만한 장소로 바꿔보세요. + + +STR_SCNR :Coaster Crazy +STR_PARK :미친 코스터 +STR_DTLS :이 산악 지대에 다양한 롤러코스터를 건설해보세요. 예산은 한정되어 있지만 시간은 제한이 없습니다. + + +STR_SCNR :Urban Park +STR_PARK :도시 공원 +STR_DTLS :이 작은 공원은 이 도시뿐만 아니라 근교 도시의 주민들에게까지 인기를 모으고 있습니다. + + +STR_SCNR :Geoffrey Gardens +STR_PARK :제프리의 정원 +STR_DTLS :대규모의 정원 공원을 북적이는 놀이공원으로 바꿔해야 합니다. + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :빙산 섬 +STR_DTLS :빙산이 이 야심찬 놀이공원에 차가운 이미지를 더하고 있습니다. + + +STR_SCNR :Volcania +STR_PARK :볼케이니아 +STR_DTLS :이번 롤러코스터 건설 도전에서는 휴화산이 무대가 됩니다. + + +STR_SCNR :Arid Heights +STR_PARK :건조한 언덕 +STR_DTLS :아무런 재정적 제한 없는 상황에서, 지속적으로 손님들을 행복하게 만들 수 있는 공원을 사막에 건설해보세요. + + +STR_SCNR :Razor Rocks +STR_PARK :날카로운 바위 +STR_DTLS :여러분의 임무는 날카로운 바위 사이에 롤러코스터로 가득한 거대한 공원을 만드는 것입니다. + + +STR_SCNR :Crater Lake +STR_PARK :분화구 호수 +STR_DTLS :이 공원의 부지는 고대 분화구에 만들어진긴 커다란 호수입니다. + + +STR_SCNR :Vertigo Views +STR_PARK :어지러운 풍경 +STR_DTLS :이 거대한 공원에는 이미 훌륭한 하이퍼코스터가 있습니다. 여러분의 임무는 그 매출을 아주 극대화시키는 것입니다. + + +STR_SCNR :Paradise Pier 2 +STR_PARK :파라다이스 부두 2 +STR_DTLS :파라다이스 부두는 바다 위의 산책로를 확장했습니다. 여러분의 임무는 이 새로운 공간을 이용하여 공원을 확장하는 것 입니다. + + +STR_SCNR :Dragon's Cove +STR_PARK :용의 동굴 +STR_DTLS :이번 롤러코스터 건설 도전에서는 해안 동굴이 무대가 됩니다. + + +STR_SCNR :Good Knight Park +STR_PARK :훌륭한 기사 공원 +STR_DTLS :한 쌍의 롤러코스터가 있는 성을 더 큰 놀이공원으로 발전시켜야 합니다. + + +STR_SCNR :Wacky Warren +STR_PARK :괴짜 미로 +STR_DTLS :대부분의 보도와 롤러코스터가 지하에 있는 공원입니다. + + +STR_SCNR :Grand Glacier +STR_PARK :웅장한 빙하 +STR_DTLS :놀이공원으로 만들기 위해 당신에게 빙하가 가득한 계곡이 주어졌습니다. + + +STR_SCNR :Crazy Craters +STR_PARK :미친 분화구 +STR_DTLS :돈이 필요없는 머나먼 세상에서, 여러분은 사람들을 행복하게 해줄 놀이공원을 건설해야 합니다. + + +STR_SCNR :Dusty Desert +STR_PARK :먼지투성이 사막 +STR_DTLS :이 사막 공원에 있는 다섯 대의 롤러코스터를 완성하십시오. + + +STR_SCNR :Woodworm Park +STR_PARK :나무좀벌레 공원 +STR_DTLS :이 역사적인 공원에는 오직 오래된 스타일의 놀이기구만을 건설할 수 있습니다. + + +STR_SCNR :Icarus Park +STR_PARK :이카루스 공원 +STR_DTLS :이 외계 공원을 개발하여 최대한의 매출을 올리세요. + + +STR_SCNR :Sunny Swamps +STR_PARK :맑은 늪지 +STR_DTLS :이 잘 구성된 놀이공원에는 이미 몇 개의 놀이기구가 있지만, 아직 확장할 수 있는 공간은 충분합니다. + + +STR_SCNR :Frightmare Hills +STR_PARK :무시무시한 언덕 +STR_DTLS :거대한 롤러코스터가 공원 가운데에 있는 무시무시한 공원 + + +STR_SCNR :Thunder Rocks +STR_PARK :천둥 바위들 +STR_DTLS :놀이공원의 기초가 될 두 개의 커다란 바위가 사막의 모래 위에 솟아 있습니다. + + +STR_SCNR :Octagon Park +STR_PARK :팔각형 공원 +STR_DTLS :이 거대한 공원에 여러분은 10개의 거대한 롤러코스터를 디자인하고 만들어야 합니다. + + +STR_SCNR :Pleasure Island +STR_PARK :즐거운 섬 +STR_DTLS :길고 가느다란 섬에서 롤러코스터 건설에 도전해보세요. + + +STR_SCNR :Icicle Worlds +STR_PARK :고드름 세상 +STR_DTLS :얼음으로 덮인 땅을 번창하는 놀이공원으로 바꿔보세요. + + +STR_SCNR :Southern Sands +STR_PARK :남부 사막 +STR_DTLS :빈틈없이 세워진 롤러코스터가 있는 사막 공원이 확장을 위해 여러분에게 주어졌습니다. + + +STR_SCNR :Tiny Towers +STR_PARK :조그마한 탑 +STR_DTLS :이 조그마한 공원에 있는 다섯 개의 미완성된 롤러코스터를 모두 완성해야 합니다. + + +STR_SCNR :Nevermore Park +STR_PARK :네버모어 공원 +STR_DTLS :공원 주변에 참신한 운송수단이 설치된 거대한 공원 + + +STR_SCNR :Pacifica +STR_PARK :패시피카 +STR_DTLS :놀이공원으로 개발하기 위해 이 거대한 섬이 여러분에게 주어졌습니다. + + +STR_SCNR :Urban Jungle +STR_PARK :도시의 정글 +STR_DTLS :버려진 거대한 마천루 빌딩은 놀이공원 개발자에게는 독특한 기회일 것입니다. + + +STR_SCNR :Terror Town +STR_PARK :공포스러운 마을 +STR_DTLS :놀이공원으로 개발하기 위해 이 도시 지역이 여러분에게 주어졌습니다. + + +STR_SCNR :Megaworld Park +STR_PARK :대세상 공원 +STR_DTLS :이미 놀이기구로 가득한 거대한 공원을 확장해야 합니다. + + +STR_SCNR :Venus Ponds +STR_PARK :비너스의 연못 +STR_DTLS :멀리 떨어진 행성에 있는 이 지역을 놀이공원으로 바꿔야 합니다. + + +STR_SCNR :Micro Park +STR_PARK :마이크로 공원 +STR_DTLS :세상에서 가장 작지만 수익이 좋은 공원을 만들어보세요. + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :알턴 타워스 +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :하이데 파르크 +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :블랙풀 플레져 비치 +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :역사적인 성채 +STR_DTLS : + +############################################################################### +## RCT2 Objects +############################################################################### +[AML1] +STR_NAME :미국 스타일 증기 기관차 +STR_DESC :부드러운 천으로 된 지붕을 가진 나무 객차와 증기 기관차 모형으로 이루어진 모형 증기 기관차 차량 +STR_CPTY :차량당 6명의 승객 + +[CLIFT1] +STR_NAME :체어 리프트 차량 +STR_DESC :체어 리프트를 위한 개방형 차량 +STR_CPTY :차량당 2명의 승객 + +[CLIFT2] +STR_NAME :스키 리프트 의자 +STR_DESC :체어 리프트를 위한 개방형 차량 +STR_CPTY :차량당 2명의 승객 + +[LIFT1] +STR_NAME :엘리베이터 +STR_DESC :손님들이 엘리베이터에 타서 수직 탑을 따라 위나 아래 층으로 이동하는 놀이기구 +STR_CPTY :승객 16명 + +[MONO1] +STR_NAME :유선형 모노레일 차량 +STR_DESC :유선형의 전두부와 후두부 차량을 가진 대용량의 모노레일 차량 +STR_CPTY :차량당 5명 또는 10명의 승객 + +[MONO2] +STR_NAME :소형 모노레일 차량 +STR_DESC :측면이 개방되어 있는 소형 모노레일 차량 +STR_CPTY :차량당 4명의 승객 + +[MONO3] +STR_NAME :복고풍 모노레일 차량 +STR_DESC :개방형 객차를 가진 모노레일 차량 +STR_CPTY :차량당 4명의 승객 + +[NRL] +STR_NAME :증기 기관차 +STR_DESC :나무 객차와 증기 기관차 모형으로 이루어진 모형 증기 기관차 차량 +STR_CPTY :객차당 6명의 승객 + +[NRL2] +STR_NAME :천장이 있는 증기 기관차 +STR_DESC :부드러운 천으로 된 지붕을 가진 나무 객차와 증기 기관차 모형으로 이루어진 모형 증기 기관차 차량 +STR_CPTY :객차당 6명의 승객 + +[SMONO] +STR_NAME :서스펜디드 모노레일 차량 +STR_DESC :대용량의 모노레일 차량 +STR_CPTY :차량당 8명의 승객 + +[TRAM1] +STR_NAME :전차 +STR_DESC :옛날 스타일의 전차 모형 +STR_CPTY :차량당 10명의 승객 + +[4X4] +STR_NAME :몬스터 트럭 +STR_DESC :급경사를 오를 수 있는 초대형 4 x 4 트럭 +STR_CPTY :트럭당 2명의 승객 + +[CHBUILD] +STR_NAME :비뚤어진 집 +STR_DESC :사람들이 비뚤어진 방과 각진 복도를 통과하면서 방향을 헷갈리게 만드는 건물 +STR_CPTY :손님 5명 + +[CIRCUS1] +STR_NAME :서커스 +STR_DESC :안에서 서커스 동물 쇼를 진행하는 커다란 텐트 +STR_CPTY :손님 30명 + +[CTCAR] +STR_NAME :체셔 고양이 +STR_DESC :트랙 기반의 경로를 따라 이동하는 고양이 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[DODG1] +STR_NAME :범퍼카 +STR_DESC :스스로 운전하는 전기 범퍼카 차량 +STR_CPTY :차량당 1명의 손님 + +[FSAUC] +STR_NAME :비행 접시 +STR_DESC :스스로 운전하는 호버크래프트 차량 +STR_CPTY :차량당 1명의 손님 + +[FWH1] +STR_NAME :관람차 +STR_DESC :개방형 의자를 가진 대형 회전 관람차 +STR_CPTY :승객 32명 + +[GOLF1] +STR_NAME :미니 골프 +STR_DESC :모형 골프 게임 +STR_CPTY : + +[GTC] +STR_NAME :고스트 트레인 +STR_DESC :으스스한 풍경과 특별한 효과 주변을 지나며 여러 높낮이를 오르내리는 괴물 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[HELICAR] +STR_NAME :미니 헬리콥터 +STR_DESC :탑승자가 페달을 밟아서 철제 트랙을 따라 움직이는 헬리콥터 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[HHBUILD] +STR_NAME :귀신의 집 +STR_DESC :무서운 복도와 으스스한 방이 있는 대형 테마 건물 +STR_CPTY :손님 15명 + +[HMAZE] +STR_NAME :미로 +STR_DESC :1.8m 높이의 울타리나 벽으로 구성되어 있고, 손님들이 출구를 찾을 때까지 돌아다녀야 하는 미로 +STR_CPTY : + +[HMCAR] +STR_NAME :귀신의 집 차량 +STR_DESC :으스스한 풍경과 특별한 효과 주변을 지나며 여러 높낮이를 오르내리는 괴물 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[HSKELT] +STR_NAME :나선 미끄럼틀 +STR_DESC :내부의 계단을 타고 올라가서 외부의 나선형 미끄럼틀을 매트를 타고 내려오는 목재 건물 +STR_CPTY : + +[MGR1] +STR_NAME :회전목마 +STR_DESC :나무로 조각된 말이 있는 전통적인 회전 목마 +STR_CPTY :승객 16명 + +[MONBK] +STR_NAME :모노레일 자전거 +STR_DESC :탑승자가 직접 페달을 밟으면 강철 모노레일 트랙 위를 움직이는 특별한 자전거 +STR_CPTY :자전거 당 1명의 탑승객 + +[OBS1] +STR_NAME :전망탑 +STR_DESC :높은 탑을 따라 올라가면서 회전하는 전망대 객실 +STR_CPTY :승객 20명 + +[OBS2] +STR_NAME :2층 전망탑 +STR_DESC :높은 탑을 따라 올라가면서 회전하는 2층 전망대 객실 +STR_CPTY :승객 32명 + +[RCR] +STR_NAME :레이싱 카 +STR_DESC :레이싱 카 모양의 차량 +STR_CPTY :차량당 승객 1명 + +[SPCAR] +STR_NAME :스포츠 카 +STR_DESC :스포츠 카 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[SRINGS] +STR_NAME :스페이스 링 +STR_DESC :동심원 모양의 고리가 탑승자를 어느 방향이든 회전시킬 수 있는 놀이기구 +STR_CPTY :각 1명 + +[SUBMAR] +STR_NAME :잠수함 +STR_DESC :수면 아래 코스를 이동하는 잠수함에 탑승하는 놀이기구 +STR_CPTY :잠수함당 4명의 승객 + +[TRUCK1] +STR_NAME :소형 트럭 +STR_DESC :소형 트럭 모양의 차량 +STR_CPTY :트럭당 승객 1명 + +[VCR] +STR_NAME :빈티지 차량 +STR_DESC :트랙을 따라 이동하는 빈티지 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[AMT1] +STR_NAME :탄광 열차 코스터 +STR_DESC :오래된 선로 트랙처럼 보이지만 튼튼한 강철로 만든 롤러코스터 트랙을 따라 달리는, 광산 차량을 테마로 한 롤러코스터 차량 +STR_CPTY :차량당 2명 또는 4명의 승객 + +[ARRSW1] +STR_NAME :서스펜디드 스윙잉 차량 +STR_DESC :차량이 코너를 돌면 자유롭게 흔들거리게 만들어진 서스펜디드 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[ARRSW2] +STR_NAME :서스펜디드 스윙잉 에어로플레인 차량 +STR_DESC :차량이 코너를 돌면 자유롭게 흔들거리게 만들어진 비행기 모양의 서스펜디드 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[ARRT1] +STR_NAME :나선 롤러코스터 +STR_DESC :나선 모양 트랙과 루프를 도는 구성을 지닌 강철 트랙의 롤러코스터 +STR_CPTY :차량당 4명의 승객 + +[ARRT2] +STR_NAME :하이퍼코스터 +STR_DESC :무릎 안전바만 채운 채로, 뒤집어지지는 않지만 큰 낙하와 빠른 속도, 편안한 승차감을 자랑하는 롤러코스터 +STR_CPTY :차량당 6명의 승객 + +[ARRX] +STR_NAME :멀티 디멘션 코스터 차량 +STR_DESC :탑승객의 머리와 발을 뒤집어버리는 등의 회전 좌석을 가진 차량 +STR_CPTY :차량당 4명의 승객 + +[BATFL] +STR_NAME :스윙잉 차량 +STR_DESC :레일을 따라 흔들거리는 작은 차량 +STR_CPTY :차량당 2명의 승객 + +[BMAIR] +STR_NAME :플라잉 롤러코스터 +STR_DESC :탑승객에게 정말로 나는 듯한 경험을 주기 위해, 트랙 밑에 달린 편안한 좌석에 앉아서 꼬여있는 트랙을 따라 움직이는 놀이기구 +STR_CPTY :차량당 4명의 승객 + +[BMFL] +STR_NAME :플로어리스 롤러 코스터 +STR_DESC :꼬여있는 트랙과 여러 전이를 미끄러지듯 통과하면서 승객들에게 광활한 허공을 느끼게 해주는, 바닥이 없는 넓은 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[BMRB] +STR_NAME :하이퍼 트위스터 차량 (광폭형) +STR_DESC :향상된 탑승감과 간단한 무릎 안전바를 갖고 있는 넓은 4인승 차량 +STR_CPTY :차량당 4명의 승객 + +[BMSD] +STR_NAME :트위스터 롤러코스터 +STR_DESC :여러 종류의 루프를 돌면서 부드러운 강철 트랙을 달리는 넓은 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[BMSU] +STR_NAME :스탠드 업 트위스터 코스터 +STR_DESC :탑승자들이 선 자세로 낙하와 여러 특수 트랙을 즐길 수 있도록 특수하게 디자인된 안전바가 있는 넓은 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[BMVD] +STR_NAME :수직 낙하 롤러코스터 +STR_DESC :자유 낙하의 극한 경험을 선사하기 위해 완전히 수직 경사 트랙을 따라 하강하는 아주 폭이 넓은 차량 +STR_CPTY :차량당 6명의 승객 + +[BOB1] +STR_NAME :봅슬레이 코스터 +STR_DESC :반원형 트랙의 커브와 뱅킹만을 따라 이동하는 봅슬레이 모양의 차량을 타고 이리 저리 꼬여있는 트랙을 따라 내려오는 놀이기구 +STR_CPTY :차량당 2명의 승객 + +[GOLTR] +STR_NAME :하이퍼 트위스터 차량 +STR_DESC :간단한 무릎 안전바를 가진 널찍한 차량 +STR_CPTY :차량당 6명의 승객 + +[INTBOB] +STR_NAME :플라잉 턴 +STR_DESC :반원형 트랙의 커브와 뱅킹만을 따라 이동하는 봅슬레이 모양의 차량을 타고 이리 저리 꼬여있는 트랙을 따라 내려오는 놀이기구 +STR_CPTY :차량당 6명의 승객 + +[INTINV] +STR_NAME :인버티드 임펄스 코스터 +STR_DESC :수직으로 솟은 트랙을 오르기 위해 역에서 급가속한 뒤, 다시 역방향으로 되돌아와 역을 통과해서 뒷쪽의 또다른 수직 트랙을 올라가는 인버티드 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[INTST] +STR_NAME :기가 코스터 +STR_DESC :90m 이상의 부드러운 낙하와 상승이 가능한 거대한 강철 롤러코스터 +STR_CPTY :차량당 4명의 승객 + +[IVMC1] +STR_NAME :인버티드 헤어핀 코스터 +STR_DESC :급회전과 급경사를 가진 지그재그 모양의 트랙 아래를 달리는 개별 차량 +STR_CPTY :차량당 4명의 승객 + +[JSTAR1] +STR_NAME :터보건 썰매 차량 +STR_DESC :한 줄로 탑승하는 터보건 썰매 모양의 롤러코스터 +STR_CPTY :차량당 4명의 승객 + +[MFT] +STR_NAME :연결식 롤러코스터 차량 +STR_DESC :하나의 열로 된 짧은 차량과 개방된 전면부를 가진 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[NEMT] +STR_NAME :인버티드 롤러코스터 +STR_DESC :거대한 루프, 트위스트와 급격한 낙하 트랙을 따라 이동하며, 탑승객이 트랙 아래에 매달린 좌석에 앉는 차량 +STR_CPTY :차량당 4명의 승객 + +[PMT1] +STR_NAME :탄광 차량 +STR_DESC :부드럽게 꼬인 트랙 구조를 따라 달리는 탄광 차량 +STR_CPTY :차량당 2명 또는 4명의 승객 + +[PREMT1] +STR_NAME :LIM 발진 롤러코스터 +STR_DESC :역에서 선형 유도 모터에 의해 가속되어 꼬여있는 트랙을 빠른 속도로 통과하는 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[PTCT1] +STR_NAME :우든 롤러코스터 차량 +STR_DESC :푹신한 좌석과 무릎 안전바가 있는 나무 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[PTCT2] +STR_NAME :우든 롤러코스터 차량 (6인승) +STR_DESC :푹신한 좌석과 무릎 안전바가 있는 나무 롤러코스터 차량 +STR_CPTY :차량당 6명의 승객 + +[PTCT2R] +STR_NAME :우든 롤러코스터 차량 (6인승, 역방향) +STR_DESC :푹신한 좌석과 무릎 안전바가 있고, 뒤쪽을 본 채로 앉아서 달리는 나무 롤러코스터 차량 +STR_CPTY :차량당 6명의 승객 + +[RCKC] +STR_NAME :로켓 차량 +STR_DESC :로켓처럼 꾸며져 있는 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[REVCAR] +STR_NAME :반전 롤러코스터 +STR_DESC :특수한 반전 섹션 위에서 앞뒤가 뒤집히는 나무 트랙 위를 운행하는 불안한 차량 +STR_CPTY :차량당 6명의 승객 + +[REVF1] +STR_NAME :역방향 자유낙하 차량 +STR_DESC :역방향 자유낙하 코스터를 위한 대형 코스터 차량 +STR_CPTY :승객 8명 + +[SBOX] +STR_NAME :조립 경주차 경주 레이서 +STR_DESC :하나의 레일로 이루어진 롤러코스터 트랙을 이동하는 조립 경주차 모양의 차량 +STR_CPTY :차량당 4명의 승객 + +[SCHT1] +STR_NAME :롤러코스터 차량 +STR_DESC :무릎 안전바가 있으며 수직 루프를 돌 수 있는 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[SFRIC1] +STR_NAME :우든 사이드 프릭션 차량 +STR_DESC :사이드 프릭션 롤러코스터를 위한 기본 차량 +STR_CPTY :차량당 4명의 승객 + +[SKYTR] +STR_NAME :미니 서스펜디드 플라잉 코스터 +STR_DESC :하나의 레일로 이루어진 트랙에 매달린 특수 차량에 얼굴을 아래로 한 자세로 타고 코너를 돌 때마다 이리 저리 자유롭게 흔들리는 차량 +STR_CPTY :차량당 승객 1명 + +[SLCFO] +STR_NAME :인버티드 셔틀 코스터 +STR_DESC :앞쪽이나 뒤쪽을 보고 2명씩 짝지어 앉아 루프와 트위스트와 급격한 전이 트랙을 지나는 차량 +STR_CPTY :차량당 4명의 승객 + +[SLCT] +STR_NAME :컴팩트 인버티드 코스터 +STR_DESC :트랙 밑에 매달린 좌석에 2명씩 짝지어 앉아 루프와 트위스트와 급격한 전이 트랙을 지나는 차량 +STR_CPTY :차량당 2명의 승객 + +[SMC1] +STR_NAME :쥐 차량 +STR_DESC :쥐처럼 생긴 개별 차량 +STR_CPTY :차량당 4명의 승객 + +[SMC2] +STR_NAME :탄광 차량 +STR_DESC :나무 탄광 트럭처럼 생긴 개별 차량 +STR_CPTY :차량당 4명의 승객 + +[SPDRCR] +STR_NAME :스파이럴 롤러코스터 +STR_DESC :한 줄로 된 좌석과 나선형 리프트 힐이 있는, 짜임새 있는 강철 트랙 롤러코스터 +STR_CPTY :차량당 6명의 승객 + +[STEEP1] +STR_NAME :스티플체이스 +STR_DESC :단선 롤러코스터 트랙을 따라 달리는 말 모양의 차량에 탑승하는 놀이기구 +STR_CPTY :차량당 2명의 승객 + +[STEEP2] +STR_NAME :모터바이크 레이스 +STR_DESC :단선 롤러코스터 트랙을 따라 달리는 오토바이 모양의 차량에 탑승하는 놀이기구 +STR_CPTY :자전거당 2명의 승객 + +[THCAR] +STR_NAME :에어 파워드 버티컬 코스터 +STR_DESC :아주 짜릿한 공기 압축 방식으로 발진하여 차량이 수직 트랙을 향해 속력을 높인 뒤, 꼭대기에 다다르면 다시 수직으로 하강하며 다시 탑승장에 도착하는 놀이기구 +STR_CPTY :차량당 2명의 승객 + +[TOGST] +STR_NAME :스탠드 업 롤러코스터 +STR_DESC :손님이 일어선 자세로 탑승하는 루핑 롤러코스터 +STR_CPTY :차량당 4명의 승객 + +[UTCAR] +STR_NAME :트위스터 차량 +STR_DESC :하트라인 트위스트에 적합한 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[UTCARR] +STR_NAME :트위스터 차량 (역방향) +STR_DESC :하트라인 트위스트에 적합한 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[VEKDV] +STR_NAME :인버티드 버티컬 셔틀 +STR_DESC :트랙 밑에 매달린 차량에 앉아서, 수직 트랙을 따라 뒤쪽 방향으로 올라간 다음 루프와 트위스트를 향해 낙하하는 놀이기구 +STR_CPTY :차량당 4명의 승객 + +[VEKST] +STR_NAME :레이 다운 롤러코스터 +STR_DESC :누운 자세로 탑승하는 특수 차량에 탑승하여 꼬인 트랙과 전이를 앞이나 뒤로 누운 자세로 즐기는 놀이기구 +STR_CPTY :차량당 4명의 승객 + +[VEKVAMP] +STR_NAME :스윙잉 플로어리스 차량 +STR_DESC :코너를 돌면 차량이 자유롭게 흔들리고, 체어 리프트 스타일의 좌석이 있는 매달린 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[VREEL] +STR_NAME :버지니아 릴 +STR_DESC :나무 트랙을 이리 저리 따라 이동함에 따라 빙글빙글 돌아가는 원형 차량 +STR_CPTY :차량당 4명의 승객 + +[WCATC] +STR_NAME :자동차 차량 +STR_DESC :자동차 모양의 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[WMMINE] +STR_NAME :우든 와일드 광산 차량 +STR_DESC :지그재그 모양의 나무 트랙을 달리면서 급격한 커브와 낙하를 통과하면 트랙을 벗어날 듯 위태롭게 기울어지는 작은 광산 트럭. +STR_CPTY :차량당 2명의 승객 + +[WMOUSE] +STR_NAME :우든 와일드 마우스 +STR_DESC :나무 트랙 위를 달리면서 급격한 헤어핀 코너와 급등·급락을 지나면서 트랙을 벗어날 듯 위태롭게 기울어지는 작은 쥐 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[WMSPIN] +STR_NAME :회전 와일드 마우스 +STR_DESC :급격한 코너와 짧은 낙하를 지나면서 속도를 내고, 차량의 부드러운 회전이 탑승객의 방향 감각을 잃게 만드는 쥐 모양의 차량 +STR_CPTY :차량당 4명의 승객 + +[ZLDB] +STR_NAME :무당벌레 차량 +STR_DESC :작은 무당벌레 모양의 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[ZLOG] +STR_NAME :통나무 차량 +STR_DESC :작은 통나무 모양의 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[C3D] +STR_NAME :3D 영화관 +STR_DESC :둥근 구 모양의 건물 안에서 3D 영화를 상영하는 영화관 +STR_CPTY :손님 20명 + +[ENTERP] +STR_NAME :엔터프라이즈 +STR_DESC :원형 놀이기구에 매달린 객실에 탑승하면 처음에 회전하기 시작하여 이후에 지지대에 의해 기울어진 채로 회전하는 놀이기구 +STR_CPTY :승객 16명 + +[GDROP1] +STR_NAME :자이로드롭 +STR_DESC :고리 모양의 좌석이 부드럽게 회전하면서 탑 꼭대기로 들어올려진 뒤에 자유낙하하고, 자기 제동에 의해 바닥에 부드럽게 정지하는 놀이기구 +STR_CPTY :승객 16명 + +[KART1] +STR_NAME :고 카트 +STR_DESC :스스로 운전하는 페트롤 엔진의 고 카트 +STR_CPTY :1인승 + +[MCARPET1] +STR_NAME :마법의 양탄자 +STR_DESC :양쪽 끝에 있는 4개의 관절 구조에 의해 원형으로 오르락 내리락하는 커다란 마법 양탄자 테마의 차량 +STR_CPTY :승객 12명 + +[SIMPOD] +STR_NAME :모션 시뮬레이터 +STR_DESC :수압식 관절에 의해 흔들리고 움직이는 모션 시뮬레이터 안에서 영화를 보는 놀이기구 +STR_CPTY :승객 8명 + +[SSC1] +STR_NAME :런치드 프리폴 +STR_DESC :압축 공기에 의해 높은 철제 탑을 향해 쏘아올려진 다음 자유 낙하하는 자유 낙하 차량 +STR_CPTY :승객 8명 + +[SWSH1] +STR_NAME :바이킹 +STR_DESC :흔들리는 거대한 해적선 +STR_CPTY :승객 16명 + +[SWSH2] +STR_NAME :360도 바이킹 +STR_DESC :반대편에 균형추가 있는 지지대에 달려있어 완전히 360도로 회전하는 배 모양의 놀이기구 +STR_CPTY :승객 12명 + +[TOPSP1] +STR_NAME :톱 스핀 +STR_DESC :대형 회전 팔 구조에 매달려있고 앞뒤로 공중제비를 도는 곤돌라에 탑승하는 놀이기구 +STR_CPTY :승객 8명 + +[TWIST1] +STR_NAME :트위스트 +STR_DESC :탑승객이 세 개의 긴 회전 팔 구조 끝에 있는 좌석에 짝지어 앉아 빙글빙글 도는 놀이기구 +STR_CPTY :승객 18명 + +[TWIST2] +STR_NAME :스노우 컵 +STR_DESC :탑승객이 짝지어 좌석에 앉아 눈사람을 기준으로 빙글빙글 도는 놀이기구 +STR_CPTY :승객 18명 + +[BBOAT] +STR_NAME :범퍼 보트 +STR_DESC :중앙 모터에 의해 움직이며 탑승객이 조종할 수 있는 원형의 작은 보트 +STR_CPTY :보트당 2명의 승객 + +[CBOAT] +STR_NAME :카누 +STR_DESC :탑승객이 스스로 페달을 밟는 긴 카누 +STR_CPTY :카누당 2명의 승객 + +[CSTBOAT] +STR_NAME :코스터 보트 +STR_DESC :보트 모양의 롤러코스터 차량 +STR_CPTY :보트당 6명의 승객 + +[DING1] +STR_NAME :보트 슬라이드 +STR_DESC :반원형 또는 밀폐형 원형 튜브 트랙을 따라 이동하는 공기 주입식 고무 보트 +STR_CPTY :보트당 2명의 승객 + +[JSKI] +STR_NAME :제트 스키 +STR_DESC :탑승객이 스스로 운전할 수 있는 단일 좌석의 제트 스키 +STR_CPTY :차량당 1명의 탑승자 + +[LFB1] +STR_NAME :통나무 수로 +STR_DESC :수로를 따라 이동하다가 긴 낙하를 지나며 물을 튀겨 탑승객을 홀딱 젖게 만드는 통나무 모양의 보트 +STR_CPTY :보트당 4명의 승객 + +[RAPBOAT] +STR_NAME :리버 래피드 +STR_DESC :구불구불한 광폭형 수로를 따라 이동하다가 폭포를 통과하면서 탑승객을 젖게 만들고, 거품 급류를 지나며 스릴을 선사하는 원형 보트 +STR_CPTY :보트당 8명의 승객 + +[RBOAT] +STR_NAME :보트 대여 +STR_DESC :탑승객들이 스스로 노를 저을 수 있는 보트 +STR_CPTY :보트당 2명의 승객 + +[RFTBOAT] +STR_NAME :리버 래프트 +STR_DESC :구불구불한 강 모양의 트랙을 따라 얌전히 이동하는 뗏목 모양의 보트 +STR_CPTY :래프트당 4명의 승객 + +[SPBOAT] +STR_NAME :스플래시 보트 +STR_DESC :광폭형 수로를 따라 이동하며 컨베이어 벨트로 경사를 오른 다음, 급경사로 가속하여 탑승객을 커다란 물보라로 홀딱 젖게 만드는 대용량의 보트 +STR_CPTY :보트당 16명의 승객 + +[SWANS] +STR_NAME :백조 보트 +STR_DESC :앞쪽 좌석의 탑승객이 페달을 직접 밟아 움직이는 백조 모양의 보트 +STR_CPTY :보트당 4명의 승객 + +[TRIKE] +STR_NAME :수중 세발자전거 +STR_DESC :물에 뜨는 바퀴를 가진 페달 달린 세발자전거 +STR_CPTY :세발자전거당 2명의 승객 + +[ATM1] +STR_NAME :ATM 기기 +STR_DESC :손님들이 가진 돈이 떨어졌을 때 돈을 찾을 수 있는 ATM 기기 + +[BALLN] +STR_NAME :풍선 가게 +STR_DESC :헬륨이 든 풍선을 파는 기념품 가게 + +[BNOODLES] +STR_NAME :고기 국수 가게 +STR_DESC :중국식 고기 국수를 파는 가게 + +[BURGB] +STR_NAME :햄버거 가게 +STR_DESC :햄버거를 파는 햄버거 모양의 건물 + +[CHCKS] +STR_NAME :프라이드 치킨 가게 +STR_DESC :프라이드 치킨 한 통을 파는 가게 + +[CHKNUG] +STR_NAME :치킨 너겟 가게 +STR_DESC :프라이드 치킨 너겟을 파는 가게 + +[CHPSH] +STR_NAME :감자칩 가게 +STR_DESC :감자칩을 파는 가게 + +[CHPSH2] +STR_NAME :감자튀김 가게 +STR_DESC :감자튀김을 파는 가게 + +[CINDR] +STR_NAME :수정과 가게 +STR_DESC :한국식 수정과를 파는 가게 + +[CNDYF] +STR_NAME :솜사탕 가게 +STR_DESC :분홍색 솜사탕을 파는 솜사탕 모양의 건물 + +[COFFS] +STR_NAME :커피 가게 +STR_DESC :커피 한 잔을 파는 예술적인 모습의 상점 + +[COOKST] +STR_NAME :쿠키 가게 +STR_DESC :커다란 쿠키를 파는 가게 + +[DOUGH] +STR_NAME :도넛 가게 +STR_DESC :도넛을 파는 가게 + +[DRNKS] +STR_NAME :음료수 가게 +STR_DESC :탄산음료를 파는 캔 모양의 상점 + +[FAID1] +STR_NAME :응급 치료소 +STR_DESC :속이 메스꺼운 손님들이 빨리 회복할 수 있는 장소 + +[FRNOOD] +STR_NAME :튀김 쌀국수 가게 +STR_DESC :중국식 튀김 쌀국수를 파는 가게 + +[FUNCAKE] +STR_NAME :휜넬 케이크 가게 +STR_DESC :휜넬 케이크를 파는 가게 + +[HATST] +STR_NAME :모자 가게 +STR_DESC :품이 큰 모자를 파는 기념품 가게 + +[HCHOC] +STR_NAME :핫초코 가게 +STR_DESC :핫초코 음료를 파는 가게 + +[HOTDS] +STR_NAME :핫도그 가게 +STR_DESC :핫도그를 파는 가게 + +[ICECR1] +STR_NAME :과일 아이스크림 가게 +STR_DESC :과일 아이스크림을 파는 가게 + +[ICECR2] +STR_NAME :아이스크림 콘 가게 +STR_DESC :아이스크림 콘을 파는 가게 + +[ICETST] +STR_NAME :아이스티 가게 +STR_DESC :아이스티 음료를 파는 가게 + +[INFOK] +STR_NAME :안내소 +STR_DESC :손님들이 공원 지도를 얻거나 우산을 살 수 있는 상점 + +[LEMST] +STR_NAME :레모네이드 가게 +STR_DESC :신선한 레모네이드 음료를 파는 가게 + +[MBSOUP] +STR_NAME :고기 완자탕 가게 +STR_DESC :중국식 고기 완자탕을 파는 가게 + +[PIZZS] +STR_NAME :피자 가게 +STR_DESC :피자 조각을 파는 가게 + +[POPCS] +STR_NAME :팝콘 가게 +STR_DESC :팝콘 한 바구니를 가득 채워 파는 가게 + +[PRETST] +STR_NAME :프레첼 가게 +STR_DESC :바삭한 프레첼을 파는 가게 + +[RSAUS] +STR_NAME :구운 소시지 가게 +STR_DESC :중국식 구운 소시지를 파는 가게 + +[SOUVS] +STR_NAME :기념품 상점 +STR_DESC :귀여운 장난감 기념품과 우산을 파는 가게 + +[SOYBEAN] +STR_NAME :두유 가게 +STR_DESC :두유 곽을 파는 가게 + +[SQDST] +STR_NAME :해산물 가게 +STR_DESC :구운 문어 다리를 파는 가게 + +[STARFRDR] +STR_NAME :스타프루트 음료 가게 +STR_DESC :스타푸르트 음료를 파는 가게 + +[SUBSTL] +STR_NAME :샌드위치 가게 +STR_DESC :신선한 서브마린 샌드위치를 파는 가게 + +[SUNGST] +STR_NAME :선글라스 가게 +STR_DESC :다양한 종류의 선글라스를 파는 가게 + +[TLT1] +STR_NAME :화장실 +STR_DESC :조립식 콘크리트 건물 안에 있는 기본형 화장실 + +[TLT2] +STR_NAME :화장실 +STR_DESC :통나무 객실 형 건물 안에 있는 화장실 + +[TOFFS] +STR_NAME :사과 토피 사탕 가게 +STR_DESC :사과 토피 사탕을 막대기에 꽂아 파는 사과 모양의 가게 + +[TSHRT] +STR_NAME :티셔츠 가게 +STR_DESC :티셔츠 기념품을 판매하는 가게 + +[WONTON] +STR_NAME :만둣국 가게 +STR_DESC :만둣국을 파는 가게 + +[ALLSORT1] +STR_NAME :사탕 + +[ALLSORT2] +STR_NAME :사탕 + +[BADSHUT] +STR_NAME :셔틀콕 + +[BADSHUT2] +STR_NAME :셔틀콕 + +[BALL1] +STR_NAME :미식축구 + +[BALL2] +STR_NAME :미식축구 + +[BALL3] +STR_NAME :축구 + +[BALL4] +STR_NAME :테니스 공 + +[BEANST1] +STR_NAME :대형 강낭콩 줄기 + +[BEANST2] +STR_NAME :대형 강낭콩 줄기 + +[BRBASE] +STR_NAME :기본 블록 + +[BRBASE2] +STR_NAME :기본 블록 + +[BRBASE3] +STR_NAME :기본 블록 + +[BRCRRF1] +STR_NAME :곡선형 지붕 + +[BRCRRF2] +STR_NAME :곡선형 지붕 + +[CARROT] +STR_NAME :대형 당근 + +[CHBBASE] +STR_NAME :체스판 블록 + +[CHEST1] +STR_NAME :보물 상자 + +[CHEST2] +STR_NAME :보물 상자 + +[CHOCROOF] +STR_NAME :초콜릿 바 + +[CNBALLS] +STR_NAME :대포알 + +[CNDYRK1] +STR_NAME :사탕 스틱 + +[COLAGUM] +STR_NAME :콜라 사탕 + +[CORROOF] +STR_NAME :물결 무늬 강철 지붕 + +[CORROOF2] +STR_NAME :물결 무늬 강철 기반 + +[CWBCRV32] +STR_NAME :곡선형 벽 + +[CWBCRV33] +STR_NAME :곡선형 블록 + +[CWFCRV32] +STR_NAME :곡선형 벽 + +[CWFCRV33] +STR_NAME :곡선형 블록 + +[FERN1] +STR_NAME :대형 양치식물 + +[GGRS1] +STR_NAME :대형 풀 + +[HANG1] +STR_NAME :교수대 + +[HELMET1] +STR_NAME :아메리칸 풋볼 헬멧 + +[ICECUBE] +STR_NAME :얼음 큐브 + +[IGROOF] +STR_NAME :이글루 천장 + +[JBEAN1] +STR_NAME :젤리빈 + +[JELBAB1] +STR_NAME :젤리빈 + +[JELDROP1] +STR_NAME :떨어진 젤리 + +[JELDROP2] +STR_NAME :떨어진 젤리 + +[JNGROOF1] +STR_NAME :천장 + +[LOLLY1] +STR_NAME :막대 사탕 + +[MALLOW1] +STR_NAME :마시멜로 + +[MALLOW2] +STR_NAME :마시멜로 + +[MINROOF1] +STR_NAME :천장 + +[MINT1] +STR_NAME :민트 + +[MMENT1] +STR_NAME :장식용 구조물 + +[MMENT2] +STR_NAME :장식용 구조물 + +[MMENT3] +STR_NAME :장식용 구조물 + +[PAGROOF1] +STR_NAME :천장 + +[PIPE32] +STR_NAME :파이프 섹션 + +[PIPE32J] +STR_NAME :파이프 섹션 + +[PIPE8] +STR_NAME :파이프 섹션 + +[PIRFLAG] +STR_NAME :해적 깃발 + +[PIRROOF1] +STR_NAME :천장 + +[PIRROOF2] +STR_NAME :천장 + +[PRCAN] +STR_NAME :대포 + +[ROMROOF1] +STR_NAME :천장 + +[ROMROOF2] +STR_NAME :주춧돌 + +[ROOF1] +STR_NAME :천장 + +[ROOF10] +STR_NAME :천장 + +[ROOF11] +STR_NAME :천장 + +[ROOF12] +STR_NAME :천장 + +[ROOF13] +STR_NAME :천장 + +[ROOF14] +STR_NAME :천장 + +[ROOF2] +STR_NAME :천장 + +[ROOF3] +STR_NAME :천장 + +[ROOF4] +STR_NAME :천장 + +[ROOF5] +STR_NAME :천장 + +[ROOF6] +STR_NAME :천장 + +[ROOF7] +STR_NAME :천장 + +[ROOF8] +STR_NAME :천장 + +[ROOF9] +STR_NAME :천장 + +[SKTBASE] +STR_NAME :블록 + +[SKTBASET] +STR_NAME :블록 + +[SKTDW] +STR_NAME :벽 + +[SKTDW2] +STR_NAME :벽 + +[SMSKULL] +STR_NAME :뼈 + +[SPCROOF1] +STR_NAME :천장 + +[STBASE] +STR_NAME :강철 블록 + +[STLBASET] +STR_NAME :강철 블록 + +[STLDW] +STR_NAME :강철 벽 + +[STLDW2] +STR_NAME :강철 벽 + +[SUMRF] +STR_NAME :천장 + +[SUPPLEG1] +STR_NAME :막대기 + +[SUPPLEG2] +STR_NAME :막대기 + +[SUPPW1] +STR_NAME :지지대 구조물 + +[SUPPW2] +STR_NAME :지지대 구조물 + +[SUPPW3] +STR_NAME :지지대 구조물 + +[TAC] +STR_NAME :애리조나삼목 + +[TAL] +STR_NAME :악어 모양의 나무 + +[TAP] +STR_NAME :알레포 파인 나무 + +[TAS] +STR_NAME :사시나무 + +[TAS1] +STR_NAME :사탕 나무 + +[TAS2] +STR_NAME :사탕 나무 + +[TAS3] +STR_NAME :사탕 나무 + +[TAS4] +STR_NAME :사탕 + +[TB1] +STR_NAME :흰색 비숍 + +[TB2] +STR_NAME :검은색 비숍 + +[TBC] +STR_NAME :선인장 + +[TBN] +STR_NAME :뼈 + +[TBN1] +STR_NAME :뼈 + +[TBP] +STR_NAME :흑양목 + +[TBR] +STR_NAME :부들 + +[TBR1] +STR_NAME :통 + +[TBR2] +STR_NAME :통 + +[TBR3] +STR_NAME :통 + +[TBR4] +STR_NAME :통 + +[TBW] +STR_NAME :부서진 바퀴 + +[TCB] +STR_NAME :클럽스 모양 나무 + +[TCC] +STR_NAME :중국 삼나무 + +[TCD] +STR_NAME :가마솥 + +[TCE] +STR_NAME :캠퍼다운 느릅나무 + +[TCF] +STR_NAME :코카시안 전나무 + +[TCFS] +STR_NAME :눈 쌓인 코카시안 전나무 + +[TCJ] +STR_NAME :노간주나무 + +[TCL] +STR_NAME :레바논삼목 + +[TCN] +STR_NAME :대포 + +[TCO] +STR_NAME :참나무 + +[TCRP] +STR_NAME :코르시카 소나무 + +[TCT] +STR_NAME :캐비지 야자 + +[TCT1] +STR_NAME :성 탑 + +[TCT2] +STR_NAME :성 탑 + +[TCY] +STR_NAME :주목 + +[TDM] +STR_NAME :다이아몬드 모양 나무 + +[TDN4] +STR_NAME :공룡 + +[TDN5] +STR_NAME :공룡 + +[TDT1] +STR_NAME :죽은 나무 + +[TDT2] +STR_NAME :죽은 나무 + +[TDT3] +STR_NAME :죽은 나무 + +[TEEPEE1] +STR_NAME :원뿔형 천막 + +[TEL] +STR_NAME :유럽 낙엽송 + +[TEN] +STR_NAME :클레오파트라의 바늘 + +[TEP] +STR_NAME :이집트식 기둥 + +[TERB] +STR_NAME :돌 블록 + +[TERS] +STR_NAME :부서진 동상 + +[TES1] +STR_NAME :이집트 동상 + +[TF1] +STR_NAME :과일 나무 + +[TF2] +STR_NAME :과일 나무 + +[TGC1] +STR_NAME :조각품 + +[TGC2] +STR_NAME :조각품 + +[TGG] +STR_NAME :징 + +[TGHC] +STR_NAME :골든 노송나무 + +[TGHC2] +STR_NAME :히바 + +[TGS] +STR_NAME :기린 동상 + +[TGS1] +STR_NAME :묘비 + +[TGS2] +STR_NAME :묘비 + +[TGS3] +STR_NAME :묘비 + +[TGS4] +STR_NAME :묘비 + +[TH1] +STR_NAME :카나리아 야자수 + +[TH2] +STR_NAME :야자수 + +[THL] +STR_NAME :수엽나무 + +[THRS] +STR_NAME :말을 탄 사람 동상 + +[THT] +STR_NAME :하트 모양 나무 + +[TIC] +STR_NAME :미국 삼나무 + +[TIG] +STR_NAME :이글루 + +[TITC] +STR_NAME :서양노송나무 + +[TJB1] +STR_NAME :수풀 + +[TJB2] +STR_NAME :수풀 + +[TJB3] +STR_NAME :수풀 + +[TJB4] +STR_NAME :수풀 + +[TJF] +STR_NAME :꽃 + +[TJP1] +STR_NAME :잡초 + +[TJP2] +STR_NAME :잡초 + +[TJT1] +STR_NAME :나무 + +[TJT2] +STR_NAME :나무 + +[TJT3] +STR_NAME :나무 + +[TJT4] +STR_NAME :나무 + +[TJT5] +STR_NAME :나무 + +[TJT6] +STR_NAME :나무 + +[TK1] +STR_NAME :흰색 나이트 + +[TK2] +STR_NAME :검은색 나이트 + +[TK3] +STR_NAME :흰색 킹 + +[TK4] +STR_NAME :검은색 킹 + +[TL0] +STR_NAME :나무 + +[TL1] +STR_NAME :나무 + +[TL2] +STR_NAME :나무 + +[TL3] +STR_NAME :나무 + +[TLC] +STR_NAME :로슨 노송나무 + +[TLP] +STR_NAME :양버들 + +[TLY] +STR_NAME :백합 + +[TM0] +STR_NAME :나무 + +[TM1] +STR_NAME :나무 + +[TM2] +STR_NAME :나무 + +[TM3] +STR_NAME :나무 + +[TMBJ] +STR_NAME :메이어 향나무 + +[TMC] +STR_NAME :왕느릅나무 + +[TMG] +STR_NAME :목련 + +[TMJ] +STR_NAME :잔해 + +[TML] +STR_NAME :나무 + +[TMM1] +STR_NAME :묘지 기념물 + +[TMM2] +STR_NAME :묘지 기념비 + +[TMM3] +STR_NAME :묘지 기념비 + +[TMO1] +STR_NAME :화성 물체 + +[TMO2] +STR_NAME :화성 물체 + +[TMO3] +STR_NAME :화성 물체 + +[TMO4] +STR_NAME :화성 물체 + +[TMO5] +STR_NAME :화성 물체 + +[TMP] +STR_NAME :칠레삼나무 + +[TMS1] +STR_NAME :독버섯 + +[TMW] +STR_NAME :바퀴 + +[TMZP] +STR_NAME :몬테수마 소나무 + +[TNS] +STR_NAME :노르웨이 가문비나무 + +[TNSS] +STR_NAME :눈 덮인 노르웨이 가문비나무 + +[TNTROOF1] +STR_NAME :천막 지붕 + +[TOH1] +STR_NAME :집 + +[TOH2] +STR_NAME :집 + +[TOH3] +STR_NAME :건물 + +[TORN1] +STR_NAME :장식용 나무 + +[TORN2] +STR_NAME :장식용 나무 + +[TOS] +STR_NAME :동상 + +[TOT1] +STR_NAME :나무 + +[TOT2] +STR_NAME :나무 + +[TOT3] +STR_NAME :나무 + +[TOT4] +STR_NAME :나무 + +[TOTEM1] +STR_NAME :토템 폴 + +[TP1] +STR_NAME :흰색 폰 + +[TP2] +STR_NAME :검은색 폰 + +[TPM] +STR_NAME :야자수 + +[TQ1] +STR_NAME :흰색 퀸 + +[TQ2] +STR_NAME :검은색 퀸 + +[TR1] +STR_NAME :하얀색 룩 + +[TR2] +STR_NAME :검은색 룩 + +[TRC] +STR_NAME :로마식 기둥 + +[TRF] +STR_NAME :붉은잣나무 + +[TRF2] +STR_NAME :붉은잣나무 + +[TRF3] +STR_NAME :눈 쌓인 붉은잣나무 + +[TRFS] +STR_NAME :눈 쌓인 붉은잣나무 + +[TRMS] +STR_NAME :로마식 동상 + +[TROPT1] +STR_NAME :나무 + +[TRWS] +STR_NAME :로마식 동상 + +[TS0] +STR_NAME :나무 + +[TS1] +STR_NAME :나무 + +[TS2] +STR_NAME :나무 + +[TS3] +STR_NAME :나무 + +[TS4] +STR_NAME :장식용 나무 + +[TS5] +STR_NAME :장식용 나무 + +[TS6] +STR_NAME :장식용 나무 + +[TSB] +STR_NAME :자작나무 + +[TSC] +STR_NAME :선인장 + +[TSC2] +STR_NAME :건물 + +[TSCP] +STR_NAME :우주 캡슐 + +[TSD] +STR_NAME :스페이드 모양의 나무 + +[TSF1] +STR_NAME :대형 눈송이 + +[TSF2] +STR_NAME :대형 눈송이 + +[TSF3] +STR_NAME :대형 눈송이 + +[TSH] +STR_NAME :말 동상 + +[TSH0] +STR_NAME :수풀 + +[TSH1] +STR_NAME :관목 + +[TSH2] +STR_NAME :수풀 + +[TSH3] +STR_NAME :수풀 + +[TSH4] +STR_NAME :관목 + +[TSH5] +STR_NAME :수풀 + +[TSM] +STR_NAME :눈사람 + +[TSNB] +STR_NAME :눈덩이 + +[TSNC] +STR_NAME :통나무 집 + +[TSP] +STR_NAME :스코틀랜드 소나무 + +[TSP1] +STR_NAME :나무 + +[TSP2] +STR_NAME :나무 + +[TSPH] +STR_NAME :집 + +[TSQ] +STR_NAME :다람쥐 모양의 나무 + +[TST1] +STR_NAME :독버섯 + +[TST2] +STR_NAME :독버섯 + +[TST3] +STR_NAME :독버섯 + +[TST4] +STR_NAME :독버섯 + +[TST5] +STR_NAME :독버섯 + +[TSTD] +STR_NAME :돌고래 동상 + +[TT1] +STR_NAME :로마 사원 + +[TTG] +STR_NAME :과녁 + +[TUS] +STR_NAME :유니콘 동상 + +[TVL] +STR_NAME :나도싸리 + +[TWH1] +STR_NAME :집 + +[TWH2] +STR_NAME :호박 집 + +[TWN] +STR_NAME :호두나무 + +[TWP] +STR_NAME :사시나무 + +[TWW] +STR_NAME :수양버들 + +[WAG1] +STR_NAME :마차 + +[WAG2] +STR_NAME :마차 + +[WDBASE] +STR_NAME :나무 블록 + +[TDF] +STR_NAME :돌고래 분수 + +[TEF] +STR_NAME :코끼리 분수 + +[TQF] +STR_NAME :큐피드 분수 + +[TTF] +STR_NAME :분수 + +[TWF] +STR_NAME :기하학적인 분수 + +[TCK] +STR_NAME :시계 + +[TG1] +STR_NAME :꽃 + +[TG10] +STR_NAME :꽃 + +[TG11] +STR_NAME :꽃 + +[TG12] +STR_NAME :꽃 + +[TG13] +STR_NAME :꽃 + +[TG14] +STR_NAME :꽃 + +[TG15] +STR_NAME :꽃 + +[TG16] +STR_NAME :꽃 + +[TG17] +STR_NAME :꽃 + +[TG18] +STR_NAME :꽃 + +[TG19] +STR_NAME :꽃 + +[TG2] +STR_NAME :꽃 + +[TG20] +STR_NAME :꽃 + +[TG21] +STR_NAME :꽃 + +[TG3] +STR_NAME :꽃 + +[TG4] +STR_NAME :꽃 + +[TG5] +STR_NAME :꽃 + +[TG6] +STR_NAME :꽃 + +[TG7] +STR_NAME :꽃 + +[TG8] +STR_NAME :꽃 + +[TG9] +STR_NAME :꽃 + +[BUTTFLY] +STR_NAME :나비 + +[COG1] +STR_NAME :톱니바퀴 + +[COG1R] +STR_NAME :톱니바퀴 + +[COG1U] +STR_NAME :톱니바퀴 + +[COG1UR] +STR_NAME :톱니바퀴 + +[COG2] +STR_NAME :작은 톱니바퀴 + +[COG2R] +STR_NAME :작은 톱니바퀴 + +[COG2U] +STR_NAME :작은 톱니바퀴 + +[COG2UR] +STR_NAME :작은 톱니바퀴 + +[FIRE1] +STR_NAME :불꽃 + +[SNAIL] +STR_NAME :달팽이 + +[SPIDER1] +STR_NAME :거미 + +[TGH1] +STR_NAME :동상 + +[TGH2] +STR_NAME :동상 + +[TSG] +STR_NAME :늪지대 + +[TSK] +STR_NAME :해골 + +[TSMP] +STR_NAME :호박 + +[WASP] +STR_NAME :말벌 + +[WDIAG] +STR_NAME :분수 + +[WHORIZ] +STR_NAME :물 분사 + +[WSPOUT] +STR_NAME :물 분출 + +[GEOROOF1] +STR_NAME :유리 지붕 + +[GEOROOF2] +STR_NAME :유리 지붕 + +[TGE1] +STR_NAME :기하학적인 조형물 + +[TGE2] +STR_NAME :기하학적인 조형물 + +[TGE3] +STR_NAME :기하학적인 조형물 + +[TGE4] +STR_NAME :기하학적인 조형물 + +[TGE5] +STR_NAME :기하학적인 조형물 + +[BADRACK] +STR_NAME :배드민턴 라켓 + +[GENSTORE] +STR_NAME :일반 상점 + +[MDSAENT] +STR_NAME :'메두사' 팻말 + +[NITROENT] +STR_NAME :'니트로' 팻말 + +[SAH] +STR_NAME :집 + +[SAH2] +STR_NAME :집 + +[SAH3] +STR_NAME :다세대 주택 + +[SALOON] +STR_NAME :주점 + +[SCLN] +STR_NAME :콜로네이드 + +[SCT] +STR_NAME :텐트 + +[SDN1] +STR_NAME :공룡 + +[SDN2] +STR_NAME :공룡 + +[SDN3] +STR_NAME :공룡 + +[SGP] +STR_NAME :대형 호박 + +[SHS1] +STR_NAME :테라스 하우스 + +[SHS2] +STR_NAME :집 + +[SMH1] +STR_NAME :탄광 건물 + +[SMH2] +STR_NAME :탄광 건물 + +[SMN1] +STR_NAME :갱도 + +[SOB] +STR_NAME :사무 빌딩 + +[SOH1] +STR_NAME :집 + +[SOH2] +STR_NAME :집 + +[SOH3] +STR_NAME :집 + +[SPS] +STR_NAME :주유소 + +[SSH] +STR_NAME :우주 캡슐 + +[SSK1] +STR_NAME :해골 + +[SST] +STR_NAME :위성 + +[STB1] +STR_NAME :성탑 + +[STB2] +STR_NAME :성탑 + +[STG1] +STR_NAME :성탑 + +[STG2] +STR_NAME :성탑 + +[STH] +STR_NAME :시청 + +[TAVERN] +STR_NAME :터번 + +[WWBANK] +STR_NAME :은행 + +[SSIG2] +STR_NAME :3D 팻말 + +[SSIG3] +STR_NAME :수직 3D 팻말 + +[SSIG4] +STR_NAME :3D 팻말 + +[SSIG1] +STR_NAME :스크롤링 전광판 + +[GLTHENT] +STR_NAME :'골리앗' 팻말 + +[PRSHIP] +STR_NAME :해적선 + +[SCOL] +STR_NAME :로마 콜로세움 + +[SIP] +STR_NAME :얼음성 + +[SMB] +STR_NAME :화성 건물 + +[SPG] +STR_NAME :탑 + +[SPYR] +STR_NAME :피라미드 + +[SSPX] +STR_NAME :스핑크스 + +[SSR] +STR_NAME :우주 로켓 + +[SVLC] +STR_NAME :화산 + +[WALLBADM] +STR_NAME :배드민턴 라켓 + +[WALLBB16] +STR_NAME :벽 + +[WALLBB32] +STR_NAME :벽 + +[WALLBB33] +STR_NAME :벽 + +[WALLBB34] +STR_NAME :돌 벽 + +[WALLBB8] +STR_NAME :벽 + +[WALLBR16] +STR_NAME :벽 + +[WALLBR32] +STR_NAME :벽 + +[WALLBR8] +STR_NAME :벽 + +[WALLBRWN] +STR_NAME :창문 + +[WALLCB16] +STR_NAME :벽 + +[WALLCB32] +STR_NAME :벽 + +[WALLCB8] +STR_NAME :벽 + +[WALLCBWN] +STR_NAME :창문 + +[WALLCF16] +STR_NAME :벽 + +[WALLCF32] +STR_NAME :벽 + +[WALLCF8] +STR_NAME :벽 + +[WALLCFAR] +STR_NAME :벽 아치 + +[WALLCFWN] +STR_NAME :창문 + +[WALLCO16] +STR_NAME :물결 무늬 강철 벽 + +[WALLCW32] +STR_NAME :벽 + +[WALLCX32] +STR_NAME :벽 + +[WALLCY32] +STR_NAME :벽 + +[WALLCZ32] +STR_NAME :벽 + +[WALLIG16] +STR_NAME :이글루 벽 + +[WALLIG24] +STR_NAME :이글루 벽 + +[WALLJB16] +STR_NAME :젤리빈 벽 + +[WALLJN32] +STR_NAME :벽 + +[WALLLT32] +STR_NAME :강철 격자 + +[WALLMM16] +STR_NAME :철책 + +[WALLMM17] +STR_NAME :철책 + +[WALLMN32] +STR_NAME :벽 + +[WALLNT32] +STR_NAME :테니스 네트 벽 + +[WALLNT33] +STR_NAME :테니스 네트 벽 + +[WALLPG32] +STR_NAME :벽 + +[WALLPOST] +STR_NAME :기둥 + +[WALLPR32] +STR_NAME :지붕 + +[WALLPR33] +STR_NAME :벽 + +[WALLPR34] +STR_NAME :벽 + +[WALLPR35] +STR_NAME :벽 + +[WALLRH32] +STR_NAME :벽 + +[WALLRK32] +STR_NAME :바위 벽 + +[WALLRS16] +STR_NAME :벽 + +[WALLRS32] +STR_NAME :벽 + +[WALLRS8] +STR_NAME :벽 + +[WALLSC16] +STR_NAME :철책 + +[WALLSK16] +STR_NAME :벽 + +[WALLSK32] +STR_NAME :벽 + +[WALLSP32] +STR_NAME :벽 + +[WALLST16] +STR_NAME :강철 벽 + +[WALLST32] +STR_NAME :강철 벽 + +[WALLST8] +STR_NAME :강철 벽 + +[WALLSTFN] +STR_NAME :강철 울타리 + +[WALLSTWN] +STR_NAME :강철 벽 + +[WALLTN32] +STR_NAME :기둥 + +[WALLTXGT] +STR_NAME :'텍사스 자이언트' 팻말 + +[WALLU132] +STR_NAME :벽 + +[WALLU232] +STR_NAME :벽 + +[WALLWD16] +STR_NAME :나무 벽 + +[WALLWD32] +STR_NAME :나무 벽 + +[WALLWD33] +STR_NAME :나무 벽 + +[WALLWD8] +STR_NAME :나무 벽 + +[WALLWDPS] +STR_NAME :나무 울타리 + +[WBR1] +STR_NAME :벽돌 벽 + +[WBR1A] +STR_NAME :벽돌 벽 + +[WBR2] +STR_NAME :돌 벽 + +[WBR2A] +STR_NAME :돌 벽 + +[WBR3] +STR_NAME :돌 벽 + +[WBRG] +STR_NAME :벽돌 벽 + +[WBW] +STR_NAME :뼈 울타리 + +[WC1] +STR_NAME :성벽 + +[WC10] +STR_NAME :성벽 + +[WC11] +STR_NAME :성벽 + +[WC12] +STR_NAME :성벽 + +[WC13] +STR_NAME :성벽 + +[WC14] +STR_NAME :벽 + +[WC15] +STR_NAME :벽 + +[WC16] +STR_NAME :울타리 + +[WC17] +STR_NAME :나무 울타리 + +[WC18] +STR_NAME :나무 울타리 + +[WC2] +STR_NAME :성벽 + +[WC3] +STR_NAME :로마식 기둥 벽 + +[WC4] +STR_NAME :성벽 + +[WC5] +STR_NAME :성벽 + +[WC6] +STR_NAME :성벽 + +[WC7] +STR_NAME :성벽 + +[WC8] +STR_NAME :성벽 + +[WC9] +STR_NAME :성벽 + +[WCH] +STR_NAME :침엽수 생울타리 + +[WCHG] +STR_NAME :침엽수 생울타리 + +[WCW1] +STR_NAME :트럼프 벽 + +[WCW2] +STR_NAME :트럼프 벽 + +[WEW] +STR_NAME :이집트 벽 + +[WFW1] +STR_NAME :나무 울타리 + +[WFWG] +STR_NAME :나무 울타리 + +[WHG] +STR_NAME :생울타리 + +[WHGG] +STR_NAME :생울타리 + +[WJF] +STR_NAME :정글 울타리 + +[WMF] +STR_NAME :그물 철책 + +[WMFG] +STR_NAME :그물 철책 + +[WMW] +STR_NAME :화성식 벽 + +[WMWW] +STR_NAME :나무 울타리 + +[WPF] +STR_NAME :울타리 + +[WPFG] +STR_NAME :울타리 + +[WPW1] +STR_NAME :나무 울타리 + +[WPW2] +STR_NAME :나무 울타리 + +[WPW3] +STR_NAME :나무 울타리 + +[WRW] +STR_NAME :로마식 벽 + +[WRWA] +STR_NAME :로마식 벽 + +[WSW] +STR_NAME :철책 + +[WSW1] +STR_NAME :철책 + +[WSW2] +STR_NAME :철책 + +[WSWG] +STR_NAME :철책 + +[WWTW] +STR_NAME :키 큰 나무 울타리 + +[WWTWA] +STR_NAME :나무 울타리 벽 + +[WALLBRDR] +STR_NAME :출입구 + +[WALLCBDR] +STR_NAME :출입구 + +[WALLCBPC] +STR_NAME :성문 + +[WALLCFDR] +STR_NAME :출입구 + +[WALLCFPC] +STR_NAME :성문 + +[WALLWF32] +STR_NAME :폭포 + +[WALLGL16] +STR_NAME :유리 벽 + +[WALLGL32] +STR_NAME :유리 벽 + +[WALLGL8] +STR_NAME :유리 벽 + +[WGW2] +STR_NAME :유리 벽 + +[WALLSIGN] +STR_NAME :전광판 + +[BN1] +STR_NAME :팻말 + +[BN2] +STR_NAME :정글 스타일 팻말 + +[BN3] +STR_NAME :고전 스타일 팻말 + +[BN4] +STR_NAME :이집트 스타일 팻말 + +[BN5] +STR_NAME :나무 팻말 + +[BN6] +STR_NAME :쥐라기 스타일 팻말 + +[BN7] +STR_NAME :탑 스타일 팻말 + +[BN8] +STR_NAME :눈 쌓인 팻말 + +[BN9] +STR_NAME :우주 스타일 팻말 + +[PATHASH] +STR_NAME :잿더미 보도 + +[PATHCRZY] +STR_NAME :벽돌 보도 + +[PATHDIRT] +STR_NAME :지저분한 보도 + +[PATHSPCE] +STR_NAME :우주 스타일 보도 + +[ROAD] +STR_NAME :도로 + +[TARMAC] +STR_NAME :타맥 보도 + +[TARMACB] +STR_NAME :갈색 타맥 보도 + +[TARMACG] +STR_NAME :녹색 타맥 보도 + +[LAMP1] +STR_NAME :가로등 + +[LAMP2] +STR_NAME :가로등 + +[LAMP3] +STR_NAME :가로등 + +[LAMP4] +STR_NAME :가로등 + +[LAMPDSY] +STR_NAME :데이지 가로등 + +[LAMPPIR] +STR_NAME :가로등 + +[LITTER1] +STR_NAME :쓰레기통 + +[LITTERMN] +STR_NAME :쓰레기통 + +[LITTERSP] +STR_NAME :쓰레기통 + +[LITTERWW] +STR_NAME :쓰레기통 + +[BENCH1] +STR_NAME :의자 + +[BENCHLOG] +STR_NAME :나무 의자 + +[BENCHPL] +STR_NAME :의자 + +[BENCHSPC] +STR_NAME :의자 + +[BENCHSTN] +STR_NAME :석재 의자 + +[JUMPFNT1] +STR_NAME :도약하는 분수 + +[JUMPSNW1] +STR_NAME :도약하는 눈덩이 + +[QTV1] +STR_NAME :대기줄 TV + +[SCGABSTR] +STR_NAME :추상적인 테마 + +[SCGCANDY] +STR_NAME :대형 사탕 테마 + +[SCGCLASS] +STR_NAME :클래식/로마 테마 + +[SCGEGYPT] +STR_NAME :이집트 테마 + +[SCGFENCE] +STR_NAME :울타리와 벽 + +[SCGGARDN] +STR_NAME :정원 + +[SCGGIANT] +STR_NAME :대형 정원 테마 + +[SCGHALLO] +STR_NAME :오싹한 테마 + +[SCGINDUS] +STR_NAME :기계 테마 + +[SCGJUNGL] +STR_NAME :정글 테마 + +[SCGJURAS] +STR_NAME :쥐라기 테마 + +[SCGMART] +STR_NAME :화성 테마 + +[SCGMEDIE] +STR_NAME :중세 테마 + +[SCGMINE] +STR_NAME :광산 테마 + +[SCGORIEN] +STR_NAME :탑 테마 + +[SCGPATHX] +STR_NAME :팻말과 보도 아이템 + +[SCGPIRAT] +STR_NAME :해적 테마 + +[SCGSHRUB] +STR_NAME :관목과 장식품 + +[SCGSIXFL] +STR_NAME :식스 플래그 테마 + +[SCGSNOW] +STR_NAME :눈과 얼음 테마 + +[SCGSPACE] +STR_NAME :우주 테마 + +[SCGSPOOK] +STR_NAME :으스스한 테마 + +[SCGSPORT] +STR_NAME :스포츠 테마 + +[SCGTREES] +STR_NAME :나무 + +[SCGURBAN] +STR_NAME :도시 테마 + +[SCGWALLS] +STR_NAME :벽과 지붕 + +[SCGWATER] +STR_NAME :인공 폭포 테마 + +[SCGWOND] +STR_NAME :동화나라 테마 + +[SCGWWEST] +STR_NAME :황량한 서부 테마 + +[PKEMM] +STR_NAME :공원 출입구 + +[PKENT1] +STR_NAME :기본 공원 입구 + +[PKESFH] +STR_NAME :공원 입구 건물 + +[WTRCYAN] +STR_NAME :기본 물 + +[WTRGREEN] +STR_NAME :독성 녹색 물 + +[WTRGRN] +STR_NAME :녹색 물 + +[WTRORNG] +STR_NAME :오렌지색 물 + +############################################################################### +## Wacky Worlds Objects +############################################################################### +[LONDONBS] +STR_NAME :런던 버스 전차 +STR_DESC :전차 모형 +STR_CPTY :차량당 10명의 승객 + +[MINELIFT] +STR_NAME :탄광 엘리베이터 +STR_DESC :탑승객들은 수직 탑을 따라 이동하는 엘리베이터에 올라타 여러 높이를 손쉽게 이동할 수 있습니다. +STR_CPTY :승객 16명 + +[SANFTRAM] +STR_NAME :샌프란시스코 전차 +STR_DESC :전차 모형 +STR_CPTY :차량당 10명의 승객 + +[STEAMTRN] +STR_NAME :마하라자 증기 기관차 +STR_DESC :부드러운 천으로 된 지붕을 가진 나무 객차와 증기 기관차 모형으로 이루어진 모형 증기 기관차 차량 +STR_CPTY :객차당 6명의 승객 + +[BLACKCAB] +STR_NAME :런던 택시 블랙 캡 라이드 +STR_DESC :런던 택시 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[CRNVBFLY] +STR_NAME :카니발 플로트 라이드 - 나비 차량 +STR_DESC :나비 퍼레이드 차량 모양의 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[CRNVFROG] +STR_NAME :카니발 플로트 라이드 - 개구리 차량 +STR_DESC :개구리 퍼레이드 차량 모양의 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[CRNVLZRD] +STR_NAME :카니발 플로트 라이드 - 도마뱀 차량 +STR_DESC :도마뱀 퍼레이드 차량 모양의 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[DRAGDODG] +STR_NAME :차이니즈 드래곤헤드 라이드 +STR_DESC :스스로 운전하는 전기 범퍼카 차량 +STR_CPTY :차량당 1명의 손님 + +[HIPPORID] +STR_NAME :히포 라이드 +STR_DESC :수면 아래 코스를 이동하는 잠수함에 탑승하는 놀이기구 +STR_CPTY :차량당 5명의 승객 + +[HUSKIE] +STR_NAME :허스키 카 +STR_DESC :트랙 기반의 경로를 따라 이동하는 허스키 썰매 모양의 차량 +STR_CPTY :차량당 2명의 승객 + +[KILLWHAL] +STR_NAME :범고래 +STR_DESC :수면 아래 코스를 이동하는 잠수함에 탑승하는 놀이기구 +STR_CPTY :차량당 5명의 승객 + +[SKIDOO] +STR_NAME :설상 스쿠터 범퍼카 +STR_DESC :스스로 운전하는 전기 범퍼카 차량 +STR_CPTY :차량당 1명의 승객 + +[ANACONDA] +STR_NAME :아나콘다 라이드 +STR_DESC :간단한 안전바가 있는 널찍한 차량 +STR_CPTY :차량당 6명의 승객 + +[BOMERANG] +STR_NAME :부메랑 코스터 +STR_DESC :짜릿한 공기 압축식 발진 이후, 수직 트랙을 따라 열차가 솟구친 다음, 다시 수직으로 하강하여 정거장으로 돌아오는 놀이기구 +STR_CPTY :차량당 2명의 승객 + +[BULLET] +STR_NAME :신칸센 코스터 +STR_DESC :일본 신칸센 테마의 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[CADDILAC] +STR_NAME :리무진 롤러코스터 +STR_DESC :리무진 테마의 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 -#WW [CONDORRD] STR_NAME :콘도르 라이드 -STR_DESC :트랙 아래를 달리는 특별한 차량에 탑승한 승객들은 콘도르 모양의 열차 안에서 공중으로 떨어지며 하늘을 나는 기분을 경험하게 됩니다. +STR_DESC :Passengers ride face-down in a lying position, suspended in a Condor-shaped car from the single-rail track, swinging freely from side to side around corners +STR_CPTY :차량당 승객 1명 + +[CONGAEEL] +STR_NAME :콩가 뱀장어 코스터 +STR_DESC :A compact steel-tracked roller coaster where the Eel-shaped train travels through corkscrews and loops STR_CPTY :차량당 4명의 승객 + +[DRAGON] +STR_NAME :드래곤 코스터 +STR_DESC :드래곤 테마의 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[FOOTBALL] +STR_NAME :풋볼 라이드 +STR_DESC :Suspended roller coaster train consisting of football-shaped cars able to swing freely as the train goes around corners +STR_CPTY :차량당 4명의 승객 + +[GORILLA] +STR_NAME :고릴라 라이드 +STR_DESC :Suspended roller coaster train consisting of gorilla-shaped cars able to swing freely as the train goes around corners +STR_CPTY :차량당 4명의 승객 + +[GRATWHTE] +STR_NAME :대백상어 라이드 +STR_DESC :간단한 안전바가 있는 널찍한 차량 +STR_CPTY :차량당 6명의 승객 + +[JAGUARRD] +STR_NAME :재규어 라이드 +STR_DESC :개별적인 차량이 부드러운 트위스트 낙하를 짜임새 있게 내려오는 롤러코스터 +STR_CPTY :차량당 4명의 승객 + +[KOLARIDE] +STR_NAME :코알라 라이드 +STR_DESC :역방향 자유낙하 코스터를 위한 대형 코스터 차량 +STR_CPTY :차량당 8명의 승객 + +[LIONRIDE] +STR_NAME :사자 라이드 +STR_DESC :A compact roller coaster with individual cars and smooth twisting drops. +STR_CPTY :차량당 4명의 승객 + +[MINECART] +STR_NAME :탄광 카트 라이드 +STR_DESC :푹신한 좌석과 무릎 안전바가 있는 나무 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[OSTRICH] +STR_NAME :타조 라이드 +STR_DESC :A looping roller coaster where the riders ride in a standing position +STR_CPTY :차량당 4명의 승객 + +[PENGUINB] +STR_NAME :펭귄 봅슬레이 +STR_DESC :Riders career down a twisting track in penguin-shaped cars guided only by the curvature and banking of the semi-circular track +STR_CPTY :차량당 2명의 승객 + +[POLARBER] +STR_NAME :북극곰 롤러코스터 +STR_DESC :Riders sit in pairs facing either forwards or backwards as they loop and twist through tight inversions +STR_CPTY :차량당 4명의 승객 + +[RHINORID] +STR_NAME :코뿔소 라이드 +STR_DESC :A compact steel-tracked roller coaster with a spiral lift hill and cars with in-line seating +STR_CPTY :차량당 6명의 승객 + +[ROCKET] +STR_NAME :1950년대 로켓 라이드 +STR_DESC :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track +STR_CPTY :차량당 4명의 승객 + +[RSSNCRRD] +STR_NAME :러시아 차량 +STR_DESC :자동차 모양의 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[SEALS] +STR_NAME :물개 롤러코스터 +STR_DESC :A compact steel-tracked roller coaster where the train travels through corkscrews and loops +STR_CPTY :차량당 4명의 승객 + +[SLOTH] +STR_NAME :나무늘보 라이드 +STR_DESC :Suspended roller coaster train consisting of Sloth-shaped cars able to swing freely as the train goes around corners +STR_CPTY :차량당 4명의 승객 + +[SPUTNIKR] +STR_NAME :스푸트니크 서스펜디드 플라잉 코스터 +STR_DESC :Passengers ride face-down in a lying position, suspended in a specially designed car from the single-rail track, swinging freely from side to side around corners +STR_CPTY :차량당 승객 2명 + +[STGCCSTR] +STR_NAME :역마차 롤러코스터 +STR_DESC :좌석이 넓고 무릎에만 안전바가 있는 우든 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[SURFBRDC] +STR_NAME :서핑 코스터 +STR_DESC :Riders ride in a standing position in wide coaster trains with specially designed restraints as they race down smooth drops and through multiple inversions +STR_CPTY :차량당 4명의 승객 + +[TAXICSTR] +STR_NAME :옐로 택시 코스터 +STR_DESC :A giant steel roller coaster capable of smooth drops and hills of over 300ft +STR_CPTY :차량당 4명의 승객 + +[TGVTRAIN] +STR_NAME :TGV 트레인 롤러코스터 +STR_DESC :역에서 선형 유도 모터에 의해 가속되어 꼬여있는 트랙을 빠른 속도로 통과하는 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[TIGRTWST] +STR_NAME :뱅갈 호랑이 롤러코스터 +STR_DESC :하트라인 트위스트에서 사용할 수 있는 롤러코스터 차량 +STR_CPTY :차량당 4명의 승객 + +[WHICGRUB] +STR_NAME :애벌레 라이드 +STR_DESC :작은 유충 모양의 차량이 있는 롤러코스터 차량 +STR_CPTY :차량당 2명의 승객 + +[COFFEECU] +STR_NAME :커피 컵 라이드 +STR_DESC :Riders ride in pairs of seats rotating around the ends of three long rotating arms +STR_CPTY :승객 18명 + +[DIAMONDR] +STR_NAME :다이아몬드 라이드 +STR_DESC :Riders ride in pairs of seats rotating around the ends of three long rotating arms +STR_CPTY :승객 18명 + +[FABERGE] +STR_NAME :파베르의 달걀 라이드 +STR_DESC :Riders ride in pairs of seats rotating around the ends of three long rotating arms +STR_CPTY :승객 18명 + +[FIGHTKIT] +STR_NAME :파이팅 카이트 라이드 +STR_DESC :Riders ride in pairs of seats rotating around the ends of three long rotating arms +STR_CPTY :승객 18명 + +[FIRECRAK] +STR_NAME :파이어 크래커 라이드 +STR_DESC :Rotating wheel with suspended passenger pods, which first starts spinning and is then tilted up by a supporting arm +STR_CPTY :승객 16명 + +[ITALYPOR] +STR_NAME :이탈리안 폴리스 라이드 +STR_DESC :Riders ride in pairs of seats rotating around the ends of three long rotating arms +STR_CPTY :승객 18명 + +[JUNKSWNG] +STR_NAME :차이니즈 정크 스윙 라이드 +STR_DESC :Ship is attached to an arm with a counterweight at the opposite end, and swings through a complete 360 degrees +STR_CPTY :승객 12명 + +[CROCFLUM] +STR_NAME :악어 라이드 +STR_DESC :Crocodile-shaped boats travel along a water channel, splashing down steep slopes to soak the riders +STR_CPTY :보트당 4명의 승객 + +[DHOWWATR] +STR_NAME :다우 워터 라이드 +STR_DESC :Decorative fishing boat, which the passengers paddle themselves +STR_CPTY :보트당 2명의 승객 + +[DOLPHINR] +STR_NAME :돌고래 라이드 +STR_DESC :Single-seater Dolphin-shaped vehicles which riders can drive themselves +STR_CPTY :차량당 1명의 탑승객 + +[MANDARIN] +STR_NAME :원앙새 워터 라이드 +STR_DESC :Swan shaped boat, propelled by the pedalling front seat passengers +STR_CPTY :보트당 4명의 승객 + +[MANTARAY] +STR_NAME :쥐가오리 라이드 +STR_DESC :Large capacity boats travel along a wide water channel, propelled up slopes by a conveyor belt, accelerating down steep slopes to soak the riders with a giant splash +STR_CPTY :보트당 16명의 승객 + +[OUTRIGGR] +STR_NAME :아웃리거 라이드 +STR_DESC :탑승객들이 스스로 페달을 밟는 긴 카누 +STR_CPTY :카누당 2명의 승객 + +[TUTLBOAT] +STR_NAME :거북이 워터 라이드 +STR_DESC :Small circular dinghies powered by a centrally-mounted motor controlled by the passengers +STR_CPTY :보트당 2명의 승객 + +[WILTLP] +STR_NAME :시들지 않는 튤립 + +[1X1ATRE2] +STR_NAME :덩굴 + +[1X1ATREE] +STR_NAME :키 작은 수풀 + +[1X1BRANG] +STR_NAME :부메랑 + +[1X1DIDGE] +STR_NAME :디제리두 + +[1X1EMUXX] +STR_NAME :에뮤 + +[1X1JUGT2] +STR_NAME :작은 열대우림 나무 1 + +[1X1JUGT3] +STR_NAME :작은 열대우림 나무 2 + +[1X1KANGA] +STR_NAME :캥거루 + +[1X1TERMM] +STR_NAME :흰개미 언덕 + +[ADPANDA] +STR_NAME :어른 팬더 + +[ANTILOPF] +STR_NAME :암컷 영양 + +[ANTILOPM] +STR_NAME :수컷 영양 + +[ANTILOPP] +STR_NAME :영양 한 쌍 + +[BABPANDA] +STR_NAME :아기 팬더 + +[BABYELE] +STR_NAME :아기 인도 코끼리 + +[BALLLAN2] +STR_NAME :공 모양 초롱 + +[BALLLANT] +STR_NAME :공 모양 초롱 + +[BambooBs] +STR_NAME :대나무 수풀 + +[BAMBOOPL] +STR_NAME :대나무 주추 + +[BSTATUE1] +STR_NAME :부서진 동상 + +[FSTATUE1] +STR_NAME :고정된 동상 + +[JACHTREE] +STR_NAME :벚나무 + +[JAPCHBLO] +STR_NAME :벚나무 + +[JAPPINTR] +STR_NAME :일본 소나무 + +[JAPSNOTR] +STR_NAME :까마귀밥나무 + +[ORIEGONG] +STR_NAME :징 + +[PCG] +STR_NAME :파이프 + +[PCO] +STR_NAME :파이프 + +[POSTBOX] +STR_NAME :영국식 우편함 + +[PST] +STR_NAME :파이프 + +[PTJ] +STR_NAME :파이프 + +[PTK] +STR_NAME :파이프 + +[PVA] +STR_NAME :파이프 + +[RBRICK01] +STR_NAME :붉은 벽돌 뒤집한 지붕 조각 + +[RBRICK02] +STR_NAME :붉은 벽돌 구석 지붕 조각 + +[RBRICK03] +STR_NAME :붉은 벽돌 평평한 지붕 가장자리 조각 + +[RBRICK04] +STR_NAME :붉은 벽돌 평평한 지붕 구석 + +[RBRICK05] +STR_NAME :붉은 벽돌 지붕 조각 2 + +[RBRICK07] +STR_NAME :붉은 벽돌 지붕 조각 3 + +[RBRICK08] +STR_NAME :붉은 벽돌 지붕 조각 1 + +[RCORR01] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR02] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR03] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR04] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR05] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR07] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR08] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR09] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR10] +STR_NAME :물결 무늬 지붕 조각 + +[RCORR11] +STR_NAME :물결 무늬 지붕 조각 + +[RDRAB05] +STR_NAME :칙칙하고 작은 뾰족탑 기본 + +[RDRAB06] +STR_NAME :칙칙하고 작은 탑 상단 또는 중간 섹션 + +[RDRAB07] +STR_NAME :칙칙하고 작은 탑 기본 + +[RDRAB08] +STR_NAME :칙칙한 뾰족탑 조각 1 + +[RDRAB09] +STR_NAME :칙칙한 뾰족탑 조각 2 + +[RDRAB10] +STR_NAME :칙칙한 뾰족탑 조각 3 + +[RDRAB11] +STR_NAME :칙칙한 지붕 조각 1 + +[RDRAB12] +STR_NAME :칙칙한 지붕 조각 2 + +[RDRAB13] +STR_NAME :칙칙한 지붕 조각 3 + +[RDRAB14] +STR_NAME :칙칙한 지붕 조각 4 + +[RGEORG01] +STR_NAME :조지아식 지붕 끄트머리 조각 1 + +[RGEORG02] +STR_NAME :조지아식 지붕 끄트머리 조각 2 + +[RGEORG03] +STR_NAME :조지아식 지붕 조각 1 + +[RGEORG04] +STR_NAME :조지아식 지붕 조각 2 + +[RGEORG05] +STR_NAME :조지아식 지붕 조각 3 + +[RGEORG06] +STR_NAME :조지아식 지붕 조각 4 + +[RGEORG07] +STR_NAME :조지아식 지붕 조각 5 + +[RGEORG08] +STR_NAME :조지아식 현관문 벽 조각 7 + +[RGEORG09] +STR_NAME :조지아식 평평한 지붕 가장자리 1 + +[RGEORG10] +STR_NAME :조지아식 평평한 지붕 가장자리 2 + +[RGEORG11] +STR_NAME :조지아식 평평한 지붕 구석 + +[RGEORG12] +STR_NAME :조지아식 지붕 조각 7 + +[ROOFICE1] +STR_NAME :눈 지붕 + +[ROOFICE2] +STR_NAME :눈 지붕 + +[ROOFICE3] +STR_NAME :눈 지붕 + +[ROOFICE4] +STR_NAME :눈 지붕 + +[ROOFICE5] +STR_NAME :눈 지붕 + +[ROOFICE6] +STR_NAME :눈 지붕 + +[RKREML01] +STR_NAME :크렘린 성탑 조각 1 + +[RKREML02] +STR_NAME :크렘린 성탑 조각 2 + +[RKREML03] +STR_NAME :크렘린 성탑 조각 3 + +[RKREML04] +STR_NAME :크렘린 지붕 조각 1 + +[RKREML05] +STR_NAME :크렘린 지붕 조각 2 + +[RKREML06] +STR_NAME :크렘린 작은 탑 중간 섹션 + +[RKREML07] +STR_NAME :크렘린 작은 탑 기본 + +[RKREML11] +STR_NAME :크렘린 작은 뾰족탑 기본 + +[RLOG01] +STR_NAME :통나무집 지붕 조각 + +[RLOG02] +STR_NAME :통나무집 지붕 조각 + +[RLOG03] +STR_NAME :통나무집 벽 조각 + +[RLOG04] +STR_NAME :통나무집 벽 조각 + +[RLOG05] +STR_NAME :통나무집 지붕 조각 + +[RMARBLE1] +STR_NAME :대리석 지붕 + +[RMARBLE2] +STR_NAME :대리석 지붕 + +[RMARBLE3] +STR_NAME :대리석 지붕 + +[RMARBLE4] +STR_NAME :대리석 지붕 + +[RMUD01] +STR_NAME :곡선형 진흙 벽 조각 + +[RMUD02] +STR_NAME :곡선형 진흙 벽 조각 + +[RMUD03] +STR_NAME :곡선형 진흙 벽 조각 + +[RMUD05] +STR_NAME :진흙 지붕 조각 + +[ROOFIG01] +STR_NAME :이글루 벽 + +[ROOFIG02] +STR_NAME :이글루 벽 + +[ROOFIG03] +STR_NAME :이글루 벽 + +[ROOFIG04] +STR_NAME :이글루 벽 + +[ROOFIG06] +STR_NAME :이글루 벽 + +[RSHOGI1] +STR_NAME :장기 지붕 + +[RSHOGI2] +STR_NAME :장기 지붕 + +[RSHOGI3] +STR_NAME :장기 지붕 + +[SMALLGEO] +STR_NAME :작은 지오스피어 + +[VERTPIPE] +STR_NAME :얼음 파이프 섹션 + +[ICEBARL1] +STR_NAME :눈 덮인 통 + +[ICEBARL2] +STR_NAME :눈 덮인 통 + +[ICEBARL3] +STR_NAME :눈 덮인 통 + +[PIPEVENT] +STR_NAME :얼음 배기관 + +[PIPEBASE] +STR_NAME :얼음 파이프 기본 + +[RTUDOR01] +STR_NAME :튜더식 지붕 조각 1 + +[RTUDOR02] +STR_NAME :튜더식 지붕 조각 1 확장 조각 + +[RTUDOR03] +STR_NAME :튜더식 지붕 조각 2 + +[RWDAUB01] +STR_NAME :초벽 지붕 + +[RWDAUB02] +STR_NAME :초벽 지붕 + +[RWDAUB03] +STR_NAME :초벽 지붕 + +[SB1HSPB1] +STR_NAME :현수교 기본 조각 + +[SB1HSPB2] +STR_NAME :현수교 기본 간격 조각 + +[SB1HSPB3] +STR_NAME :현수교 중간 섹션 조각 + +[SB2PALM1] +STR_NAME :탈의실 베란다 + +[SB2SKY01] +STR_NAME :석재 마천루 계단 기본 + +[SBH1TEPE] +STR_NAME :원뿔형 천막 + +[SBH1WGWH] +STR_NAME :수레바퀴 + +[SBH2SHLT] +STR_NAME :서치라이트 + +[SBH3CAC1] +STR_NAME :선인장 + +[SBH3CAC2] +STR_NAME :선인장 + +[SBH3CAC3] +STR_NAME :선인장 + +[SBH3CSKL] +STR_NAME :소 두개골 + +[SBH3OSCR] +STR_NAME :롤러코스터 어워드 상 + +[SBH3PLM1] +STR_NAME :야자수 + +[SBH3PLM2] +STR_NAME :야자수 + +[SBH3PLM3] +STR_NAME :야자수 + +[SBH3RT66] +STR_NAME :66번도 팻말 + +[SBH4TOTM] +STR_NAME :커다란 토템 기둥 + +[SBSKYS01] +STR_NAME :석재 마천루 벽 조각 + +[SBSKYS02] +STR_NAME :석재 마천루 벽 조각 + +[SBSKYS03] +STR_NAME :마천루 엘리베이터 조각 + +[SBSKYS04] +STR_NAME :마천루 엘리베이터 조각 + +[SBSKYS05] +STR_NAME :마천루 철제 세트 1 볼록한 조각 + +[SBSKYS06] +STR_NAME :마천루 철제 세트 1 오목한 조각 + +[SBSKYS07] +STR_NAME :마천루 철제 세트 2 볼록한 조각 + +[SBSKYS08] +STR_NAME :마천루 철제 세트 2 오목한 조각 + +[SBSKYS09] +STR_NAME :마천루 철제 세트 2 오목한 조각 + +[SBSKYS10] +STR_NAME :마천루 오목한 조각 + +[SBSKYS11] +STR_NAME :마천루 오목한 지붕 + +[SBSKYS12] +STR_NAME :마천루 볼록한 조각 + +[SBSKYS13] +STR_NAME :마천루 볼록한 지붕 + +[SBSKYS14] +STR_NAME :마천루 지붕 조각 + +[SBSKYS15] +STR_NAME :마천루 지붕 조각 + +[SBSKYS16] +STR_NAME :마천루 지붕 조각 + +[SBSKYS17] +STR_NAME :마천루 지붕 조각 + +[SBSKYS18] +STR_NAME :마천루 지붕 조각 + +[SBWIND01] +STR_NAME :풍화된 오목한 벽 구석 + +[SBWIND02] +STR_NAME :풍화된 오목한 지붕 구석 + +[SBWIND03] +STR_NAME :풍화된 오목한 벽 구석 + +[SBWIND04] +STR_NAME :풍화된 볼록한 벽 구석 + +[SBWIND05] +STR_NAME :풍화된 볼록한 지붕 구석 + +[SBWIND06] +STR_NAME :풍화된 볼록한 벽 구석 + +[SBWIND07] +STR_NAME :풍화된 바위 층 기반 + +[SBWIND08] +STR_NAME :풍화된 바위 층 기반 + +[SBWIND09] +STR_NAME :풍화된 바위 층 중간 섹션 + +[SBWIND10] +STR_NAME :풍화된 바위 층 중간 섹션 + +[SBWIND11] +STR_NAME :풍화된 바위 층 중간 섹션 + +[SBWIND12] +STR_NAME :풍화된 바위 층 중간 섹션 + +[SBWIND13] +STR_NAME :풍화된 바위 층 꼭대기 + +[SBWIND14] +STR_NAME :풍화된 바위 층 꼭대기 + +[SBWIND15] +STR_NAME :풍화된 지붕 평평한 지붕 조각 + +[SBWIND16] +STR_NAME :풍화된 지붕 평평한 지붕 조각 + +[SBWIND17] +STR_NAME :풍화된 지붕 평평한 지붕 조각 + +[SBWIND18] +STR_NAME :풍화된 바닥 조각 + +[SBWIND19] +STR_NAME :풍화된 바닥 조각 + +[SBWIND20] +STR_NAME :풍화된 벽 기본 + +[SBWIND21] +STR_NAME :풍화된 벽 기본 + +[SBWPLM01] +STR_NAME :탈의실 파라솔 + +[SBWPLM02] +STR_NAME :탈의실 베란다 + +[SBWPLM03] +STR_NAME :탈의실 지붕 조각 + +[SBWPLM04] +STR_NAME :탈의실 지붕 조각 + +[SBWPLM05] +STR_NAME :탈의실 지붕 조각 + +[SBWPLM06] +STR_NAME :탈의실 벽 조각 + +[SBWPLM07] +STR_NAME :탈의실 벽 조각 + +[SBWPLM08] +STR_NAME :탈의실 벽 조각 + +[TALLLAN1] +STR_NAME :키 큰 초롱 + +[TALLLAN2] +STR_NAME :키 큰 초롱 + +[TERRARMY] +STR_NAME :병마용 + +[TJBLOCK1] +STR_NAME :마하라자 궁전 조각 + +[TJBLOCK2] +STR_NAME :마하라자 궁전 조각 + +[TJBLOCK3] +STR_NAME :마하라자 궁전 조각 + +[TNT1] +STR_NAME :TNT 무더기 + +[TNT2] +STR_NAME :TNT 통 + +[TNT3] +STR_NAME :TNT 기폭장치 + +[TNT4] +STR_NAME :TNT 상자 + +[TRCKPRT1] +STR_NAME :다이아몬드 카트 + +[TRCKPRT2] +STR_NAME :빈 카트 + +[TRCKPRT3] +STR_NAME :다이아몬드 수갱 + +[TRCKPRT4] +STR_NAME :카트 수갱 + +[TRCKPRT5] +STR_NAME :굽은 트랙 + +[TRCKPRT6] +STR_NAME :끊어진 트랙 + +[TRCKPRT7] +STR_NAME :끄트머리 트랙 + +[TRCKPRT8] +STR_NAME :분기 트랙 + +[TRCKPRT9] +STR_NAME :직선 트랙 + +[UKPHONE] +STR_NAME :영국 공중전화 박스 + +[WABORG01] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WABORG02] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WABORG03] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WABORG04] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WABORG05] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WABORG06] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WABORG07] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WABORG08] +STR_NAME :호주 원주민 토착 예술 세트 조각 + +[WAZTEC01] +STR_NAME :사원 지붕 조각 + +[WAZTEC02] +STR_NAME :사원 지붕 조각 + +[WAZTEC03] +STR_NAME :사원 벽 조각 + +[WAZTEC04] +STR_NAME :사원 벽 조각 + +[WAZTEC05] +STR_NAME :사원 벽 조각 + +[WAZTEC06] +STR_NAME :사원 벽 조각 + +[WAZTEC07] +STR_NAME :사원 벽 조각 + +[WAZTEC08] +STR_NAME :사원 벽 조각 + +[WAZTEC09] +STR_NAME :사원 벽 조각 + +[WAZTEC10] +STR_NAME :사원 벽 조각 + +[WAZTEC11] +STR_NAME :사원 벽 구석 조각 + +[WAZTEC12] +STR_NAME :사원 벽 구석 조각 + +[WAZTEC13] +STR_NAME :사원 벽 조각 + +[WAZTEC14] +STR_NAME :사원 벽 조각 + +[WAZTEC15] +STR_NAME :사원 지붕 조각 + +[WAZTEC16] +STR_NAME :사원 지붕 조각 + +[WAZTEC17] +STR_NAME :사원 지붕 조각 + +[WAZTEC18] +STR_NAME :사원 지붕 조각 + +[WAZTEC19] +STR_NAME :사원 지붕 조각 + +[WAZTEC20] +STR_NAME :사원 계단 조각 + +[WAZTEC21] +STR_NAME :사원 계단 조각 + +[WAZTEC22] +STR_NAME :사원 벽 조각 + +[WAZTEC23] +STR_NAME :사원 벽 조각 + +[WAZTEC24] +STR_NAME :사원 벽 조각 + +[WAZTEC25] +STR_NAME :사원 벽 조각 + +[WAZTEC26] +STR_NAME :사원 벽 구석 조각 + +[WAZTEC27] +STR_NAME :사원 벽 구석 조각 + +[WCUZCO01] +STR_NAME :기념물 벽 조각 + +[WCUZCO02] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO03] +STR_NAME :기념물 벽 조각 + +[WCUZCO04] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO05] +STR_NAME :기념물 벽 조각 + +[WCUZCO06] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO07] +STR_NAME :기념물 벽 조각 + +[WCUZCO08] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO09] +STR_NAME :기념물 벽 조각 + +[WCUZCO10] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO11] +STR_NAME :기념물 벽 조각 + +[WCUZCO12] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO13] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO14] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO15] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO16] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO17] +STR_NAME :기념물 벽 조각 + +[WCUZCO18] +STR_NAME :기념물 부서진 벽 조각 + +[WCUZCO19] +STR_NAME :기념물 계단 조각 + +[WCUZCO20] +STR_NAME :기념물 계단 조각 + +[WCUZCO21] +STR_NAME :기념물 벽 구석 조각 + +[WCUZCO22] +STR_NAME :기념물 벽 구석 조각 + +[WCUZCO23] +STR_NAME :기념물 벽 구석 조각 + +[WCUZCO24] +STR_NAME :기념물 벽 구석 조각 + +[WCUZCO25] +STR_NAME :기념물 계단 조각 + +[WCUZCO26] +STR_NAME :기념물 계단 조각 + +[WCUZCO27] +STR_NAME :기념물 벽 조각 + +[WCUZCO28] +STR_NAME :기념물 부서진 벽 조각 + +[WDRAB09] +STR_NAME :칙칙한 계단 조각 1 + +[WDRAB10] +STR_NAME :칙칙한 벽 조각 9 + +[WDRAB11] +STR_NAME :칙칙한 벽 조각 10 + +[WDRAB12] +STR_NAME :칙칙한 벽 조각 11 + +[WDRAB13] +STR_NAME :칙칙하고 점진적인 조각 2 + +[WGEORG07] +STR_NAME :조지아식 지면 바닥 벽 조각 4 + +[WGEORG08] +STR_NAME :조지아식 지면 바닥 벽 조각 5 + +[WGEORG09] +STR_NAME :조지아식 지면 바닥 벽 조각 6 + +[WGEORG10] +STR_NAME :조지아식 벽 조각 4 + +[WGEORG11] +STR_NAME :조지아식 벽 조각 5 + +[WGEORG12] +STR_NAME :조지아식 벽 조각 6 + +[WKREML01] +STR_NAME :크렘린 점진적 벽 조각 1 + +[WKREML02] +STR_NAME :크렘린 점진적 벽 조각 2 + +[WKREML03] +STR_NAME :크렘린 벽 조각 1 + +[WKREML04] +STR_NAME :크렘린 벽 조각 2 + +[WKREML05] +STR_NAME :크렘린 벽 조각 3 + +[WKREML06] +STR_NAME :크렘린 벽 조각 4 + +[WMAYAN01] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN02] +STR_NAME :잃어버린 도시 평평한 지붕 조각 + +[WMAYAN03] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN04] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN05] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN06] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN07] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN08] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN09] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN10] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN11] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN12] +STR_NAME :잃어버린 도시 계단 조각 + +[WMAYAN13] +STR_NAME :잃어버린 도시 계단 조각 + +[WMAYAN14] +STR_NAME :잃어버린 도시 계단 조각 + +[WMAYAN15] +STR_NAME :잃어버린 도시 계단 조각 + +[WMAYAN16] +STR_NAME :잃어버린 도시 계단 조각 + +[WMAYAN17] +STR_NAME :잃어버린 도시 기둥 조각 + +[WMAYAN18] +STR_NAME :잃어버린 도시 기둥 조각 + +[WMAYAN20] +STR_NAME :잃어버린 도시 벽 조각 + +[WMAYAN21] +STR_NAME :잃어버린 도시 평평한 지붕 조각 + +[WMAYAN22] +STR_NAME :잃어버린 도시 평평한 지붕 조각 + +[WMAYAN23] +STR_NAME :잃어버린 도시 벽 구석 조각 + +[WMAYAN24] +STR_NAME :잃어버린 도시 벽 구석 조각 + +[WMAYAN25] +STR_NAME :잃어버린 도시 벽 구석 조각 + +[WMAYAN26] +STR_NAME :잃어버린 도시 벽 구석 조각 + +[WNAUTI01] +STR_NAME :해상 지붕 조각 + +[WNAUTI02] +STR_NAME :해상 지붕 조각 + +[WNAUTI03] +STR_NAME :해상 지붕 조각 + +[WNAUTI04] +STR_NAME :해상 지붕 조각 + +[WNAUTI05] +STR_NAME :해상 지붕 조각 + +[WTUDOR12] +STR_NAME :튜더식 벽 조각 4 + +[WTUDOR13] +STR_NAME :튜더식 지면 바닥 벽 조각 + +[WTUDOR14] +STR_NAME :튜더식 지면 바닥 벽 조각 1 + +[WTUDOR15] +STR_NAME :튜더식 지면 바닥 벽 조각 2 + +[WTUDOR16] +STR_NAME :튜더식 지면 바닥 벽 조각 3 + +[WTUDOR17] +STR_NAME :튜더식 지면 바닥 벽 조각 4 + +[WTUDOR18] +STR_NAME :튜더식 지면 바닥 벽 조각 5 + +[CAMPFANI] +STR_NAME :캠프 파이어 + +[CONVEYR1] +STR_NAME :컨베이어 벨트 구석 + +[CONVEYR2] +STR_NAME :컨베이어 벨트 상승 + +[CONVEYR3] +STR_NAME :컨베이어 벨트 끄트머리 + +[CONVEYR4] +STR_NAME :곧은 컨베이어 벨트 + +[CONVEYR5] +STR_NAME :컨베이어 벨트 구석 역방향 + +[FISHHOLE] +STR_NAME :낚시 구멍 + +[FLAMNGO1] +STR_NAME :먹이를 먹는 홍학 + +[FLAMNGO2] +STR_NAME :쳐다보는 홍학 + +[FLAMNGO3] +STR_NAME :몸치장을 하는 홍학 + +[FOUNTARC] +STR_NAME :오스트레일리아 분수 세트 2 + +[FOUNTROW] +STR_NAME :오스트레일리아 분수 세트 2 + +[G1DANCER] +STR_NAME :마디 그라 댄서 + +[G2DANCER] +STR_NAME :마디 그라 댄서 + +[INUIT] +STR_NAME :이누이트 + +[INUIT2] +STR_NAME :이누이트 + +[INFLAG01] +STR_NAME :인디언 실크 깃발 + +[INFLAG02] +STR_NAME :인디언 실크 깃발 + +[INFLAG03] +STR_NAME :인디언 실크 깃발 + +[INFLAG04] +STR_NAME :인디언 실크 깃발 + +[INFLAG05] +STR_NAME :인디언 실크 깃발 + +[JPFLAG01] +STR_NAME :일본식 실크 깃발 + +[JPFLAG02] +STR_NAME :일본식 실크 깃발 + +[JPFLAG03] +STR_NAME :일본식 실크 깃발 + +[JPFLAG04] +STR_NAME :일본식 실크 깃발 + +[JPFLAG05] +STR_NAME :일본식 실크 깃발 + +[JPFLAG06] +STR_NAME :일본식 실크 깃발 + +[OILPUMP] +STR_NAME :오일 펌프 + +[SBALLOON] +STR_NAME :움직이는 풍선 + +[WCUZFOUN] +STR_NAME :기념물 분수 + +[WROPECOR] +STR_NAME :해상 구석 지붕 울타리 + +[WROPESWA] +STR_NAME :해상 지붕 울타리 + +[1X2ABR01] +STR_NAME :원주민 평면 타일 + +[1X2ABR02] +STR_NAME :원주민 뱀 예술작품 + +[1X2ABR03] +STR_NAME :원주민의 혼이 담긴 예수랒ㄱ품 + +[1X2AZT01] +STR_NAME :머리가 있는 사원 벽 조각 + +[1X2AZT02] +STR_NAME :머리가 있는 사원의 부서진 벽 조각 + +[1X2LGCHM] +STR_NAME :통나무집 측면 굴뚝 + +[AFRCLION] +STR_NAME :사자 + +[AFRRHINO] +STR_NAME :코뿔소 + +[ATRACTOR] +STR_NAME :트랙터 + +[AFRZEBRA] +STR_NAME :얼룩말 + +[1X4BRG01] +STR_NAME :현수교 시작 측면 1 + +[1X4BRG02] +STR_NAME :현수교 시작 측면 2 + +[1X4BRG03] +STR_NAME :현수교 탑 측면 1 + +[1X4BRG04] +STR_NAME :현수교 탑 측면 2 + +[1X4BRG05] +STR_NAME :현수교 케이블 조각 + +[3X3ATRE1] +STR_NAME :정글 나무 2 + +[3X3MANTR] +STR_NAME :맹그로브 나무 + +[50ROCKET] +STR_NAME :1950년대 로켓 + +[BamboRf1] +STR_NAME :대나무 지붕 + +[BAMBORF2] +STR_NAME :대나무 지붕 + +[BamboRf3] +STR_NAME :대나무 지붕 + +[BIGGEOSP] +STR_NAME :대형 구 + +[CIRCUS] +STR_NAME :서커스 + +[COWBOY01] +STR_NAME :카우보이 1 + +[COWBOY02] +STR_NAME :카우보이 2 + +[DAMTOWER] +STR_NAME :댐 타워 + +[EIFFEL] +STR_NAME :에펠 탑 + +[FATBUDDA] +STR_NAME :살찐 부처상 + +[GIRAFFE1] +STR_NAME :기린 1 + +[GIRAFFE2] +STR_NAME :기린 2 + +[GOLDBUDA] +STR_NAME :금부처상 + +[HIPPO01] +STR_NAME :하마 1 + +[HIPPO02] +STR_NAME :하마 2 + +[INDIANST] +STR_NAME :아메리카 원주민 + +[LARGEJU1] +STR_NAME :큰 열대우림 속 나무 + +[LINCOLNS] +STR_NAME :워싱턴 동상 + +[RDRAB01] +STR_NAME :칙칙한 대형 탑 중간 조각 + +[RDRAB02] +STR_NAME :칙칙한 대형 탑 기본 + +[RDRAB03] +STR_NAME :칙칙한 대형 탑 상단 + +[RDRAB04] +STR_NAME :칙칙한 대형 탑 부서진 기본 + +[REDWOOD] +STR_NAME :삼나무 + +[RKREML08] +STR_NAME :크렘린 대형 탑 기본 + +[RKREML09] +STR_NAME :크렘린 대형 탑 상단 + +[RKREML10] +STR_NAME :크렘린 대형 탑 중간 조각 + +[RTUDOR05] +STR_NAME :튜더식 지붕 조각 3 + +[RTUDOR06] +STR_NAME :튜더식 지붕 조각 4 + +[SHIVA] +STR_NAME :시바 + +[SOFLIBRT] +STR_NAME :자유의 여신상 + +[SPUTNIK] +STR_NAME :스푸트니크 + +[TAJMCBSE] +STR_NAME :마하라자 궁전 탑 기본 + +[TAJMCOLM] +STR_NAME :마하라자 궁전 탑 기둥 + +[TAJMCTOP] +STR_NAME :마하라자 궁전 탑 상단 + +[1X2GLAMA] +STR_NAME :황금 라마 + +[3X3ALTRE] +STR_NAME :표범이 있는 정글의 나무 + +[3X3ATRE2] +STR_NAME :정글의 나무 1 + +[3X3ATRE3] +STR_NAME :포도가 열린 정글의 나무 + +[3X3EUCAL] +STR_NAME :유칼립투스 나무 + +[3X3HMSEN] +STR_NAME :HMS 인데버 + +[ADULTELE] +STR_NAME :인도 코끼리 성체 + +[ATOMIUM] +STR_NAME :아토미움 + +[BIGBEN] +STR_NAME :빅벤과 영국 국회 의사당 + +[BIGDISH] +STR_NAME :위성 접시 + +[CDRAGON] +STR_NAME :용 + +[EASERLND] +STR_NAME :이스터 섬 조각상 + +[EVILSAM] +STR_NAME :나쁜 사무라이 + +[GDSTAUE1] +STR_NAME :황금 조각상 1 + +[GDSTAUE2] +STR_NAME :황금 조각상 2 + +[GEISHA] +STR_NAME :게이샤 + +[GOODSAM] +STR_NAME :좋은 사무라이 + +[GWOCTUR1] +STR_NAME :중국 만리장성 직선 탑 + +[GWOCTUR2] +STR_NAME :중국 만리장성 구석 탑 + +[HELIPAD] +STR_NAME :헬리패드 + +[ICEFOR01] +STR_NAME :결빙 + +[ICEFOR02] +STR_NAME :결빙 + +[MBSKYR01] +STR_NAME :마천루 지붕 조각 + +[MBSKYR02] +STR_NAME :마천루 끝 + +[OVRGRWNT] +STR_NAME :오래된 잡초 나무 + +[POGODAL] +STR_NAME :탑 + +[PAGODAM] +STR_NAME :탑 + +[PAGODAS] +STR_NAME :탑 + +[PAGODATW] +STR_NAME :탑 + +[RADAR] +STR_NAME :레이더 접시 + +[SPACEORB] +STR_NAME :천체 + +[SUNKEN] +STR_NAME :침몰선 + +[TAJMDOME] +STR_NAME :마하라자 궁전 돔 + +[WINDMILL] +STR_NAME :풍차 + +[TMARCH1] +STR_NAME :마하라자 궁전 아치 1 + +[TMARCH2] +STR_NAME :마하라자 궁전 아치 2 + +[W2CORR01] +STR_NAME :물결 무늬 벽 조각 + +[W2CORR02] +STR_NAME :물결 무늬 벽 조각 + +[W2CORR03] +STR_NAME :물결 무늬 벽 조각 + +[W2CORR04] +STR_NAME :물결 무늬 벽 조각 + +[W2CORR05] +STR_NAME :물결 무늬 벽 조각 + +[W2CORR06] +STR_NAME :물결 무늬 벽 조각 + +[W2CORR07] +STR_NAME :물결 무늬 벽 조각 + +[W2CORR08] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR01] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR02] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR03] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR04] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR05] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR06] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR07] +STR_NAME :물결 무늬 벽 조각 + +[W3CORR08] +STR_NAME :물결 무늬 벽 조각 + +[WALLNA01] +STR_NAME :해상 벽 조각 + +[WALLNA02] +STR_NAME :해상 벽 조각 + +[WALLNA03] +STR_NAME :해상 벽 조각 + +[WALLNA04] +STR_NAME :해상 벽 조각 + +[WALLNA05] +STR_NAME :해상 벽 조각 + +[WALLNA06] +STR_NAME :해상 벽 조각 + +[WALLNA07] +STR_NAME :해상 벽 조각 + +[WALLNA08] +STR_NAME :해상 벽 조각 + +[WALLNA09] +STR_NAME :해상 벽 조각 + +[WALLNA10] +STR_NAME :해상 벽 조각 + +[WALLNA11] +STR_NAME :해상 벽 조각 + +[WALLNA12] +STR_NAME :해상 벽 조각 + +[WALLNA13] +STR_NAME :해상 벽 조각 + +[WALLNA14] +STR_NAME :해상 벽 조각 + +[WWDAUB01] +STR_NAME :초벽 벽 + +[WWDAUB02] +STR_NAME :초벽 벽 + +[WWDAUB03] +STR_NAME :초벽 벽 + +[WWDAUB04] +STR_NAME :초벽 벽 + +[WWDAUB05] +STR_NAME :초벽 벽 + +[WWDAUB06] +STR_NAME :초벽 벽 + +[WWDAUB07] +STR_NAME :초벽 벽 + +[WBambo01] +STR_NAME :대나무 벽 + +[WBambo02] +STR_NAME :대나무 벽 + +[WBambo03] +STR_NAME :대나무 벽 + +[WBAMBO04] +STR_NAME :대나무 벽 + +[WBambo05] +STR_NAME :대나무 벽 + +[WBambo11] +STR_NAME :대나무 벽 + +[WBambo12] +STR_NAME :대나무 벽 + +[WBambo13] +STR_NAME :대나무 벽 + +[WBambo14] +STR_NAME :대나무 벽 + +[WBambo15] +STR_NAME :대나무 벽 + +[WBambo21] +STR_NAME :대나무 벽 + +[WBRICK01] +STR_NAME :붉은 벽돌 벽 조각 1 + +[WBRICK02] +STR_NAME :붉은 벽돌 벽 조각 2 + +[WBRICK03] +STR_NAME :붉은 벽돌 벽 조각 3 + +[WBRICK04] +STR_NAME :붉은 벽돌 벽 조각 4 + +[WBRICK05] +STR_NAME :붉은 벽돌 벽 조각 5 + +[WBRICK08] +STR_NAME :붉은 벽돌 벽 조각 8 + +[WBRICK11] +STR_NAME :붉은 벽돌 벽 조각 11 + +[WBRICK12] +STR_NAME :붉은 벽돌 벽 조각 12 + +[WBRICK13] +STR_NAME :붉은 벽돌 벽 조각 13 + +[WCORR01] +STR_NAME :물결 무늬 벽 조각 + +[WCORR02] +STR_NAME :물결 무늬 벽 조각 + +[WCORR03] +STR_NAME :물결 무늬 벽 조각 + +[WCORR04] +STR_NAME :물결 무늬 벽 조각 + +[WCORR05] +STR_NAME :물결 무늬 벽 조각 + +[WCORR06] +STR_NAME :물결 무늬 벽 조각 + +[WCORR07] +STR_NAME :물결 무늬 벽 조각 + +[WCORR08] +STR_NAME :물결 무늬 벽 조각 + +[WCORR09] +STR_NAME :물결 무늬 벽 조각 + +[WCORR10] +STR_NAME :물결 무늬 벽 조각 + +[WCORR11] +STR_NAME :물결 무늬 벽 조각 + +[WCORR12] +STR_NAME :물결 무늬 벽 조각 + +[WCORR13] +STR_NAME :물결 무늬 벽 조각 + +[WCORR14] +STR_NAME :물결 무늬 벽 조각 + +[WCORR15] +STR_NAME :물결 무늬 벽 조각 + +[WCORR16] +STR_NAME :물결 무늬 벽 조각 + +[WDRAB01] +STR_NAME :칙칙한 벽 조각 1 + +[WDRAB02] +STR_NAME :칙칙한 벽 조각 2 + +[WDRAB03] +STR_NAME :칙칙한 벽 조각 3 + +[WDRAB04] +STR_NAME :칙칙한 벽 조각 4 + +[WDRAB05] +STR_NAME :칙칙한 벽 조각 5 + +[WDRAB06] +STR_NAME :칙칙한 벽 조각 6 + +[WDRAB07] +STR_NAME :칙칙한 벽 조각 7 + +[WDRAB08] +STR_NAME :칙칙한 벽 조각 8 + +[WGEORG01] +STR_NAME :조지아식 벽 조각 1 + +[WGEORG02] +STR_NAME :조지아식 지면 바닥 벽 조각 1 + +[WGEORG03] +STR_NAME :조지아식 벽 조각 2 + +[WGEORG04] +STR_NAME :조지아식 지면 바닥 벽 조각 2 + +[WGEORG05] +STR_NAME :조지아식 벽 조각 3 + +[WGEORG06] +STR_NAME :조지아식 지면 바닥 벽 조각 3 + +[WGWOC1] +STR_NAME :중국 만리장성 앞쪽 벽 조각 + +[WGWOC2] +STR_NAME :중국 만리장성 뒤쪽 벽 조각 + +[WGWOC3] +STR_NAME :중국 만리장성 중간 벽 조각 + +[WALLICE1] +STR_NAME :얼음 벽 + +[WALLICE2] +STR_NAME :얼음 벽 + +[WALLICE3] +STR_NAME :얼음 벽 + +[WALLICE4] +STR_NAME :얼음 벽 + +[WALLICE5] +STR_NAME :얼음 벽 + +[WALLICE6] +STR_NAME :얼음 벽 + +[WALLICE7] +STR_NAME :얼음 벽 + +[WALLICE8] +STR_NAME :얼음 벽 + +[WALLICE9] +STR_NAME :얼음 벽 + +[WALLIC10] +STR_NAME :얼음 벽 + +[WIGLOO1] +STR_NAME :이글루 벽 + +[WIGLOO2] +STR_NAME :이글루 벽 + +[WKREML07] +STR_NAME :크렘린 벽 조각 5 + +[WKREML08] +STR_NAME :크렘린 벽 조각 6 + +[WKREML09] +STR_NAME :크렘린 벽 조각 7 + +[WKREML10] +STR_NAME :크렘린 벽 조각 8 + +[WLOG01] +STR_NAME :통나무집 벽 조각 + +[WLOG02] +STR_NAME :통나무집 벽 조각 + +[WLOG03] +STR_NAME :통나무집 벽 조각 + +[WLOG04] +STR_NAME :통나무집 벽 조각 + +[WLOG05] +STR_NAME :통나무집 벽 조각 + +[WLOG06] +STR_NAME :통나무집 벽 조각 + +[WMARBLE1] +STR_NAME :화려하게 장식된 대리석 벽 + +[WMARBLE2] +STR_NAME :화려하게 장식된 대리석 벽 + +[WMARBLE3] +STR_NAME :화려하게 장식된 대리석 벽 + +[WMARBLE4] +STR_NAME :화려하게 장식된 대리석 벽 + +[WMARBLE5] +STR_NAME :화려하게 장식된 대리석 벽 + +[WMARBLE6] +STR_NAME :화려하게 장식된 대리석 벽 + +[WMARBPL1] +STR_NAME :평탄한 대리석 벽 + +[WMARBPL2] +STR_NAME :평탄한 대리석 벽 + +[WMARBPL3] +STR_NAME :평탄한 대리석 벽 + +[WMARBPL4] +STR_NAME :평탄한 대리석 벽 + +[WMARBPL5] +STR_NAME :평탄한 대리석 벽 + +[WMARBPL6] +STR_NAME :평탄한 대리석 벽 + +[WMARBPL7] +STR_NAME :평탄한 대리석 벽 + +[WMUD01] +STR_NAME :진흙 벽 조각 + +[WMUD02] +STR_NAME :진흙 벽 조각 + +[WMUD03] +STR_NAME :진흙 벽 조각 + +[WMUD04] +STR_NAME :진흙 벽 조각 + +[WMUD05] +STR_NAME :진흙 벽 조각 + +[WMUD06] +STR_NAME :진흙 벽 조각 + +[WMUD07] +STR_NAME :진흙 벽 조각 + +[WMUD08] +STR_NAME :진흙 벽 조각 + +[WPALM01] +STR_NAME :탈의실 벽 조각 + +[WPALM02] +STR_NAME :탈의실 벽 조각 + +[WPALM03] +STR_NAME :탈의실 벽 조각 + +[WPALM04] +STR_NAME :탈의실 벽 조각 + +[WPALM05] +STR_NAME :탈의실 벽 조각 + +[WSHOGI01] +STR_NAME :쇼기 벽 + +[WSHOGI02] +STR_NAME :쇼기 벽 + +[WSHOGI03] +STR_NAME :쇼기 벽 + +[WSHOGI04] +STR_NAME :쇼기 벽 + +[WSHOGI05] +STR_NAME :쇼기 벽 + +[WSHOGI06] +STR_NAME :쇼기 벽 + +[WSHOGI07] +STR_NAME :쇼기 벽 + +[WSHOGI08] +STR_NAME :쇼기 벽 + +[WSHOGI09] +STR_NAME :쇼기 벽 + +[WSHOGI10] +STR_NAME :쇼기 벽 + +[WSHOGI11] +STR_NAME :쇼기 벽 + +[WSHOGI12] +STR_NAME :쇼기 벽 + +[WSHOGI13] +STR_NAME :쇼기 벽 + +[WSHOGI14] +STR_NAME :쇼기 벽 + +[WSHOGI15] +STR_NAME :쇼기 벽 + +[WSHOGI16] +STR_NAME :쇼기 벽 + +[WSHOGI17] +STR_NAME :쇼기 벽 + +[WSKYSC01] +STR_NAME :마천루 철제 세트 2 벽 조각 + +[WSKYSC02] +STR_NAME :마천루 철제 세트 2 벽 조각 + +[WSKYSC03] +STR_NAME :마천루 철제 세트 1 벽 조각 + +[WSKYSC04] +STR_NAME :마천루 리프트 조각 조각 + +[WSKYSC05] +STR_NAME :마천루 리프트 조각 조각 + +[WSKYSC06] +STR_NAME :마천루 벽 조각 + +[WSKYSC07] +STR_NAME :마천루 리프트 조각 조각 + +[WSKYSC08] +STR_NAME :마천루 벽 조각 + +[WSKYSC09] +STR_NAME :마천루 벽 조각 + +[WSKYSC10] +STR_NAME :석재 마천루 벽 조각 + +[WSKYSC11] +STR_NAME :석재 마천루 벽 조각 + +[WSKYSC12] +STR_NAME :석재 마천루 벽 조각 + +[WTUDOR01] +STR_NAME :튜더식 지면 바닥 벽 조각 1 + +[WTUDOR02] +STR_NAME :튜더식 지면 바닥 벽 조각 2 + +[WTUDOR03] +STR_NAME :튜더식 지면 바닥 벽 조각 3 + +[WTUDOR04] +STR_NAME :튜더식 지면 바닥 벽 조각 4 + +[WTUDOR05] +STR_NAME :튜더식 지면 바닥 벽 조각 5 + +[WTUDOR06] +STR_NAME :튜더식 지면 바닥 벽 조각 6 + +[WTUDOR07] +STR_NAME :튜더식 지면 바닥 벽 조각 7 + +[WTUDOR08] +STR_NAME :튜더식 지면 바닥 벽 조각 8 + +[WTUDOR09] +STR_NAME :튜더식 벽 조각 1 + +[WTUDOR10] +STR_NAME :튜더식 벽 조각 2 + +[WTUDOR11] +STR_NAME :튜더식 벽 조각 3 + +[WWIND03] +STR_NAME :풍화된 벽 조각 + +[WWIND04] +STR_NAME :풍화된 벽 조각 + +[WWIND05] +STR_NAME :풍화된 벽 조각 + +[WWIND06] +STR_NAME :풍화된 벽 조각 + +[WBamboPC] +STR_NAME :대나무 벽 + +[SCGAFRIC] +STR_NAME :아프리카 테마 + +[SCGARTIC] +STR_NAME :남극 테마 + +[SCGASIA] +STR_NAME :아시아 테마 + +[SCGAUSTR] +STR_NAME :오스트레일리아 테마 + +[SCGEUROP] +STR_NAME :유럽 테마 + +[SCGNAMRC] +STR_NAME :북아메리카 테마 + +[SCGSAMER] +STR_NAME :남아메리카 테마 + +[AFRICENT] +STR_NAME :아프리카식 공원 입구 + +[EUROENT] +STR_NAME :유럽식 공원 입구 + +[ICEENT] +STR_NAME :얼음 공원 입구 + +[JAPENT] +STR_NAME :일본식 공원 입구 + +[NAENT] +STR_NAME :북아메리카식 공원 입구 + +[OZENTRAN] +STR_NAME :오스트레일리아식 공원 입구 + +[SAMERENT] +STR_NAME :남아메리카식 공원 입구 + +############################################################################### +## Time Twister Objects +############################################################################### +[SCHOOLBS] +STR_NAME :스쿨 버스 라이드 +STR_DESC :노란 버스 테마의 모형 전차 +STR_CPTY :차량당 10명의 승객 + +[TELEPTER] +STR_NAME :텔레포터 +STR_DESC :탑승객들은 수직 탑을 따라 이동하는 엘리베이터에 올라타 여러 높이를 손쉽게 이동할 수 있습니다. +STR_CPTY :승객 16명 + +[ZEPLELIN] +STR_NAME :비행선 모노레일 차량 +STR_DESC :유선형의 전두부와 후두부 차량을 가진 대용량의 모노레일 차량 +STR_CPTY :차량당 승객 5명 또는 10명 + +[BMVOCTPS] +STR_NAME :외계 전망탑 +STR_DESC :높은 탑을 따라 올라가면서 회전하는 전망대 객실 +STR_CPTY :승객 20명 + +[CYCLOPSX] +STR_NAME :사이클롭스 라이드 +STR_DESC :대형 사이클롭스의 눈을 운전하는 놀이기구 +STR_CPTY :차량당 1명의 손님 + +[FIGTKNIT] +STR_NAME :파이팅 나이트 범퍼카 +STR_DESC :말 테마의 범퍼카에서 마상 창 시합을 하는 느낌을 받게 해주는 놀이기구 +STR_CPTY :차량당 1명의 손님 + +[FLWRPOWR] +STR_NAME :가든 파워 라이드 +STR_DESC :중앙 모터에 의해 움직이며 탑승객이 조종할 수 있는 꽃 모양의 작은 보트 +STR_CPTY :차량당 승객 1명 + +[FUNHOUSE] +STR_NAME :펀 하우스 +STR_DESC :건물 containing moving walls and floors to disorientate people walking through it +STR_CPTY :손님 5명 + +[HALOFMRS] +STR_NAME :거울의 방 +STR_DESC :건물 containing warped mirrors which distort the reflection of the viewer +STR_CPTY :손님 5명 + +[HOVERCAR] +STR_NAME :호버 카 라이드 +STR_DESC :Mag Lev technology has been implemented to create the illusion of futuristic hover cars +STR_CPTY :차량당 2명의 승객 + +[MGR2] +STR_NAME :2층 회전목마 +STR_DESC :Traditional enclosed double-deck carousel with carved wooden horses +STR_CPTY :승객 32명 + +[PEGASUSX] +STR_NAME :페가수스 라이드 +STR_DESC :Powered vehicles in the shape of Pegasus drawing a cart, follow a track-based route +STR_CPTY :차량당 2명의 승객 + +[SPOKPRSN] +STR_NAME :귀신의 감옥집 +STR_DESC :Building containing dungeons and mannequins of incarcerated figures, to scare people walking through it +STR_CPTY :손님 16명 + +[TIMEMACH] +STR_NAME :타임 머신 +STR_DESC :Guests sit in a specially designed sphere, and experience the illusion of time travel +STR_CPTY :손님 1명 + +[TRICATOP] +STR_NAME :트리케라톱스 범퍼카 +STR_DESC :트리케라톱스 모양의 범퍼카에 타고 서로 함께 부딛히는 차량 +STR_CPTY :차량당 1명의 손님 + +[BARNSTRM] +STR_NAME :곡예 비행기 코스터 +STR_DESC :거대한 루프, 트위스트와 급격한 낙하 트랙을 따라 이동하며, 탑승객이 트랙 아래에 매달린 좌석에 앉는 차량 +STR_CPTY :차량당 4명의 승객 + +[BATTRRAM] +STR_NAME :공성 망치 코스터 +STR_DESC :A compact steel-tracked roller coaster with a spiral lift hill and cars with in-line seating +STR_CPTY :차량당 6명의 승객 + +[BLCKDETH] +STR_NAME :블랙 데스 라이드 +STR_DESC :Riders career down a twisting track in Rat-shaped cars guided only by the curvature and banking of the semi-circular track +STR_CPTY :차량당 2명의 승객 + +[CERBERUS] +STR_NAME :케르베로스 코스터 +STR_DESC :Sitting in comfortable trains with only simple lap restraints riders enjoy giant smooth drops and twisting track as well as plenty of 'air time' over the hills +STR_CPTY :차량당 4명의 승객 + +[DRAGNFLY] +STR_NAME :잠자리 코스터 +STR_DESC :Passengers ride suspended in a specially designed car from the single-rail track, swinging freely from side to side around corners +STR_CPTY :승객 2명 per car + +[GANSTRCR] +STR_NAME :갱스터 카 코스터 +STR_DESC :1920s Themed Gangster cars are accelerated out of the station by linear induction motors to speed through twisting inversions +STR_CPTY :차량당 4명의 승객 + +[HARPIESX] +STR_NAME :하피 코스터 +STR_DESC :Riders are held in special harnesses in a lying-down position, travelling through twisted track and inversions either on their backs or facing the ground +STR_CPTY :차량당 4명의 승객 + +[HOTRODXX] +STR_NAME :개조 자동차 코스터 +STR_DESC :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station +STR_CPTY :차량당 2명의 승객 + +[HOVERBKE] +STR_NAME :호버 바이크 라이드 +STR_DESC :Riders sit on futuristic bike-shaped vehicles which travel along a single-rail track +STR_CPTY :차량당 2명의 승객 + +[HOVRBORD] +STR_NAME :호버보드 코스터 +STR_DESC :Guests ride on a futuristic hoverboard, swinging freely from side to side around corners +STR_CPTY :차량당 승객 2명 + +[JETPACKX] +STR_NAME :제트 팩 부스터 +STR_DESC :Riders sit in a vehicle which is launched up a vertical section of track +STR_CPTY :차량당 8명의 승객 + +[JETPLANE] +STR_NAME :제트여객기 코스터 +STR_DESC :A compact roller coaster with individual cars and smooth twisting drops +STR_CPTY :차량당 4명의 승객 + +[JOUSTING] +STR_NAME :저스팅 나이트 코스터 +STR_DESC :Riders sit on the back of Horse-shaped vehicles along a single-rail track +STR_CPTY :차량당 2명의 승객 + +[POLCHASE] +STR_NAME :폴리스 체이스 코스터 +STR_DESC :A looping roller coaster where the riders ride in a sitting position +STR_CPTY :차량당 4명의 승객 + +[POLICECR] +STR_NAME :폴리스 카 코스터 +STR_DESC :1960s Themed Police cars run on wooden tracks, turning around on special reversing sections +STR_CPTY :차량당 6명의 승객 + +[PTERODAC] +STR_NAME :익룡 코스터 +STR_DESC :Riders are held in comfortable seats below the track, travelling through twisted track to give the ultimate prehistoric flying experience +STR_CPTY :차량당 4명의 승객 + +[RAPTORXX] +STR_NAME :랩터 레이서 코스터 +STR_DESC :Riders sit on the back of Raptor-shaped vehicles along a single-rail track +STR_CPTY :차량당 2명의 승객 + +[SEAPLANE] +STR_NAME :수상비행기 라이드 +STR_DESC :Suspended roller coaster train consisting of cars able to swing freely as the train goes around corners +STR_CPTY :차량당 4명의 승객 + +[STAMPHRD] +STR_NAME :소 떼 코스터 +STR_DESC :A looping roller coaster with vehicles in the shape of a stampeding dinosaur herd. +STR_CPTY :차량당 4명의 승객 + +[VALKYRIE] +STR_NAME :발키리 코스터 +STR_DESC :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_CPTY :차량당 6명의 승객 + +[1920RACR] +STR_NAME :1920년대 레이싱 카 +STR_DESC :1920년대 레이싱 카 테마의 고 카트에 타고 레이스를 펼치는 놀이기구 +STR_CPTY :1인승 + +[CAVMNCAR] +STR_NAME :석기시대 차 +STR_DESC :석기시대의 고 카트에 타고 레이스를 펼치는 놀이기구 +STR_CPTY :1인승 + +[DINOEGGS] +STR_NAME :공룡 알 라이드 +STR_DESC :탑승객 두 명이 움직이는 어미 공룡 주위를 도는 좌석에 앉아 즐기는 놀이기구 +STR_CPTY :승객 18명 + +[FLALMACE] +STR_NAME :메이스 라이드 +STR_DESC :Riders sit on a themed chair which is attached to a motor driven spinning arm. +STR_CPTY :의자당 1명의 승객 + +[GINTSPDR] +STR_NAME :B급 영화 자이언트 스파이더 라이드 +STR_DESC :Riders ride in pairs of themed seats which rotate around a large B-Movie Spider. +STR_CPTY :승객 18명 + +[MICROBUS] +STR_NAME :마이크로버스 라이드 +STR_DESC :Riders view a film inside the motion simulator pod while it is twisted and moved around by a hydraulic arm +STR_CPTY :승객 8명 + +[NEPTUNEX] +STR_NAME :넵튠 라이드 +STR_DESC :Riders ride in pairs, in themed seats rotating around an animated statue of Neptune. +STR_CPTY :승객 18명 + +[TOMMYGUN] +STR_NAME :기관 단총 라이드 +STR_DESC :Riders ride in pairs of themed seats which rotate around a large replica Tommy Gun. +STR_CPTY :승객 18명 + +[TREBUCHT] +STR_NAME :투석기 라이드 +STR_DESC :Passengers ride in a carriage suspended by two large arms, based on a Dark Age Siege Weapon +STR_CPTY :승객 8명 + +[FLYGBOAT] +STR_NAME :플라잉 보트 라이드 +STR_DESC :Flying Boat shaped cars run on roller coaster track to allow twisting curves and steep drops, splashing down into sections of water for gentle river sections +STR_CPTY :보트당 16명의 승객 + +[OAKBAREL] +STR_NAME :참나무 통 라이드 +STR_DESC :Oak Barrels meander along a wide water channel, splashing through waterfalls and thrilling riders through foaming rapids +STR_CPTY :보트당 8명의 승객 + +[RIVRSTYX] +STR_NAME :스틱스 강 +STR_DESC :강 모양의 트랙을 따라 조용히 흘러가는 보트 +STR_CPTY :보트당 4명의 승객 + +[TRILOBTE] +STR_NAME :삼엽충 보트 +STR_DESC :Trilobite shaped cars run on roller coaster track to allow twisting curves and steep drops, splashing down into sections of water for gentle river sections +STR_CPTY :보트당 16명의 승객 + +[1920SAND] +STR_NAME :아르데코 음식 상점 +STR_DESC :국수와 신선한 레모네이드를 파는 가게 + +[1960TSRT] +STR_NAME :사랑과 평화 티셔츠 +STR_DESC :꽃무늬 티셔츠를 파는 상점 + +[MEDISOUP] +STR_NAME :마녀의 비약 수프 +STR_DESC :걸쭉한 죽 스타일의 수프를 파는 가게 + +[MKTSTAL1] +STR_NAME :사과 토피 사탕 시장 상점 +STR_DESC :끈적거리는 사과 토피 사탕을 파는 가게 + +[MKTSTAL2] +STR_NAME :레모네이드 시장 상점 +STR_DESC :신선한 레모네이드를 파는 오래된 테마의 가게 + +[MOONJUCE] +STR_NAME :달빛 주스 +STR_DESC :최신 청량음료를 파는 가게 + +[MYTHOSEA] +STR_NAME :포세이돈의 해산물 가게 +STR_DESC :포세이돈의 짭짤한 음식을 파는 가게 + +[SOFTOYST] +STR_NAME :봉제인형 가게 +STR_DESC :귀엽고 부드러운 공룡 인형을 파는 가게 + +[1920SLMP] +STR_NAME :기간 가로등 + +[ALENTRE1] +STR_NAME :외계 나무 + +[ALENTRE2] +STR_NAME :외계 나무 + +[ARMRBODY] +STR_NAME :마법 아머 + +[ARMRHELM] +STR_NAME :마법 헬멧 + +[ARMRSHLD] +STR_NAME :마법 방패 + +[ARMRSWRD] +STR_NAME :마법 검 + +[ARTDEC01] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC02] +STR_NAME :아트 데코 반전된 구석 조각 + +[ARTDEC03] +STR_NAME :문이 있는 아트 데코 벽 + +[ARTDEC04] +STR_NAME :창문이 있는 아트 데코 벽 + +[ARTDEC05] +STR_NAME :창문이 있는 아트 데코 벽 + +[ARTDEC06] +STR_NAME :아트 데코 상단 조각 + +[ARTDEC07] +STR_NAME :아트 데코 구석 조각 + +[ARTDEC08] +STR_NAME :아트 데코 상단 구석 조각 + +[ARTDEC09] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC10] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC11] +STR_NAME :창문이 있는 아트 데코 구석 + +[ARTDEC12] +STR_NAME :철책이 있는 아트 데코 구석 + +[ARTDEC13] +STR_NAME :아트 데코 상단 구석 조각 + +[ARTDEC14] +STR_NAME :창문이 있는 아트 데코 구석 + +[ARTDEC15] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC16] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC17] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC18] +STR_NAME :아트 데코 상단 조각 + +[ARTDEC19] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC20] +STR_NAME :아트 데코 벽 조각 + +[ARTDEC21] +STR_NAME :철책이 있는 아트 데코 벽 + +[ARTDEC22] +STR_NAME :철책이 있는 아트 데코 벽 + +[ARTDEC23] +STR_NAME :철책이 있는 아트 데코 벽 + +[ARTDEC24] +STR_NAME :철책이 있는 아트 데코 벽 + +[ARTDEC28] +STR_NAME :아트 데코 지붕 조각 + +[ARTDEC29] +STR_NAME :아트 데코 반전된 구석 조각 + +[BIGBASSX] +STR_NAME :대형 베이스 기타 + +[BIGGUTAR] +STR_NAME :대형 기타 + +[CHPRBKE1] +STR_NAME :오토바이 + +[CHPRBKE2] +STR_NAME :오토바이 + +[ELECFEN5] +STR_NAME :Electric Fence Inverted 구석 조각 + +[FIREMANX] +STR_NAME :움직이는 소방관 + +[FUTSKY16] +STR_NAME :Sandstone Skyscraper Mid Slope 구석 + +[FUTSKY17] +STR_NAME :Sandstone Skyscraper Filler + +[FUTSKY18] +STR_NAME :Sandstone Skyscraper Doorway + +[FUTSKY19] +STR_NAME :Sandstone Skyscraper Bottom 구석 + +[FUTSKY21] +STR_NAME :Sandstone Skyscraper Mid 벽 Section + +[FUTSKY23] +STR_NAME :Sandstone Skyscraper Inverted 구석 Top + +[FUTSKY29] +STR_NAME :Sandstone Skyscraper Bottom 곡선형 Slope + +[FUTSKY34] +STR_NAME :Sandstone Skyscraper 지붕 + +[FUTSKY35] +STR_NAME :Sandstone Skyscraper Mid 곡선형 Slope + +[FUTSKY42] +STR_NAME :Sandstone Skyscraper 곡선형 Slope Top + +[FUTSKY52] +STR_NAME :Sandstone Skyscraper Bottom Inverted 구석 + +[FUTSKY53] +STR_NAME :Sandstone Skyscraper Mid 구석 + +[FUTSKY54] +STR_NAME :Obsidian SkyScraper 지붕 조각 + +[GLDCHEST] +STR_NAME :보물 상자 + +[GOLDFLEC] +STR_NAME :황금 양모 + +[HAYBAILS] +STR_NAME :건초 + +[HEVBTH05] +STR_NAME :Heavenly Baths Arch + +[HEVBTH06] +STR_NAME :Heavenly Baths Arch + +[HEVBTH07] +STR_NAME :Heavenly Baths Arch + +[HEVBTH08] +STR_NAME :Heavenly Baths 계단 + +[HEVBTH09] +STR_NAME :Heavenly Baths 계단 + +[HEVBTH10] +STR_NAME :Heavenly Baths Architecture + +[HEVBTH11] +STR_NAME :Heavenly Baths Architecture + +[HEVBTH12] +STR_NAME :Heavenly Baths Architecture + +[HEVBTH13] +STR_NAME :Heavenly Baths Architecture + +[HEVBTH14] +STR_NAME :Heavenly Bath Window + +[HEVBTH15] +STR_NAME :Heavenly Bath Floor + +[HEVROF01] +STR_NAME :Heavenly Bath 지붕 + +[HEVROF02] +STR_NAME :Heavenly Bath 지붕 + +[HEVROF03] +STR_NAME :Heavenly Bath 지붕 + +[HEVROF04] +STR_NAME :Heavenly Bath 지붕 + +[HRBWAL01] +STR_NAME :항구 벽 + +[HRBWAL02] +STR_NAME :항구 벽 with Fishing Gear + +[HRBWAL03] +STR_NAME :항구 벽 with Moor + +[HRBWAL04] +STR_NAME :항구 벽 with Moor + +[HRBWAL05] +STR_NAME :항구 벽 with Moor + +[HRBWAL06] +STR_NAME :항구 벽 with Moor + +[HURCLULS] +STR_NAME :헤라클레스 + +[INDWAL01] +STR_NAME :Industrial 벽 Set + +[INDWAL02] +STR_NAME :Industrial 벽 Set + +[INDWAL03] +STR_NAME :Industrial 벽 Set + +[INDWAL04] +STR_NAME :Industrial 벽 Set + +[INDWAL05] +STR_NAME :Industrial 지붕 구석 조각 + +[INDWAL06] +STR_NAME :Industrial 지붕 구석 조각 + +[INDWAL07] +STR_NAME :Industrial 벽 with Doorway + +[INDWAL08] +STR_NAME :Industrial 벽 with Doorway + +[INDWAL09] +STR_NAME :Industrial 벽 with Doorway + +[INDWAL10] +STR_NAME :Industrial 벽 with Doorway + +[INDWAL11] +STR_NAME :Industrial 벽 with Doorway + +[INDWAL12] +STR_NAME :Industrial 벽 with Doorway + +[INDWAL13] +STR_NAME :Industrial 벽 with Doorway + +[INDWAL14] +STR_NAME :Industrial 벽 구석 조각 + +[INDWAL15] +STR_NAME :Industrial 벽 구석 조각 + +[INDWAL16] +STR_NAME :Industrial 벽 with Window + +[INDWAL17] +STR_NAME :Industrial 벽 with Window + +[INDWAL18] +STR_NAME :Industrial 벽 with Window + +[INDWAL19] +STR_NAME :Industrial 벽 with Window + +[INDWAL20] +STR_NAME :Industrial 지붕 조각 + +[INDWAL21] +STR_NAME :Industrial 지붕 조각 + +[INDWAL22] +STR_NAME :Industrial 지붕 조각 + +[INDWAL23] +STR_NAME :Industrial 지붕 조각 + +[INDWAL24] +STR_NAME :Industrial 지붕 조각 + +[INDWAL25] +STR_NAME :Industrial 지붕 조각 + +[INDWAL26] +STR_NAME :Industrial 지붕 조각 + +[INDWAL27] +STR_NAME :Industrial 지붕 조각 + +[INDWAL28] +STR_NAME :Industrial 지붕 조각 + +[INDWAL29] +STR_NAME :Industrial 지붕 조각 + +[INDWAL30] +STR_NAME :Industrial 벽 with Window + +[INDWAL31] +STR_NAME :Industrial 벽 with Window + +[INDWAL32] +STR_NAME :Industrial 벽 with Window + +[JAILXX01] +STR_NAME :감옥 벽 조각 + +[JAILXX02] +STR_NAME :감옥 벽 조각 + +[JAILXX03] +STR_NAME :감옥 벽 조각 + +[JAILXX04] +STR_NAME :감옥 벽 조각 + +[JAILXX05] +STR_NAME :감옥 벽 조각 + +[JAILXX06] +STR_NAME :감옥 벽 조각 + +[JAILXX07] +STR_NAME :감옥 벽 지붕 + +[JAILXX08] +STR_NAME :반전된 감옥 조각 + +[JAILXX09] +STR_NAME :반전된 감옥 조각 + +[JAILXX10] +STR_NAME :반전된 감옥 조각 + +[JAILXX11] +STR_NAME :반전된 감옥 조각 + +[JAILXX12] +STR_NAME :반전된 감옥 조각 + +[JAILXX13] +STR_NAME :반전된 감옥 조각 + +[JAILXX14] +STR_NAME :감옥 감시탑 계단 + +[JAILXX15] +STR_NAME :감옥 감시탑 계단 + +[JAILXX16] +STR_NAME :감옥 감시탑 + +[JAILXX20] +STR_NAME :감옥 벽 구석 + +[JAILXX21] +STR_NAME :감옥 벽 구석 + +[JAZZMBR1] +STR_NAME :재즈 밴드 멤버 + +[JAZZMBR2] +STR_NAME :재즈 밴드 멤버 + +[JAZZMBR3] +STR_NAME :재즈 밴드 멤버 + +[JAZZMBR4] +STR_NAME :재즈 밴드 멤버 + +[MAMTHW01] +STR_NAME :대형 매머드 울타리 + +[MAMTHW02] +STR_NAME :대형 매머드 울타리 + +[MAMTHW03] +STR_NAME :Large Angled Mammoth Fence + +[MAMTHW04] +STR_NAME :Large Angled Mammoth Fence + +[MAMTHW05] +STR_NAME :Small Angled Mammoth Fence + +[MAMTHW06] +STR_NAME :Small Angled Mammoth Fence + +[MCASTL02] +STR_NAME :성벽 + +[MCASTL03] +STR_NAME :성벽 + +[MCASTL04] +STR_NAME :성벽 + +[MCASTL05] +STR_NAME :Castle Ramparts 구석 + +[MCASTL06] +STR_NAME :Castle Ramparts + +[MCASTL07] +STR_NAME :Castle Ramparts 구석 + +[MCASTL08] +STR_NAME :Castle Ramparts Inverted 구석 + +[MCASTL09] +STR_NAME :Castle 구석 조각 + +[MCASTL10] +STR_NAME :Castle Ramparts 구석 + +[MCASTL19] +STR_NAME :Castle 구석 조각 + +[MDBUCKET] +STR_NAME :바구니 + +[MEDSTOOL] +STR_NAME :Stool + +[MEDTOOLS] +STR_NAME :Farm Tools + +[MEDTRGET] +STR_NAME :화살 과녁 + +[METEORCR] +STR_NAME :Meteor Crater 구석 + +[METEORST] +STR_NAME :Meteor Crater 벽 + +[METRCRS1] +STR_NAME :Meteor Crater 벽 with Crystals + +[METRCRS2] +STR_NAME :Meteor Crater 벽 with Crystals + +[MINOTAUR] +STR_NAME :미노타우로스 상 + +[OLDNYK01] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK02] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK03] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK04] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK05] +STR_NAME :뉴욕 지붕 조각 + +[OLDNYK06] +STR_NAME :뉴욕 구석 충전제 + +[OLDNYK07] +STR_NAME :반전된 뉴욕 구석 조각 + +[OLDNYK08] +STR_NAME :반전된 뉴욕 구석 조각 + +[OLDNYK09] +STR_NAME :반전된 뉴욕 구석 조각 + +[OLDNYK10] +STR_NAME :반전된 뉴욕 구석 조각 + +[OLDNYK11] +STR_NAME :선이 있는 뉴욕 벽 + +[OLDNYK12] +STR_NAME :뉴욕 빨랫줄 + +[OLDNYK13] +STR_NAME :선이 있는 뉴욕 벽 + +[OLDNYK14] +STR_NAME :뉴욕 빨랫줄 + +[OLDNYK15] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK16] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK17] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK18] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK19] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK31] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK33] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK34] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK35] +STR_NAME :뉴욕 지붕 조각 + +[PRIMWAL1] +STR_NAME :Wood Fence with Dead Vines + +[PRIMWAL2] +STR_NAME :Wood Fence with Dead Vines + +[PRIMWAL3] +STR_NAME :Wood Fence with Dead Vines + +[PSNTWL02] +STR_NAME :암흑 시대 마을 하단 벽 조각 + +[PSNTWL03] +STR_NAME :암흑 시대 마을 하단 벽 조각 + +[PSNTWL04] +STR_NAME :암흑 시대 마을 하단 벽 조각 + +[PSNTWL05] +STR_NAME :암흑 시대 마을 하단 벽 조각 + +[PSNTWL06] +STR_NAME :암흑 시대 마을 하단 벽 조각 + +[PSNTWL07] +STR_NAME :암흑 시대 마을 하단 벽 조각 + +[PSNTWL08] +STR_NAME :암흑 시대 마을 하단 구석 조각 + +[PSNTWL09] +STR_NAME :암흑 시대 마을 상단 벽 조각 + +[PSNTWL10] +STR_NAME :암흑 시대 마을 상단 벽 조각 + +[PSNTWL11] +STR_NAME :암흑 시대 마을 상단 벽 조각 + +[PSNTWL12] +STR_NAME :암흑 시대 마을 상단 벽 조각 + +[PSNTWL13] +STR_NAME :암흑 시대 마을 상단 벽 조각 + +[PSNTWL14] +STR_NAME :암흑 시대 마을 지붕 조각 + +[PSNTWL15] +STR_NAME :반전된 암흑 시대 마을 지붕 조각 + +[PSNTWL16] +STR_NAME :암흑 시대 마을 지붕 조각 + +[PSNTWL17] +STR_NAME :암흑 시대 마을 지붕 조각 + +[PSNTWL20] +STR_NAME :암흑 시대 마을 창가 화단 지붕 + +[PSNTWL21] +STR_NAME :암흑 시대 마을 창가 화단 지붕 + +[PSNTWL23] +STR_NAME :암흑 시대 마을 상단 구석 조각 + +[PSNTWL24] +STR_NAME :암흑 시대 마을 창가 화단 + +[PSNTWL25] +STR_NAME :암흑 시대 마을 창가 화단 + +[PSNTWL29] +STR_NAME :암흑 시대 마을 창가 화단 지붕 + +[PSNTWL30] +STR_NAME :암흑 시대 마을 창가 화단 지붕 + +[PSNTWL31] +STR_NAME :암흑 시대 마을 구석 지붕 조각 + +[RDMETO03] +STR_NAME :붉은 유성 크레이터 벽 + +[RDMETO04] +STR_NAME :반전된 붉은 유성 크레이터 구석 + +[RUNWAY01] +STR_NAME :활주로 조각 + +[RUNWAY02] +STR_NAME :활주로 조각 + +[RUNWAY03] +STR_NAME :활주로 구석 조각 +[RUNWAY04] +STR_NAME :활주로 가장자리 조각 + +[RUNWAY05] +STR_NAME :활주로 조각 + +[RUNWAY06] +STR_NAME :반전된 활주로 구석 조각 + +[SCHNCRSH] +STR_NAME :난파된 수상비행기 + +[SCHNDRUM] +STR_NAME :기름통 + +[SCHNPL05] +STR_NAME :수상비행기 + +[SCHNPL06] +STR_NAME :수상비행기 + +[SCHNTNNY] +STR_NAME :레이싱 스피커 장치 + +[SHWDFRST] +STR_NAME :숲 속 나무 + +[SMOKSK02] +STR_NAME :Smoke Stack Mid + +[SMOKSK03] +STR_NAME :Smoke Stack 기본 + +[SPCSHP06] +STR_NAME :Space Ship Cross Section + +[SPCSHP09] +STR_NAME :Space Ship Docking Section + +[SPCSHP10] +STR_NAME :Space Ship Engine Section + +[SPCSHP11] +STR_NAME :Space Ship Living Section + +[STNESTA1] +STR_NAME :돌이 된 사람 + +[STNESTA2] +STR_NAME :돌이 된 사람 + +[STNESTA3] +STR_NAME :돌이 된 사람 + +[STNESTA4] +STR_NAME :돌이 된 사람 + +[STOOLSET] +STR_NAME :의자 + +[SWAMPLT1] +STR_NAME :Swamp Plant + +[SWAMPLT2] +STR_NAME :Swamp Fern + +[SWAMPLT3] +STR_NAME :Swamp Fern + +[SWAMPLT4] +STR_NAME :Swamp Plant + +[SWAMPLT5] +STR_NAME :Swamp Plant + +[SWAMPLT6] +STR_NAME :Swamp Fern + +[SWAMPLT7] +STR_NAME :Swamp Fern + +[SWAMPLT8] +STR_NAME :Swamp Fern + +[SWAMPLT9] +STR_NAME :Swamp Fern + +[SWRDSTNE] +STR_NAME :Sword in the Stone + +[TARPIT04] +STR_NAME :거품이 이는 타르갱 + +[TARPIT05] +STR_NAME :거품이 이는 타르갱 + +[TARPIT06] +STR_NAME :거품이 이는 타르갱 + +[TARPIT07] +STR_NAME :거품이 이는 타르갱 + +[TARPIT08] +STR_NAME :거품이 이는 타르갱 + +[TARPIT09] +STR_NAME :거품이 이는 타르갱 + +[TARPIT10] +STR_NAME :거품이 이는 타르갱 + +[TARPIT11] +STR_NAME :거품이 이는 타르갱 + +[TARPIT12] +STR_NAME :거품이 이는 타르갱 + +[TARPIT13] +STR_NAME :거품이 이는 타르갱 + +[TARPIT14] +STR_NAME :거품이 이는 타르갱 + +[VALKRI01] +STR_NAME :발키리 + +[VALKRI02] +STR_NAME :Valkyrie + +[WDNCART2] +STR_NAME :Wooden Cart + +[WEPNRACK] +STR_NAME :Weapon Set + +[WISKYBL1] +STR_NAME :Whisky Barrel + +[WISKYBL2] +STR_NAME :Whisky Barrels + +[YEWTREEX] +STR_NAME :Yew Tree + +[ZEUSSTAT] +STR_NAME :Zeus Statue + +[ALENPLT1] +STR_NAME :Alien Plant + +[ALENPLT2] +STR_NAME :Alien Plant + +[ALLSEEYE] +STR_NAME :Animatronic All Seeing Eye + +[ALNSTR01] +STR_NAME :Alien Structure Small + +[ALNSTR02] +STR_NAME :Alien Structure Small + +[ALNSTR03] +STR_NAME :Alien Structure Small + +[ALNSTR04] +STR_NAME :Alien Skylight Small + +[ALNSTR05] +STR_NAME :Alien Tower Bottom + +[ALNSTR06] +STR_NAME :Alien Tower Middle + +[ALNSTR07] +STR_NAME :Alien Tower Top + +[ARGONAU1] +STR_NAME :Animatronic Argonaut + +[ARGONAU2] +STR_NAME :Animatronic Argonaut + +[ARGONAU3] +STR_NAME :Animatronic Argonaut + +[ASTRONGT] +STR_NAME :Animatronic Astronaut + +[BKRGANG1] +STR_NAME :Biker + +[BOLPOT01] +STR_NAME :Boiling Pot + +[CAGDSTAT] +STR_NAME :Animatronic Eagle on Cage + +[CAVEMENX] +STR_NAME :Animatronic Caveman lighting Fire + +[CHANMAID] +STR_NAME :Animatronic Chained Maiden + +[CLNSMEN1] +STR_NAME :Animatronic Clansman + +[COMPEYEX] +STR_NAME :Super Computer Monitor + +[COOKSPIT] +STR_NAME :Animal cooking on Spit + +[DINSIGN1] +STR_NAME :Neon Diner Sign + +[DINSIGN2] +STR_NAME :Neon Diner Sign + +[DINSIGN3] +STR_NAME :Neon Diner Sign + +[DINSIGN4] +STR_NAME :Neon Diner Sign + +[DKFIGHT1] +STR_NAME :Animatronic Knight + +[DKFIGHT2] +STR_NAME :Animatronic Knight + +[DRGNATTK] +STR_NAME :Dragon Attacking + +[ELECFEN1] +STR_NAME :Electric Fence 구석 조각 + +[ELECFEN2] +STR_NAME :Electric Fence + +[ELECFEN3] +STR_NAME :Electric Fence with Light + +[ELECFEN4] +STR_NAME :Electric Fence 부서진 + +[EVALIEN1] +STR_NAME :Animatronic Evil Alien + +[EVALIEN2] +STR_NAME :Animatronic Evil Alien + +[EVALIEN3] +STR_NAME :Animatronic Evil Alien + +[FIRCANON] +STR_NAME :Animatronic Firing Cannon + +[FLTSIGN1] +STR_NAME :Anti-Gravity LCD Billboard + +[FLTSIGN2] +STR_NAME :Anti-Gravity LCD Billboard + +[FRBEACON] +STR_NAME :Fiery Beacon + +[FUROBOT1] +STR_NAME :로봇 + +[FUROBOT2] +STR_NAME :로봇 + +[FUTSKY01] +STR_NAME :Sandstone Skyscraper Walkway + +[FUTSKY02] +STR_NAME :Sandstone Skyscraper Filler + +[FUTSKY03] +STR_NAME :Sandstone Skyscraper Bottom 구석 + +[FUTSKY04] +STR_NAME :Sandstone Skyscraper 곡선형 Slope Top + +[FUTSKY05] +STR_NAME :Sandstone Skyscraper 구석 Top + +[FUTSKY06] +STR_NAME :Sandstone Skyscraper Mid 곡선형 Slope + +[FUTSKY07] +STR_NAME :Sandstone Skyscraper Mid 벽 Section + +[FUTSKY08] +STR_NAME :Sandstone Skyscraper Mid 벽 Section + +[FUTSKY09] +STR_NAME :Sandstone Skyscraper Mid 벽 Section + +[FUTSKY10] +STR_NAME :Sandstone Skyscraper Bottom Slope 기본 + +[FUTSKY11] +STR_NAME :Sandstone Skyscraper Mid 구석 + +[FUTSKY12] +STR_NAME :Sandstone Skyscraper Mid 벽 Section + +[FUTSKY13] +STR_NAME :Sandstone Skyscraper 지붕 Spire + +[FUTSKY14] +STR_NAME :Sandstone Skyscraper 지붕 Spire + +[FUTSKY15] +STR_NAME :Sandstone Skyscraper Docking Bay + +[FUTSKY33] +STR_NAME :Sandstone Skyscraper Walkway + +[FUTSKY36] +STR_NAME :Obsidian SkyScraper Door 조각 + +[FUTSKY37] +STR_NAME :Obsidian SkyScraper Shallow Slope 구석 + +[FUTSKY38] +STR_NAME :Obsidian SkyScraper Shallow Sloped 벽 + +[FUTSKY39] +STR_NAME :Obsidian SkyScraper Shallow Slope 구석 + +[FUTSKY40] +STR_NAME :Obsidian SkyScraper Steep Sloped 벽 + +[FUTSKY41] +STR_NAME :Obsidian SkyScraper Steep Sloped 벽 + +[FUTSKY44] +STR_NAME :Obsidian SkyScraper Steep Sloped 벽 + +[FUTSKY46] +STR_NAME :Obsidian SkyScraper Steep Slope 구석 + +[FUTSKY47] +STR_NAME :Obsidian SkyScraper 벽 + +[FUTSKY48] +STR_NAME :Obsidian SkyScraper 벽 with Window + +[FWRPRDC1] +STR_NAME :Groovy Dancer + +[GANGSTER] +STR_NAME :Animatronic Gangster + +[GDALIEN1] +STR_NAME :Animatronic Good Alien + +[GDALIEN2] +STR_NAME :Animatronic Good Alien + +[GDALIEN3] +STR_NAME :Animatronic Good Alien + +[GEYSERXX] +STR_NAME :간헐천 + +[GGNTOCTO] +STR_NAME :B-Movie 대형 Octopus + +[GGNTSPID] +STR_NAME :B-Movie 대형 Spider + +[GSCORPO2] +STR_NAME :Animatronic attacking Scorpion + +[GSCORPON] +STR_NAME :Animatronic attacking Scorpion + +[GUYQWIFX] +STR_NAME :Singer with Quiff + +[HEVBTH01] +STR_NAME :Heavenly Bath Pool + +[HEVBTH02] +STR_NAME :Heavenly Bath Pool 구석 + +[HEVBTH03] +STR_NAME :Heavenly Baths Fountain + +[HEVBTH04] +STR_NAME :Heavenly Baths Fountain + +[HEVBTH16] +STR_NAME :Heavenly Bath Pool Steps + +[HEVBTH17] +STR_NAME :Heavenly Bath Pool Edge + +[HORSECRT] +STR_NAME :말 + +[HOVRCAR1] +STR_NAME :Hovercar on Stand + +[HOVRCAR2] +STR_NAME :Hovercar on Stand + +[HOVRCAR3] +STR_NAME :Hovercar Flying + +[HOVRCAR4] +STR_NAME :Hovercar Flying + +[HVRBIKE1] +STR_NAME :Hoverbike on Stand + +[HVRBIKE2] +STR_NAME :Hoverbike on Stand + +[HVRBIKE3] +STR_NAME :Hoverbike Flying + +[HVRBIKE4] +STR_NAME :Hoverbike Flying + +[KILLRVIN] +STR_NAME :Climbing Vine Tree + +[KNFIGHT1] +STR_NAME :Animatronic Dark Knight + +[KNFIGHT2] +STR_NAME :Animatronic Dark Knight + +[LARGECPU] +STR_NAME :Super Computer Large CPU + +[LASERX01] +STR_NAME :레이저 울타리 + +[LASERX02] +STR_NAME :레이저 울타리 구석 + +[MDUSASTA] +STR_NAME :Animatronic Medusa + +[PDFLAG02] +STR_NAME :Period Flag + +[PDFLAG03] +STR_NAME :Period Flag + +[PDFLAG04] +STR_NAME :Period Flag + +[PDFLAG05] +STR_NAME :Period Flag + +[PDFLAG06] +STR_NAME :Period Flag + +[PDFLAG08] +STR_NAME :Period Flag + +[PDFLAG13] +STR_NAME :Period Flag + +[PDFLAG14] +STR_NAME :Period Flag + +[PDFLAG15] +STR_NAME :Period Flag + +[PDFLAG16] +STR_NAME :Period Flag + +[POLWTBTN] +STR_NAME :Animatronic Police Officer + +[PRIMHEAD] +STR_NAME :Wood Fence with Man Eating Plant + +[PRIMHEAR] +STR_NAME :Wood Fence with Man Eating Plant + +[PRIMROOR] +STR_NAME :Wood Fence with Climbing Vines + +[PRIMROOT] +STR_NAME :Wood Fence with Climbing Vines + +[PRIMSCRN] +STR_NAME :Wood Fence with Man Eating Plant + +[PRIMST01] +STR_NAME :Wood Fence with Man Eating Plant + +[PRIMST02] +STR_NAME :Wood Fence with Man Eating Plant + +[PRIMST03] +STR_NAME :Wood Fence with Man Eating Plant + +[PRIMTALL] +STR_NAME :Wood Fence with Man Eating Plant + +[PSNTWL01] +STR_NAME :암흑 시대 마을 지붕 with Chimney + +[RCKNROLR] +STR_NAME :Cool Dude + +[ROBNHOOD] +STR_NAME :Animatronic Robin Hood + +[RSWATRES] +STR_NAME :Rollerskating Waitress + +[SCHNBOST] +STR_NAME :부표 + +[SCHNBOUY] +STR_NAME :부표 + +[SCHNPL01] +STR_NAME :수상비행기 + +[SCHNPL02] +STR_NAME :수상비행기 + +[SCHNPL03] +STR_NAME :수상비행기 + +[SCHNPL04] +STR_NAME :수상비행기 + +[SDRAGFLY] +STR_NAME :Animatronic Dragonflies + +[SKELETO1] +STR_NAME :Animatronic Skeletal Army + +[SKELETO2] +STR_NAME :Animatronic Skeletal Army + +[SKELETO3] +STR_NAME :Animatronic Skeletal Army + +[SMALLCPU] +STR_NAME :Super Computer Small CPU + +[SMOKSK01] +STR_NAME :Large Smoking Chimney + +[SOUPCRN2] +STR_NAME :원생액 + +[SOUPCRNR] +STR_NAME :원생액 + +[SOUPED01] +STR_NAME :원생액 + +[SOUPED02] +STR_NAME :원생액 + +[SOUPTL01] +STR_NAME :원생액 + +[SOUPTL02] +STR_NAME :원생액 + +[SPACRANG] +STR_NAME :Animatronic Space Ranger + +[SPCSHP01] +STR_NAME :Space Ship Cargo Section + +[SPCSHP02] +STR_NAME :Space Ship Comms Section + +[SPCSHP03] +STR_NAME :Space Ship Solar Section + +[SPCSHP04] +STR_NAME :Space Ship Solar Panels + +[SPCSHP05] +STR_NAME :Space Ship Gravity Section + +[SPCSHP07] +STR_NAME :Space Ship Control Deck + +[SPCSHP08] +STR_NAME :Space Ship Fuel Section + +[SPCSHP12] +STR_NAME :Space Ship Science Section + +[SPEAKR01] +STR_NAME :Small Speaker + +[SPEAKR02] +STR_NAME :Large Speaker + +[SPIKTAIL] +STR_NAME :Animatronic Stegosaurus + +[SPTERDAC] +STR_NAME :Animatronic flapping Pterodactyl + +[STGBAND1] +STR_NAME :밴드 멤버 + +[STGBAND2] +STR_NAME :밴드 멤버 + +[STGBAND3] +STR_NAME :밴드 멤버 + +[STGBAND4] +STR_NAME :밴드 멤버 + +[STMDRAN1] +STR_NAME :Steaming Drains + +[STRICTOP] +STR_NAME :Animatronic Triceratops + +[TARPIT01] +STR_NAME :거품이 이는 타르갱 + +[TARPIT02] +STR_NAME :거품이 이는 타르갱 + +[TARPIT03] +STR_NAME :거품이 이는 타르갱 + +[TITANSTA] +STR_NAME :Atlas Statue + +[TYRANREX] +STR_NAME :Animatronic T-Rex + +[VOLCVENT] +STR_NAME :Active Volcanic Vent + +[WAVEKING] +STR_NAME :Animatronic Waving King + +[WHCCOLDS] +STR_NAME :Witches around Cauldron + +[ARTDEC25] +STR_NAME :아트 데코 구석 with Windows + +[ARTDEC26] +STR_NAME :아트 데코 구석 with Railings + +[ARTDEC27] +STR_NAME :아트 데코 Top 구석 Section + +[FUTSKY20] +STR_NAME :Sandstone Skyscraper Bottom Inverted 구석 + +[FUTSKY22] +STR_NAME :Sandstone Skyscraper Bottom Inverted 구석 + +[FUTSKY24] +STR_NAME :Sandstone Skyscraper Bottom Inverted 구석 + +[FUTSKY25] +STR_NAME :Sandstone Skyscraper Bottom Inverted 구석 + +[FUTSKY26] +STR_NAME :Sandstone Skyscraper Bottom Inverted 구석 + +[FUTSKY28] +STR_NAME :Sandstone Walkway T-Junction + +[FUTSKY30] +STR_NAME :Sandstone Walkway 구석 + +[FUTSKY31] +STR_NAME :Sandstone Walkway Cross Section + +[FUTSKY32] +STR_NAME :Sandstone Walkway End Section + +[JAILXX17] +STR_NAME :감옥 문 + +[MAJOROAK] +STR_NAME :대형 오크 + +[MCASTL01] +STR_NAME :Castle Inverted 구석 + +[MCASTL11] +STR_NAME :Castle Portcullis + +[MCASTL12] +STR_NAME :Castle Entrance + +[MELMTREE] +STR_NAME :Large Elm Tree + +[OLDNYK24] +STR_NAME :반전된 뉴욕 구석 지붕 + +[OLDNYK25] +STR_NAME :뉴욕 지붕 조각 + +[OLDNYK26] +STR_NAME :뉴욕식 입구 + +[OLDNYK32] +STR_NAME :뉴욕 지붕 조각 + +[1950SCAR] +STR_NAME :1950년대 자동차 + +[4X4DINER] +STR_NAME :Period Diner + +[4X4GMANT] +STR_NAME :대형 Mangrove Tree + +[4X4STNHN] +STR_NAME :Stone Age Temple + +[4X4TRPIT] +STR_NAME :거품이 이는 타르갱 + +[4X4VOLCA] +STR_NAME :Volcano with small trees + +[ALENCRSH] +STR_NAME :UFO 추락 현장 + +[ALNSTR08] +STR_NAME :Alien Structure Large + +[ALNSTR09] +STR_NAME :Alien Structure Large + +[ALNSTR10] +STR_NAME :Alien Structure Large + +[ALNSTR11] +STR_NAME :Alien Skylight Large + +[ASHNYMPH] +STR_NAME :Ash Tree with Nymphs + +[BANDBUSX] +STR_NAME :Rock Band Tour Bus + +[BIGDRUMS] +STR_NAME :대형 드럼 키트 + +[CAVENTRA] +STR_NAME :Cave Entrance + +[CORNS2X2] +STR_NAME :Roman Palace 구석 조각 + +[CORVS2X2] +STR_NAME :Roman Palace 구석 조각 + +[CRATR2X2] +STR_NAME :Small Meteor Crater + +[CRATR4X4] +STR_NAME :Large Meteor Crater + +[CRSSS2X2] +STR_NAME :Roman Palace Cross Section + +[CRSVS2X2] +STR_NAME :Roman Palace Cross Section + +[CYCLOPSS] +STR_NAME :Cyclops Statue + +[FEASTABL] +STR_NAME :Feast Table + +[FOOTPRNT] +STR_NAME :대형 공룡 발자국 + +[FORBIDFT] +STR_NAME :Forbidden Fruit Tree + +[GBEETLEX] +STR_NAME :1950년대 자동차 + +[GHOTROD1] +STR_NAME :Hot Rod Car + +[GHOTROD2] +STR_NAME :Hot Rod Car + +[GSCHLBUS] +STR_NAME :스쿨 버스 + +[HADESXXX] +STR_NAME :Hades Statue + +[HISTFIX1] +STR_NAME :Alien Historical Structures + +[HISTFIX2] +STR_NAME :Alien Historical Structures + +[HODSHUT1] +STR_NAME :Robin Hood's Hut + +[HODSHUT2] +STR_NAME :Robin Hood's Hut + +[HRBWAL07] +STR_NAME :항구 벽 구석 조각 + +[HRBWAL08] +STR_NAME :항구 벽 구석 조각 + +[HRBWAL09] +STR_NAME :항구 벽 with Dock + +[HRBWAL11] +STR_NAME :항구 Dock + +[JAILXX18] +STR_NAME :감옥 Water Tower + +[JETPLAN1] +STR_NAME :Jet Aeroplane + +[JETPLAN2] +STR_NAME :Jet Aeroplane + +[JETPLAN3] +STR_NAME :Jet Aeroplane + +[MCASTL13] +STR_NAME :Castle Tower 구석 조각 + +[MCASTL14] +STR_NAME :Castle Tower 구석 조각 + +[MCASTL15] +STR_NAME :Castle Tower Cross 조각 + +[MCASTL16] +STR_NAME :Castle Tower Straight 조각 + +[MCASTL17] +STR_NAME :Castle Tower T 조각 + +[MCASTL18] +STR_NAME :Castle Tower T 조각 + +[METOAN01] +STR_NAME :Meteor Crater 구석 + +[METOAN02] +STR_NAME :Meteor Crater Inverted 구석 + +[OLDNYK20] +STR_NAME :뉴욕 지붕 조각 + +[OLDNYK21] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK22] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK23] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK27] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK28] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK29] +STR_NAME :뉴욕 벽 조각 + +[OLDNYK30] +STR_NAME :뉴욕 벽 조각 + +[PEASTHUT] +STR_NAME :Peasant Hut + +[PERAMOB1] +STR_NAME :Period Automobile + +[PERAMOB2] +STR_NAME :Period Automobile + +[PERDTK01] +STR_NAME :Period Truck + +[PERDTK02] +STR_NAME :Period Truck + +[PLOUGHXX] +STR_NAME :Plough + +[PRDYACHT] +STR_NAME :Period Sailing Yacht + +[PSNTWL26] +STR_NAME :암흑 시대 마을 지붕 조각 + +[PSNTWL27] +STR_NAME :암흑 시대 마을 구석 지붕 조각 + +[PSNTWL28] +STR_NAME :반전된 암흑 시대 마을 지붕 조각 + +[RDMET2X2] +STR_NAME :Small Red Meteor Crater + +[RDMET4X4] +STR_NAME :Large Red Meteor Crater + +[RDMETO01] +STR_NAME :Red Meteor Crater 구석 + +[RDMETO02] +STR_NAME :Red Meteor Crater 구석 + +[ROBNCAMP] +STR_NAME :Robin Hood's Camp + +[ROMNC2X2] +STR_NAME :Roman Palace 구석 조각 + +[ROMNE2X1] +STR_NAME :Roman Palace End 조각 + +[ROMNM2X2] +STR_NAME :Roman Palace Cross Section + +[ROMNS2X2] +STR_NAME :Roman Palace Straight 조각 + +[ROMVC2X2] +STR_NAME :Roman Palace 구석 조각 + +[ROMVE2X1] +STR_NAME :Roman Palace End 조각 + +[ROMVM2X2] +STR_NAME :Roman Palace Cross Section + +[ROMVS2X2] +STR_NAME :Roman Palace Straight 조각 + +[SCHNPIT2] +STR_NAME :Seaplane Pits + +[SCHNPITS] +STR_NAME :Seaplane Pits + +[SCHNTENT] +STR_NAME :Marquee + +[SHIPB4X4] +STR_NAME :Luxury Liner Bow + +[SHIPM4X4] +STR_NAME :Luxury Liner 중간 섹션 + +[SHIPS4X4] +STR_NAME :Luxury Liner Stern + +[STRGS2X2] +STR_NAME :Roman Palace Straight 조각 + +[STRVS2X2] +STR_NAME :Roman Palace Straight 조각 + +[TAVERNXX] +STR_NAME :Dark Ages Tavern + +[TRAVLR01] +STR_NAME :Traveller Van + +[TRAVLR02] +STR_NAME :Microbus + +[JAILXX19] +STR_NAME :감옥 울타리 + +[MSPKWA01] +STR_NAME :Spiked Fence + +[1920PATH] +STR_NAME :Sidewalk FootPath + +[FUTRPAT2] +STR_NAME :Sky Walk FootPath + +[FUTRPATH] +STR_NAME :Circuit FootPath + +[JURRPATH] +STR_NAME :Rocky FootPath + +[MEDIPATH] +STR_NAME :Wooden FootPath + +[MYTHPATH] +STR_NAME :모자이크 보도 + +[RANBPATH] +STR_NAME :무지개 보도 + +[FIRHYDRT] +STR_NAME :소화전 + +[MEDBENCH] +STR_NAME :벤치 + +[SCG1920S] +STR_NAME :광란의 20년대 테마 + +[SCG1920W] +STR_NAME :광란의 20년대 벽 세트 + +[SCG1960S] +STR_NAME :로큰롤 테마 + +[SCGFUTUR] +STR_NAME :미래 테마 + +[SCGJURRA] +STR_NAME :선사시대 테마 + +[SCGMEDIV] +STR_NAME :암흑시대 테마 + +[SCGMYTHO] +STR_NAME :신화 테마 + +[1920SENT] +STR_NAME :광란의 20년대 공원 입구 + +[FUTURENT] +STR_NAME :초현대적 공원 입구 + +[GLDYRENT] +STR_NAME :로큰롤 공원 입구 + +[JURASENT] +STR_NAME :선사시대 공원 입구 + +[MEDIENTR] +STR_NAME :암흑시대 공원 입구 + +[MYTHENTR] +STR_NAME :신화 공원 입구 + +############################################################################### +## RCT2 Scenarios +############################################################################### + +STR_SCNR :알프스의 모험 +STR_PARK :알프스의 모험 +STR_DTLS :작은 산악 스키 리조트를 눈 테마 놀이공원으로 바꿔보세요. + + +STR_SCNR :우호 비행장 +STR_PARK :우호 비행장 +STR_DTLS :이 버려진 비행장에 날아다니는 것을 주제로 한 놀이공원을 만들어보세요. + + +STR_SCNR :보타니의 하얀 파도 +STR_PARK :보타니의 하얀 파도 +STR_DTLS :당신의 목표는 이 파라다이스 섬에 고수익 공원을 만드는 것입니다. + + +STR_SCNR :식스 플래그 벨기에 건설 +STR_PARK :식스 플래그 벨기에 +STR_DTLS :이 유럽의 식스 플래그 공원을 당신만의 스타일으로 만들어 보세요. + + +STR_SCNR :식스 플래그 그레이트 어드벤처 건설 +STR_PARK :그레이트 어드벤처 +STR_DTLS :이 식스 플래그 공원을 당신의 디자인 기술로 재탄생시키십시오. + + +STR_SCNR :식스 플래그 네덜란드 건설 +STR_PARK :식스 플래그 네덜란드 +STR_DTLS :이 유럽의 식스 플래그 공원을 당신이 원하는 대로 만들어 보세요. + + +STR_SCNR :식스 플래그 매직 마운틴 건설 +STR_PARK :매직 마운틴 +STR_DTLS :이 대형 식스 플래그 공원을 당신만의 스타일로 만들어 보세요. + + +STR_SCNR :식스 플래그 오버 텍사스 건설 +STR_PARK :오버 텍사스 +STR_DTLS :이 식스 플래그 공원에 처음부터 놀이기구를 건설하여 시작해보세요. + + +STR_SCNR :당신만의 식스 플래그 공원 건설 +STR_PARK :식스 플래그 +STR_DTLS :당신만의 디자인대로 식스 플래그 공원을 만드세요. 다른 식스 플래그 공원의 놀이기구를 짓거나 자신만의 놀이기구를 만들어보세요. + + +STR_SCNR :북적이는 시장 +STR_PARK :북적이는 시장 +STR_DTLS :이 작은 시장에 고객들을 유치하기 위해 놀이기구와 롤러코스터를 지어 상점과 가게의 수익을 늘리는 것이 목표입니다. + + +STR_SCNR :이상한 성 +STR_PARK :이상한 성 +STR_DTLS :당신은 큰 성을 물려받았습니다. 이제 이 성을 작은 놀이공원으로 바꾸는 것이 당신이 해야할 일입니다. + + +STR_SCNR :먼지투성이 그린 +STR_PARK :먼지투성이 그린 +STR_DTLS :사막의 고속도로 교차로 근처에 있는 먼지투성이 그린을 작은 골프 리조트에서 번화한 놀이공원으로 개발할 수 있는 기회가 생겼습니다. + + +STR_SCNR :일렉트릭 농장 +STR_PARK :일렉트릭 농장 +STR_DTLS :당신은 작은 농장을 물려받았습니다. 각 지역과 농장의 건물 사이에 작은 놀이공원을 건설하는 것이 당신의 목표입니다. + + +STR_SCNR :극한의 높이 +STR_PARK :극한의 높이 +STR_DTLS :재정적 제한이 없는 이 사막 공원을 사람들이 극한의 스릴을 찾는 곳으로 확장하는 것이 당신의 목표입니다. + + +STR_SCNR :공장 놀이터 +STR_PARK :공장 놀이터 +STR_DTLS :버려진 공장 지대에 기계를 주제로 한 놀이공원을 만들어보세요 + + +STR_SCNR :버섯 숲 +STR_PARK :버섯 숲 +STR_DTLS :당신의 목표는 오직 오래된 나무 놀이기구만을 사용해서 버섯 숲에 번화한 놀이공원을 만드는 것입니다. + + +STR_SCNR :유령 도시 +STR_PARK :유령 도시 +STR_DTLS :대형 놀이공원 회사에 고용된 당신의 임무는 버려진 광산촌 주위에 대형 롤러코스터 공원을 건설하는 것입니다. + + +STR_SCNR :그래비티 정원 +STR_PARK :그래비티 정원 +STR_DTLS :당신의 목표는 아름다운 그래비티 정원에 롤러코스터 공원을 만드는 것입니다. 다른 놀이기구는 안 됩니다. 롤러코스터만 만드세요! + + +STR_SCNR :지옥 풍경 +STR_PARK :지옥 풍경 +STR_DTLS :마그마 강이 흐르는 용암으로 위태롭게 둘러싸인 공원 + + +STR_SCNR :행운의 호수 +STR_PARK :행운의 호수 +STR_DTLS :자본에는 제한이 없지만 호수가 있는 곳이기 때문에 이 공원을 확장하고 관리하는 건 많이 힘들 것입니다. + + +STR_SCNR :무지개 정상 +STR_PARK :무지개 정상 +STR_DTLS :이 공원은 산 허리에 만들어야 하고, 높은 건물은 지을 수 없습니다. 공원을 확장하여 성공할 자신이 있습니까? + + +STR_SCNR :식스 플래그 벨기에 +STR_PARK :식스 플래그 벨기에 +STR_DTLS :직접 팔을 걷어붙이고 이 식스 플래그 공원을 개선해보세요. + + +STR_SCNR :식스 플래그 그레이트 어드벤처 +STR_PARK :그레이트 어드벤처 +STR_DTLS :식스 플래그의 빠진 놀이기구를 건설해보거나, 공원을 개선하기 위해 자신만의 놀이기구를 건설해보세요! 하지만 공원에 더 많은 손님을 모아야 한다는 궁극적인 목표를 잊어서는 안됩니다! + + +STR_SCNR :식스 플래그 네덜란드 +STR_PARK :식스 플래그 네덜란드 +STR_DTLS :직접 팔을 걷어붙이고 이 식스 플래그 공원을 개선해보세요. + + +STR_SCNR :식스 플래그 매직 마운틴 +STR_PARK :매직 마운틴 +STR_DTLS :식스 플래그의 빠진 놀이기구를 건설해보거나, 공원을 개선하기 위해 자신만의 놀이기구를 건설해보세요! 하지만 대출을 갚고 공원 가치를 높여야 한다는 궁극적인 목표를 잊어서는 안됩니다! + + +STR_SCNR :식스 플래그 오버 텍사스 +STR_PARK :오버 텍사스 +STR_DTLS :식스 플래그의 빠진 놀이기구를 건설해보거나, 공원을 개선하기 위해 자신만의 놀이기구를 건설해보세요! 하지만 공원에 더 많은 손님을 모아야 한다는 궁극적인 목표를 잊어서는 안됩니다! + +############################################################################### +## Wacky Worlds Scenarios +############################################################################### + +STR_SCNR :아프리카 - 아프리카 다이아몬드 광산 +STR_PARK :아프리카의 광산 +STR_DTLS :다이아몬드 폐광을 물려받은 당신은 값비싼 다이아몬드를 발견했고 그 판매 수익으로 세계 일류의 테마파크를 짓기로 결심했습니다. + + +STR_SCNR :아프리카 - 오아시스 +STR_PARK :신기루의 광기 +STR_DTLS :사막에서 놀이공원을 짓기에 아주 적당한 오아시스를 발견했습니다. 오아시스로 가는 교통편은 이미 존재합니다. + + +STR_SCNR :아프리카 - 빅토리아 폭포 +STR_PARK :폭포 너머 +STR_DTLS :공원을 운영하기 충분하고 값싼 전기를 생산하는 수력 발전 댐이 지어졌습니다. 댐을 건설하느라 진 빚을 갚기 위해 높은 가치의 놀이공원을 지어야 합니다. + + +STR_SCNR :남극 - 버려진 환경 복구 +STR_PARK :얼음에 뒤덮인 모험 +STR_DTLS :환경부에서 눈꼴사납고 낡은 정유 시설을 최고의 관광 명소로 만들어달라고 합니다. 땅값은 싸지만 대출 이자는 높습니다. 오래된 건물은 고철로 팔아 버릴 수 있습니다. + + +STR_SCNR :아시아 - 중국 만리장성의 관광 진흥 +STR_PARK :만리장성 +STR_DTLS :관광 당국이 만리장성 주변의 땅에 놀이공원을 지어서 관광객 수를 늘리기로 결정했습니다. 돈이 문제가 아니군요! + + +STR_SCNR :아시아 - 일본 연안 간척 +STR_PARK :오키나와 해변 +STR_DTLS :기존 공원은 이미 공간이 모자랍니다. 대출을 받아서 바다로 확장해나갈 수밖에 없습니다. 지진 우려와 약한 기반을 이유로 건설 높이가 제한됩니다. + + +STR_SCNR :아시아 - 마하라자 궁전 +STR_PARK :마하라자 공원 +STR_DTLS :인도의 왕에게서 국민들에게 즐길 거리를 만들어달라는 임무를 받았습니다. 마하라자 궁전을 연상시키는 공원을 만들어보세요. + + +STR_SCNR :오스트레일리아 - 에어즈 록 +STR_PARK :에어즈 어드벤처 +STR_DTLS :오스트레일리아 원주민들을 도와 공원을 문화 인식 프로그램의 일환으로 개발하려 합니다. 원주민들의 독특한 문화유산을 알리기 위해 많은 관광객을 모아야 합니다. + + +STR_SCNR :오스트레일리아 - 해변의 즐거움 +STR_PARK :해변의 바베큐 파티 +STR_DTLS :근처 지역 사업가의 해안 공원이 파산해버렸습니다. 이미 작은 공원을 운영하고 있는 당신은 건설사로부터 그 공원을 구입하였습니다. 두 공원을 합쳐 크게 사업을 확장해보세요. + + +STR_SCNR :유럽 - 유럽 문화 축제 +STR_PARK :유럽의 축제 +STR_DTLS :유럽 문화 축제의 경영권을 확보한 당신은 이제 유럽 연합의 보조금을 갚기 위해 현재의 유럽 의회 임기가 끝날 때까지 손님을 늘려야합니다. + + +STR_SCNR :유럽 - 혁신 +STR_PARK :잿더미를 딛고 +STR_DTLS :방치되어 있는 낡은 공원이 있습니다. 이 공원이 과거에 누렸던 영광을 재현하기 위해 유럽 연합의 허가를 받았습니다! 허가를 받은 만큼 공원을 혁신해서 보답하세요. + + +STR_SCNR :북 아메리카 - 최고의 하와이 섬 +STR_PARK :왁자지껄 와이키키 +STR_DTLS :하와이 주민들이 이제 파도타기가 지겨워져서 좀 더 자극적인 뭔가를 원하고 있습니다. 주민들도 만족시키면서 이 지역의 관광객들이 찾아오고 싶어하는 공원을 만드세요. + + +STR_SCNR :북 아메리카 - 그랜드 캐니언 +STR_PARK :불행의 계곡 +STR_DTLS :이 아름답지만 제한적인 공간에 공원을 만들어야 합니다. 미국 원주민에게서 반대편 땅을 구입할 수 있습니다. 줄어들고 있는 마을 인구를 유지하기 위해서라도 목표를 달성해야 합니다. + + +STR_SCNR :북 아메리카 - 롤러코스터 천국 +STR_PARK :롤러코스터 천국 +STR_DTLS :당신은 긴 휴식기를 가지는 동안 이 도시 공원을 롤러코스터 천국으로 바꾸고자 하는 성공한 사업 거물입니다. 돈은 문제가 되지 않는군요! + + +STR_SCNR :남 아메리카 - 잃어버린 도시 잉카 +STR_PARK :잃어버린 도시를 세운 자 +STR_DTLS :이 지역의 관광산업을 보다 활기차게 만들기 위해서는 주변 환경과 잘 어울리는 공원을 지어야 합니다. 높이 제한이 있습니다. + + +STR_SCNR :남 아메리카 - 열대우림 고원 +STR_PARK :열대우림 고원 +STR_DTLS :소중한 열대우림 속의 제한된 공간만을 받았습니다. 이곳의 벌목 산업을 대신할 수 있는 방법을 제공하기 위해 기존의 빈 공간을 최대한 많이 활용해야 합니다. + + +STR_SCNR :남 아메리카 - 리오 축제 +STR_PARK :슈거로프 해안 +STR_DTLS :리오 근처의 작은 공원을 운영하고 있는데 은행이 대출금을 조기 회수하려 합니다. 때이른 빚 독촉을 갚기 위해서 빨리 돈을 벌어야 합니다. + +############################################################################### +## Time Twister Scenarios +############################################################################### + +STR_SCNR :암흑시대 - 성 +STR_PARK :클리프사이드 성 +STR_DTLS :이 지역의 전투 재현 단체는 자신들의 취미를 진지하게 생각하고 있습니다. 그들은 당신에게 클리프사이드 성 부지에 암흑시대 테마파크를 건설해달라고 요청해왔습니다. + + +STR_SCNR :암흑 시대 - 로빈 후드 +STR_PARK :셔우드 숲 +STR_DTLS :부자들의 재산을 빼앗아 필요한 사람들에게 나누어주기 위해서 당신과 수하들은 셔우드 숲에 놀이공원을 만들기로 결정했습니다. + + +STR_SCNR :미래 - 첫 만남 +STR_PARK :외계인의 축제 +STR_DTLS :먼 행성에서 생명체가 발견되었습니다. 외계인을 주제로 한 놀이공원을 만들어서 전에 없던 뜨거운 관심을 받아 돈을 벌어보세요. + + +STR_SCNR :미래 - 미래 세계 +STR_PARK :제미니 시티 +STR_DTLS :당신의 미래에 대한 독창적이고 이상적인 시각을 보여줄 때입니다. 첨단의 매력이 느껴지는 미래의 공원 디자인을 제안해봅시다. + + +STR_SCNR :신화 - 영화 세트장 +STR_PARK :애니매트로닉 앤틱스 +STR_DTLS :이번 임무는 옛 영화 세트장에 설립된 기존 테마파크를 운영하고 발전시키는 것입니다. 흑백 스크린에 신화 속 인물을 옮겨놓은 스톱 모션 애니메이션의 선구자들에게 이 공원을 헌정합시다. + + +STR_SCNR :신화 - 문명의 요람 +STR_PARK :신화의 광기 +STR_DTLS :특별한 고고학적 가치를 가진 섬을 소유하게 되었습니다. 이 지역의 풍부한 신화적 유산을 기반으로 한 테마파크를 건설해서 유산 보존 기금을 마련하기로 결정했습니다. + + +STR_SCNR :선사시대 - 소행성 충돌 후 +STR_PARK :크레이터 대학살 +STR_DTLS :당신은 오래된 운석공을 소유하고 있습니다. 기업가 정신을 발휘한 당신은 운석 테마 파크를 건설해서 쓸모없어 보이는 이 땅을 엄청난 행운의 땅으로 바꾸기로 결심했습니다. + + +STR_SCNR :선사시대 - 쥐라기 사파리 +STR_PARK :코스터사우르스 +STR_DTLS :당신은 쥐라기 시대 놀이공원을 건설하는 임무를 받았습니다. 색다른 식물과 동물 전시장에 관객이 쉽게 접근할 수 있도록 하려면, 계곡을 가로지르는 놀이기구를 만들어야 할 것입니다. + + +STR_SCNR :선사시대 - 석기시대 +STR_PARK :돌무더기 산책 +STR_DTLS :고속도로 개발자들을 막고 고대 열석을 보호하기 위해, 석기 시대 테마파크를 건설하여 수익을 내야 합니다. 하지만 사람이 살기 조금 힘든 곳인만큼 손님을 모으기가 어려울 것입니다. + + +STR_SCNR :광란의 20년대 - 감옥 섬 +STR_PARK :앨커트래즈 +STR_DTLS :주류 밀매자와 폭력범으로 득실대던 악명 높은 감옥 섬이 경매에 부쳐졌습니다. 이곳을 최고의 관광지로 바꾸기로 한 당신에게 돈은 신경 쓸 필요가 없네요. + + +STR_SCNR :광란의 20년대 - 슈나이더 컵 +STR_PARK :슈나이더 해안 +STR_DTLS :할아버지의 슈나이더 컵 우승 75주년이 얼마 남지 않았습니다. 당신은 할아버지의 업적을 기리기 위해 유명한 수상비행기 경주를 딴 놀이공원을 짓기로 했습니다. + + +STR_SCNR :광란의 20년대 - 마천루 +STR_PARK :메트로폴리스 +STR_DTLS :당신은 도시 저층부 근처의 빈 공간을 갖게 되었습니다. 최대한 이익을 많이 얻기 위해, 20년대에 유행했던 아르데코식 건축물을 본딴 마천루 테마파크를 지어보세요. + + +STR_SCNR :로큰롤 - 사랑과 평화 +STR_PARK :우드스톡 +STR_DTLS :매년 열리는 대형 음악 축제가 당신의 땅에서 열립니다. 최신 유행하는 놀이공원을 지어, 자유로운 영혼을 가진 관객들이 즐거워할 수 있게 만드세요. + + +STR_SCNR :로큰롤 - 로큰롤 +STR_PARK :로큰롤 부흥 +STR_DTLS :이 오래된 놀이공원은 더 나은 미래를 기대하고 있습니다. 소유자를 도와 이 공원을 복고풍의 로큰롤 공원으로 바꾸어 성공적인 장소로 변모시켜보세요. diff --git a/data/language/polish.txt b/data/language/polish.txt index 071314a9ab..f276526e0b 100644 --- a/data/language/polish.txt +++ b/data/language/polish.txt @@ -29,29 +29,29 @@ STR_0024 :Go Karts STR_0025 :Log Flume STR_0026 :River Rapids STR_0027 :Dodgems -STR_0028 :Pirate Ship +STR_0028 :Statek piracki STR_0029 :Swinging Inverter Ship -STR_0030 :Food Stall +STR_0030 :Budka z jedzeniem STR_0031 :Unknown Stall (1D) -STR_0032 :Drink Stall +STR_0032 :Budka z napojami STR_0033 :Unknown Stall (1F) -STR_0034 :Shop +STR_0034 :Stoisko STR_0035 :Merry-Go-Round STR_0036 :Unknown Stall (22) -STR_0037 :Information Kiosk -STR_0038 :Toilets +STR_0037 :Punkt informacyjny +STR_0038 :Toalety STR_0039 :Ferris Wheel STR_0040 :Motion Simulator -STR_0041 :3D Cinema +STR_0041 :Kino 3D STR_0042 :Top Spin STR_0043 :Space Rings STR_0044 :Reverse Freefall Coaster STR_0045 :Lift STR_0046 :Vertical Drop Roller Coaster -STR_0047 :Cash Machine +STR_0047 :Bankomat STR_0048 :Twist STR_0049 :Haunted House -STR_0050 :First Aid Room +STR_0050 :Punkt pierwszej pomocy STR_0051 :Circus Show STR_0052 :Ghost Train STR_0053 :Steel Twister Roller Coaster @@ -837,10 +837,9 @@ STR_0831 :{SMALLFONT}{BLACK}Oddal widok STR_0832 :{SMALLFONT}{BLACK}Obróć widok o 90{DEGREE} STR_0833 :{SMALLFONT}{BLACK}Pauza STR_0834 :{SMALLFONT}{BLACK}Menu zapisu i opcji -# ------------------------------------------ Polish end -STR_0835 :Game initialization failed -STR_0836 :Unable to start game in a minimized state -STR_0837 :Unable to initialize graphics system +STR_0835 :Inicjalizacja gry nie powiodła się +STR_0836 :Nie można uruchomić gry w trybie zminimalizowanym +STR_0837 :Nie można zainicjalizować systemu graficznego STR_0838 : STR_0839 :{UINT16} x {UINT16} STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16} @@ -851,8 +850,9 @@ STR_0843 : STR_0844 : STR_0845 : STR_0846 : -STR_0847 :About 'OpenRCT2' +STR_0847 :O 'OpenRCT2' STR_0848 :RollerCoaster Tycoon 2 +# ------------------------------------------ Polish end STR_0849 :{WINDOW_COLOUR_2}Version 2.01.028 STR_0850 :{WINDOW_COLOUR_2}Copyright {COPYRIGHT} 2002 Chris Sawyer, all rights reserved STR_0851 :{WINDOW_COLOUR_2}Designed and programmed by Chris Sawyer @@ -903,7 +903,7 @@ STR_0893 :Zrzut ekranu nieudany ! STR_0894 :Landscape data area full ! STR_0895 :Can't build partly above and partly below ground STR_0896 :{POP16}{POP16}{STRINGID} Construction -STR_0897 :Direction +STR_0897 :Kierunek STR_0898 :{SMALLFONT}{BLACK}Left-hand curve STR_0899 :{SMALLFONT}{BLACK}Right-hand curve STR_0900 :{SMALLFONT}{BLACK}Left-hand curve (small radius) @@ -913,7 +913,7 @@ STR_0903 :{SMALLFONT}{BLACK}Right-hand curve (very small radius) STR_0904 :{SMALLFONT}{BLACK}Left-hand curve (large radius) STR_0905 :{SMALLFONT}{BLACK}Right-hand curve (large radius) STR_0906 :{SMALLFONT}{BLACK}Straight -STR_0907 :Slope +STR_0907 :Nachylenie STR_0908 :Roll/Banking STR_0909 :Seat Rot. STR_0910 :{SMALLFONT}{BLACK}Roll for left-hand curve @@ -984,41 +984,39 @@ STR_0973 :OK STR_0974 :Atrakcje STR_0975 :Sklepy STR_0976 :Toalety i Punkty Informacyjne -STR_0977 :Nowa atrakcja transportowa -STR_0978 :Nowa łagodna atrakcja -STR_0979 :Nowa kolejka górska -STR_0980 :Nowa intensywna atrakcja -STR_0981 :Nowa wodna atrakcja -STR_0982 :Nowy sklep lub stoisko +STR_0977 :Nowe atrakcje transportowe +STR_0978 :Nowe łagodne atrakcje +STR_0979 :Nowe kolejki górskie +STR_0980 :Nowe intensywne atrakcje +STR_0981 :Nowe wodne atrakcje +STR_0982 :Nowe sklepiki lub stoiska STR_0983 :Badania i rozwój STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP} STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP} STR_0986 :{BLACK}{CURRENCY2DP} -# ------------------------------------------ Polish end -STR_0987 :Too many rides/attractions -STR_0988 :Can't create new ride/attraction... +STR_0987 :Zbyt wiele atrakcji +STR_0988 :Nie można stworzyć nowej atrakcji... STR_0989 :{STRINGID} +# ------------------------------------------ Polish end STR_0990 :{SMALLFONT}{BLACK}Construction -STR_0991 :Station platform # ------------------------------------------ Polish start +STR_0991 :Platforma ze stacją STR_0992 :{SMALLFONT}{BLACK}Zniszcz całą atrakcję STR_0993 :Zniszcz atrakcję STR_0994 :Zniszcz STR_0995 :{WINDOW_COLOUR_1}Jesteś pewien, że chcesz zniszczyć {STRINGID}? STR_0996 :Widok ogólny STR_0997 :{SMALLFONT}{BLACK}Wybór widoku -# ------------------------------------------ Polish end -STR_0998 :No more stations allowed on this ride -STR_0999 :Requires a station platform -STR_1000 :Track is not a complete circuit -STR_1001 :Track unsuitable for type of train -STR_1002 :Can't open {POP16}{POP16}{POP16}{STRINGID}... -STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID}... -STR_1004 :Can't close {POP16}{POP16}{POP16}{STRINGID}... -STR_1005 :Can't start construction on {POP16}{POP16}{POP16}{STRINGID}... -STR_1006 :Must be closed first -STR_1007 :Unable to create enough vehicles -# ------------------------------------------ Polish start +STR_0998 :Nie można utworzyć więcej stacji dla tej atrakcji +STR_0999 :Wymaga platformy ze stacją +STR_1000 :Tor nie jest obwodem zamkniętym +STR_1001 :Tor nieodpowiedni dla tego typu kolejki +STR_1002 :Nie można otworzyć {POP16}{POP16}{POP16}{STRINGID}... +STR_1003 :Nie można testować {POP16}{POP16}{POP16}{STRINGID}... +STR_1004 :Nie można zamknąć {POP16}{POP16}{POP16}{STRINGID}... +STR_1005 :Nie można rozpocząć konstrukcji {POP16}{POP16}{POP16}{STRINGID}... +STR_1006 :Musi być najpierw zamknięte +STR_1007 :Nie można utworzyć wystarczająco wagonów STR_1008 :{SMALLFONT}{BLACK}Otwórz, zamknij lub testuj atrakcję STR_1009 :{SMALLFONT}{BLACK}Otwórz / zamknij wszystkie atrakcje STR_1010 :{SMALLFONT}{BLACK}Otwórz / zamknij park @@ -1039,7 +1037,7 @@ STR_1023 :{POP16}{POP16}{POP16}{COMMA16} cars per train STR_1024 :{COMMA16} car per train STR_1025 :{COMMA16} cars per train STR_1026 :Station platform too long! -STR_1027 :{SMALLFONT}{BLACK}Locate this on Main View +STR_1027 :{SMALLFONT}{BLACK}Zlokalizuj na głównym oknie STR_1028 :Off edge of map! STR_1029 :Cannot build partly above and partly below water! STR_1030 :Can only build this underwater! @@ -1070,11 +1068,11 @@ STR_1053 :{SMALLFONT}{BLACK}Atrakcje w parku STR_1054 :{SMALLFONT}{BLACK}Nazwij atrakcję STR_1055 :{SMALLFONT}{BLACK}Nazwij osobę STR_1056 :{SMALLFONT}{BLACK}Nazwij pracownika +STR_1057 :Nazwa kolejki/atrakcji +STR_1058 :Wprowadź nową nazwę dla tej kolejki/atrakcji +STR_1059 :Nie można zmienić nazwy kolejki/atrakcji... +STR_1060 :Nieprawidłowa nazwa kolejki/atrakcji # ------------------------------------------ Polish end -STR_1057 :Ride/attraction name -STR_1058 :Enter new name for this ride/attraction: -STR_1059 :Can't rename ride/attraction... -STR_1060 :Invalid ride/attraction name STR_1061 :Normal mode STR_1062 :Continuous circuit mode STR_1063 :Reverse-Incline launched shuttle mode @@ -1239,12 +1237,12 @@ STR_1219 :{BLACK}{SMALLDOWN} STR_1220 :Exit only STR_1221 :No entrance STR_1222 :No exit -STR_1223 :{SMALLFONT}{BLACK}Transport rides -STR_1224 :{SMALLFONT}{BLACK}Gentle rides -STR_1225 :{SMALLFONT}{BLACK}Roller coasters -STR_1226 :{SMALLFONT}{BLACK}Thrill rides -STR_1227 :{SMALLFONT}{BLACK}Water rides -STR_1228 :{SMALLFONT}{BLACK}Shops & stalls +STR_1223 :{SMALLFONT}{BLACK}Atrakcje transportowe +STR_1224 :{SMALLFONT}{BLACK}Łagodne atrakcje +STR_1225 :{SMALLFONT}{BLACK}Kolejki górskie +STR_1226 :{SMALLFONT}{BLACK}Emocjonujące atrakcje +STR_1227 :{SMALLFONT}{BLACK}Atrakcje wodne +STR_1228 :{SMALLFONT}{BLACK}Sklepiki i kioski STR_1229 :train STR_1230 :trains STR_1231 :Train @@ -1329,13 +1327,13 @@ STR_1309 :Rings STR_1310 :{COMMA16} ring STR_1311 :{COMMA16} rings STR_1312 :Ring {COMMA16} -STR_1313 :player -STR_1314 :players -STR_1315 :Player -STR_1316 :Players -STR_1317 :{COMMA16} player -STR_1318 :{COMMA16} players -STR_1319 :Player {COMMA16} +STR_1313 :gracz +STR_1314 :graczy +STR_1315 :Gracz +STR_1316 :Graczy +STR_1317 :{COMMA16} gracz +STR_1318 :{COMMA16} graczy +STR_1319 :Gracz {COMMA16} STR_1320 :course STR_1321 :courses STR_1322 :Course @@ -1413,18 +1411,18 @@ STR_1393 :{SMALLFONT}{BLACK}Vehicle details and options STR_1394 :{SMALLFONT}{BLACK}Operating options STR_1395 :{SMALLFONT}{BLACK}Maintenance options STR_1396 :{SMALLFONT}{BLACK}Colour scheme options -STR_1397 :{SMALLFONT}{BLACK}Sound & music options +STR_1397 :{SMALLFONT}{BLACK}Opcje dźwięku & muzyki STR_1398 :{SMALLFONT}{BLACK}Measurements and test data -STR_1399 :{SMALLFONT}{BLACK}Graphs -STR_1400 :Entrance -STR_1401 :Exit +STR_1399 :{SMALLFONT}{BLACK}Wykresy +STR_1400 :Wejście +STR_1401 :Wyjście STR_1402 :{SMALLFONT}{BLACK}Build or move entrance to ride/attraction STR_1403 :{SMALLFONT}{BLACK}Build or move exit from ride/attraction STR_1404 :{SMALLFONT}{BLACK}Rotate 90{DEGREE} STR_1405 :{SMALLFONT}{BLACK}Mirror image STR_1406 :{SMALLFONT}{BLACK}Toggle scenery on/off (if available for this design) STR_1407 :{WINDOW_COLOUR_2}Build this... -STR_1408 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY} +STR_1408 :{WINDOW_COLOUR_2}Koszt: {BLACK}{CURRENCY} STR_1409 :Entry/Exit Platform STR_1410 :Vertical Tower # ------------------------------------------ Polish start @@ -1482,12 +1480,12 @@ 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 :Goście STR_1464 :Helix up (small) STR_1465 :Helix up (large) STR_1466 :Helix down (small) STR_1467 :Helix down (large) -STR_1468 :Staff +STR_1468 :Personel STR_1469 :Ride must start and end with stations STR_1470 :Station not long enough STR_1471 :{WINDOW_COLOUR_2}Speed: @@ -1693,9 +1691,9 @@ STR_1668 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}Unknown STR_1669 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}{COMMA16}% STR_1670 :{WINDOW_COLOUR_2}Total customers: {BLACK}{COMMA32} STR_1671 :{WINDOW_COLOUR_2}Total profit: {BLACK}{CURRENCY2DP} -STR_1672 :Brakes +STR_1672 :Hamulce STR_1673 :Spinning Control Toggle Track -STR_1674 :Brake speed +STR_1674 :Prędkość hamowania STR_1675 :{POP16}{VELOCITY} STR_1676 :{SMALLFONT}{BLACK}Set speed limit for brakes STR_1677 :{WINDOW_COLOUR_2}Popularity: {BLACK}Unknown @@ -1712,26 +1710,26 @@ STR_1687 :Water splash STR_1688 :Base size 4 x 1 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_1694 :{SMALLFONT}{BLACK}Staff -STR_1695 :{SMALLFONT}{BLACK}Income and costs +STR_1691 :{WINDOW_COLOUR_2} Koszt: {BLACK}{CURRENCY} +STR_1692 :{WINDOW_COLOUR_2} Koszt: {BLACK}od {CURRENCY} +STR_1693 :{SMALLFONT}{BLACK}Goście +STR_1694 :{SMALLFONT}{BLACK}Personel +STR_1695 :{SMALLFONT}{BLACK}Przychody i koszty 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_1701 :Hire new Mechanic -STR_1702 :Hire new Security Guard -STR_1703 :Hire new Entertainer -STR_1704 :Can't hire new staff... +STR_1699 :Za dużo ludzi w grze +STR_1700 :Zatrudnij nowego dozorcę +STR_1701 :Zatrudnij nowego mechan. +STR_1702 :Zatrudnij nowego ochron. +STR_1703 :Zatrudnij nowego komika +STR_1704 :Nie można zatrudnić nowych pracowników... STR_1705 :{SMALLFONT}{BLACK}Sack this staff member -STR_1706 :{SMALLFONT}{BLACK}Move this person to a new location +STR_1706 :{SMALLFONT}{BLACK}Przenieś tę osobę do nowej lokalizacji STR_1707 :Too many staff in game STR_1708 :{SMALLFONT}{BLACK}Set patrol area for this staff member STR_1709 :Sack staff -STR_1710 :Yes +STR_1710 :Tak STR_1711 :{WINDOW_COLOUR_1}Are you sure you want to sack {STRINGID}? STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Sweep footpaths STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Water gardens @@ -1753,15 +1751,15 @@ STR_1727 :Prawa do budowy nie są na sprzedaż! STR_1728 :Nie można tu kupić praw do budowy... STR_1729 :Teren nie należy do parku! # ------------------------------------------ Polish end -STR_1730 :{RED}Closed - - +STR_1730 :{RED}Zamknięte - - STR_1731 :{WHITE}{STRINGID} - - -STR_1732 :Build -STR_1733 :Mode -STR_1734 :{WINDOW_COLOUR_2}Number of laps: +STR_1732 :Buduj +STR_1733 :Tryb +STR_1734 :{WINDOW_COLOUR_2}Liczba okrążeń: STR_1735 :{SMALLFONT}{BLACK}Number of laps of circuit STR_1736 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1737 :{COMMA16} -STR_1738 :Can't change number of laps... +STR_1738 :Nie można zmienić liczby okrążeń... STR_1739 :Race won by guest {INT32} STR_1740 :Race won by {STRINGID} STR_1741 :Not yet constructed ! @@ -1800,7 +1798,7 @@ STR_1773 :Only one on-ride photo section allowed per ride STR_1774 :Only one cable lift hill allowed per ride STR_1775 :Off STR_1776 :On -STR_1777 :{WINDOW_COLOUR_2}Music +STR_1777 :{WINDOW_COLOUR_2}Muzyka atrakcji STR_1778 :{STRINGID} - - STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Panda costume STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tiger costume @@ -1814,7 +1812,7 @@ STR_1787 :{INLINE_SPRITE}{06}{20}{00}{00} Bandit costume STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Sheriff costume STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Pirate costume STR_1790 :{SMALLFONT}{BLACK}Select uniform colour for this type of staff -STR_1791 :{WINDOW_COLOUR_2}Uniform colour: +STR_1791 :{WINDOW_COLOUR_2}Kolor uniformu: STR_1792 :Responding to {STRINGID} breakdown call STR_1793 :Heading to {STRINGID} for an inspection STR_1794 :Fixing {STRINGID} @@ -1833,16 +1831,16 @@ STR_1806 :Brakes failure STR_1807 :Control failure STR_1808 :{WINDOW_COLOUR_2}Last breakdown: {BLACK}{STRINGID} STR_1809 :{WINDOW_COLOUR_2}Current breakdown: {OUTLINE}{RED}{STRINGID} -STR_1810 :{WINDOW_COLOUR_2}Carrying: +STR_1810 :{WINDOW_COLOUR_2}Niesie: STR_1811 :Can't build this here... STR_1812 :{SMALLFONT}{BLACK}{STRINGID} STR_1813 :Miscellaneous Objects -STR_1814 :Actions -STR_1815 :Thoughts +STR_1814 :Akcje +STR_1815 :Myśli STR_1816 :{SMALLFONT}{BLACK}Select information type to show in guest list STR_1817 :({COMMA16}) -STR_1818 :{WINDOW_COLOUR_2}All guests -STR_1819 :{WINDOW_COLOUR_2}All guests (summarised) +STR_1818 :{WINDOW_COLOUR_2}Wszycy goście +STR_1819 :{WINDOW_COLOUR_2}Wszyscy goście (pogrupowani) STR_1820 :{WINDOW_COLOUR_2}Guests {STRINGID} STR_1821 :{WINDOW_COLOUR_2}Guests thinking {STRINGID} STR_1822 :{WINDOW_COLOUR_2}Guests thinking about {POP16}{STRINGID} @@ -1865,7 +1863,7 @@ STR_1837 :Satysfakcja: Nieznana STR_1838 :Satysfakcja: {COMMA16}% STR_1839 :Niezawodność: {COMMA16}% STR_1840 :Przestoje w pracy: {COMMA16}% -STR_1841 :Zysk: {CURRENCY} per hour +STR_1841 :Zysk: {CURRENCY} na godzinę STR_1842 :Ulubiony dla: {COMMA16} gościa STR_1843 :Ulubiony dla: {COMMA16} gości STR_1844 :{SMALLFONT}{BLACK}Wybierz rodzaj informacji do pokazania @@ -1923,7 +1921,7 @@ STR_1891 :No {STRINGID} in park yet! STR_1892 : STR_1893 : STR_1894 :{WINDOW_COLOUR_2}{STRINGID} sold: {BLACK}{COMMA32} -STR_1895 :{SMALLFONT}{BLACK}Build new ride/attraction +STR_1895 :{SMALLFONT}{BLACK}Zbuduj nową atrakcję # ------------------------------------------ Polish start STR_1896 :{WINDOW_COLOUR_2}Przychody/wydatki STR_1897 :{WINDOW_COLOUR_2}Budowa atrakcji @@ -1954,263 +1952,262 @@ STR_1921 :{SMALLFONT}{BLACK}Nowa gra STR_1922 :{SMALLFONT}{BLACK}Kontynuuj zapisaną grę STR_1923 :{SMALLFONT}{BLACK}Samouczek STR_1924 :{SMALLFONT}{BLACK}Wyjdź -# ------------------------------------------ Polish end -STR_1925 :Can't place person here... +STR_1925 :Nie można postawić tutaj osoby... STR_1926 :{SMALLFONT} STR_1927 :{YELLOW}{STRINGID} has broken down STR_1928 :{RED}{STRINGID} has crashed! -STR_1929 :{RED}{STRINGID} still hasn't been fixed{NEWLINE}Check where your mechanics are and consider organizing them better -STR_1930 :{SMALLFONT}{BLACK}Turn on/off tracking information for this guest - (If tracking is on, guest's movements will be reported in the message area) -STR_1931 :{STRINGID} has joined the queue line for {STRINGID} -STR_1932 :{STRINGID} is on {STRINGID} -STR_1933 :{STRINGID} is in {STRINGID} -STR_1934 :{STRINGID} has left {STRINGID} -STR_1935 :{STRINGID} has left the park -STR_1936 :{STRINGID} has bought {STRINGID} -STR_1937 :{SMALLFONT}{BLACK}Show information about the subject of this message -STR_1938 :{SMALLFONT}{BLACK}Show view of guest -STR_1939 :{SMALLFONT}{BLACK}Show view of staff member -STR_1940 :{SMALLFONT}{BLACK}Show happiness, energy, hunger etc. for this guest -STR_1941 :{SMALLFONT}{BLACK}Show which rides this guest has been on -STR_1942 :{SMALLFONT}{BLACK}Show financial information about this guest -STR_1943 :{SMALLFONT}{BLACK}Show guest's recent thoughts -STR_1944 :{SMALLFONT}{BLACK}Show items guest is carrying -STR_1945 :{SMALLFONT}{BLACK}Show orders and options for this staff member -STR_1946 :{SMALLFONT}{BLACK}Select costume for this entertainer -STR_1947 :{SMALLFONT}{BLACK}Show areas patrolled by selected staff type, and locate the nearest staff member -STR_1948 :{SMALLFONT}{BLACK}Hire a new staff member of the selected type -STR_1949 :Financial Summary -STR_1950 :Financial Graph -STR_1951 :Park Value Graph -STR_1952 :Profit Graph +STR_1929 :{RED}Atrakcja {STRINGID} wziąż nie została naprawiona.{NEWLINE}Sprawdź gdzie znajdują się twoi mechanicy i rozważ lepszą organizację ich pracy +STR_1930 :{SMALLFONT}{BLACK}Wł/wył. informacje o tym gościu (jeśli śledzenie jest włączone działania gościa będą wyświetlane w oknie wiadomości) +STR_1931 :{STRINGID} stanął w kolejce do atrakcji {STRINGID} +STR_1932 :{STRINGID} jest na atrakcji {STRINGID} +STR_1933 :{STRINGID} korzysta z atrakcji {STRINGID} +STR_1934 :{STRINGID} opuścił atrakcję {STRINGID} +STR_1935 :{STRINGID} opuścił park +STR_1936 :{STRINGID} kupił {STRINGID} +STR_1937 :{SMALLFONT}{BLACK}Wyświetl informacje o przedmiocie tej wiadomości +STR_1938 :{SMALLFONT}{BLACK}Wyświetl podgląd gościa +STR_1939 :{SMALLFONT}{BLACK}Wyświetl podgląd pracownika +STR_1940 :{SMALLFONT}{BLACK}Pokaż zadowolenie, energię, poziom głodu itp. dla wybranego gościa +STR_1941 :{SMALLFONT}{BLACK}Pokaż z jakich atrakcji skorzystał wybrany gość +STR_1942 :{SMALLFONT}{BLACK}Wyświetl informacje finansowe o wybranym gościu +STR_1943 :{SMALLFONT}{BLACK}Pokaż ostatnie myśli wybranego gościa +STR_1944 :{SMALLFONT}{BLACK}Pokaż przedmioty niesione przez wybranego gościa +STR_1945 :{SMALLFONT}{BLACK}Pokaż polecenia i opcje dla wybranego pracownika +STR_1946 :{SMALLFONT}{BLACK}Wybierz kostium dla wybranego komika +STR_1947 :{SMALLFONT}{BLACK}Pokaż tereny patrolowane przez pracowników wybranego rodzaju i znajdź najbliższego pracownika +STR_1948 :{SMALLFONT}{BLACK}Zatrudnij nowego pracownika wybranego rodzaju +STR_1949 :Podsumowanie finansowe +STR_1950 :Wykres finansów +STR_1951 :Wykres wartości parku +STR_1952 :Wykres zysków STR_1953 :Marketing -STR_1954 :Research Funding -STR_1955 :{WINDOW_COLOUR_2}Number of circuits: -STR_1956 :{SMALLFONT}{BLACK}Number of circuits of track per ride +STR_1954 :Środki przeznaczone na badania +STR_1955 :{WINDOW_COLOUR_2}Liczba okrążeń: +STR_1956 :{SMALLFONT}{BLACK}Liczba okrążeń toru w czasie jednego przejazdu STR_1957 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1958 :{COMMA16} -STR_1959 :Can't change number of circuits... -STR_1960 :{WINDOW_COLOUR_2}Balloon price: -STR_1961 :{WINDOW_COLOUR_2}Cuddly Toy price: -STR_1962 :{WINDOW_COLOUR_2}Park Map price: -STR_1963 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_1964 :{WINDOW_COLOUR_2}Umbrella price: -STR_1965 :{WINDOW_COLOUR_2}Drink price: -STR_1966 :{WINDOW_COLOUR_2}Burger price: -STR_1967 :{WINDOW_COLOUR_2}Chips price: -STR_1968 :{WINDOW_COLOUR_2}Ice Cream price: -STR_1969 :{WINDOW_COLOUR_2}Candyfloss price: +STR_1959 :Nie mogę zmienić liczby okrążeń... +STR_1960 :{WINDOW_COLOUR_2}Cena balonu: +STR_1961 :{WINDOW_COLOUR_2}Cena przytulanki: +STR_1962 :{WINDOW_COLOUR_2}Cena planu parku: +STR_1963 :{WINDOW_COLOUR_2}Cena zdjęcia z przejażdżki: +STR_1964 :{WINDOW_COLOUR_2}Cena parasola: +STR_1965 :{WINDOW_COLOUR_2}Cena napoju: +STR_1966 :{WINDOW_COLOUR_2}Cena hamburgera: +STR_1967 :{WINDOW_COLOUR_2}Cena frytek: +STR_1968 :{WINDOW_COLOUR_2}Cena lodów: +STR_1969 :{WINDOW_COLOUR_2}Cena waty cukrowej: STR_1970 :{WINDOW_COLOUR_2} STR_1971 :{WINDOW_COLOUR_2} STR_1972 :{WINDOW_COLOUR_2} -STR_1973 :{WINDOW_COLOUR_2}Pizza price: +STR_1973 :{WINDOW_COLOUR_2}Cena pizzy: STR_1974 :{WINDOW_COLOUR_2} -STR_1975 :{WINDOW_COLOUR_2}Popcorn price: -STR_1976 :{WINDOW_COLOUR_2}Hot Dog price: -STR_1977 :{WINDOW_COLOUR_2}Tentacle price: -STR_1978 :{WINDOW_COLOUR_2}Hat price: -STR_1979 :{WINDOW_COLOUR_2}Toffee Apple price: -STR_1980 :{WINDOW_COLOUR_2}T-Shirt price: -STR_1981 :{WINDOW_COLOUR_2}Doughnut price: -STR_1982 :{WINDOW_COLOUR_2}Coffee price: +STR_1975 :{WINDOW_COLOUR_2}Cena popcornu: +STR_1976 :{WINDOW_COLOUR_2}Cena hot-doga: +STR_1977 :{WINDOW_COLOUR_2}Cena macki: +STR_1978 :{WINDOW_COLOUR_2}Cena kapelusza: +STR_1979 :{WINDOW_COLOUR_2}Cena jabłka kand.: +STR_1980 :{WINDOW_COLOUR_2}Cena podkoszulki: +STR_1981 :{WINDOW_COLOUR_2}Cena pączka: +STR_1982 :{WINDOW_COLOUR_2}Cena kawy: STR_1983 :{WINDOW_COLOUR_2} -STR_1984 :{WINDOW_COLOUR_2}Fried Chicken price: -STR_1985 :{WINDOW_COLOUR_2}Lemonade price: +STR_1984 :{WINDOW_COLOUR_2}Cena kurczaka: +STR_1985 :{WINDOW_COLOUR_2}Cena lemoniady: STR_1986 :{WINDOW_COLOUR_2} STR_1987 :{WINDOW_COLOUR_2} -STR_1988 :Balloon -STR_1989 :Cuddly Toy -STR_1990 :Park Map -STR_1991 :On-Ride Photo -STR_1992 :Umbrella -STR_1993 :Drink -STR_1994 :Burger -STR_1995 :Chips -STR_1996 :Ice Cream -STR_1997 :Candyfloss -STR_1998 :Empty Can -STR_1999 :Rubbish -STR_2000 :Empty Burger Box +STR_1988 :Balon +STR_1989 :Przytulanka +STR_1990 :Plan parku +STR_1991 :Zdjęcie z przejażdżki +STR_1992 :Parasol +STR_1993 :Napój +STR_1994 :Hamburger +STR_1995 :Frytki +STR_1996 :Lody +STR_1997 :Wata cukrowa +STR_1998 :Pusta puszka +STR_1999 :Śmiecie +STR_2000 :Puste pudełko po hamburgerze STR_2001 :Pizza -STR_2002 :Voucher +STR_2002 :Kupon STR_2003 :Popcorn STR_2004 :Hot Dog -STR_2005 :Tentacle -STR_2006 :Hat -STR_2007 :Toffee Apple -STR_2008 :T-Shirt -STR_2009 :Doughnut -STR_2010 :Coffee -STR_2011 :Empty Cup -STR_2012 :Fried Chicken -STR_2013 :Lemonade -STR_2014 :Empty Box -STR_2015 :Empty Bottle -STR_2016 :Balloons -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_2028 :Empty Burger Boxes -STR_2029 :Pizzas -STR_2030 :Vouchers +STR_2005 :Macka +STR_2006 :Kapelusz +STR_2007 :Jabłko kandyzowane +STR_2008 :Koszulka +STR_2009 :Pączek +STR_2010 :Kawa +STR_2011 :Pusty kubek +STR_2012 :Kurczak +STR_2013 :Lemoniada +STR_2014 :Puste pudełko +STR_2015 :Pusta butelka +STR_2016 :Balony +STR_2017 :Przytulanki +STR_2018 :Plany parku +STR_2019 :Zdjęcia z przejażdżki +STR_2020 :Parasole +STR_2021 :Napoje +STR_2022 :Hamburgery +STR_2023 :Frytki +STR_2024 :Lody +STR_2025 :Wata cukrowa +STR_2026 :Puste puszki +STR_2027 :Śmiecie +STR_2028 :Puste pudełka po hamburgerach +STR_2029 :Pizze +STR_2030 :Kupony STR_2031 :Popcorn -STR_2032 :Hot Dogs -STR_2033 :Tentacles -STR_2034 :Hats -STR_2035 :Toffee Apples -STR_2036 :T-Shirts -STR_2037 :Doughnuts -STR_2038 :Coffees -STR_2039 :Empty Cups -STR_2040 :Fried Chicken -STR_2041 :Lemonade -STR_2042 :Empty Boxes -STR_2043 :Empty Bottles -STR_2044 :a Balloon -STR_2045 :a Cuddly Toy -STR_2046 :a Park Map -STR_2047 :an On-Ride Photo -STR_2048 :an Umbrella -STR_2049 :a Drink -STR_2050 :a Burger -STR_2051 :some Chips -STR_2052 :an Ice Cream -STR_2053 :some Candyfloss -STR_2054 :an Empty Can -STR_2055 :some Rubbish -STR_2056 :an Empty Burger Box -STR_2057 :a Pizza -STR_2058 :a Voucher -STR_2059 :some Popcorn -STR_2060 :a Hot Dog -STR_2061 :a Tentacle -STR_2062 :a Hat -STR_2063 :a Toffee Apple -STR_2064 :a T-Shirt -STR_2065 :a Doughnut -STR_2066 :a Coffee -STR_2067 :an Empty Cup -STR_2068 :some Fried Chicken -STR_2069 :some Lemonade -STR_2070 :an Empty Box -STR_2071 :an Empty Bottle -STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Balloon -STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Cuddly Toy -STR_2074 :Map of {STRINGID} -STR_2075 :On-Ride Photo of {STRINGID} -STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Umbrella -STR_2077 :Drink -STR_2078 :Burger -STR_2079 :Chips -STR_2080 :Ice Cream -STR_2081 :Candyfloss -STR_2082 :Empty Can -STR_2083 :Rubbish -STR_2084 :Empty Burger Box +STR_2032 :Hot dogi +STR_2033 :Macki +STR_2034 :Kapelusze +STR_2035 :Jabłka kandyzowane +STR_2036 :Koszulki +STR_2037 :Pączki +STR_2038 :Kawy +STR_2039 :Puste kubki +STR_2040 :Kurczak +STR_2041 :Lemoniada +STR_2042 :Puste pudełka +STR_2043 :Puste butelki +STR_2044 :balon +STR_2045 :przytulanka +STR_2046 :plan parku +STR_2047 :zdjęcie z przejażdżki +STR_2048 :parasol +STR_2049 :napój +STR_2050 :hamburgera +STR_2051 :trochę frytek +STR_2052 :lody +STR_2053 :trochę waty cukrowej +STR_2054 :pustą puszkę +STR_2055 :trochę śmieci +STR_2056 :puste pudełko po hamburgerze +STR_2057 :pizza +STR_2058 :kupon +STR_2059 :trochę popcornu +STR_2060 :Hot Dog +STR_2061 :Macka +STR_2062 :Kapelusz +STR_2063 :jabłko kandyzowane +STR_2064 :koszulka +STR_2065 :Pączek +STR_2066 :Kawa +STR_2067 :pusty kubek +STR_2068 :Kurczak +STR_2069 :trochę lemoniady +STR_2070 :puste pudełko +STR_2071 :pustą butelkę +STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Balon +STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Przytulanka +STR_2074 :Plan {STRINGID} +STR_2075 :Zdjęcie z przejażdżki {STRINGID} +STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Parasol +STR_2077 :Napój +STR_2078 :Hamburger +STR_2079 :Frytki +STR_2080 :Lody +STR_2081 :Wata cukrowa +STR_2082 :Pusta puszka +STR_2083 :Śmiecie +STR_2084 :Puste pudełko po hamburgerze STR_2085 :Pizza -STR_2086 :Voucher for {STRINGID} +STR_2086 :Kupon na {STRINGID} STR_2087 :Popcorn STR_2088 :Hot Dog -STR_2089 :Tentacle -STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Hat -STR_2091 :Toffee Apple -STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} T-Shirt -STR_2093 :Doughnut -STR_2094 :Coffee -STR_2095 :Empty Cup -STR_2096 :Fried Chicken -STR_2097 :Lemonade -STR_2098 :Empty Box -STR_2099 :Empty Bottle -STR_2100 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2101 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2102 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2103 :{WINDOW_COLOUR_2}Pretzel price: -STR_2104 :{WINDOW_COLOUR_2}Hot Chocolate price: -STR_2105 :{WINDOW_COLOUR_2}Iced Tea price: -STR_2106 :{WINDOW_COLOUR_2}Funnel Cake price: -STR_2107 :{WINDOW_COLOUR_2}Sunglasses price: +STR_2089 :Macka +STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Kapelusz +STR_2091 :jabłko kandyzowane +STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Koszulka +STR_2093 :Pączek +STR_2094 :Kawa +STR_2095 :Pusty kubek +STR_2096 :Kurczak +STR_2097 :Lemoniada +STR_2098 :Puste pudełko +STR_2099 :Pusta butelka +STR_2100 :{WINDOW_COLOUR_2}Cena zdjęcia z przejażdżki: +STR_2101 :{WINDOW_COLOUR_2}Cena zdjęcia z przejażdżki: +STR_2102 :{WINDOW_COLOUR_2}Cena zdjęcia z przejażdżki: +STR_2103 :{WINDOW_COLOUR_2}Cena precla: +STR_2104 :{WINDOW_COLOUR_2}Cena gorącej czekolady: +STR_2105 :{WINDOW_COLOUR_2}Cena mrożonej herbaty: +STR_2106 :{WINDOW_COLOUR_2}Cena makaronika: +STR_2107 :{WINDOW_COLOUR_2}Cena okularów: STR_2108 :{WINDOW_COLOUR_2}Beef Noodles price: -STR_2109 :{WINDOW_COLOUR_2}Fried Rice Noodles price: -STR_2110 :{WINDOW_COLOUR_2}Wonton Soup price: -STR_2111 :{WINDOW_COLOUR_2}Meatball Soup price: -STR_2112 :{WINDOW_COLOUR_2}Fruit Juice price: -STR_2113 :{WINDOW_COLOUR_2}Soybean Milk price: -STR_2114 :{WINDOW_COLOUR_2}Sujongkwa price: -STR_2115 :{WINDOW_COLOUR_2}Sub Sandwich price: -STR_2116 :{WINDOW_COLOUR_2}Cookie price: +STR_2109 :{WINDOW_COLOUR_2}Cena smażonej ryby: +STR_2110 :{WINDOW_COLOUR_2}Cena zupy wonton: +STR_2111 :{WINDOW_COLOUR_2}Cena zupy klopsikowej: +STR_2112 :{WINDOW_COLOUR_2}Cena soku owocowego: +STR_2113 :{WINDOW_COLOUR_2}Cena mleka sojowego: +STR_2114 :{WINDOW_COLOUR_2}Cena sujongkwa: +STR_2115 :{WINDOW_COLOUR_2}Cena kanapki: +STR_2116 :{WINDOW_COLOUR_2}Cena ciasteczka: STR_2117 :{WINDOW_COLOUR_2} STR_2118 :{WINDOW_COLOUR_2} STR_2119 :{WINDOW_COLOUR_2} STR_2120 :{WINDOW_COLOUR_2}Roast Sausage price: STR_2121 :{WINDOW_COLOUR_2} -STR_2122 :On-Ride Photo -STR_2123 :On-Ride Photo -STR_2124 :On-Ride Photo -STR_2125 :Pretzel -STR_2126 :Hot Chocolate -STR_2127 :Iced Tea -STR_2128 :Funnel Cake -STR_2129 :Sunglasses +STR_2122 :Zdjęcie z przejażdżki +STR_2123 :Zdjęcie z przejażdżki +STR_2124 :Zdjęcie z przejażdżki +STR_2125 :Precel +STR_2126 :Gorąca czekolada +STR_2127 :Mrożona herbata +STR_2128 :Makaronik +STR_2129 :Okulary przeciwsłoneczne STR_2130 :Beef Noodles STR_2131 :Fried Rice Noodles -STR_2132 :Wonton Soup -STR_2133 :Meatball Soup -STR_2134 :Fruit Juice -STR_2135 :Soybean Milk +STR_2132 :Zupa wonton +STR_2133 :Zupa klopsikowa +STR_2134 :Sok owocowy +STR_2135 :Mleko sojowe STR_2136 :Sujongkwa -STR_2137 :Sub Sandwich -STR_2138 :Cookie -STR_2139 :Empty Bowl -STR_2140 :Empty Drink Carton -STR_2141 :Empty Juice Cup -STR_2142 :Roast Sausage -STR_2143 :Empty Bowl -STR_2144 :On-Ride Photos -STR_2145 :On-Ride Photos -STR_2146 :On-Ride Photos -STR_2147 :Pretzels -STR_2148 :Hot Chocolates -STR_2149 :Iced Teas -STR_2150 :Funnel Cakes -STR_2151 :Sunglasses +STR_2137 :Kanapka +STR_2138 :Ciasteczko +STR_2139 :Pusta miska +STR_2140 :Pusty karton +STR_2141 :Pusty kubek po soku +STR_2142 :Pieczona kiełbaska +STR_2143 :Pusta miska +STR_2144 :Zdjęcie z przejażdżki +STR_2145 :Zdjęcie z przejażdżki +STR_2146 :Zdjęcie z przejażdżki +STR_2147 :Precle +STR_2148 :Gorące czekolady +STR_2149 :Mrożone herbaty +STR_2150 :Makaroniki +STR_2151 :Okulary przeciwsłoneczne STR_2152 :Beef Noodles STR_2153 :Fried Rice Noodles -STR_2154 :Wonton Soups -STR_2155 :Meatball Soups -STR_2156 :Fruit Juices -STR_2157 :Soybean Milks +STR_2154 :Zupy wonton +STR_2155 :Zupy klopsikowe +STR_2156 :Soki owocowe +STR_2157 :Mleko sojowe STR_2158 :Sujongkwa -STR_2159 :Sub Sandwiches -STR_2160 :Cookies -STR_2161 :Empty Bowls -STR_2162 :Empty Drink Cartons -STR_2163 :Empty Juice cups -STR_2164 :Roast Sausages -STR_2165 :Empty Bowls -STR_2166 :an On-Ride Photo -STR_2167 :an On-Ride Photo -STR_2168 :an On-Ride Photo -STR_2169 :a Pretzel -STR_2170 :a Hot Chocolate -STR_2171 :an Iced Tea -STR_2172 :a Funnel Cake -STR_2173 :a pair of Sunglasses +STR_2159 :Kanapki +STR_2160 :Ciasteczka +STR_2161 :Puste miski +STR_2162 :Puste kartony +STR_2163 :Puste kubki po soku +STR_2164 :Pieczone kiełbaski +STR_2165 :Puste miski +STR_2166 :zdjęcie z przejażdżki +STR_2167 :zdjęcie z przejażdżki +STR_2168 :zdjęcie z przejażdżki +STR_2169 :precla +STR_2170 :gorącą czekoladą +STR_2171 :herbat +STR_2172 :marakonik +STR_2173 :okulary STR_2174 :some Beef Noodles STR_2175 :some Fried Rice Noodles -STR_2176 :some Wonton Soup -STR_2177 :some Meatball Soup -STR_2178 :a Fruit Juice -STR_2179 :some Soybean Milk -STR_2180 :some Sujongkwa +STR_2176 :trochę zupy wonton +STR_2177 :trochę zupy klopsikowej +STR_2178 :sok owocowy +STR_2179 :trochę mleka sojowego +STR_2180 :trochę Sujongkwa STR_2181 :a Sub Sandwich STR_2182 :a Cookie STR_2183 :an Empty Bowl @@ -2221,11 +2218,11 @@ STR_2187 :an Empty Bowl STR_2188 :On-Ride Photo of {STRINGID} STR_2189 :On-Ride Photo of {STRINGID} STR_2190 :On-Ride Photo of {STRINGID} -STR_2191 :Pretzel -STR_2192 :Hot Chocolate -STR_2193 :Iced Tea +STR_2191 :Precel +STR_2192 :Gorącza czekolada +STR_2193 :Mrożona herbata STR_2194 :Funnel Cake -STR_2195 :Sunglasses +STR_2195 :Okulary przeciwsłoneczne STR_2196 :Beef Noodles STR_2197 :Fried Rice Noodles STR_2198 :Wonton Soup @@ -2234,7 +2231,7 @@ STR_2200 :Fruit Juice STR_2201 :Soybean Milk STR_2202 :Sujongkwa STR_2203 :Sub Sandwich -STR_2204 :Cookie +STR_2204 :Ciasteczko STR_2205 :Empty Bowl STR_2206 :Empty Drink Carton STR_2207 :Empty Juice Cup @@ -2253,18 +2250,18 @@ STR_2219 :{RED}{COMMA16} people have died in an accident on {STRINGID} STR_2220 :{WINDOW_COLOUR_2}Park Rating: {BLACK}{COMMA16} STR_2221 :{SMALLFONT}{BLACK}Park Rating: {COMMA16} STR_2222 :{SMALLFONT}{BLACK}{STRINGID} -STR_2223 :{WINDOW_COLOUR_2}Guests in park: {BLACK}{COMMA16} -STR_2224 :{WINDOW_COLOUR_2}Cash: {BLACK}{CURRENCY2DP} -STR_2225 :{WINDOW_COLOUR_2}Cash: {RED}{CURRENCY2DP} -STR_2226 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} -STR_2227 :{WINDOW_COLOUR_2}Company value: {BLACK}{CURRENCY} +STR_2223 :{WINDOW_COLOUR_2}Gości w parku: {BLACK}{COMMA16} +STR_2224 :{WINDOW_COLOUR_2}Gotówka: {BLACK}{CURRENCY2DP} +STR_2225 :{WINDOW_COLOUR_2}Gotówka: {RED}{CURRENCY2DP} +STR_2226 :{WINDOW_COLOUR_2}Wartość parku: {BLACK}{CURRENCY} +STR_2227 :{WINDOW_COLOUR_2}Wartość spółki: {BLACK}{CURRENCY} STR_2228 :{WINDOW_COLOUR_2}Last month's profit from food/drink and{NEWLINE}merchandise sales: {BLACK}{CURRENCY} STR_2229 :Slope up to vertical STR_2230 :Vertical track STR_2231 :Holding brake for drop STR_2232 :Cable lift hill -STR_2233 :{SMALLFONT}{BLACK}Park information -STR_2234 :Recent Messages +STR_2233 :{SMALLFONT}{BLACK}Informacje o parku +STR_2234 :Najnowsze wiadomości STR_2235 :{SMALLFONT}{STRINGID} {STRINGID} # ------------------------------------------ Polish start STR_2236 :Stycznia @@ -2289,7 +2286,7 @@ STR_2254 :Łagodne atrakcje STR_2255 :Kolejki górskie STR_2256 :Intensywne atrakcje STR_2257 :Wodne atrakcje -STR_2258 :Sklepy i stoiska +STR_2258 :Sklepiki i kioski STR_2259 :Scenerie i dekoracje STR_2260 :Bez budżetu STR_2261 :Minimalny @@ -2314,7 +2311,7 @@ STR_2279 :Łagodne atrakcje STR_2280 :Kolejki górskie STR_2281 :Intensywne atrakcje STR_2282 :Wodne atrakcje -STR_2283 :Sklepy i stoiska +STR_2283 :Sklepiki i kioski STR_2284 :Scenerie i dekoracje STR_2285 :Wstępne badania STR_2286 :Projektowanie @@ -2324,11 +2321,9 @@ STR_2289 :{STRINGID} {STRINGID} STR_2290 :{SMALLFONT}{BLACK}{STRINGID} {STRINGID} STR_2291 :Wybierz scenariusz dla nowej gry STR_2292 :{WINDOW_COLOUR_2}Odwiedzone atrakcje: -STR_2293 :{BLACK} Nic -# ------------------------------------------ Polish end -STR_2294 :{SMALLFONT}{BLACK}Change base land style -STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land -# ------------------------------------------ Polish start +STR_2293 :{BLACK} Brak +STR_2294 :{SMALLFONT}{BLACK}Zmień podstawowy styl gruntu +STR_2295 :{SMALLFONT}{BLACK}Zmień poziome krawędzie gruntu STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na wejście do parku STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} atrakcji STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} atrakcjach @@ -2338,20 +2333,18 @@ STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} na STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} napojach STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} pamiątce STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} wydane na {BLACK}{COMMA16} pamiątkach -# ------------------------------------------ Polish end -STR_2305 :Track design files -STR_2306 :Save track design -STR_2307 :Select {STRINGID} design -STR_2308 :{STRINGID} Track Designs -STR_2309 :Install New Track Design -STR_2310 :Build custom design -STR_2311 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} (approx.) -STR_2312 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} (approx.) -STR_2313 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} (approx.) +STR_2305 :Plik z projektami tras +STR_2306 :Zapisz projekt trasy +STR_2307 :Wybierz {STRINGID} projekt +STR_2308 :{STRINGID} projekty tras +STR_2309 :Zainstaluj nowy projekt trasy +STR_2310 :Stwórz własny projekt +STR_2311 :{WINDOW_COLOUR_2}Emocje: {BLACK}{COMMA2DP32} (około) +STR_2312 :{WINDOW_COLOUR_2}Intensywność: {BLACK}{COMMA2DP32} (około) +STR_2313 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} (około) STR_2314 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID} -STR_2315 :{WINDOW_COLOUR_2}Cost: {BLACK}around {CURRENCY} -STR_2316 :{WINDOW_COLOUR_2}Space required: {BLACK}{COMMA16} x {COMMA16} blocks -# ------------------------------------------ Polish start +STR_2315 :{WINDOW_COLOUR_2}Koszt: {BLACK}around {CURRENCY} +STR_2316 :{WINDOW_COLOUR_2}Zajmowany teren: {BLACK}{COMMA16} x {COMMA16} pól STR_2317 :{WINDOW_COLOUR_2}Jakość dźwięku: STR_2318 :Niska STR_2319 :Średnia @@ -2395,7 +2388,7 @@ STR_2356 :{WINDOW_COLOUR_2}Skontrolowane atrakcje: {BLACK}{COMMA16} STR_2357 :Dom STR_2358 :Jednostki STR_2359 :Prawdziwe wartości -STR_2360 :{WINDOW_COLOUR_2}Rozdzielczość: +STR_2360 :Rozdzielczość: STR_2361 :Wygładzanie terenu STR_2362 :{SMALLFONT}{BLACK}Włącza wyświetlanie krawędzi elementów terenu STR_2363 :Siatka terenu @@ -2421,31 +2414,30 @@ STR_2382 :Teren STR_2383 :Woda STR_2384 :{WINDOW_COLOUR_2}Twój cel: STR_2385 :{BLACK}Brak -# ------------------------------------------ Polish end -STR_2386 :{BLACK}To have at least {COMMA16} guests in your park at the end of {MONTHYEAR}, with a park rating of at least 600 -STR_2387 :{BLACK}To achieve a park value of at least {POP16}{POP16}{CURRENCY} at the end of {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} -STR_2388 :{BLACK}Have Fun! -STR_2389 :{BLACK}Build the best {STRINGID} you can! -STR_2390 :{BLACK}To have 10 different types of roller coasters operating in your park, each with an excitement value of at least 6.00 +STR_2386 :{BLACK}Miej przynajmniej {COMMA16} gościu w parku na koniec roku {MONTHYEAR} przy atrakcyjności parku wynoszącej przynajmniej 600 +STR_2387 :{BLACK}Uzyskaj wartość parku nie mniejszą niż {POP16}{POP16}{CURRENCY} na koniec {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} +STR_2388 :{BLACK}Baw się dobrze! +STR_2389 :{BLACK}Wybuduj tą atrakcję ({STRINGID}) najlepiej jak potrafisz! +STR_2390 :{BLACK}Zbuduj w parku 10 różnych działających kolejek górskich, każda o współczynniku emocji wynoszącym przynajmniej 6.00 STR_2391 :{BLACK}To have at least {COMMA16} guests in your park. You must not let the park rating drop below 700 at any time! -STR_2392 :{BLACK}To achieve a monthly income from ride tickets of at least {POP16}{POP16}{CURRENCY} -STR_2393 :{BLACK}To have 10 different types of roller coasters operating in your park, each with a minimum length of {LENGTH}, and an excitement rating of at least 7.00 -STR_2394 :{BLACK}To finish building all 5 of the partially built roller coasters in this park, designing them to achieve excitement ratings of at least {POP16}{POP16}{COMMA2DP32} each -STR_2395 :{BLACK}To repay your loan and achieve a park value of at least {POP16}{POP16}{CURRENCY} -STR_2396 :{BLACK}To achieve a monthly profit from food, drink and merchandise sales of at least {POP16}{POP16}{CURRENCY} -STR_2397 :None -STR_2398 :Number of guests at a given date -STR_2399 :Park value at a given date -STR_2400 :Have fun -STR_2401 :Build the best ride you can -STR_2402 :Build 10 roller coasters -STR_2403 :Number of guests in park -STR_2404 :Monthly income from ride tickets -STR_2405 :Build 10 roller coasters of a given length -STR_2406 :Finish building 5 roller coasters -STR_2407 :Repay loan and achieve a given park value -STR_2408 :Monthly profit from food/merchandise -# ------------------------------------------ Polish start +STR_2392 :{BLACK}Uzyskaj miesięczny przychód ze sprzedaży biletów na aktracje w wysokości przynajmniej {POP16}{POP16}{CURRENCY} +STR_2393 :{BLACK}Zbuduj w parku 10 różnych działających kolejek górskich, każda o współczynniku emocji wynoszącym przynajmniej 7.00 i nie krótsza niż {LENGTH} +STR_2394 :{BLACK}Dokończ budowę 5 częściowo już wybudowanych kolejek górskich, projektując je tak aby współczynnik emocji każdej z nich nie był mniejszy niż {POP16}{POP16}{COMMA2DP32} +STR_2395 :{BLACK}Spłać pożyczki i osiągnij wartość parku nie mniejszą niż {POP16}{POP16}{CURRENCY} +STR_2396 :{BLACK}Osiągnij miesięczny zysk ze sprzedaży żywności i innych towarów nie mniejszy niż {POP16}{POP16}{CURRENCY} +STR_2397 :Brak +STR_2398 :Liczba gości w konkretnym dniu +STR_2399 :Wartość parku w konkretnym dniu +STR_2400 :Baw się dobrze +STR_2401 :Zbuduj najlepszą atrakcję +STR_2402 :Zbuduj 10 kolejek górskich +STR_2403 :Liczba gości w parku +STR_2404 :Miesięczny przychód z biletów na atrakcje +STR_2405 :Zbuduj 10 kolejek górskich o określonej długości +STR_2406 :Ukończ budowę 5 kolejek górskich +STR_2407 :Spłać pożyczki i osiągnij konkretną wartość parku +# 'innych towarów' not in org. pl translation +STR_2408 :Miesięczny zysk ze sprzedaży żywności i innych towarów STR_2409 :{WINDOW_COLOUR_2}Trwające kampanie marketingowe STR_2410 :{BLACK}Brak STR_2411 :{WINDOW_COLOUR_2}Dostępne kampanie marketingowe @@ -2484,47 +2476,45 @@ STR_2442 : STR_2443 :{WINDOW_COLOUR_2}Koszt tygodniowy: {BLACK}{CURRENCY2DP} STR_2444 :{WINDOW_COLOUR_2}Koszt łączny: {BLACK}{CURRENCY2DP} STR_2445 :Rozpocznij kampanię -STR_2446 :{YELLOW}Twoja kampania marketingowa na darmowe wejście do parku zakończyła się -STR_2447 :{YELLOW}Twoja kampania marketingowa na darmowe przejażdżki {STRINGID} zakończyła się -STR_2448 :{YELLOW}Twoja kampania marketingowa na wejście do parku za połowę ceny zakończyła się -STR_2449 :{YELLOW}Twoja kampania marketingowa na darmowe {STRINGID} zakończyła się -STR_2450 :{YELLOW}Twoja kmapania reklamująca park zakończyła się -STR_2451 :{YELLOW}Twoja kampania reklamująca {STRINGID} zakończyła się -# ------------------------------------------ Polish end -STR_2452 :{WINDOW_COLOUR_2}Cash (less loan): {BLACK}{CURRENCY2DP} -STR_2453 :{WINDOW_COLOUR_2}Cash (less loan): {RED}{CURRENCY2DP} +STR_2446 :{YELLOW}Twoja kampania marketingowa na darmowe wejście do parku dobiegła końca +STR_2447 :{YELLOW}Twoja kampania marketingowa na darmowe przejażdżki {STRINGID} dobiegła końca +STR_2448 :{YELLOW}Twoja kampania marketingowa na wejście do parku za połowę ceny dobiegła końca +STR_2449 :{YELLOW}Twoja kampania marketingowa na darmowe {STRINGID} dobiegła końca +STR_2450 :{YELLOW}Twoja kmapania reklamująca park dobiegła końca +STR_2451 :{YELLOW}Twoja kampania reklamująca {STRINGID} dobiegła końca +STR_2452 :{WINDOW_COLOUR_2}Gotówka (minus pożyczka): {BLACK}{CURRENCY2DP} +STR_2453 :{WINDOW_COLOUR_2}Gotówka (minus pożyczka): {RED}{CURRENCY2DP} STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - STR_2455 :{SMALLFONT}{BLACK}+{CURRENCY2DP} - STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} - -STR_2457 :{SMALLFONT}{BLACK}Show financial accounts -STR_2458 :{SMALLFONT}{BLACK}Show graph of cash (less loan) over time -STR_2459 :{SMALLFONT}{BLACK}Show graph of park value over time -STR_2460 :{SMALLFONT}{BLACK}Show graph of weekly profit -STR_2461 :{SMALLFONT}{BLACK}Show marketing campaigns -STR_2462 :{SMALLFONT}{BLACK}Show view of park entrance -STR_2463 :{SMALLFONT}{BLACK}Show graph of park ratings over time -STR_2464 :{SMALLFONT}{BLACK}Show graph of guest numbers over time -STR_2465 :{SMALLFONT}{BLACK}Show park entrance price and information -STR_2466 :{SMALLFONT}{BLACK}Show park statistics -STR_2467 :{SMALLFONT}{BLACK}Show objectives for this game -STR_2468 :{SMALLFONT}{BLACK}Show recent awards this park has received -STR_2469 :{SMALLFONT}{BLACK}Select level of research & development -STR_2470 :{SMALLFONT}{BLACK}Research new transport rides -STR_2471 :{SMALLFONT}{BLACK}Research new gentle rides -STR_2472 :{SMALLFONT}{BLACK}Research new roller coasters -STR_2473 :{SMALLFONT}{BLACK}Research new thrill rides -STR_2474 :{SMALLFONT}{BLACK}Research new water rides -STR_2475 :{SMALLFONT}{BLACK}Research new shops and stalls -STR_2476 :{SMALLFONT}{BLACK}Research new scenery and themeing -STR_2477 :{SMALLFONT}{BLACK}Select operating mode for this ride/attraction -STR_2478 :{SMALLFONT}{BLACK}Show graph of velocity against time -STR_2479 :{SMALLFONT}{BLACK}Show graph of altitude against time -STR_2480 :{SMALLFONT}{BLACK}Show graph of vertical acceleration against time -STR_2481 :{SMALLFONT}{BLACK}Show graph of lateral acceleration against time -STR_2482 :{SMALLFONT}{BLACK}Profit: {CURRENCY} per week, Park Value: {CURRENCY} -STR_2483 :{WINDOW_COLOUR_2}Weekly profit: {BLACK}+{CURRENCY2DP} -STR_2484 :{WINDOW_COLOUR_2}Weekly profit: {RED}{CURRENCY2DP} -# ------------------------------------------ Polish start +STR_2457 :{SMALLFONT}{BLACK}Pokaż rachunki +STR_2458 :{SMALLFONT}{BLACK}Pokaż wykres zmian gotówki w czasie pomniejszonej o wysokość pożyczki +STR_2459 :{SMALLFONT}{BLACK}Pokaż wykres zmian wartości parku w czasie +STR_2460 :{SMALLFONT}{BLACK}Pokaż wykres tygodniowego zysku +STR_2461 :{SMALLFONT}{BLACK}Pokaż kampanie reklamowe +STR_2462 :{SMALLFONT}{BLACK}Pokaż widok na wejście do parku +STR_2463 :{SMALLFONT}{BLACK}Pokaż wykres zmian atrakcyjności parku w czasie +STR_2464 :{SMALLFONT}{BLACK}Pokaż wykres zmian liczby gości w czasie +STR_2465 :{SMALLFONT}{BLACK}Pokaż cenę wstępu do parku i informację o parku +STR_2466 :{SMALLFONT}{BLACK}Wyświetl statystyki parku +STR_2467 :{SMALLFONT}{BLACK}Wyświetl cel gry +STR_2468 :{SMALLFONT}{BLACK}Wyświetl nagrody, które ostatnio zdobył park +STR_2469 :{SMALLFONT}{BLACK}Wybierz poziom badań i rozwoju +STR_2470 :{SMALLFONT}{BLACK}Opracuj nowe atrakcje przejazdowe +STR_2471 :{SMALLFONT}{BLACK}Opracuj nowe łagodne atrakcje +STR_2472 :{SMALLFONT}{BLACK}Opracuj nowe kolejki górskie +STR_2473 :{SMALLFONT}{BLACK}Opracuj nowe atrakcje z dreszczykiem emocji +STR_2474 :{SMALLFONT}{BLACK}Opracuj nowe atrakcje wodne +STR_2475 :{SMALLFONT}{BLACK}Opracuj nowe sklepiki i kioski +STR_2476 :{SMALLFONT}{BLACK}Opracuj nową scenerię i stylizację +STR_2477 :{SMALLFONT}{BLACK}Wybierz tryb pracy dla tej atrakcji +STR_2478 :{SMALLFONT}{BLACK}Pokaż wykres prędkości względem czasu +STR_2479 :{SMALLFONT}{BLACK}Pokaż wykres wysokości względem czasu +STR_2480 :{SMALLFONT}{BLACK}Pokaż wykres przyspieszenia pionowego względem czasu +STR_2481 :{SMALLFONT}{BLACK}Pokaż wykres przyspieszenia poprzecznego względem czasu +STR_2482 :{SMALLFONT}{BLACK}Zysk: {CURRENCY} na tydzień, Wartość parku: {CURRENCY} +STR_2483 :{WINDOW_COLOUR_2}Tygodniowy zysk: {BLACK}+{CURRENCY2DP} +STR_2484 :{WINDOW_COLOUR_2}Tygodniowy zysk: {RED}{CURRENCY2DP} STR_2485 :Sterowanie STR_2486 :Ogólne STR_2487 :Pokazuj "prawdziwe" imiona gości @@ -2533,39 +2523,39 @@ STR_2489 :Skróty klawiszowe... STR_2490 :Przypisanie klawiszy STR_2491 :Zresetuj klawisze STR_2492 :{SMALLFONT}{BLACK}Przywróć wszystkie skróty klawiszowe do ustawień domyślnych -# ------------------------------------------ Polish end -STR_2493 :Close top-most window -STR_2494 :Close all floating windows -STR_2495 :Cancel construction mode -STR_2496 :Pause game -STR_2497 :Zoom view out -STR_2498 :Zoom view in -STR_2499 :Rotate view clockwise -STR_2500 :Rotate construction object -STR_2501 :Underground view toggle -STR_2502 :Remove base land toggle -STR_2503 :Remove vertical land toggle -STR_2504 :See-through rides toggle -STR_2505 :See-through scenery toggle -STR_2506 :Invisible supports toggle -STR_2507 :Invisible people toggle -STR_2508 :Height marks on land toggle -STR_2509 :Height marks on ride tracks toggle -STR_2510 :Height marks on paths toggle -STR_2511 :Adjust land -STR_2512 :Adjust water -STR_2513 :Build scenery -STR_2514 :Build paths -STR_2515 :Build new ride -STR_2516 :Show financial information -STR_2517 :Show research information -STR_2518 :Show rides list -STR_2519 :Show park information -STR_2520 :Show guest list -STR_2521 :Show staff list -STR_2522 :Show recent messages -STR_2523 :Show map -STR_2524 :Screenshot +# START OF CONTROLS LIST +STR_2493 :Zamknij okno z wierzu +STR_2494 :Zamknij wszystkie dodatkowe okna +STR_2495 :Wyjdź z trybu budowania +STR_2496 :Wstrzymaj grę +STR_2497 :Oddalenie widoku +STR_2498 :Przybliżenie widoku +STR_2499 :Obrót widoku +STR_2500 :Obrót budowanego obiektu +STR_2501 :Widok podziemny +STR_2502 :Usuń grunt podstawowy +STR_2503 :Usuń grunt pionowy +STR_2504 :Przezroczyste atrakcje +STR_2505 :Przezroczysta sceneria +STR_2506 :Niewidzialne sporniki +STR_2507 :Niewidzialni ludzie +STR_2508 :Znaczniki wysokości na gruncie +STR_2509 :Znaczniki wysokości na torach +STR_2510 :Znaczniki wysokości na dróżkach +STR_2511 :Zmień ziemię +STR_2512 :Zmień wodę +STR_2513 :Buduj scenerię +STR_2514 :Buduj dróżki +STR_2515 :Buduj nową atrakcję +STR_2516 :Wyświetl informacje finansowe +STR_2517 :Wyświetl informacje nt. badań +STR_2518 :Wyświetl listę atrakcji +STR_2519 :Wyświetl informacje o parku +STR_2520 :Wyświetl listę gości +STR_2521 :Wyświetl listę pracowników +STR_2522 :Wyświetl ostatnie wiadomości +STR_2523 :Pokaż mapę +STR_2524 :Zrzut ekranu STR_2525 :??? STR_2526 :??? STR_2527 :??? @@ -2578,8 +2568,8 @@ STR_2533 :Backspace STR_2534 :Tab STR_2535 :??? STR_2536 :??? -STR_2537 :Clear -STR_2538 :Return +STR_2537 :Wyczyść +STR_2538 :Wróć STR_2539 :??? STR_2540 :??? STR_2541 :??? @@ -2598,22 +2588,22 @@ STR_2553 :??? STR_2554 :??? STR_2555 :??? STR_2556 :??? -STR_2557 :Spacebar +STR_2557 :Spacja STR_2558 :PgUp STR_2559 :PgDn STR_2560 :End STR_2561 :Home -STR_2562 :Left -STR_2563 :Up -STR_2564 :Right -STR_2565 :Down -STR_2566 :Select -STR_2567 :Print -STR_2568 :Execute -STR_2569 :Snapshot +STR_2562 :Strzałka w lewo +STR_2563 :Strzałka w górę +STR_2564 :Strzałka w prawo +STR_2565 :Strzałka w dół +STR_2566 :Wybierz +STR_2567 :Drukuj +STR_2568 :Wykonaj +STR_2569 :Migawka STR_2570 :Insert STR_2571 :Delete -STR_2572 :Help +STR_2572 :Pomoc STR_2573 :0 STR_2574 :1 STR_2575 :2 @@ -2721,8 +2711,9 @@ STR_2676 :??? STR_2677 :??? STR_2678 :??? STR_2679 :??? +# END OF CONTROLS LIST STR_2680 :All research complete -STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} +STR_2681 :{MEDIUMFONT}{BLACK}Zwiększa twoją gotówkę o {CURRENCY} STR_2682 : STR_2683 : STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive @@ -2735,23 +2726,23 @@ STR_2690 :Map Generation STR_2691 :{WINDOW_COLOUR_2}Base height: STR_2692 :{WINDOW_COLOUR_2}Water level: STR_2693 :{WINDOW_COLOUR_2}Terrain: -STR_2694 :Generate -STR_2695 :Random terrain -STR_2696 :Place trees +STR_2694 :Generuj +STR_2695 :Losowy teren +STR_2696 :Umieść drzewa STR_2697 :??? STR_2698 :??? STR_2699 :??? -STR_2700 :Autosave frequency: -STR_2701 :Every minute -STR_2702 :Every 5 minutes -STR_2703 :Every 15 minutes -STR_2704 :Every 30 minutes -STR_2705 :Every hour -STR_2706 :Never -STR_2707 :Open new window -STR_2708 :{WINDOW_COLOUR_1}Are you sure you want to overwrite {STRINGID}? -STR_2709 :Overwrite -STR_2710 :Type the name of the file. +STR_2700 :Częstotliwość autozapisu: +STR_2701 :Co minutę +STR_2702 :Co 5 minut +STR_2703 :Co 15 minut +STR_2704 :Co 30 minut +STR_2705 :Co godzinę +STR_2706 :Nigdy +STR_2707 :Otwórz nowe okno +STR_2708 :{WINDOW_COLOUR_1}Jesteś pewien, że chcesz nadpisać {STRINGID}? +STR_2709 :Nadpisz +STR_2710 :Wpisz nazwę pliku. STR_2711 :; STR_2712 := STR_2713 :, @@ -2805,8 +2796,8 @@ STR_2753 :Skoszona trawa STR_2754 :Podlej kwiaty STR_2755 :Usuń wandalizm STR_2756 :Usuń śmieci -STR_2757 :Wymuś słońce -STR_2758 :Wymuś burzę +STR_2757 : +STR_2758 : STR_2759 :Mniejsze odstępy STR_2760 :+{CURRENCY} STR_2761 : @@ -2833,88 +2824,88 @@ STR_2780 :Dodatkowe okno podglądu STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} STR_2782 :SHIFT + STR_2783 :CTRL + -STR_2784 :Change keyboard shortcut -STR_2785 :{WINDOW_COLOUR_2}Press new shortcut key for:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} -STR_2786 :{SMALLFONT}{BLACK}Click on shortcut description to select new key -STR_2787 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} -STR_2788 :{WINDOW_COLOUR_2}Congratulations !{NEWLINE}{BLACK}You achieved your objective with a company value of {CURRENCY} ! -STR_2789 :{WINDOW_COLOUR_2}You have failed your objective ! -STR_2790 :Enter name into scenario chart -STR_2791 :Enter name -STR_2792 :Please enter your name for the scenario chart: +STR_2784 :Zmień skrót klawiszowy +STR_2785 :{WINDOW_COLOUR_2}Wciśnij nowy klawisz skrótu dla:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2786 :{SMALLFONT}{BLACK}Kliknij opis skrótu, aby wybrać nowy klawisz +STR_2787 :{WINDOW_COLOUR_2}Wartość parku: {BLACK}{CURRENCY} +STR_2788 :{WINDOW_COLOUR_2}Gratulacje!{NEWLINE}{BLACK}Cel osiągnięty! Wartość twojej spółki wynosi {CURRENCY}! +STR_2789 :{WINDOW_COLOUR_2}Porażka! Cel nie został osiągnięty! +STR_2790 :Podaj imię do listy scenariuszy +STR_2791 :Podaj imię +STR_2792 :Podaj swoje imię do listy scenariuszy: STR_2793 :{SMALLFONT}(Completed by {STRINGID}) -STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY} -STR_2795 :Sort -STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed -# ------------------------------------------ Polish start +STR_2794 :{WINDOW_COLOUR_2}Ukończony przez: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} z wartością spółki wynoszącą: {BLACK}{CURRENCY} +STR_2795 :Sortuj +STR_2796 :{SMALLFONT}{BLACK}Sortuj listę atrakcji według wyświetlonych informacji STR_2797 :Przesuń widok gdy kursor blisko krawędzi STR_2798 :{SMALLFONT}{BLACK}Włącza przesuwanie widoku, gdy kursor zbliży się do krawędzi ekranu -# ------------------------------------------ Polish end -STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments -STR_2800 :{WINDOW_COLOUR_2}Total admissions: {BLACK}{COMMA32} -STR_2801 :{WINDOW_COLOUR_2}Income from admissions: {BLACK}{CURRENCY2DP} -STR_2802 :Map -STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map -STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map -STR_2805 :{SMALLFONT}{BLACK}Show map of park -STR_2806 :{RED}Guests are complaining about the disgusting state of the paths in your park{NEWLINE}Check where your handymen are and consider organizing them better -STR_2807 :{RED}Guests are complaining about the amount of litter in your park{NEWLINE}Check where your handymen are and consider organizing them better -STR_2808 :{RED}Guests are complaining about the vandalism in your park{NEWLINE}Check where your security guards are and consider organizing them better -STR_2809 :{RED}Guests are hungry and can't find anywhere to buy food -STR_2810 :{RED}Guests are thirsty and can't find anywhere to buy drinks -STR_2811 :{RED}Guests are complaining because they can't find the toilets in your park -STR_2812 :{RED}Guests are getting lost or stuck{NEWLINE}Check whether the layout of your footpaths needs improving to help the guests find their way around -STR_2813 :{RED}Your park entrance fee is too high!{NEWLINE}Reduce your entrance fee or improve the value of the park to attract more guests -STR_2814 :{WINDOW_COLOUR_2}Most untidy park award -STR_2815 :{WINDOW_COLOUR_2}Tidiest park award -STR_2816 :{WINDOW_COLOUR_2}Award for the park with the best roller coasters -STR_2817 :{WINDOW_COLOUR_2}Best value park award -STR_2818 :{WINDOW_COLOUR_2}Most beautiful park award -STR_2819 :{WINDOW_COLOUR_2}Worst value park award -STR_2820 :{WINDOW_COLOUR_2}Safest park award -STR_2821 :{WINDOW_COLOUR_2}Best staff award -STR_2822 :{WINDOW_COLOUR_2}Best park food award -STR_2823 :{WINDOW_COLOUR_2}Worst park food award -STR_2824 :{WINDOW_COLOUR_2}Best park toilets award -STR_2825 :{WINDOW_COLOUR_2}Most disappointing park award -STR_2826 :{WINDOW_COLOUR_2}Best water rides award -STR_2827 :{WINDOW_COLOUR_2}Best custom-designed rides award -STR_2828 :{WINDOW_COLOUR_2}Most dazzling ride colour schemes award -STR_2829 :{WINDOW_COLOUR_2}Most confusing park layout award -STR_2830 :{WINDOW_COLOUR_2}Best gentle ride award -STR_2831 :{TOPAZ}Your park has received an award for being 'The most untidy park in the country'! -STR_2832 :{TOPAZ}Your park has received an award for being 'The tidiest park in the country'! -STR_2833 :{TOPAZ}Your park has received an award for being 'The park with the best roller coasters'! -STR_2834 :{TOPAZ}Your park has received an award for being 'The best value park in the country'! -STR_2835 :{TOPAZ}Your park has received an award for being 'The most beautiful park in the country'! -STR_2836 :{TOPAZ}Your park has received an award for being 'The worst value park in the country'! -STR_2837 :{TOPAZ}Your park has received an award for being 'The safest park in the country'! -STR_2838 :{TOPAZ}Your park has received an award for being 'The park with the best staff'! -STR_2839 :{TOPAZ}Your park has received an award for being 'The park with the best food in the country'! -STR_2840 :{TOPAZ}Your park has received an award for being 'The park with the worst food in the country'! -STR_2841 :{TOPAZ}Your park has received an award for being 'The park with the best toilet facilities in the country'! -STR_2842 :{TOPAZ}Your park has received an award for being 'The most disappointing park in the country'! -STR_2843 :{TOPAZ}Your park has received an award for being 'The park with the best water rides in the country'! -STR_2844 :{TOPAZ}Your park has received an award for being 'The park with the best custom-designed rides'! -STR_2845 :{TOPAZ}Your park has received an award for being 'The park with the most dazzling choice of colour schemes'! -STR_2846 :{TOPAZ}Your park has received an award for being 'The park with the most confusing layout'! -STR_2847 :{TOPAZ}Your park has received an award for being 'The park with the best gentle rides'! -STR_2848 :{WINDOW_COLOUR_2}No recent awards -STR_2849 :New scenario installed successfully -STR_2850 :New track design installed successfully -STR_2851 :Scenario already installed -STR_2852 :Track design already installed -STR_2853 :Forbidden by the local authority! -STR_2854 :{RED}Guests can't get to the entrance of {STRINGID} !{NEWLINE}Construct a path to the entrance -STR_2855 :{RED}{STRINGID} has no path leading from its exit !{NEWLINE}Construct a path from the ride exit -STR_2856 :{WINDOW_COLOUR_2}Tutorial -STR_2857 :{WINDOW_COLOUR_2}(Press a key or mouse button to take control) -STR_2858 :Can't start marketing campaign... -STR_2859 :Another instance of OpenRCT2 is already running -STR_2860 :Infogrames Interactive credits... -STR_2861 :{WINDOW_COLOUR_2}Licensed to Infogrames Interactive Inc. -STR_2862 :Music acknowledgements... -STR_2863 :Music acknowledgements +STR_2799 :{SMALLFONT}{BLACK}Przejrzyj lub zmień funkcje przypisane do klawiszy sterujących +STR_2800 :{WINDOW_COLOUR_2}Całkowita liczba gości: {BLACK}{COMMA32} +STR_2801 :{WINDOW_COLOUR_2}Wpływy z opłat za wstęp: {BLACK}{CURRENCY2DP} +STR_2802 :Plan parku +STR_2803 :{SMALLFONT}{BLACK}Podświetl tych gości na mapie +STR_2804 :{SMALLFONT}{BLACK}Podświetl tych pracowników na mapie +STR_2805 :{SMALLFONT}{BLACK}Pokaż plan parku +# alerts +STR_2806 :{RED}Goście skarżą się na fatalny stan ścieżek w twoim parku{NEWLINE}Sprawdź gdzie znajduja się twoi dozorcy i rozważ lepszą organizacje ich pracy +STR_2807 :{RED}Goście skarżą się na śmieci leżące na ziemi w twoim parku{NEWLINE}Sprawdź gdzie znajdują się twoi dozorcy i rozwać lepszą organizację ich pracy +STR_2808 :{RED}Goście skarzą się na wandalizm w twoim parku{NEWLINE}Sprawdź gdzie znajdują się twoi ochroniarze i rozwać poprawę organizacji ich pracy +STR_2809 :{RED}Goście są głodni i nie mogą znaleźć miejsca gdzie mogliby kupić coś do jedzenia +STR_2810 :{RED}Goście są spragnieni i nie mogą znaleźć miejsca gdzie mogliby kupić jakieś napoje +STR_2811 :{RED}Goście się skarżą, że w twoim parku bardzo ciężko jest znaleźć ubikację +STR_2812 :{RED}Goście gubią się lub zatrzymują w jednym miejscu{NEWLINE}Sprawdź czy nie należy zmienić rozplanowania ścieżek, aby ludzie poruszali się po parku z większą łatwością +STR_2813 :{RED}Opłata za wstęp do twojego parku jest zbyt wysoka!{NEWLINE}Zmniejsz ją lub podnieś wartość parku, aby przyciągnąc większą liczbę gości +STR_2814 :{WINDOW_COLOUR_2}Nagroda dla najbardziej zaśmieconego parku +STR_2815 :{WINDOW_COLOUR_2}Nagroda dla najczystszego parku +STR_2816 :{WINDOW_COLOUR_2}Nagroda za najlepsze kolejki górskie +STR_2817 :{WINDOW_COLOUR_2}Nagroda dla parku o najwyższej wartości +STR_2818 :{WINDOW_COLOUR_2}Nagroda dla najpiękniejszego parku +STR_2819 :{WINDOW_COLOUR_2}Nagroda dla parku o najniższej wartości +STR_2820 :{WINDOW_COLOUR_2}Nagroda dla najbezpieczniejszego parku +STR_2821 :{WINDOW_COLOUR_2}Nagroda za najlepszy personel +STR_2822 :{WINDOW_COLOUR_2}Nagroda za najlepsze jedzenie +STR_2823 :{WINDOW_COLOUR_2}Nagroda za najgorsze jedzenie +STR_2824 :{WINDOW_COLOUR_2}Nagroda za najlepsze ubikacje +STR_2825 :{WINDOW_COLOUR_2}Nagroda za najbardziej rozczarowującego parku +STR_2826 :{WINDOW_COLOUR_2}Nagroda za najlepsze atrakcje wodne +STR_2827 :{WINDOW_COLOUR_2}Nagroda za najlepsze atrakcje współczesnego parku +STR_2828 :{WINDOW_COLOUR_2}Nagroda za najbardziej oszałamiającą kolorystykę atrakcji +STR_2829 :{WINDOW_COLOUR_2}Nagroda za najbardziej niezrozumiałego planu parku +STR_2830 :{WINDOW_COLOUR_2}Nagroda za najlepsze łagodne atrakcje +STR_2831 :{TOPAZ}Twój park został ogłoszony najbardziej zaśmieconym parkiem w kraju! +STR_2832 :{TOPAZ}Twój park został ogłoszony najczystszym parkiem w kraju! +STR_2833 :{TOPAZ}Twój park dostał nagrodę za najlepsze kolejki górskie! +STR_2834 :{TOPAZ}Twój park dostał nagrodę za najwyższą wartość w kraju! +STR_2835 :{TOPAZ}Twój park został ogłoszony najpiękniejszym parkiem w kraju! +STR_2836 :{TOPAZ}Twój park otrzymał nagrodę za najniższą wartość w kraju! +STR_2837 :{TOPAZ}Twój park otrzymał nagrodę za najwyższe bezpieczeństwo w kraju! +STR_2838 :{TOPAZ}Twój park otrzymał nagrodę za najlepszy personel! +STR_2839 :{TOPAZ}Twój park otrzymał nagrodę za najlepsze jedzenie w kraju! +STR_2840 :{TOPAZ}Twój park otrzymał nagrodę za najgorsze jedzenie w kraju! +STR_2841 :{TOPAZ}Twój park otrzymał nagrodę za najlepsze ubikacje w kraju! +STR_2842 :{TOPAZ}Twój park został ogłoszony najbardziej rozczarowującym parkiem w kraju! +STR_2843 :{TOPAZ}Twój park otrzymał nagrodę za najlepsze atrakcje wodne w kraju! +STR_2844 :{TOPAZ}Twój park otrzymał nagrodę za najlepsze atrakcje własnego projektu! +STR_2845 :{TOPAZ}Twój park otrzymał nagrodę za najbardziej oszałamiającą kolorystykę! +STR_2846 :{TOPAZ}Twój park otrzymał nagrodę za najbardziej niezrozumiały plan! +STR_2847 :{TOPAZ}Twój park otrzymał nagrodę za najbardziej łagodne atrakcje! +STR_2848 :{WINDOW_COLOUR_2}Twój park nie otrzymał ostatnio nagród +STR_2849 :Zainstalowano nowy scenariusz +STR_2850 :Zainstalowano nowy projekt trasy +STR_2851 :Ten scenariusz jest już zainstalowany +STR_2852 :Ten projekt trasy jest już zainstalowany +STR_2853 :Zabronione przez władze lokalne! +STR_2854 :{RED}Goście nie mogą dotrzeć do wejścia do atrakcji {STRINGID}!{NEWLINE}Zbuduj dróżkę prowadzącą do wejścia +STR_2855 :Przy wyjściu z atrakcji {RED}{STRINGID} nie ma żadnej dróżki!{NEWLINE}Zbuduj dróżkę prowadzącą do wyjścia +STR_2856 :{WINDOW_COLOUR_2}Samouczek +STR_2857 :{WINDOW_COLOUR_2}(Wciśnij klawisz lub przycisk myszy, aby przejąć kontrolę) +STR_2858 :Nie można rozpocząć kampanii reklamowej... +STR_2859 :Gra OpenRCT2 jest już uruchomiona +STR_2860 :Informacje o autorach, Infogrames Interactive... +STR_2861 :{WINDOW_COLOUR_2}Licencja przyznana Infogrames Interactive Inc. +STR_2862 :Muzyka... +STR_2863 :Muzyka +# song names was translated in polish exe STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) non copyright STR_2865 :{WINDOW_COLOUR_2}Heyken's Serenade: (J.Heyken) British Standard Music Coy; GEMA, BRITICO STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Composer unknown) Copyright Control @@ -3061,7 +3052,7 @@ STR_3006 :{PALEGOLD}ABC STR_3007 :{LIGHTPINK}ABC STR_3008 :{PEARLAQUA}ABC STR_3009 :{PALESILVER}ABC -STR_3010 :Unable to load file... +STR_3010 :Nie można wczytać pliku... STR_3011 :File contains invalid data STR_3012 :Dodgems beat style STR_3013 :Fairground organ style @@ -3105,85 +3096,81 @@ STR_3050 :Golf hole B STR_3051 :Golf hole C STR_3052 :Golf hole D STR_3053 :Golf hole E -STR_3054 :Loading... +STR_3054 :Ładowanie... # ------------------------------------------ Polish start STR_3055 :Biały STR_3056 :Przezroczysty -STR_3057 :{WINDOW_COLOUR_2}Znacznik Budowy: -# ------------------------------------------ Polish end -STR_3058 :Brick walls -STR_3059 :Hedges -STR_3060 :Ice blocks -STR_3061 :Wooden fences -STR_3062 :{SMALLFONT}{BLACK}Standard roller coaster track +STR_3057 :{WINDOW_COLOUR_2}Znacznik budowy: +STR_3058 :Ceglane ściany +STR_3059 :Żywopłoty +STR_3060 :Lodowe bloki +STR_3061 :Drewniane płoty +STR_3062 :{SMALLFONT}{BLACK}Standardowa trasa kolejki górskiej STR_3063 :{SMALLFONT}{BLACK}Water channel (track submerged) -STR_3064 :Beginner Parks -STR_3065 :Challenging Parks -STR_3066 :Expert Parks -STR_3067 :{OPENQUOTES}Real{ENDQUOTES} Parks -STR_3068 :Other Parks -STR_3069 :Top Section -STR_3070 :Slope to Level -STR_3071 :{WINDOW_COLOUR_2}Same price throughout park -STR_3072 :{SMALLFONT}{BLACK}Select whether this price is used throughout the entire park -STR_3073 :{RED}WARNING: Your park rating has dropped below 700 !{NEWLINE}If you haven't raised the park rating in 4 weeks, your park will be closed down -STR_3074 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have 3 weeks to raise the park rating -STR_3075 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have only 2 weeks to raise the park rating, or your park will be closed down -STR_3076 :{RED}FINAL WARNING: Your park rating is still below 700 !{NEWLINE}In just 7 days your park will be closed down unless you can raise the rating -STR_3077 :{RED}CLOSURE NOTICE: Your park has been closed down ! -STR_3078 :Plain entrance -STR_3079 :Wooden entrance -STR_3080 :Canvas tent entrance -STR_3081 :Castle entrance (grey) -STR_3082 :Castle entrance (brown) -STR_3083 :Jungle entrance -STR_3084 :Log cabin entrance -STR_3085 :Classical/Roman entrance -STR_3086 :Abstract entrance -STR_3087 :Snow/Ice entrance -STR_3088 :Pagoda entrance -STR_3089 :Space entrance -STR_3090 :{SMALLFONT}{BLACK}Select style of entrance, exit, and station -STR_3091 :You are not allowed to remove this section! -STR_3092 :You are not allowed to move or modify the station for this ride! -STR_3093 :{WINDOW_COLOUR_2}Favourite: {BLACK}{STRINGID} -STR_3094 :N/A -STR_3095 :{WINDOW_COLOUR_2}Lift hill chain speed: +STR_3064 :Tryb początkujący +STR_3065 :Tryb zaawansowany +STR_3066 :Tryb eksperta +STR_3067 :{OPENQUOTES}Prawdziwe{ENDQUOTES} parki +STR_3068 :Inne parki +STR_3069 :Część górna +STR_3070 :Spadek do poziomu +STR_3071 :{WINDOW_COLOUR_2}Taka sama cena w całym parku +STR_3072 :{SMALLFONT}{BLACK}Czy wybrana cena ma obowiązywać w całym parku +STR_3073 :{RED}UWAGA: Atrakcyjność twojego parku spadła poniżej 700!{NEWLINE}Jeśli w ciągu 4 tygodni nie sprawisz, że atrakcyjność parku wzrośnie, zostanie on zamknięty +STR_3074 :{RED}UWAGA: Atrakcyjność twojego parku wciąż jest niższa od 700!{NEWLINE}Pozostały ci 3 tygodnie na jej zwiększenie +STR_3075 :{RED}UWAGA: Atrakcyjność twojego parku wciąż jest niższa od 700!{NEWLINE}Pozostały ci już tylko 2 tygodnie na jej zwiększenie albo park zostanie zamknięty +STR_3076 :{RED}OSTATNIE OSTRZEŻENIE: Atrakcyjność twojego parku wciąż jest niższa od 700!{NEWLINE}Już za 7 dni twój park zostanie zamknięty, jeśli nie rozwiążesz tego problemu +STR_3077 :{RED}INFORMACJ: Twój park został zamknięty! +STR_3078 :Zwykłe wejście +STR_3079 :Drewniane wejście +STR_3080 :Wejście w postaci płóciennego namiotu +STR_3081 :Brama zamkowa (szara) +STR_3082 :Brama zamkowa (brązowa) +STR_3083 :Wejście do dżungli +STR_3084 :Wejście do chaty drwala +STR_3085 :Wejście klasyczne/rzymskie +STR_3086 :Wejście abstrakcyjne +STR_3087 :Wejście śnieżne/lodowe +STR_3088 :Wejście w stylu japońskim +STR_3089 :Wejście w stylu kosmicznym +STR_3090 :{SMALLFONT}{BLACK}Wybierz styl wejścia i stacji +STR_3091 :Nie można usunąć tego segmentu! +STR_3092 :Nie można przesuwać ani modyfikować stacji dla tej atrakcji! +STR_3093 :{WINDOW_COLOUR_2}Ulubione: {BLACK}{STRINGID} +STR_3094 :Brak +STR_3095 :{WINDOW_COLOUR_2}Prędkość wyciągarki: STR_3096 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} -STR_3097 :{SMALLFONT}{BLACK}Select lift hill chain speed -STR_3098 :Can't change lift hill speed... -STR_3099 :{SMALLFONT}{BLACK}Select colour -STR_3100 :{SMALLFONT}{BLACK}Select second colour -STR_3101 :{SMALLFONT}{BLACK}Select third colour -STR_3102 :{SMALLFONT}{BLACK}Re-paint coloured scenery on landscape -STR_3103 :Can't re-paint this... -STR_3104 :{SMALLFONT}{BLACK}List rides -STR_3105 :{SMALLFONT}{BLACK}List shops and stalls +STR_3097 :{SMALLFONT}{BLACK}Ustaw prędkość wyciągarki +STR_3098 :Nie można zmienić prędkości wyciągarki +STR_3099 :{SMALLFONT}{BLACK}Wybierz kolor +STR_3100 :{SMALLFONT}{BLACK}Wybierz drugi kolor +STR_3101 :{SMALLFONT}{BLACK}Wybierz trzeci kolor +STR_3102 :{SMALLFONT}{BLACK}Ustaw ponownie kolor scenerii na terenie +STR_3103 :Nie można tego przemalować... +STR_3104 :{SMALLFONT}{BLACK}Lista przejażdżek +STR_3105 :{SMALLFONT}{BLACK}Lista sklepów i stoisk STR_3106 :{SMALLFONT}{BLACK}List information kiosks and other guest facilities -# ------------------------------------------ Polish start STR_3107 :Zamknij STR_3108 :Testuj STR_3109 :Otwórz -# ------------------------------------------ Polish end -STR_3110 :{WINDOW_COLOUR_2}Block Sections: {BLACK}{COMMA16} -STR_3111 :{SMALLFONT}{BLACK}Click on design to build it -STR_3112 :{SMALLFONT}{BLACK}Click on design to rename or delete it -STR_3113 :Select a different design -STR_3114 :{SMALLFONT}{BLACK}Go back to design selection window -STR_3115 :{SMALLFONT}{BLACK}Save track design -STR_3116 :{SMALLFONT}{BLACK}Save track design (Not possible until ride has been tested and statistics have been generated) -STR_3117 :{BLACK}Calling mechanic... -STR_3118 :{BLACK}{STRINGID} is heading for the ride -STR_3119 :{BLACK}{STRINGID} is fixing the ride -STR_3120 :{SMALLFONT}{BLACK}Locate nearest available mechanic, or mechanic fixing ride -STR_3121 :Unable to locate mechanic, or all nearby mechanics are busy -STR_3122 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guest -STR_3123 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guests -STR_3124 :Broken {STRINGID} -STR_3125 :{WINDOW_COLOUR_2}Excitement Factor: {BLACK}+{COMMA16}% -STR_3126 :{WINDOW_COLOUR_2}Intensity Factor: {BLACK}+{COMMA16}% -STR_3127 :{WINDOW_COLOUR_2}Nausea Factor: {BLACK}+{COMMA16}% -# ------------------------------------------ Polish start +STR_3110 :{WINDOW_COLOUR_2}Segmenty blokowe: {BLACK}{COMMA16} +STR_3111 :{SMALLFONT}{BLACK}Kliknij projekt, aby go wybudować +STR_3112 :{SMALLFONT}{BLACK}Kliknij projekt, aby zmienić jego nazwę lub go usunąć +STR_3113 :Wybierz inny projekt +STR_3114 :{SMALLFONT}{BLACK}Wróć do okna wyboru projektu +STR_3115 :{SMALLFONT}{BLACK}Zapisz projekt trasy +STR_3116 :{SMALLFONT}{BLACK}Zapisz projekt trasy (niedostępne do czasu sprawdzenia atrakcji i wygenerowania statystyk) +STR_3117 :{BLACK}Wzywane jest mechanik... +STR_3118 :{BLACK}{STRINGID} zmierza w stronę atrakcji +STR_3119 :{BLACK}{STRINGID} naprawia atrakcję +STR_3120 :{SMALLFONT}{BLACK}Znajdź najbliższego wolnego mechanika lub mechanika naprawiającego atrakcję +STR_3121 :Nie udało się znaleźć mechanika lub wszyscy mechanicy w okolicy są zajęci +STR_3122 :{WINDOW_COLOUR_2}Ulubiona atrakcja: {BLACK}{COMMA16} gości +STR_3123 :{WINDOW_COLOUR_2}Ulubiona atrakcja: {BLACK}{COMMA16} gości +STR_3124 :Zepsute: {STRINGID} +STR_3125 :{WINDOW_COLOUR_2}Emocje: {BLACK}+{COMMA16}% +STR_3126 :{WINDOW_COLOUR_2}Intensywność: {BLACK}+{COMMA16}% +STR_3127 :{WINDOW_COLOUR_2}Tolerancja nudności: {BLACK}+{COMMA16}% STR_3128 :Zapisz Projekt Trasy STR_3129 :Zapisz Projekt Trasy ze Scenerią STR_3130 :Zapisz @@ -3200,8 +3187,8 @@ STR_3139 :Cable lift unable to work in this operating mode STR_3140 :Cable lift hill must start immediately after station STR_3141 :Multi-circuit per ride not possible with cable lift hill STR_3142 :{WINDOW_COLOUR_2}Capacity: {BLACK}{STRINGID} -STR_3143 :{SMALLFONT}{BLACK}Show people on map -STR_3144 :{SMALLFONT}{BLACK}Show rides and stalls on map +STR_3143 :{SMALLFONT}{BLACK}Pokaż ludzi +STR_3144 :{SMALLFONT}{BLACK}Pokaż przejażdżki i stoiska STR_3145 :{SMALLFONT}{BLACK}Scroll {STRINGID} left STR_3146 :{SMALLFONT}{BLACK}Scroll {STRINGID} right STR_3147 :{SMALLFONT}{BLACK}Scroll {STRINGID} left fast @@ -3214,9 +3201,9 @@ STR_3153 :{SMALLFONT}{BLACK}Scroll {STRINGID} down fast STR_3154 :{SMALLFONT}{BLACK}Scroll {STRINGID} up/down STR_3155 : STR_3156 : -STR_3157 :map -STR_3158 :graph -STR_3159 :list +STR_3157 :mapa +STR_3158 :wykres +STR_3159 :lista STR_3160 : STR_3161 : STR_3162 :Unable to allocate enough memory @@ -3246,12 +3233,12 @@ STR_3185 :Small Scenery STR_3186 :Large Scenery STR_3187 :Walls/Fences STR_3188 :Path Signs -STR_3189 :Footpaths +STR_3189 :Ścieżki STR_3190 :Path Extras STR_3191 :Scenery Groups -STR_3192 :Park Entrance -STR_3193 :Water -STR_3194 :Scenario Description +STR_3192 :Wejście do parku +STR_3193 :Woda +STR_3194 :Opis scenariusza STR_3195 :Invention List STR_3196 :{WINDOW_COLOUR_2}Research Group: {BLACK}{STRINGID} STR_3197 :{WINDOW_COLOUR_2}Items pre-invented at start of game: @@ -3268,51 +3255,51 @@ STR_3207 :Roller Coaster Designer STR_3208 :Track Designs Manager STR_3209 :Back to Previous Step: STR_3210 :Forward to Next Step: -STR_3211 :{WINDOW_COLOUR_2}Map size: +STR_3211 :{WINDOW_COLOUR_2}Rozmiar mapy: STR_3212 :{POP16}{COMMA16} x {PUSH16}{COMMA16} -STR_3213 :Can't decrease map size any further -STR_3214 :Can't increase map size any further -STR_3215 :Too close to edge of map -STR_3216 :{SMALLFONT}{BLACK}Select park-owned land etc. -STR_3217 :Land Owned -STR_3218 :Construction Rights Owned -STR_3219 :Land For Sale -STR_3220 :Construction Rights For Sale -STR_3221 :{SMALLFONT}{BLACK}Set land to be owned by the park -STR_3222 :{SMALLFONT}{BLACK}Set construction rights only to be owned by the park -STR_3223 :{SMALLFONT}{BLACK}Set land to be available to purchase by the park -STR_3224 :{SMALLFONT}{BLACK}Set construction rights to be available to purchase by the park +STR_3213 :Nie można bardziej zmniejszyć mapy +STR_3214 :Nie można bardziej zwiększyć mapy +STR_3215 :Za blisko do krawędzi mapy +STR_3216 :{SMALLFONT}{BLACK}Wybierz teren należący do parku itp. +STR_3217 :Posiadany teren +STR_3218 :Posiadane pozwolenia na budowe +STR_3219 :Teren na sprzedaż +STR_3220 :Pozwolenia na bud. na sprzedaż +STR_3221 :{SMALLFONT}{BLACK}Przekaż własność terenu parkowi +STR_3222 :{SMALLFONT}{BLACK}Przekaż pozwolenie na budowę parkowi +STR_3223 :{SMALLFONT}{BLACK}Ustaw teren jako dostępny do nabycia +STR_3224 :{SMALLFONT}{BLACK}Ustaw pozwolenie na budowę jako możliwe do nabycia STR_3225 :{SMALLFONT}{BLACK}Toggle on/off building a random cluster of objects around the selected position -STR_3226 :{SMALLFONT}{BLACK}Build park entrance -STR_3227 :Too many park entrances! -STR_3228 :{SMALLFONT}{BLACK}Set starting positions for people -STR_3229 :Block Brakes cannot be used directly after station -STR_3230 :Block Brakes cannot be used directly after each other -STR_3231 :Block Brakes cannot be used directly after the top of this lift hill -STR_3232 :Options - Financial -STR_3233 :Options - Guests -STR_3234 :Options - Park -STR_3235 :{SMALLFONT}{BLACK}Show financial options -STR_3236 :{SMALLFONT}{BLACK}Show guest options -STR_3237 :{SMALLFONT}{BLACK}Show park options -STR_3238 :No Money -STR_3239 :{SMALLFONT}{BLACK}Make this park a 'no money' park with no financial restrictions -STR_3240 :{WINDOW_COLOUR_2}Initial cash: -STR_3241 :{WINDOW_COLOUR_2}Initial loan: -STR_3242 :{WINDOW_COLOUR_2}Maximum loan size: -STR_3243 :{WINDOW_COLOUR_2}Annual interest rate: -STR_3244 :Forbid marketing campaigns -STR_3245 :{SMALLFONT}{BLACK}Forbid advertising, promotional schemes, and other marketing campaigns +STR_3226 :{SMALLFONT}{BLACK}Zbuduj wejście do parku +STR_3227 :Za dużo wejść do parku! +STR_3228 :{SMALLFONT}{BLACK}Ustaw początkowe rozmieszczenie ludzi +STR_3229 :Hamulce tarczowe nie mogą znajdować się bezpośrednio za stacją +STR_3230 :Hamulce tarczowe nie mogą znajdować się bezpośrednio za sobą +STR_3231 :Hamulce tarczowe nie mogą znajdować się bezpośrednio za szczytem wzniesienia z wyciągarki +STR_3232 :Opcje - Finanse +STR_3233 :Opcje - Goście +STR_3234 :Opcje - Park +STR_3235 :{SMALLFONT}{BLACK}Wyświetl opcje finansowe +STR_3236 :{SMALLFONT}{BLACK}Wyświetl opcje gości +STR_3237 :{SMALLFONT}{BLACK}Wyświetl opcje parku +STR_3238 :Bez pieniędzy +STR_3239 :{SMALLFONT}{BLACK}Ta opcja pozwala znieść wszelkie ograniczenia finansowe dla parku +STR_3240 :{WINDOW_COLOUR_2}Początkowa gotówka: +STR_3241 :{WINDOW_COLOUR_2}Początkowe zadłużenie: +STR_3242 :{WINDOW_COLOUR_2}Maksymalne zadłużenie: +STR_3243 :{WINDOW_COLOUR_2}Oprocentowanie pożyczek: +STR_3244 :Zakaz kampanii reklamowych +STR_3245 :{SMALLFONT}{BLACK}Zakaż przeprowadzania kampanii reklamowych, promocji i innych działań marketingowych STR_3246 :{WINDOW_COLOUR_2}{CURRENCY} STR_3247 :{WINDOW_COLOUR_2}{COMMA16}% -STR_3248 :Can't increase initial cash any further! -STR_3249 :Can't reduce initial cash any further! -STR_3250 :Can't increase initial loan any further! -STR_3251 :Can't reduce initial loan any further! -STR_3252 :Can't increase maximum loan size any further! -STR_3253 :Can't reduce maximum loan size any further! -STR_3254 :Can't increase interest rate any further! -STR_3255 :Can't reduce interest rate any further! +STR_3248 :Nie można bardziej zwiększyć ilości początkowej gotówki! +STR_3249 :Nie można bardziej zmniejszyć ilości początkowej gotówki! +STR_3250 :Nie można bardziej zwiększyć początkowego zadłużenia! +STR_3251 :Nie można bardziej zmniejszyć początkowego zadłużenia! +STR_3252 :Nie można bardziej zwiększyć maksymalnego zadłużenia! +STR_3253 :Nie można bardziej zmniejszyć maksymalnego zadłużenia! +STR_3254 :Nie można bardziej zwiększyć oprocentowania pożyczek! +STR_3255 :Nie można bardziej zmniejszyć oprocentowania pożyczek! STR_3256 :Guests prefer less intense rides STR_3257 :{SMALLFONT}{BLACK}Select whether guests should generally prefer less intense rides only STR_3258 :Guests prefer more intense rides @@ -3334,34 +3321,34 @@ STR_3273 :Park rating higher difficult level STR_3274 :{SMALLFONT}{BLACK}Make the park rating value more challenging STR_3275 :Guest generation higher difficult level STR_3276 :{SMALLFONT}{BLACK}Make it more difficult to attract guests to the park -STR_3277 :{WINDOW_COLOUR_2}Cost to buy land: -STR_3278 :{WINDOW_COLOUR_2}Cost to buy construction rights: +STR_3277 :{WINDOW_COLOUR_2}Koszt zakupu ziemi: +STR_3278 :{WINDOW_COLOUR_2}Koszt zakupu planów budowy: STR_3279 :Free park entry / Pay per ride STR_3280 :Pay to enter park / Free rides STR_3281 :{WINDOW_COLOUR_2}Entry price: STR_3282 :{SMALLFONT}{BLACK}Select objective and park name STR_3283 :{SMALLFONT}{BLACK}Select rides to be preserved -STR_3284 :Objective Selection +STR_3284 :Wybór celu STR_3285 :Preserved Rides STR_3286 :{SMALLFONT}{BLACK}Select objective for this scenario -STR_3287 :{WINDOW_COLOUR_2}Objective: -STR_3288 :{SMALLFONT}{BLACK}Select climate -STR_3289 :{WINDOW_COLOUR_2}Climate: +STR_3287 :{WINDOW_COLOUR_2}Cel: +STR_3288 :{SMALLFONT}{BLACK}Wybierz klimat +STR_3289 :{WINDOW_COLOUR_2}Klimat: STR_3290 :Cool and wet STR_3291 :Warm STR_3292 :Hot and dry STR_3293 :Cold STR_3294 :Change... -STR_3295 :{SMALLFONT}{BLACK}Change name of park -STR_3296 :{SMALLFONT}{BLACK}Change name of scenario +STR_3295 :{SMALLFONT}{BLACK}Zmień nazwę parku +STR_3296 :{SMALLFONT}{BLACK}Zmień nazwę scenariusza STR_3297 :{SMALLFONT}{BLACK}Change detail notes about park / scenario -STR_3298 :{WINDOW_COLOUR_2}Park Name: {BLACK}{STRINGID} +STR_3298 :{WINDOW_COLOUR_2}Nazwa parku: {BLACK}{STRINGID} STR_3299 :{WINDOW_COLOUR_2}Park/Scenario Details: -STR_3300 :{WINDOW_COLOUR_2}Scenario Name: {BLACK}{STRINGID} +STR_3300 :{WINDOW_COLOUR_2}Nazwa scenariusza: {BLACK}{STRINGID} STR_3301 :{WINDOW_COLOUR_2}Objective Date: STR_3302 :{WINDOW_COLOUR_2}{MONTHYEAR} -STR_3303 :{WINDOW_COLOUR_2}Number of guests: -STR_3304 :{WINDOW_COLOUR_2}Park value: +STR_3303 :{WINDOW_COLOUR_2}Liczba gości: +STR_3304 :{WINDOW_COLOUR_2}Wartość parku: STR_3305 :{WINDOW_COLOUR_2}Monthly income: STR_3306 :{WINDOW_COLOUR_2}Monthly profit: STR_3307 :{WINDOW_COLOUR_2}Minimum length: @@ -3370,18 +3357,18 @@ STR_3309 :{WINDOW_COLOUR_2}{COMMA16} STR_3310 :{WINDOW_COLOUR_2}{LENGTH} STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} STR_3312 :{WINDOW_COLOUR_2}Rides/attractions under a preservation order: -STR_3313 :Scenario Name -STR_3314 :Enter name for scenario: +STR_3313 :Nazwa scenariusza +STR_3314 :Wprowadź nazwę dla scenariusza: STR_3315 :Park/Scenario Details -STR_3316 :Enter description of this scenario: -STR_3317 :No details yet +STR_3316 :Wprowadź opis tego scenariusza: +STR_3317 :Brak szczegółów STR_3318 :{SMALLFONT}{BLACK}Select which group this scenario appears in STR_3319 :{WINDOW_COLOUR_2}Scenario Group: STR_3320 :Unable to save scenario file... STR_3321 :New objects installed successfully -STR_3322 :{WINDOW_COLOUR_2}Objective: {BLACK}{STRINGID} +STR_3322 :{WINDOW_COLOUR_2}Cel: {BLACK}{STRINGID} STR_3323 :Missing object data, ID: -STR_3324 :Requires Add-On Pack: +STR_3324 :Wymaga dodatku: {STRINGID} STR_3325 :Requires an Add-On Pack STR_3326 :{WINDOW_COLOUR_2}(no image) STR_3327 :Starting positions for people not set @@ -3395,7 +3382,7 @@ STR_3334 :{SMALLFONT}{BLACK}Select whether to save any additional plug-in obj STR_3335 :Roller Coaster Designer - Select Ride Types & Vehicles STR_3336 :Track Designs Manager - Select Ride Type STR_3337 : -STR_3338 :{BLACK}Custom-designed layout +STR_3338 :{BLACK}Projekt własny STR_3339 :{BLACK}{COMMA16} design available, or custom-designed layout STR_3340 :{BLACK}{COMMA16} designs available, or custom-designed layout # ------------------------------------------ Polish start @@ -3407,38 +3394,38 @@ STR_3345 :Menadżer projektów tras # ------------------------------------------ Polish end STR_3346 :Can't save track design... STR_3347 :Ride is too large, contains too many elements, or scenery is too spread out -STR_3348 :Rename -STR_3349 :Delete +STR_3348 :Zmień nazwę +STR_3349 :Usuń STR_3350 :Track design name STR_3351 :Enter new name for this track design: STR_3352 :Can't rename track design... STR_3353 :New name contains invalid characters STR_3354 :Another file exists with this name, or file is write-protected STR_3355 :File is write-protected or locked -STR_3356 :Delete File +STR_3356 :Usuń plik STR_3357 :{WINDOW_COLOUR_2}Are you sure you want to permanently delete {STRINGID} ? STR_3358 :Can't delete track design... STR_3359 :{BLACK}No track designs of this type -STR_3360 :Warning! +STR_3360 :Uwaga! STR_3361 :Too many track designs of this type - Some will not be listed. STR_3362 : STR_3363 : -STR_3364 :Advanced +STR_3364 :Zaawansowane STR_3365 :{SMALLFONT}{BLACK}Allow selection of individual items of scenery in addition to scenery groups -STR_3366 :{BLACK}= Ride -STR_3367 :{BLACK}= Food Stall -STR_3368 :{BLACK}= Drink Stall -STR_3369 :{BLACK}= Souvenir Stall -STR_3370 :{BLACK}= Info. Kiosk -STR_3371 :{BLACK}= First Aid -STR_3372 :{BLACK}= Cash Machine -STR_3373 :{BLACK}= Toilet -STR_3374 :Warning: Too many objects selected! +STR_3366 :{BLACK}= Atrakcja +STR_3367 :{BLACK}= Budka z jedzeniem +STR_3368 :{BLACK}= Budka z napojami +STR_3369 :{BLACK}= Stoisko z pamiątk. +STR_3370 :{BLACK}= Punkt informacyjny +STR_3371 :{BLACK}= Pierwsza pomoc +STR_3372 :{BLACK}= Bankomat +STR_3373 :{BLACK}= Toaleta +STR_3374 :Uwaga: Zaznaczono zbyt wiele obiektów! STR_3375 :Not all objects in this scenery group could be selected STR_3376 :Install new track design... STR_3377 :{SMALLFONT}{BLACK}Install a new track design file -STR_3378 :Install -STR_3379 :Cancel +STR_3378 :Zainstaluj +STR_3379 :Anuluj STR_3380 :Unable to install this track design... STR_3381 :File is not compatible or contains invalid data STR_3382 :File copy failed @@ -3448,59 +3435,57 @@ STR_3384 :An existing track design already has this name - Please select a ne STR_3385 :Podstawy STR_3386 :Budowanie Własnych Przejażdżek STR_3387 :Budowanie Kolejek Górskich -# ------------------------------------------ Polish end STR_3388 :Unable to switch to selected mode STR_3389 :Unable to select additional item of scenery... -STR_3390 :Too many items selected +STR_3390 :Zaznaczono zbyt wiele rzeczy # Start of tutorial strings. Not used at the moment, so not necessary to translate. -STR_3391 :{SMALLFONT}{BLACK}Here is our park - Let's have a quick look around... -STR_3392 :{SMALLFONT}{BLACK}Holding down the RIGHT mouse button and moving the mouse is the quickest way to move the view... -STR_3393 :{SMALLFONT}{BLACK}To view more of the park, you can zoom the view out using the icon at the top of the screen... -STR_3394 :{SMALLFONT}{BLACK}You can also rotate the view in 90 degree steps... -STR_3395 :{SMALLFONT}{BLACK}Building anything at this scale is a bit difficult, so let's zoom the view back in again... -STR_3396 :{SMALLFONT}{BLACK}Let's build a simple ride to get the park started... -STR_3397 :{SMALLFONT}{BLACK}The white 'ghost' image shows where the ride will be built. We'll move the pointer to select the position then click to build it... -STR_3398 :{SMALLFONT}{BLACK}Rides need an entrance and an exit. We'll move the pointer to a square on the edge of the ride and then click to build first the entrance and then the exit... -STR_3399 :{SMALLFONT}{BLACK}We need to build footpaths to allow guests to reach our new ride... -STR_3400 :{SMALLFONT}{BLACK}For the path to the ride entrance we'll use a special 'queue line' path... -STR_3401 :{SMALLFONT}{BLACK}For the exit path, just an 'ordinary' path will do... -STR_3402 :{SMALLFONT}{BLACK}Right, lets open the ride! To open the ride we click the flag icon on the ride window and select 'open'... -STR_3403 :{SMALLFONT}{BLACK}But where are the guests? -STR_3404 :{SMALLFONT}{BLACK}Oh - The park is still closed! Right - Let's open it... -STR_3405 :{SMALLFONT}{BLACK}While we're waiting for our first guests, let's build some scenery... -STR_3406 :{SMALLFONT}{BLACK}Here's our empty park. We're going to build a simple custom-designed ride... -STR_3407 :{SMALLFONT}{BLACK}First we need to choose a starting position... -STR_3408 :{SMALLFONT}{BLACK}The section of track we've just built is a 'station platform', to allow guests to get on and off the ride... -STR_3409 :{SMALLFONT}{BLACK}We'll extend the platform a bit by adding a couple more station platform sections... -STR_3410 :{SMALLFONT}{BLACK}The icons at the top of the construction window let you choose different track pieces to add... -STR_3411 :{SMALLFONT}{BLACK}We'll select a left-hand curve... -STR_3412 :{SMALLFONT}{BLACK}The curve hasn't been built yet, but the white ghost image shows where it will be built. Clicking the large 'build this' icon actually builds the track... -STR_3413 :{SMALLFONT}{BLACK}Now we want to build straight track, so we click the straight track icon... +STR_3391 :{SMALLFONT}{BLACK}Oto nasz park - rozejrzyjmy się po nim trochę... +STR_3392 :{SMALLFONT}{BLACK}Najszybszym sposobem przesuwania ekranu jest przytrzymanie wciśniętego PRAWEGO przycisku myszy i poruszanie nią... +STR_3393 :{SMALLFONT}{BLACK}Jeżeli chcesz widzieć na ekranie większy obszar parku, możesz oddalić widok, klikając ikonę znajdująca się na górnej części ekranu... +STR_3394 :{SMALLFONT}{BLACK}Możesz też obrócić widok o 90 stopni... +STR_3395 :{SMALLFONT}{BLACK}Budowanie czegokolwiek w tej skali jest nieco uciążliwe. Przybliżmy więc z powrotem widok naszego parku... +STR_3396 :{SMALLFONT}{BLACK}Zbudujmy prostą atrakcję, żeby nasz park zaczął działać... +STR_3397 :{SMALLFONT}{BLACK}Biało-przezroczysty 'duch' atrakcji pokazuje ci, gdzie zostanie ona wybudowana. Przesuniemy teraz kursor myszy tam, gdzie chcemy postawić naszą atrakcję, i kliknięciem umieścimy ją we wskazanym miejscu... +STR_3398 :{SMALLFONT}{BLACK}Atrakcje potrzebują wejścia i wyjścia. Przesuniemy teraz kursor na pole przylegające do atrakcji i kliknięciem myszy zbydujemy wejście. Tak samo postąpimy z wyjściem... +STR_3399 :{SMALLFONT}{BLACK}Musimy zbudować dróżki, żeby goście odwiedzający nasz park mogli dojść do nowej atrakcji... +STR_3400 :{SMALLFONT}{BLACK}Dróżka prowadząca do wejścia atrakcji będzie specjalną 'dróżką kolejkową.' +STR_3401 :{SMALLFONT}{BLACK}Za wyjściem wystarczy zbudować 'zwykłą dróżkę'... +STR_3402 :{SMALLFONT}{BLACK}Świetnie, otwórzmy naszą atrakcję! Aby to zrobić, należy kliknąć ikonę flagi w oknie atrakcji i wybrać 'otwórz'... +STR_3403 :{SMALLFONT}{BLACK}Ale gdzie są goście? +STR_3404 :{SMALLFONT}{BLACK}Ach - park jest jeszcze zamknięty! Szybko - otwórzmy go... +STR_3405 :{SMALLFONT}{BLACK}Czekając na pierwszych gości, zajmijmy się rozmieszczeniem scenerii... +STR_3406 :{SMALLFONT}{BLACK}Oto pusty park. Wybudujmy prostą atrakcję wg. własnego projektu. +STR_3407 :{SMALLFONT}{BLACK}Najpierw musimy wybrać początek trasy... +STR_3408 :{SMALLFONT}{BLACK}Odcinek torów, który właśnie wybudowaliśmy jest 'peronem stacji'. Tutaj goście mogą wsiadać i wysiadać z wagoników... +STR_3409 :{SMALLFONT}{BLACK}Wydłużmy trochę stację, dodając jeszcze kilka takich odcników... +STR_3410 :{SMALLFONT}{BLACK}Ikony znajdujące się u góry okna budowy są do wyboru różnych elementów torów... +STR_3411 :{SMALLFONT}{BLACK}Wybierzmy lewy skręt... +STR_3412 :{SMALLFONT}{BLACK}Skręt nie został jeszcze wybudowany, ale jego 'duch' wskazuje, w którym miejscu zostanie umieszczony. Dopiero klikając dużą ikonę 'Buduj to', faktycznie budujemy tory... +STR_3413 :{SMALLFONT}{BLACK}Teraz, kiedy trasa jest już gotowa, musimy zbudować wejście i wyjście z atrakcji... STR_3414 :{SMALLFONT}{BLACK}Now that the circuit is complete, we need to build the ride entrance and exit... -STR_3415 :{SMALLFONT}{BLACK}Let's test our ride to check it works... -STR_3416 :{SMALLFONT}{BLACK}White it's being tested, we'll build the queue line and exit path... -STR_3417 :{SMALLFONT}{BLACK}OK - Let's open the park and the ride... -STR_3418 :{SMALLFONT}{BLACK}Our new ride isn't very exciting - Perhaps we should add some scenery? -STR_3419 :{SMALLFONT}{BLACK}To build scenery above other scenery or in mid-air, hold down the SHIFT key and move the mouse to select the height... -STR_3420 :{SMALLFONT}{BLACK}Some types of scenery can be re-painted after it's built... -STR_3421 :{SMALLFONT}{BLACK}Let's add some music to the ride... -STR_3422 :{SMALLFONT}{BLACK}Let's build a roller coaster ! -STR_3423 :{SMALLFONT}{BLACK}There are loads of pre-designed coasters, but we're going to build our own custom design... -STR_3424 :{SMALLFONT}{BLACK}That's the station platform built. Now we need a lift hill... -STR_3425 :{SMALLFONT}{BLACK}Roller coaster trains aren't powered, so a 'chain lift' is needed to pull the train up the first hill... -STR_3426 :{SMALLFONT}{BLACK}That's the lift hill complete - Now for the first drop... -STR_3427 :{SMALLFONT}{BLACK}Those curves are a bad idea - The riders will be flung to the sides by the lateral G forces as the train hurtles around... -STR_3428 :{SMALLFONT}{BLACK}Banking the curves will improve the ride - Riders will be pushed down into their seats instead of flung to the sides... -STR_3429 :{SMALLFONT}{BLACK}No - That won't work! Look at the height marks - The second hill is taller than the lift hill... -STR_3430 :{SMALLFONT}{BLACK}To ensure the train makes it around, each hill should be slightly smaller than the previous one... -STR_3431 :{SMALLFONT}{BLACK}That's better - Our train should make it up that hill now! Let's try some more twisted track... -STR_3432 :{SMALLFONT}{BLACK}We need to slow the train before the final curve and station, so let's add some brakes... -STR_3433 :{SMALLFONT}{BLACK}And finally we'll add 'block brakes', which allow two trains to operate more safely on the circuit... -STR_3434 :{SMALLFONT}{BLACK}Let's test the ride and see if it works! -STR_3435 :{SMALLFONT}{BLACK}Great - It worked! Let's add the footpaths and let guests onto our new roller coaster... -STR_3436 :{SMALLFONT}{BLACK}While waiting for our first riders, we could customise the ride a bit... +STR_3415 :{SMALLFONT}{BLACK}Sprawdźmy naszą atrakcję, aby przekonać się, jak się sprawuje... +STR_3416 :{SMALLFONT}{BLACK}Gdy atrakcja jest sprawdzana, zbudujemy miejsce, w którym ludzie będą się ustawiali w kolejce do wejścia i dróżkę prowadzącą do wyjścia z atrakcji... +STR_3417 :{SMALLFONT}{BLACK}W porządku - otwórzmy park i atrakcję... +STR_3418 :{SMALLFONT}{BLACK}Nasza nowa atrakcja nie zapewnia gościom zbyt wielu emocji - może powinniśmy dodać trochę scenerii? +STR_3419 :{SMALLFONT}{BLACK}Aby wybudować scenerię nad inną lub w powietrzu, przytrzymaj wciśnięty przycisk SHIFT i porusz kursorem, dzieki czemu wybierzesz wysokość... +STR_3420 :{SMALLFONT}{BLACK}W przypadku niektórych rodzajów scenerii po wybudowaniu można zmienić ich kolor... +STR_3421 :{SMALLFONT}{BLACK}Dodajmy jakąś muzykę do naszej atrakcji... +STR_3422 :{SMALLFONT}{BLACK}Zbudujmy kolejkę górską! +STR_3423 :{SMALLFONT}{BLACK}Jest pełno gotowych kolejek górskich, ale my wybudujemy ją według naszego własnego projektu... +STR_3424 :{SMALLFONT}{BLACK}Mamy już peron stacji. teraz potrzebujemy wzniesienia z wyciągarki... +STR_3425 :{SMALLFONT}{BLACK}Wagoniki kolejki górskiej nie posiadają własnego napędu, więc potrzebna jest wyciągarka, która najpierw wciągnie kolejkę pod górę... +STR_3426 :{SMALLFONT}{BLACK}Wyciągarka jest gotowa - teraz pierwszy spadek... +STR_3427 :{SMALLFONT}{BLACK}Te zakręty to zły pomysł - pasażerowie będą miotani siedząc w bezwładności... +STR_3428 :{SMALLFONT}{BLACK}Nachylone zakręty będą dużo lepszym pomysłem - pasażerowie zostaną wciągnięci w siedzenia zamiast w bok wagonika... +STR_3429 :{SMALLFONT}{BLACK}Nie - to nie zadziała! Spójrz na znaczniki wysokości - drugie wzniesienie jest wyższe od tego z wyciągarki... +STR_3430 :{SMALLFONT}{BLACK}Aby upewnić się, że kolejka pokona kolejne wzniesienia, każde z nich musi być nieco niższe od poprzedniego... +STR_3431 :{SMALLFONT}{BLACK}Teraz lepiej - nasza kolejka powinna podjechać pod to wzniesienie! Spróbujmy nieco bardziej zakręconej trasy... +STR_3432 :{SMALLFONT}{BLACK}Musimy sprawić, aby nasza kolejka zwolniła przed tym ostatnim zakrętem i samą stacją. Dodajmy więc hamulce do torów... +STR_3433 :{SMALLFONT}{BLACK}Na koniec dodamy hamulce tarczowe, które pozwolą dwóm kolejkom bezpiezniej poruszać się po trasie... +STR_3434 :{SMALLFONT}{BLACK}Sprawdźmy naszą kolejkę, aby przekonać się, jak się sprawuje... +STR_3435 :{SMALLFONT}{BLACK}Świetnie - działa! Dodajmy teraz jeszcze dróżki i pozwólmy gościom bawić się na naszej nowej kolejce górskiej... +STR_3436 :{SMALLFONT}{BLACK}Czekając na pierwszych pasażerów, możemy trochę zmodyfikować naszą kolejkę... # End of tutorial strings -# ------------------------------------------ Polish start STR_3437 :{SMALLFONT}{BLACK}Usuwanie scenerii z terenu STR_3438 :Nie można stąd usunąć całej scenerii... STR_3439 :Usuń scenerię @@ -3512,9 +3497,1086 @@ STR_3444 :Strona 5 STR_3445 :Ustaw obszar do patrolowania STR_3446 :Wyłącz patrolowanie +# New strings, cleaner +STR_5120 :Finanse +STR_5121 :Badania +STR_5122 :Select rides by track type (like in RCT1) +STR_5123 :Odnów atrakcje +STR_5124 : +STR_5125 :All destructable +STR_5126 :Losowa muzyka tytułowa +STR_5127 :{SMALLFONT}{BLACK}Disable land elevation +STR_5128 :Rozmiar zaznaczenia +STR_5129 :Enter selection size between {COMMA16} and {COMMA16} +STR_5130 :Rozmiar mapy +STR_5131 :Enter map size between {COMMA16} and {COMMA16} +STR_5132 :Napraw przejażdżki +STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights +STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights +STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights +STR_5136 :Prawa do ziemi +STR_5137 :Unlock operating limits +STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} +STR_5139 :{WHITE}{STRINGID} +STR_5140 :Disable brakes failure +STR_5141 :Disable all breakdowns +STR_5142 :Normal Speed +STR_5143 :Quick Speed +STR_5144 :Fast Speed +STR_5145 :Turbo Speed +STR_5146 :Hyper Speed +STR_5147 :Kody +STR_5148 :{SMALLFONT}{BLACK}Zmień prędkość gry +STR_5149 :{SMALLFONT}{BLACK}Otwórz okno kodów +STR_5150 :Włącz narzędzia debugowania #Thousands separator STR_5151 :. -#Decimal separator +#Decimals separator STR_5152 :, +STR_5153 :Edytuj motywy... +STR_5154 :Hardware display +STR_5155 :Zezwalaj na testowanie nieskończonych tras +STR_5156 :{SMALLFONT}{BLACK}Allows testing of most ride types even when the track is unfinished, does not apply to block sectioned modes +STR_5157 :Odblokuj wszystkie ceny +STR_5158 :Wyjdź do menu +STR_5159 :Opuść OpenRCT2 +STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, Rok {POP16}{COMMA16} +STR_5161 :Format daty: +STR_5162 :dzień/miesiąc/rok +STR_5163 :miesiąc/dzień/rok +STR_5164 :Nazwa kanału Twitch +STR_5165 :Nazywaj gości nickami śledzących twój kanał +STR_5166 :{SMALLFONT}{BLACK}Twoi goście będą nazywani tak jak osoby śledzące twój kanał +STR_5167 :Track follower guests +STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers +STR_5169 :Nazywaj gości nickami twoich widzów +STR_5170 :{SMALLFONT}{BLACK}Twoi goście będą nazywani tak jak twoi widzowie +STR_5171 :Track chat guests +STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants +STR_5173 :Wyświetlaj chat Twitcha jako powiadomienia +STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications +STR_5175 :Wprowadź nazwę swojego kanału Twitch +STR_5176 :Włącz integracje z Twitchem +STR_5177 :Tryb pełnego ekranu: +STR_5178 :{SMALLFONT}{BLACK}Kody finansowe +STR_5179 :{SMALLFONT}{BLACK}Kody związane z gośćmi +STR_5180 :{SMALLFONT}{BLACK}Kody związane z parkiem +STR_5181 :{SMALLFONT}{BLACK}Kody związane z atrakcjami +STR_5182 :{INT32} +STR_5183 :Base height +STR_5184 :Enter base height between {COMMA16} and {COMMA16} +STR_5185 :Poziom wody +STR_5186 :Wprowadź poziom wody pomiędzy {COMMA16} a {COMMA16} +STR_5187 :Finanse +STR_5188 :New Campaign +STR_5189 :Badania +STR_5190 :Mapa +STR_5191 :Viewport +STR_5192 :Ostatnie wiadomości +STR_5193 :Land +STR_5194 :Water +STR_5195 :Wyczyść scenerie +STR_5196 :Land Rights +STR_5197 :Sceneria +STR_5198 :Footpath +STR_5199 :Ride Construction +STR_5200 :Track Design Place +STR_5201 :Nowa atrakcja +STR_5202 :Track Design Selection +STR_5203 :Atrakcja +STR_5204 :Lista atrakcji +STR_5205 :Gość +STR_5206 :Lista gości +STR_5207 :Personel +STR_5208 :Lista pracowników +STR_5209 :Banner +STR_5210 :Object Selection +STR_5211 :Invention List +STR_5212 :Scenario Options +STR_5213 :Objective Options +STR_5214 :Map Generation +STR_5215 :Track Design Manager +STR_5216 :Track Design Manager List +STR_5217 :Kody +STR_5218 :Motywy +STR_5219 :Opcje +STR_5220 :Skróty klawiszowe +STR_5221 :Change Keyboard Shortcut +STR_5222 :Load/Save +STR_5223 :Save Prompt +STR_5224 :Demolish Ride Prompt +STR_5225 :Fire Staff Prompt +STR_5226 :Track Delete Prompt +STR_5227 :Save Overwrite Prompt +STR_5228 :{SMALLFONT}{BLACK}Główne +STR_5229 :{SMALLFONT}{BLACK}Park +STR_5230 :{SMALLFONT}{BLACK}Narzędzia +STR_5231 :{SMALLFONT}{BLACK}Atrakcje i goście +STR_5232 :{SMALLFONT}{BLACK}Edytory +STR_5233 :{SMALLFONT}{BLACK}Różne +STR_5234 :{SMALLFONT}{BLACK}Monity +STR_5235 :{SMALLFONT}{BLACK}Ustawienia +STR_5236 :Okno: +STR_5237 :Paleta: +STR_5238 :Obecny motyw: +STR_5239 :Duplikuj +STR_5240 :Enter a name for the theme +STR_5241 :Can't change this theme +STR_5242 :Theme name already exists +STR_5243 :Invalid characters used +STR_5244 :Motywy +STR_5245 :Top Toolbar +STR_5246 :Bottom Toolbar +STR_5247 :Track Editor Bottom Toolbar +STR_5248 :Scenario Editor Bottom Toolbar +STR_5249 :Title Menu Buttons +STR_5250 :Title Exit Button +STR_5251 :Title Options Button +STR_5252 :Title Scenario Selection +STR_5253 :Informacje o parku +STR_5254 :Stwórz +STR_5255 :{SMALLFONT}{BLACK}Create a new title sequence from scratch +STR_5256 :Create a new theme to make changes to +STR_5257 :{SMALLFONT}{BLACK}Create a new theme based on the current one +STR_5258 :{SMALLFONT}{BLACK}Delete the current theme +STR_5259 :{SMALLFONT}{BLACK}Rename the current theme +STR_5260 :Duży zrzut ekranu +STR_5261 :Filter +STR_5262 :Zakręcone światy +STR_5263 :Zakręcone czasy +STR_5264 :Custom +STR_5265 :{SMALLFONT}{BLACK}Select which content sources are visible +STR_5266 :{SMALLFONT}{BLACK}Ekran +STR_5267 :{SMALLFONT}{BLACK}Jednostki i miary +STR_5268 :{SMALLFONT}{BLACK}Dźwięk +STR_5269 :{SMALLFONT}{BLACK}Sterowanie i interfejs +STR_5270 :{SMALLFONT}{BLACK}Różne +STR_5271 :{SMALLFONT}{BLACK}Twitch +STR_5272 :{SMALLFONT}{BLACK}Small Scenery +STR_5273 :{SMALLFONT}{BLACK}Large Scenery +STR_5274 :{SMALLFONT}{BLACK}Footpaths +STR_5275 :Search for Objects +STR_5276 :Enter the name of an object to search for +STR_5277 :Clear +STR_5278 :Tryb piaskownicy +STR_5279 :Tryb piaskownicy wyłączony +STR_5280 :{SMALLFONT}{BLACK}Allow editing land ownership settings through the Map window and other options that are normally restricted to the Scenario Editor +STR_5281 :{SMALLFONT}{BLACK}Features +STR_5282 :RCT1 Ride Open/Close Lights +STR_5283 :RCT1 Park Open/Close Lights +STR_5284 :RCT1 Scenario Selection Font +STR_5285 :BUM!!! +STR_5286 :{SMALLFONT}{BLACK}Niektórzy goście eksplodują +STR_5287 :Ride is already broken down +STR_5288 :Atrakcja jest zamknięta +STR_5289 :No breakdowns available for this ride +STR_5290 :Napraw przejażdżkę +STR_5291 :Can't force breakdown +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_5298 :{RED}{STRINGID} +STR_5299 :{LIGHTPINK}{STRINGID} +STR_5300 :{SMALLFONT}{BLACK}Quick fire staff +STR_5301 :{MEDIUMFONT}{BLACK}Usuń swoją pożyczkę +STR_5302 :Usuń pożyczkę +STR_5303 :Zezwól na budowę podczas pauzy +STR_5304 :Sekwencja tytułowa: +STR_5305 :RollerCoaster Tycoon 1 +STR_5306 :RollerCoaster Tycoon 1 (CF) +STR_5307 :RollerCoaster Tycoon 1 (CF + LL) +STR_5308 :RollerCoaster Tycoon 2 +STR_5309 :OpenRCT2 +STR_5310 :Random +STR_5311 :{SMALLFONT}{BLACK}Narzędzia debugowania +STR_5312 :Pokaż konsole +STR_5313 :Show tile inspector +STR_5314 :Tile inspector +STR_5315 :Trawa +STR_5316 :Piach +STR_5317 :Ziemia +STR_5318 :Rock +STR_5319 :Martian +STR_5320 :Checkerboard +STR_5321 :Grass clumps +STR_5322 :Ice +STR_5323 :Grid (red) +STR_5324 :Grid (yellow) +STR_5325 :Grid (blue) +STR_5326 :Grid (green) +STR_5327 :Sand (dark) +STR_5328 :Sand (light) +STR_5329 :Checkerboard (inverted) +STR_5330 :Underground view +STR_5331 :Rock +STR_5332 :Wood (red) +STR_5333 :Wood (black) +STR_5334 :Ice +STR_5335 :Ride entrance +STR_5336 :Ride exit +STR_5337 :Park entrance +STR_5338 :Element type +STR_5339 :{SMALLFONT}{BLACK}Base height +STR_5340 :{SMALLFONT}{BLACK}Clearance height +STR_5341 :Flags +STR_5342 :Choose a map tile +STR_5343 :Rozmieszczaj pracowników automatycznie +STR_5344 :Lista zmian +STR_5345 :Kody finansowe +STR_5346 :Kody związane z gośćmi +STR_5347 :Kody związane z parkiem +STR_5348 :Kody związane z atrakcjami +STR_5349 :{SMALLFONT}{BLACK}Wszystkie przejażdżki +STR_5350 :Max +STR_5351 :Min +STR_5352 :{BLACK}Szczęście: +STR_5353 :{BLACK}Energia: +STR_5354 :{BLACK}Głód: +STR_5355 :{BLACK}Pragnienie: +STR_5356 :{BLACK}Nudności: +STR_5357 :{BLACK}Tolerancja nudności: +STR_5358 :{BLACK}Pęcherz: +STR_5359 :Usuń gości +STR_5360 :{SMALLFONT}{BLACK}Usuwa wszystkich gości z mapy +STR_5361 :Daj wszystkim gościom: +STR_5362 :{BLACK}Set all guests' preferred ride intensity to: +STR_5363 :Więcej niż 1 +STR_5364 :Mniej niż 15 +STR_5365 :{BLACK}Szybkość personelu: +STR_5366 :Normalnie +STR_5367 :Szybko +STR_5368 :Reset crash status +STR_5369 :Parametry parku... +STR_5370 :{SMALLFONT}{BLACK}Click this button to modify park{NEWLINE}parameters like restrictions,{NEWLINE}guest generation and money. +STR_5371 :Object Selection +STR_5372 :Invert right mouse dragging +STR_5373 :Nazwa {STRINGID} +STR_5374 :Data {STRINGID} +STR_5375 :{UP} +STR_5376 :{DOWN} +STR_5377 :{SMALLFONT}{BLACK}Saves +STR_5378 :{SMALLFONT}{BLACK}Script +STR_5379 :{SMALLFONT}{BLACK}Skip to next wait command +STR_5380 :{SMALLFONT}{BLACK}Start playing title sequence +STR_5381 :{SMALLFONT}{BLACK}Stop playing title sequence +STR_5382 :{SMALLFONT}{BLACK}Restart title sequence +STR_5383 :{SMALLFONT}{BLACK}Create a new title sequence based on the current one +STR_5384 :{SMALLFONT}{BLACK}Delete the current title sequence +STR_5385 :{SMALLFONT}{BLACK}Rename the current title sequence +STR_5386 :{SMALLFONT}{BLACK}Insert a new command +STR_5387 :{SMALLFONT}{BLACK}Edit the selected command +STR_5388 :{SMALLFONT}{BLACK}Delete the selected command +STR_5389 :{SMALLFONT}{BLACK}Skip to the selected command in the title sequence +STR_5390 :{SMALLFONT}{BLACK}Move the selected command down +STR_5391 :{SMALLFONT}{BLACK}Move the selected command up +STR_5392 :{SMALLFONT}{BLACK}Add a save to the title sequence +STR_5393 :{SMALLFONT}{BLACK}Remove the selected save from the title sequence +STR_5394 :{SMALLFONT}{BLACK}Rename the selected save +STR_5395 :{SMALLFONT}{BLACK}Load the selected save in game +STR_5396 :{SMALLFONT}{BLACK}Reload the title sequence if changes have been made to it outside of the game +STR_5397 :Can only be used on the title screen +STR_5398 :Cannot edit title sequence while it's playing +STR_5399 :Press the stop button to continue editing +STR_5400 :Can't change this title sequence +STR_5401 :Create a new title sequence to make changes to +STR_5402 :Failed to load title sequence +STR_5403 :There may be no Load or Wait command or a save may be invalid +STR_5404 :Name already exists +STR_5405 :Enter a name for the save +STR_5406 :Enter a name for the title sequence +STR_5407 :Add +STR_5408 :Remove +STR_5409 :Insert +STR_5410 :Edit +STR_5411 :Reload +STR_5412 :Skip to +STR_5413 :Load +STR_5414 :Load{MOVE_X}{87}Six Flags Magic Mountain.SC6 +STR_5415 :Load{MOVE_X}{87}{STRING} +STR_5416 :Load{MOVE_X}{87}No save selected +STR_5417 :Location +STR_5418 :Location{MOVE_X}{87}{COMMA16} {COMMA16} +STR_5419 :Rotate +STR_5420 :Rotate{MOVE_X}{87}{COMMA16} +STR_5421 :Zoom +STR_5422 :Zoom{MOVE_X}{87}{COMMA16} +STR_5423 :Wait +STR_5424 :Wait{MOVE_X}{87}{COMMA16} +STR_5425 :Restart +STR_5426 :End +STR_5427 :Pozycja: +STR_5428 :Counter-clockwise rotations: +STR_5429 :Poziom przybliżenia: +STR_5430 :Seconds to wait: +STR_5431 :Save to load: +STR_5432 :Komenda: +STR_5433 :Title Sequences +STR_5434 :Command Editor +STR_5435 :Zmień nazwę zapisu +STR_5436 :Edytuj sekwencje tytułowe... +STR_5437 :Nie wybrano zapisu +STR_5438 :Can't make changes while command editor is open +STR_5439 :A wait command with at least 4 seconds is required with a restart command +STR_5440 :Minimize fullscreen on focus loss +STR_5441 :{SMALLFONT}{BLACK}Identifies rides by track type,{NEWLINE}so vehicles can be changed{NEWLINE}afterwards, like in RCT1. +STR_5442 :Wymuś ocenę parku: +STR_5443 :Prędkość{MOVE_X}{87}{STRINGID} +STR_5444 :Prędkość: +STR_5445 :Prędkość +STR_5446 :Get +STR_5447 :Type {STRINGID} +STR_5448 :Ride / Vehicle {STRINGID} +STR_5449 :Zmniejsz prędkość gry +STR_5450 :Zwiększ prędkość gry +STR_5451 :Otwórz okno kodów +STR_5452 :Toggle visibility of toolbars +STR_5453 :Select another ride +STR_5454 :Odblokuj FPS +STR_5455 :Enable sandbox mode +STR_5456 :Disable clearance checks +STR_5457 :Disable support limits +STR_5458 :Rotate clockwise +STR_5459 :Rotate counterclockwise +STR_5460 :Rotate view counterclockwise +STR_5461 :Zmień parametry gości +STR_5462 :{CURRENCY} +STR_5463 :Cel: Baw się dobrze! +STR_5464 :General +STR_5465 :Klimat +STR_5466 :Personel +STR_5467 :ALT + +STR_5468 :Ostatnie wiadomości +STR_5469 :Scroll map up +STR_5470 :Scroll map left +STR_5471 :Scroll map down +STR_5472 :Scroll map right +STR_5473 :Cykl dnia i nocy +STR_5474 :Wyświetlaj tekst na bannerach wielkimi literami +STR_5475 :{COMMA16} tygodni +STR_5476 :Sprzęt +STR_5477 :Wyświetlanie mapy +STR_5478 :Sterowanie +STR_5479 :Pasek narzędzi +STR_5480 :Show toolbar buttons for: +STR_5481 :Motywy +STR_5482 :{WINDOW_COLOUR_2}Time since last inspection: {BLACK}1 minute +STR_5483 :{BLACK}(pozostało {COMMA16} tygodni) +STR_5484 :{BLACK}(pozostał {COMMA16} tydzień) +STR_5485 :{SMALLFONT}{STRING} +STR_5486 :{BLACK}{COMMA16} +STR_5487 :{SMALLFONT}{BLACK}Pokaż ostatnie wiadomości +STR_5488 :No entrance (OpenRCT2 only!) +STR_5489 :{SMALLFONT}{BLACK}Show only tracked guests +STR_5490 :Wyłącz dźwięk gdy okno gry jest nieaktywne +STR_5491 :Inventions list +STR_5492 :Scenario options +STR_5493 :Wyślij wiadomość +STR_5494 : +STR_5495 :Lista graczy +STR_5496 :Gracz: +STR_5497 :Ping: +STR_5498 :Lista serwerów +STR_5499 :Nazwa gracza: +STR_5500 :Dodaj serwer +STR_5501 :Uruchom serwer +STR_5502 :Multiplayer +STR_5503 :Wprowadź IP lub hostname: +STR_5504 :{SMALLFONT}{BLACK}Pokaż status gry wieloosobowej +STR_5505 :Nie można połączyć z serwerem. +STR_5506 :Guests ignore intensities +STR_5507 :Handymen mow grass by default +STR_5508 :Zezwól na ładowanie plików ze złymi sumami kontrolnymi +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 :Domyślne urządzenie audio +STR_5511 :(UNKNOWN) +STR_5512 :Zapisz grę jako +STR_5513 :Szybki zapis +STR_5514 :Wyłącz wandalizm +STR_5515 :{SMALLFONT}{BLACK}Stops guests from vandalizing your park when they're angry +STR_5516 :{SMALLFONT}{BLACK}Black +STR_5517 :{SMALLFONT}{BLACK}Gray +STR_5518 :{SMALLFONT}{BLACK}White +STR_5519 :{SMALLFONT}{BLACK}Dark purple +STR_5520 :{SMALLFONT}{BLACK}Light purple +STR_5521 :{SMALLFONT}{BLACK}Bright purple +STR_5522 :{SMALLFONT}{BLACK}Dark blue +STR_5523 :{SMALLFONT}{BLACK}Light blue +STR_5524 :{SMALLFONT}{BLACK}Icy blue +STR_5525 :{SMALLFONT}{BLACK}Dark water +STR_5526 :{SMALLFONT}{BLACK}Light water +STR_5527 :{SMALLFONT}{BLACK}Saturated green +STR_5528 :{SMALLFONT}{BLACK}Dark green +STR_5529 :{SMALLFONT}{BLACK}Moss green +STR_5530 :{SMALLFONT}{BLACK}Bright green +STR_5531 :{SMALLFONT}{BLACK}Olive green +STR_5532 :{SMALLFONT}{BLACK}Dark olive green +STR_5533 :{SMALLFONT}{BLACK}Bright yellow +STR_5534 :{SMALLFONT}{BLACK}Yellow +STR_5535 :{SMALLFONT}{BLACK}Dark yellow +STR_5536 :{SMALLFONT}{BLACK}Light orange +STR_5537 :{SMALLFONT}{BLACK}Dark orange +STR_5538 :{SMALLFONT}{BLACK}Light brown +STR_5539 :{SMALLFONT}{BLACK}Saturated brown +STR_5540 :{SMALLFONT}{BLACK}Dark brown +STR_5541 :{SMALLFONT}{BLACK}Salmon pink +STR_5542 :{SMALLFONT}{BLACK}Bordeaux red +STR_5543 :{SMALLFONT}{BLACK}Saturated red +STR_5544 :{SMALLFONT}{BLACK}Bright red +STR_5545 :{SMALLFONT}{BLACK}Dark pink +STR_5546 :{SMALLFONT}{BLACK}Bright pink +STR_5547 :{SMALLFONT}{BLACK}Light pink +STR_5548 :Show all operating modes +STR_5549 :rok/miesiąc/dzień +STR_5550 :{POP16}{POP16}Year {COMMA16}, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} +STR_5551 :rok/dzień/miesiąc +STR_5552 :{POP16}{POP16}Year {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} +STR_5553 :Wstrzymuj grę gdy nakładka Steam jest otwarta +STR_5554 :{SMALLFONT}{BLACK}Enable mountain tool +STR_5555 :Show vehicles from other track types +STR_5556 :Wyrzuć gracza +STR_5557 :Nie rozłączaj po desynchronizacji (tryb wieloosobowy) +STR_5558 :A restart is required for this setting to take effect +STR_5559 :10 min. inspections +STR_5560 :{SMALLFONT}{BLACK}Sets the inspection time to 'Every 10 minutes' on all rides +STR_5561 :Nie udało się załadować języka +STR_5562 :UWAGA! +STR_5563 :Ta funkcja jest obecnie niestabilna, zachowaj szczególną ostrożność. +STR_5564 :Insert Corrupt Element +STR_5565 :{SMALLFONT}{BLACK}Inserts a corrupt map element at top of tile. This will hide any element above the corrupt element. +STR_5566 :Hasło: +STR_5567 :Rozgłoś +STR_5568 :Wymagane hasło +STR_5569 :Ten serwer wymaga hasła +STR_5570 :Aktualizuj liste +STR_5571 :Dołącz do gry +STR_5572 :Dodaj do ulubionych +STR_5573 :Usuń z ulubionych +STR_5574 :Nazwa: +STR_5575 :Limit graczy: +STR_5576 :Port: +STR_5577 :Won południowokoreański (W) +STR_5578 :Rosyjski rubel (R) +STR_5579 :Współczynnik skali okna: +STR_5580 :Korona czeska (Kc) +STR_5581 :Pokaż licznik FPS +STR_5582 :Nie pozwól na wyjście kursora poza okno +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 :Automatycznie otwieraj sklepy i stoiska +STR_5587 :{SMALLFONT}{BLACK}Gdy aktywne, sklepy i stoiska będą automatycznie otwierane po zbudowaniu +STR_5588 :{SMALLFONT}{BLACK}Przejdź do rozgrywki wieloosobowej +STR_5589 :Ustawienia powiadomień +STR_5590 :Nagrody parku +STR_5591 :Marketing campaign has finished +STR_5592 :Ostrzeżenia dotyczące parku +STR_5593 :Ostrzeżenia dotyczące oceny parku +STR_5594 :Atrakcja popsuła się +STR_5595 :Ride has crashed +STR_5596 :Ostrzeżenia dotyczące atrakcji +STR_5597 :Ride / scenery researched +STR_5598 :Ostrzeżenia dotyczące gości +STR_5599 :Gość się zgubił +STR_5600 :Gość opuścił park +STR_5601 :Gość stoi w kolejce do atrakcji +STR_5602 :Gość korzysta z atrakcji +STR_5603 :Gość opuścił atrakcje +STR_5604 :Gość kupił nowy przedmiot +STR_5605 :Guest has used facility +STR_5606 :Gość zmarł +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 :Zakręcone światy +STR_5624 :Zakręcone czasy +STR_5625 :{OPENQUOTES}Prawdziwe{ENDQUOTES} parki +STR_5626 :Inne parki +STR_5627 :Group scenario list by: +STR_5628 :Source game +STR_5629 :Poziom trudności +STR_5630 :Enable unlocking of scenarios +STR_5631 :Original DLC Parks +STR_5632 :Build your own... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Wydane pieniądze: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Commands ran: {BLACK}{COMMA16} +STR_5637 :Nie można tego zrobić.. +STR_5638 :Odmowa dostępu +STR_5639 :{SMALLFONT}{BLACK}Pokaż listę graczy +STR_5640 :{SMALLFONT}{BLACK}Zarządzaj grupami +STR_5641 :Domyślna grupa: +STR_5642 :Grupa: +STR_5643 :Dodaj grupę +STR_5644 :Usuń grupę +STR_5645 :Chat +STR_5646 :Terraform +STR_5647 :Toggle Pause +STR_5648 :Ustal poziom wody +STR_5649 :Stwórz przejażdżkę +STR_5650 :Usuń przejażdżkę +STR_5651 :Zbuduj przejażdżkę +STR_5652 :Właściwości przejażdżki +STR_5653 :Sceneria +STR_5654 :Ścieżka +STR_5655 :Gość +STR_5656 :Pracownik +STR_5657 :Park Properties +STR_5658 :Park Funding +STR_5659 :Wyrzuć gracza +STR_5660 :Modyfikuj grupy +STR_5661 :Zmień grupę gracza +STR_5662 :N/A +STR_5663 :Clear Landscape +STR_5664 :Cheat +STR_5701 :{WINDOW_COLOUR_2}Last action: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Locate player's most recent action +STR_5703 :Nie można wyrzucić hosta +STR_5704 :Ostatnia akcja: +STR_5705 :Can't set to this group +STR_5706 :Nie można usunąć grupy, do której należą gracze +STR_5707 :Ta grupa nie może być modyfikowana +STR_5708 :Nie można zmienić grupy do której należy host +STR_5709 :Zmień nazwę grupy +STR_5710 :Nazwa grupy +STR_5711 :Wprowadź nową nazwę dla tej grupy: +STR_5712 :Can't modify permission that you do not have yourself +STR_5713 :Wyrzuć gracza +STR_5714 :Pokaż okno opcji +STR_5715 :Nowa gra +STR_5716 :Niedostępne w trybie wieloosobowym +# For identifying client network version in server list window +STR_5717 :Wersja: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Wersja: {STRING} +STR_5719 :Słonecznie +STR_5720 :Częśc. pochmurnie +STR_5721 :Pochmurnie +STR_5722 :Deszczowo +STR_5723 :Duży deszcz +STR_5724 :Burza +STR_5725 :{BLACK}Wymuś pogodę: +STR_5726 :{SMALLFONT}{BLACK}Ustawia aktualną pogodę w parku +STR_5727 :Jakość skalowania +STR_5728 :Requires hardware display option +STR_5729 :{SMALLFONT}{BLACK}Requires hardware display option +STR_5730 :Najbliższy sąsiad +STR_5731 :Linear +STR_5732 :Anisotropic +STR_5733 :Use NN scaling at integer scales +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Renderowanie +STR_5735 :Status sieci +STR_5736 :Gracz +STR_5737 :Zamknięte, {COMMA16} człowiek nadal korzysta z przejażdżki +STR_5738 :Zamknięte, {COMMA16} ludzi nadal korzysta z przejażdżki +STR_5739 :{WINDOW_COLOUR_2}Goście na przejażdżce: {BLACK}{COMMA16} +STR_5740 :Stałe kampanie reklamowe +STR_5741 :{SMALLFONT}{BLACK}Nigdy niekończące się kampanie reklamowe +STR_5742 :Uwierzytelnianie ... +STR_5743 :Łączenie ... +STR_5744 :Szukanie adresu serwera ... +STR_5745 :Wykryto desynchronizacje z serwerem +STR_5746 :Rozłączono +STR_5747 :Rozłączono: {STRING} +STR_5748 :Wyrzucono +STR_5749 :Wynoś się z serwera! +STR_5750 :Zamknięto połączenie +STR_5751 :Brak danych +STR_5752 :{OUTLINE}{RED}{STRING} opuścił grę +STR_5753 :{OUTLINE}{RED}{STRING} opuścił grę ({STRING}) +STR_5754 :Nieprawidłowa nazwa gracza +STR_5755 :Niewłaściwa wersja gry +STR_5756 :Błędne hasło +STR_5757 :Serwer osiągnął maksymalną liczbę graczy +STR_5758 :{OUTLINE}{GREEN}{STRING} dołączył do gry +STR_5759 :Pobieranie mapy ... ({INT32} / {INT32}) +STR_5760 :Dolar hongkoński (HK$) +STR_5761 :Dolar tajwański (NT$) +STR_5762 :Juan chiński (CN{YEN}) +STR_5763 :Wszystkie pliki +STR_5764 :Nieprawidłowy typ atrakcji +STR_5765 :Nie można edytować atrakcji o nieprawidłowym typie +STR_5766 : +STR_5767 :Przychód +STR_5768 :Wszystkich klientów +STR_5769 :Całkowity zysk +STR_5770 :Klientów na godzinę +STR_5771 :Koszty eksploatacji +STR_5772 :Wiek +STR_5773 :Wszystkich klientów: {COMMA32} +STR_5774 :Całkowity zysk: {CURRENCY2DP} +STR_5775 :Klienci: {COMMA32} na godzinę +STR_5776 :Wybudowano: w tym roku +STR_5777 :Wybudowano: w zeszłym roku +STR_5778 :Wybudowano: {COMMA16} lat temu +STR_5779 :Przychód: {CURRENCY2DP} na godzinę +STR_5780 :Koszty eksploatacji: {CURRENCY2DP} na godzinę +STR_5781 :Koszty eksploatacji: nieznane +STR_5782 :Połączono. Naciśnij '{STRING}' aby pisać na chacie. -# Note: as this is an unmaintained language, don't add new strings unless you intend to become the mainainer. +############# +# Scenarios # +############# + +## RCT Original + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Deep in the forest, build a thriving theme park in a large cleared area + + +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 + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Starting from scratch, build a theme park around a large lake + + +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 + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Convert the beautiful Evergreen Gardens into a thriving theme park + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Develop Bumbly Beach's small amusement park into a thriving theme park + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Several islands form the basis for this new park + + +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 + + +STR_SCNR :Dinky Park +STR_PARK :Dinky Park +STR_DTLS :A small, cramped amusement park which requires major expansion + + +STR_SCNR :Aqua Park +STR_PARK :Aqua Park +STR_DTLS :A park with some excellent water-based rides requires expansion + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Convert a large abandoned mine from a tourist attraction into a theme park + + +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 + + +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 + + +STR_SCNR :Mothball Mountain +STR_PARK :Mothball Mountain +STR_DTLS :In the hilly forests of Mothball Mountain, build a theme park from scratch + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Convert the Egyptian Ruins tourist attraction into a thriving theme park + + +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 + + +STR_SCNR :Big Pier +STR_PARK :Big Pier +STR_DTLS :Convert this sleepy town's pier into a thriving attraction + + +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 + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :A well-established park, which has a few problems + + +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 + + +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 + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Just for fun! + +## Corkscrew Follies + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Develop the seaside cliffs into a thriving amusement 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 + + +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 + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :An old redundant bridge is yours to develop into an amusement park + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Covering land both sides of a highway, this park has several rides already operating + + +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 + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :This castle is all yours to turn into a theme park + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape + + +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 + + +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 + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :A series of stepped lakes form the basis for this new park + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :This elderly park has many historical rides but is badly in debt + + +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 + + +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 + + +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 + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :A vast canyon is yours to turn into a theme 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 + + +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 + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters + + +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 + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people + + +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 + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? + + +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 + + +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 + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists + + +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 + + +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 + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :A large garden park needs turning into a thriving theme park + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :A dormant volcano is the setting of this coaster-building challenge + + +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 + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :A large lake in an ancient crater is the setting for this park + + +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 + + +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 + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :This sea-side cove is the setting for this coaster-building challenge + + +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 + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :A park which has much of its footpaths and coasters underground + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :A glacier-filled valley is yours to develop into a theme park + + +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 + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Five coasters require completion in this desert park + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :This historical park is only allowed to build older-styled rides + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Develop this alien park to maximize its profit + + +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 + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :A scary park with a giant centrepiece coaster + + +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 + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In this large park you must design and build ten large coasters + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :An icy landscape needs turning into a thriving theme park + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :A desert park with some cleverly designed coasters is yours to expand + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In this tiny park you must finish building the five existing coasters + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :A large park with a novel transporation system around its edge + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :This large island is all yours to develop as an amusement park + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :This urban area is all yours to develop into as an amusement park + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :A giant park already packed full of rides needs improving + + +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 + + +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 + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : + +######### +# Rides # +######### + +#WW +[CONDORRD] +STR_NAME :Condor Ride +STR_DESC :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air in Condor-shaped trains +STR_CPTY :4 passengers per car diff --git a/data/language/portuguese_br.txt b/data/language/portuguese_br.txt index b3e29cc507..4daca5d697 100644 --- a/data/language/portuguese_br.txt +++ b/data/language/portuguese_br.txt @@ -1,99 +1,99 @@ -# STR_XXXX part is read and XXXX becomes the string id number. +# STR_XXXX part is read and XXXX becomes the string id number. # Everything after the colon and before the new line will be saved as the string. # Use # at the beginning of a line to leave a comment. STR_0000 : STR_0001 :{STRINGID} {COMMA16} -STR_0002 :Spiral Roller Coaster -STR_0003 :Stand-up Roller Coaster -STR_0004 :Suspended Swinging Coaster -STR_0005 :Inverted Roller Coaster +STR_0002 :Montanha-Russa em Espiral +STR_0003 :Montanha-Russa em Pé +STR_0004 :Montanha-Russa de Balanço Suspensa +STR_0005 :Montanha-Russa Invertida STR_0006 :Montanha-Russa Junior -STR_0007 :Miniature Railway +STR_0007 :Ferrovia em Miniatura STR_0008 :Monotrilho -STR_0009 :Mini Suspended Coaster -STR_0010 :Boat Ride -STR_0011 :Wooden Wild Mouse -STR_0012 :Steeplechase -STR_0013 :Passeio de carro -STR_0014 :Launched Freefall -STR_0015 :Bobsleigh Coaster -STR_0016 :Observation Tower -STR_0017 :Looping Roller Coaster -STR_0018 :Dinghy Slide -STR_0019 :Mine Train Coaster +STR_0009 :Mini-Montanha Suspensa +STR_0010 :Passeio de Barco +STR_0011 :Rato Maluco de Madeira +STR_0012 :Corrida de Obstáculos +STR_0013 :Passeio de Carro +STR_0014 :Queda-Livre Lançada +STR_0015 :Montanha de Trenó +STR_0016 :Torre de Observação +STR_0017 :Montanha-Russa de Looping +STR_0018 :Escorregador de Barcos +STR_0019 :Montanha-Russa de Trem de Mina STR_0020 :Teleférico -STR_0021 :Corkscrew Roller Coaster +STR_0021 :Montanha-Russa de Parafuso STR_0022 :Labirinto -STR_0023 :Spiral Slide +STR_0023 :Escorregador em Espiral STR_0024 :Karts -STR_0025 :Log Flume -STR_0026 :River Rapids -STR_0027 :Dodgems +STR_0025 :Canal de Troncos +STR_0026 :Correnteza Veloz +STR_0027 :Carrinho de Bate-Bate STR_0028 :Barco Pirata -STR_0029 :Swinging Inverter Ship -STR_0030 :Food Stall -STR_0031 :Unknown Stall (1D) -STR_0032 :Drink Stall -STR_0033 :Unknown Stall (1F) -STR_0034 :Shop +STR_0029 :Navio de Balanço Reverso +STR_0030 :Barraca de Comida +STR_0031 :Barraca Desconhecida (1D) +STR_0032 :Barraca de Bebida +STR_0033 :Barraca Desconhecida (1F) +STR_0034 :Loja STR_0035 :Carrossel -STR_0036 :Unknown Stall (22) +STR_0036 :Barraca Desconhecida (22) STR_0037 :Quiosque de Informações STR_0038 :Banheiros STR_0039 :Roda Gigante -STR_0040 :Motion Simulator +STR_0040 :Simulador de Movimento STR_0041 :Cinema 3D STR_0042 :Top Spin -STR_0043 :Giroscopio Humano -STR_0044 :Reverse Freefall Coaster +STR_0043 :Giroscópio Humano +STR_0044 :Montanha de Queda-Livre Reversa STR_0045 :Elevador -STR_0046 :Vertical Drop Roller Coaster +STR_0046 :Montanha-Russa de Queda Vertical STR_0047 :Caixa Eletrônico STR_0048 :Twist -STR_0049 :Casa Assombrada +STR_0049 :Casa Mal-Assombrada STR_0050 :Primeiros Socorros -STR_0051 :Circus Show -STR_0052 :Ghost Train -STR_0053 :Steel Twister Roller Coaster -STR_0054 :Wooden Roller Coaster -STR_0055 :Side-Friction Roller Coaster -STR_0056 :Wild Mouse -STR_0057 :Multi-Dimension Roller Coaster -STR_0058 :Unknown Ride (38) -STR_0059 :Flying Roller Coaster -STR_0060 :Unknown Ride (3A) +STR_0051 :Circo +STR_0052 :Trem Fantasma +STR_0053 :Montanha-Russa Tornado de Aço +STR_0054 :Montanha-Russa de Madeira +STR_0055 :Montanha-Russa de Fricção Lateral +STR_0056 :Rato Maluco +STR_0057 :Montanha-Russa Multi-Dimensional +STR_0058 :Brinquedo Desconhecido (38) +STR_0059 :Montanha-Russa Voadora +STR_0060 :Brinquedo Desconhecido (3A) STR_0061 :Virginia Reel -STR_0062 :Splash Boats -STR_0063 :Mini Helicopters -STR_0064 :Lay-down Roller Coaster +STR_0062 :Barcos de Splash +STR_0063 :Mini-Helicópteros +STR_0064 :Montanha-Russa Deitada STR_0065 :Monotrilho Suspenso -STR_0066 :Unknown Ride (40) -STR_0067 :Reverser Roller Coaster -STR_0068 :Heartline Twister Coaster -STR_0069 :Mini Golfe -STR_0070 :Giga Coaster -STR_0071 :Roto-Drop -STR_0072 :Flying Saucers -STR_0073 :Crooked House -STR_0074 :Monorail Cycles -STR_0075 :Compact Inverted Coaster +STR_0066 :Brinquedo Desconhecido (40) +STR_0067 :Montanha-Russa Reversa +STR_0068 :Montanha Tornado Linha do Coração +STR_0069 :Minigolfe +STR_0070 :Giga Montanha-Russa +STR_0071 :Queda Giratória +STR_0072 :Discos Voadores +STR_0073 :Casa Maluca +STR_0074 :Bicicletas de Monotrilho +STR_0075 :Montanha Compacta Invertida STR_0076 :Montanha-Russa D'água -STR_0077 :Air Powered Vertical Coaster -STR_0078 :Inverted Hairpin Coaster +STR_0077 :Montanha Vertical de Propulsão Hidráulica +STR_0078 :Montanha Fechada Invertida STR_0079 :Tapete Mágico STR_0080 :Submarino -STR_0081 :River Rafts -STR_0082 :Unknown Ride (50) +STR_0081 :Balsas de rio +STR_0082 :Brinquedo Desconhecido (50) STR_0083 :Enterprise -STR_0084 :Unknown Ride (52) -STR_0085 :Unknown Ride (53) -STR_0086 :Unknown Ride (54) -STR_0087 :Unknown Ride (55) -STR_0088 :Inverted Impulse Coaster +STR_0084 :Brinquedo Desconhecido (52) +STR_0085 :Brinquedo Desconhecido (53) +STR_0086 :Brinquedo Desconhecido (54) +STR_0087 :Brinquedo Desconhecido (55) +STR_0088 :Montanha de Impulso Invertida STR_0089 :Mini Montanha-Russa -STR_0090 :Mine Ride -STR_0091 :Unknown Ride (59) -STR_0092 :LIM Launched Roller Coaster +STR_0090 :Brinquedo de Mina +STR_0091 :Brinquedo Desconhecido (59) +STR_0092 :Montanha-Russa de Indução Linear STR_0093 : STR_0094 : STR_0095 : @@ -513,31 +513,31 @@ STR_0508 : STR_0509 : STR_0510 : STR_0511 : -STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. -STR_0513 :A looping roller coaster where the riders ride in a standing position -STR_0514 :Trains suspended beneath the roller coaster track swing out to the side around corners -STR_0515 :A steel roller coaster with trains that are held beneath the track, with many complex and twisting track elements -STR_0516 :A gentle roller coaster for people who haven't yet got the courage to face the larger rides -STR_0517 :Passengers ride in miniature trains along a narrow-gauge railway track -STR_0518 :Passengers travel in electric trains along a monorail track -STR_0519 :Passengers ride in small cars hanging beneath the single-rail track, swinging freely from side to side around corners -STR_0520 :A dock platform where guests can drive/row personal watercraft on a body of water -STR_0521 :A fast and twisting roller coaster with tight turns and steep drops. Intensity is bound to be high. -STR_0522 :A smaller roller coaster where the riders sit above the track with no car around them -STR_0523 :Riders travel slowly in powered vehicles along a track-based route -STR_0524 :Freefall car is pneumatically launched up a tall steel tower and then allowed to freefall down -STR_0525 :Riders career down a twisting track guided only by the curvature and banking of the semi-circular track -STR_0526 :Passengers travel in a rotating observation cabin which travels up a tall tower -STR_0527 :A smooth steel-tracked roller coaster capable of vertical loops -STR_0528 :Riders travel in inflatable dinghies down a twisting semi-circular or completely enclosed tube track -STR_0529 :Mine train themed roller coaster trains career along steel roller coaster track made to look like old railway track -STR_0530 :Cars hang from a steel cable which runs continuously from one end of the ride to the other and back again -STR_0531 :A compact steel-tracked roller coaster where the train travels through corkscrews and loops +STR_0512 :Uma montanha russa compacta com subida de elevação em espiral e quedas suaves e retorcidas +STR_0513 :Uma montanha russa de loopipng onde passageiros andam em pé +STR_0514 :Trens suspensos abaixo do trilho da montanha-russa balançam para fora nas curvas +STR_0515 :Uma montanha-russa de aço com trens presos abaixo do trilho, com muitos elementos complexos e retorcidos +STR_0516 :Uma montanha-russa suave para pessoas que ainda não tem coragem de encarar atrações maiores +STR_0517 :Passageiros passeiam em trens em miniatura por uma ferrovia de via estreita +STR_0518 :Passageiros viajam em trens eletrizados por uma pista de monotrilho +STR_0519 :Passageiros poasseiam em carrinhos presos abaixo do trilho, balançando livremente lado a lado nas curvas +STR_0520 :Um cais onde visitantes podem dirigir/remar barcos na água +STR_0521 :Uma montanha-russa rápida e retorcida com curvas fechadas e quedas íngremes. Intensidade será alta +STR_0522 :Uma montanha-russa menor onde passageiros sentam acima do trilho com nenhum carro envolta +STR_0523 :Passageiros viajam devagar em veículos motorizados por uma rota baseada na pista +STR_0524 :O carro de queda livre é pneumaticamente lançado para cima em uma alta torre de aço e então desce em queda livre +STR_0525 :Passageiros descem por um trilho retorcido guiados apenas pela curvatura e inclinação do trilho semi-circular +STR_0526 :Passageiros viajam em uma cabine de observação rotativa que viaja até o topo de uma torre alta +STR_0527 :Uma montanha-russa suave de aço capaz de fazer loops verticais +STR_0528 :Passageiros viajam em barcos infláveis em tubo encurvado semi-circular ou completamente fechado. +STR_0529 :Montanha russa tematizada como trem de mina percorre o trilho de aço feito para parecer uma ferrovia velha +STR_0530 :Carros pendurados por um cabo de aço andam continuamente de uma ponta da atração à outra e volta +STR_0531 :Uma montanha-russa de aço compacta onde trens viajam por parafusos e loops STR_0532 : STR_0533 : -STR_0534 :Self-drive petrol-engined go karts -STR_0535 :Log-shaped boats travel along a water channel, splashing down steep slopes to soak the riders -STR_0536 :Circular boats meander along a wide water channel, splashing through waterfalls and thrilling riders through foaming rapids +STR_0534 :Passageiros pilotam karts com motor a gasolina +STR_0535 :Barcos em formato de troncos viajam por um canal d'água, esparrinhando água e molhando passageiros em declives íngremes +STR_0536 :Barcos circulares serpenteiam por um largo canal d'água, esparrinhando por cachoeiras e empolgando os passageiros por corredeiras espumantes STR_0537 : STR_0538 : STR_0539 : @@ -555,55 +555,55 @@ STR_0550 : STR_0551 : STR_0552 : STR_0553 : -STR_0554 :The car is accelerated out of the station along a long level track using Linear Induction Motors, then heads straight up a vertical spike of track, freefalling back down to return to the station -STR_0555 :Guests ride in an elevator up or down a vertical tower to get from one level to another -STR_0556 :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_0554 :O carro é acelerado para fora da estação em uma longa pista reta usando Motores de Indução Linear, então vai direto para o pico da pista vertical, caindo em queda livre para voltar à estação +STR_0555 :Visitantes passeiam dentro de um elevador para cima ou para baixo em uma torre vertical para ir de um andar ao outro +STR_0556 :Carros muito largos descem por uma pista completamente vertical para uma melhor experiência de uma montanha-russa em queda livre STR_0557 : STR_0558 : STR_0559 : STR_0560 : STR_0561 : -STR_0562 :Powered cars travel along a multi-level track past spooky scenery and special effects -STR_0563 :Sitting in comfortable trains with only simple lap restraints riders enjoy giant smooth drops and twisting track as well as plenty of 'air time' over the hills -STR_0564 :Running on wooden track, this coaster is fast, rough, noisy, and gives an 'out of control' riding experience with plenty of 'air time' -STR_0565 :A simple wooden roller coaster capable of only gentle slopes and turns, where the cars are only kept on the track by side friction wheels and gravity -STR_0566 :Individual roller coaster cars zip around a tight zig-zag layout of track with sharp corners and short sharp drops -STR_0567 :Sitting in seats suspended either side of the track, riders are pitched head-over-heels while they plunge down steep drops and travel through various inversions +STR_0562 :Carros motorizados percorrem uma pista de vários níveis passando por cenários assustadores e efeitos especiais +STR_0563 :Sentados em trens confortáveis apenas com uma trava simples, passageiros divertem-se em grandes quedas suaves e trilhos retorcidos como também muitos 'tempo no ar' pelas colinas +STR_0564 :Correndo em trilho de madeira, esta montanha-russa é rápida, selvagem, barulhenta, e dá a sensação de 'fora de controle' com muitos 'tempo no ar' +STR_0565 :Uma montanha-russa de madeira simples capaz de fazer só ladeiras e curvas suaves, onde os carros são mantidos no trilho pela fricção lateral e gravidade +STR_0566 :Carros individuais de montanha-russa percorrem em alta velocidade pistas em zig-zag com curvas fechadas e pequenas quedas +STR_0567 :Sentados em cadeiras suspensas de cada lado do trilho, passageiros são lançados para cima enquanto são puxados para baixo em quedas íngremes e viajam por várias inversões STR_0568 : -STR_0569 :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air +STR_0569 :Passeando embaixo do trilho em travas especiais, passageiros tem a sensação de voo enquanto arrebatam pelo ar STR_0570 : -STR_0571 :Circular cars spin around as they travel along the zig-zagging wooden track -STR_0572 :Large capacity boats travel along a wide water channel, propelled up slopes by a conveyer belt, accelerating down steep slopes to soak the riders with a gaint splash -STR_0573 :Powered helicoper shaped cars running on a steel track, controlled by the pedalling of the riders -STR_0574 :Riders are held in special harnesses in a lying-down position, travlling through twisted track and inversions either on their backs or facing the ground -STR_0575 :Powered trains hanging from a single rail transport people around the park +STR_0571 :Carros circulares giram enquanto viajam por uma pista de madeira em zig-zag +STR_0572 :Barcos de alta capacidade viajam por um largo canal d'água, subindo por uma correia transportadora, acelerando ladeira abaixo para molhar os passageiros com uma onda gigante +STR_0573 :Carros motorizados em formato de helicopteros correm por um trilho de aço, controlados pelo pedalar dos passageiros +STR_0574 :Passageiros são segurados por uma trava especial na posição deitada, viajando por trilhos retorcidos e inversões tanto de costas quanto olhando para o chão +STR_0575 :Trens motorizados pendurados em um trilho único transportam pessoas pelo parque STR_0576 : -STR_0577 :Bogied cars run on wooden tracks, turning around on special reversing sections -STR_0578 :Cars run along track enclosed by circular hoops, traversing steep drops and heartline twists +STR_0577 :Carros correm em trilhos de madeira, virando em seções reversoras especiais +STR_0578 :Carros correm em trilhos envolvidos por anéis, passando por quedas íngremes e giros na 'linha do coração' STR_0579 : -STR_0580 :A giant steel roller coaster capable of smooth drops and hills of over 300ft -STR_0581 :A ring of seats is pulled to the top of a tall tower while gently rotating, then allowed to free-fall down, stopping gently at the bottom using magnetic brakes +STR_0580 :Uma montanha-russa de aço gigante capaz de quedas suaves e colinas maiores que 90m +STR_0581 :Um anel de assentos é puxado para o topo de uma alta torre enquando gira lentamente, então desce em queda livre, parando suavemente na parte inferior usando freios magnéticos STR_0582 : STR_0583 : -STR_0584 :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders -STR_0585 :Riders sit in pairs of seats suspended beneath the track as they loop and twist through tight inversions -STR_0586 :Boat shaped cars run on roller coaster track to allow twisting curves and steep drops, splashing down into sections of water for gentle river sections -STR_0587 :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station -STR_0588 :Individual cars run beneath a zig-zagging track with hairpin turns and sharp drops +STR_0584 :Bicicletas especiais correm em uma pista de aço de monotrilho, controladas pelo pedalar dos passageiros +STR_0585 :Passageiros sentam em um par de cadeiras suspensas abaixo do trilho enquanto fazem loops e giros por inversões estreitas +STR_0586 :Carros em formato de barcos correm em um trilho de montanha-russa que permite curvas retorcidas e quedas íngremes, esparrinhando água em seções aquáticas que viram um rio suave. +STR_0587 :Depois de um lançamento de propulsão hidráulica emocionante, o trem acelerado sobe verticalmente, passa pelo topo, e desce verticalmente ao outro lado para voltar à estação +STR_0588 :Carros individuais correm por baixo de um trilho em zig-zag com curvas fechadas e quedas acentuadas STR_0589 : -STR_0590 :Riders ride in a submerged submarine through an underwater course -STR_0591 :Raft-shaped boats gently meander around a river track +STR_0590 :Passageiros passeiam em um submarino submergido por um percurso subaquático +STR_0591 :Barcos em forma de balsas serpenteiam delicadamente em uma pista de rio STR_0592 : STR_0593 : STR_0594 : STR_0595 : STR_0596 : STR_0597 : -STR_0598 :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track -STR_0599 :A compact roller coaster with individual cars and smooth twisting drops -STR_0600 :Powered mine trains career along a smooth and twisted track layout +STR_0598 :Trens de montanha-russa invertida são acelerados para fora da estação para subir em uma pista vertical, então volta pela estação e sobe de costas em outra pista vertical +STR_0599 :Uma montanha-russa compacta com carros individuais e suaves quedas retorcidas +STR_0600 :Trens de mina motorizados viajam por uma pista suave e retorcida STR_0601 : -STR_0602 :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions +STR_0602 :Trens da montanha-russa são acelerados para fora da estação por motores de indução linear passando em alta velocidade por inversões retorcidas STR_0603 :Visitante {INT32} STR_0604 :Visitante {INT32} STR_0605 :Visitante {INT32} @@ -769,16 +769,16 @@ STR_0764 :Visitante {INT32} STR_0765 :Visitante {INT32} STR_0766 :Visitante {INT32} STR_0767 :Visitante {INT32} -STR_0768 :Faz-Tudo {INT32} +STR_0768 :Faxineiro {INT32} STR_0769 :Mecânico {INT32} STR_0770 :Segurança {INT32} STR_0771 :Animador {INT32} -STR_0772 :Park Sem Nome{POP16}{POP16} -STR_0773 :Park Sem Nome{POP16}{POP16} -STR_0774 :Park Sem Nome{POP16}{POP16} -STR_0775 :Park Sem Nome{POP16}{POP16} -STR_0776 :Park Sem Nome{POP16}{POP16} -STR_0777 :Park Sem Nome{POP16}{POP16} +STR_0772 :Parque Sem Nome{POP16}{POP16} +STR_0773 :Parque Sem Nome{POP16}{POP16} +STR_0774 :Parque Sem Nome{POP16}{POP16} +STR_0775 :Parque Sem Nome{POP16}{POP16} +STR_0776 :Parque Sem Nome{POP16}{POP16} +STR_0777 :Parque Sem Nome{POP16}{POP16} STR_0778 :Entrar STR_0779 :1º de STR_0780 :2 de @@ -852,11 +852,11 @@ STR_0846 : STR_0847 :Sobre 'OpenRCT2' STR_0848 :RollerCoaster Tycoon 2 STR_0849 :{WINDOW_COLOUR_2}Version 2.01.028 -STR_0850 :{WINDOW_COLOUR_2}Copyright {COPYRIGHT} 2002 Chris Sawyer, todos os Direitos Reservados +STR_0850 :{WINDOW_COLOUR_2}Copyright {COPYRIGHT} 2002 Chris Sawyer, todos os direitos reservados STR_0851 :{WINDOW_COLOUR_2}Projetado e programado por Chris Sawyer STR_0852 :{WINDOW_COLOUR_2}Gráficos por Simon Foster STR_0853 :{WINDOW_COLOUR_2}Som e musícas por Allister Brimble -STR_0854 :{WINDOW_COLOUR_2}Sons adicionais gravador por David Ellis +STR_0854 :{WINDOW_COLOUR_2}Sons adicionais gravados por David Ellis STR_0855 :{WINDOW_COLOUR_2}Representação por Jacqui Lyons na Marjacq Ltd. STR_0856 :{WINDOW_COLOUR_2}Obrigado a: STR_0857 :{WINDOW_COLOUR_2}Peter James Adcock, Joe Booth, and John Wardley @@ -881,23 +881,23 @@ STR_0875 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP STR_0876 :{BLACK}{DOWN} STR_0877 :Muito baixo ! STR_0878 :Muito alto ! -STR_0879 :Não é possível baixar terra aqui... -STR_0880 :Não é possível aumentar a terra aqui... +STR_0879 :Não é possível abaixar o terreno aqui... +STR_0880 :Não é possível aumentar o terreno aqui... STR_0881 :Objeto no caminho STR_0882 :Carregar Jogo STR_0883 :Salvar Jogo -STR_0884 :Carregar Landscape -STR_0885 :Salvar Landscape +STR_0884 :Carregar Paisagem +STR_0885 :Salvar Paisagem STR_0886 :Sair do Jogo STR_0887 :Sair do Editor de Cenário -STR_0888 :Sair do Designer de Montanha-Russa -STR_0889 :Sair do Gerenciamento de Designs de Pista +STR_0888 :Sair do Construtor de Montanha-Russa +STR_0889 :Sair do Gerenciador de Projetos de Pista STR_0890 :SCR{COMMA16}.BMP STR_0891 :Captura de tela STR_0892 :Captura de tela salvo no disco como '{STRINGID}' STR_0893 :Capturas de tela falhou ! -STR_0894 :Landscape data area full ! -STR_0895 :Impossível construir parcialmente em cima e em baixo do chão +STR_0894 :Dados da área da paisagem cheios ! +STR_0895 :Impossível construir parcialmente em cima e embaixo do chão STR_0896 :{POP16}{POP16}{STRINGID} Construção STR_0897 :Sentido STR_0898 :{SMALLFONT}{BLACK}Curva para esquerda @@ -908,31 +908,31 @@ STR_0902 :{SMALLFONT}{BLACK}Curva para esquerda (raio muito pequeno) STR_0903 :{SMALLFONT}{BLACK}Curva para esquerda (raio muito pequeno) STR_0904 :{SMALLFONT}{BLACK}Curva para esquerda (raio grande) STR_0905 :{SMALLFONT}{BLACK}Curva para esquerda (raio grande) -STR_0906 :{SMALLFONT}{BLACK}Em Linha Reta +STR_0906 :{SMALLFONT}{BLACK}Linha reta STR_0907 :Inclinação -STR_0908 :Rolar/Banking -STR_0909 :Seat Rot. -STR_0910 :{SMALLFONT}{BLACK}Roll for left-hand curve -STR_0911 :{SMALLFONT}{BLACK}Roll for right-hand curve -STR_0912 :{SMALLFONT}{BLACK}No roll -STR_0913 :{SMALLFONT}{BLACK}Move to previous section -STR_0914 :{SMALLFONT}{BLACK}Move to next section -STR_0915 :{SMALLFONT}{BLACK}Construct the selected section -STR_0916 :{SMALLFONT}{BLACK}Remove the highlighted section -STR_0917 :{SMALLFONT}{BLACK}Vertical drop -STR_0918 :{SMALLFONT}{BLACK}Steep slope down -STR_0919 :{SMALLFONT}{BLACK}Slope down -STR_0920 :{SMALLFONT}{BLACK}Level -STR_0921 :{SMALLFONT}{BLACK}Slope up -STR_0922 :{SMALLFONT}{BLACK}Steep slope up -STR_0923 :{SMALLFONT}{BLACK}Vertical rise -STR_0924 :{SMALLFONT}{BLACK}Helix down -STR_0925 :{SMALLFONT}{BLACK}Helix up +STR_0908 :Giro/Inclinação +STR_0909 :Rot. Banco +STR_0910 :{SMALLFONT}{BLACK}Curva retorcida para a esquerda +STR_0911 :{SMALLFONT}{BLACK}Curva retorcida para a direita +STR_0912 :{SMALLFONT}{BLACK}Sem retorção +STR_0913 :{SMALLFONT}{BLACK}Mover para a seção anterior +STR_0914 :{SMALLFONT}{BLACK}Mover para a próxima seção +STR_0915 :{SMALLFONT}{BLACK}Construir seção destacada +STR_0916 :{SMALLFONT}{BLACK}Remover seção destacada ou anterior +STR_0917 :{SMALLFONT}{BLACK}Queda vertical +STR_0918 :{SMALLFONT}{BLACK}Descida íngreme +STR_0919 :{SMALLFONT}{BLACK}Descida +STR_0920 :{SMALLFONT}{BLACK}Nivelado +STR_0921 :{SMALLFONT}{BLACK}Subida +STR_0922 :{SMALLFONT}{BLACK}Subida íngreme +STR_0923 :{SMALLFONT}{BLACK}Subir na vertical +STR_0924 :{SMALLFONT}{BLACK}Espiral para baixo +STR_0925 :{SMALLFONT}{BLACK}Espiral para cima STR_0926 :Impossível remover isto... STR_0927 :Impossível construir isto aqui... -STR_0928 :{SMALLFONT}{BLACK}Corrente elevador, para puxar os carros para cima -STR_0929 :Curva 'S' (esquerda) -STR_0930 :Curva 'S' (direita) +STR_0928 :{SMALLFONT}{BLACK}Corrente de elevação, para puxar os carros para cima +STR_0929 :Curva em 'S' (esquerda) +STR_0930 :Curva em 'S' (direita) STR_0931 :Loop Vertical (esquerda) STR_0932 :Loop Vertical (direita) STR_0933 :Aumentar ou diminuir o terreno primeiro @@ -942,9 +942,9 @@ STR_0936 :Entrada do parque no caminho STR_0937 :{SMALLFONT}{BLACK}Opções de visão STR_0938 :{SMALLFONT}{BLACK}Ajuste de altura do solo e inclinação STR_0939 :Subterrâneo/Visão interna -STR_0940 :Remover base da terra +STR_0940 :Remover terreno base STR_0941 :Remover faces verticais -STR_0942 :Ver Através das Atrações +STR_0942 :Ver Através dos Brinquedos STR_0943 :Ver Através dos Cenários STR_0944 :Salvar STR_0945 :Não Salvar @@ -955,9 +955,9 @@ STR_0949 :Salvar antes de sair ? STR_0950 :Carregar Jogo STR_0951 :Sair do Jogo STR_0952 :Sair do Jogo -STR_0953 :Load Landscape +STR_0953 :Carregar Paisagem STR_0954 : -STR_0955 :{SMALLFONT}{BLACK}Escolha um ângulo de rotação do assento para esta seção da pista +STR_0955 :{SMALLFONT}{BLACK}Escolha um ângulo de rotação do banco para esta seção da pista STR_0956 :-180{DEGREE} STR_0957 :-135{DEGREE} STR_0958 :-90{DEGREE} @@ -977,14 +977,14 @@ STR_0971 :+495{DEGREE} STR_0972 :Cancelar STR_0973 :OK STR_0974 :Atrações -STR_0975 :Lojas, Barracas & Stands +STR_0975 :Lojas e Barracas STR_0976 :Banheiros e Quiosques de Informações STR_0977 :Novas Atrações de Transporte -STR_0978 :Novas Atrações Suaves/Calmas +STR_0978 :Novas Atrações Tranquilas STR_0979 :Novas Montanhas-Russas STR_0980 :Novas Atrações Emocionantes STR_0981 :Novas Atrações Aquáticas -STR_0982 :Novas Lojas, Barracas & Stands +STR_0982 :Novas Lojas e Barracas STR_0983 :Pesquisa e Desenvolvimento STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP} STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP} @@ -993,7 +993,7 @@ STR_0987 :Muitas atrações STR_0988 :Impossível criar uma nova atração... STR_0989 :{STRINGID} STR_0990 :{SMALLFONT}{BLACK}Construção -STR_0991 :Plataforma da estação +STR_0991 :Plataforma de estação STR_0992 :{SMALLFONT}{BLACK}Demolir toda a atração STR_0993 :Demolir atração STR_0994 :Demolir @@ -1001,9 +1001,9 @@ STR_0995 :{WINDOW_COLOUR_1}Você tem certeza que deseja demolir completamente STR_0996 :Visão Geral STR_0997 :{SMALLFONT}{BLACK}Ver seleção STR_0998 :Não há mais estações permitidas nesta atração -STR_0999 :Requer uma plataforma da estação +STR_0999 :Requer uma plataforma de estação STR_1000 :A pista não é um circuito completo -STR_1001 :Track unsuitable for type of train +STR_1001 :Pista inadequada para este tipo de trem STR_1002 :Impossível Abrir {POP16}{POP16}{POP16}{STRINGID}... STR_1003 :Impossível Testar {POP16}{POP16}{POP16}{STRINGID}... STR_1004 :Impossível Fechar {POP16}{POP16}{POP16}{STRINGID}... @@ -1031,82 +1031,82 @@ STR_1025 :{COMMA16} carros por trens STR_1026 :Plataforma da estação é muito longa! STR_1027 :{SMALLFONT}{BLACK}Localizar isto na Visão Principal STR_1028 :Fora da borda do mapa! -STR_1029 :Cannot build partly above and partly below water! -STR_1030 :Can only build this underwater! -STR_1031 :Can't build this underwater! -STR_1032 :Can only build this on water! -STR_1033 :Can only build this above ground! -STR_1034 :Can only build this on land! -STR_1035 :Local authority won't allow construction above tree-height! +STR_1029 :Impossível construir parcialmente acima ou abaixo d'água! +STR_1030 :Somente possível construir isto embaixo d'água! +STR_1031 :Impossível construir isto embaixo d'água! +STR_1032 :Somente possível construir isto em cima da água! +STR_1033 :Somente possível construir isto acima do chão! +STR_1034 :Somente possível construir isto em terra! +STR_1035 :Autoridades locais não autorizam construções acima da altura das árvores! STR_1036 :Carregar Jogo -STR_1037 :Load Landscape +STR_1037 :Carregar Paisagem STR_1038 :Converter jogo salvo em cenário -STR_1039 :Install new track design +STR_1039 :Instalar novo projeto de pista STR_1040 :Salvar Jogo STR_1041 :Salvar Cenário -STR_1042 :Save Landscape +STR_1042 :Salvar Paisagem STR_1043 :OpenRCT2 Jogo Salvo STR_1044 :OpenRCT2 Arquivo de Cenário -STR_1045 :OpenRCT2 Landscape File -STR_1046 :OpenRCT2 Arquivo de Projeto da Pista +STR_1045 :OpenRCT2 Arquivo de Paisagem +STR_1046 :OpenRCT2 Arquivo de Projeto de Pista STR_1047 :Falha ao salvar o jogo! STR_1048 :Falha ao salvar o cenário! -STR_1049 :Landscape save failed! +STR_1049 :Falha ao salvar a paisagem! STR_1050 :Falha ao carregar o jogo...{NEWLINE}Arquivo contém dados inválidos! STR_1051 :Suportes Invisíveis STR_1052 :Pessoas Invisíveis -STR_1053 :{SMALLFONT}{BLACK}Rides/attractions in park -STR_1054 :{SMALLFONT}{BLACK}Name ride/attraction -STR_1055 :{SMALLFONT}{BLACK}Name person -STR_1056 :{SMALLFONT}{BLACK}Name staff member -STR_1057 :Ride/attraction name +STR_1053 :{SMALLFONT}{BLACK}Atrações no parque +STR_1054 :{SMALLFONT}{BLACK}Nomear atração +STR_1055 :{SMALLFONT}{BLACK}Nomear pessoa +STR_1056 :{SMALLFONT}{BLACK}Nomear funcionário +STR_1057 :Nome da atração STR_1058 :Digite o novo nome para esta atração: -STR_1059 :Impossível renomear a atração.. +STR_1059 :Impossível renomear a atração... STR_1060 :Nome inválido para a atração STR_1061 :Modo normal STR_1062 :Modo de circuito contínuo -STR_1063 :Reverse-Incline launched shuttle mode -STR_1064 :Lançamento alimentado (estação de passagem) -STR_1065 :Shuttle mode -STR_1066 :Boat hire mode -STR_1067 :Upward launch -STR_1068 :Rotating lift mode -STR_1069 :Station to station mode -STR_1070 :Single ride per admission -STR_1071 :Unlimited rides per admission +STR_1063 :Modo vai-e-vem lançado reverso-inclinado +STR_1064 :Lançamento motorizado (passando pela estação) +STR_1065 :Modo vai-e-vem +STR_1066 :Modo aluguel de barcos +STR_1067 :Lancamento para cima +STR_1068 :Modo de subida rotativa +STR_1069 :Modo estação à estação +STR_1070 :Um passeio por ingresso +STR_1071 :Passeios ilimitados por ingresso STR_1072 :Modo de labirinto STR_1073 :Modo de corrida -STR_1074 :Modo de Bumper-car -STR_1075 :Modo de Balanço -STR_1076 :Modo de lojas e barraca -STR_1077 :Modo de Rotação +STR_1074 :Modo de bate-bate +STR_1075 :Modo de balanço +STR_1076 :Modo de lojas e barracas +STR_1077 :Modo de rotação STR_1078 :Rotação para frente STR_1079 :Rotação para trás -STR_1080 :Film: {ENDQUOTES}Avenging aviators{ENDQUOTES} -STR_1081 :3D film: {ENDQUOTES}Mouse tails{ENDQUOTES} -STR_1082 :Space rings mode -STR_1083 :Beginners mode -STR_1084 :LIM-powered launch -STR_1085 :Film: {ENDQUOTES}Thrill riders{ENDQUOTES} +STR_1080 :Filme: {ENDQUOTES}Aviadores Vingadores{ENDQUOTES} +STR_1081 :Filme em 3D: {ENDQUOTES}Caudas de Rato{ENDQUOTES} +STR_1082 :Modo giroscópio humano +STR_1083 :Modo iniciante +STR_1084 :Lançamento por indução linear +STR_1085 :Filme: {ENDQUOTES}Pilotos de Emoção{ENDQUOTES} STR_1086 :Filme em 3D: {ENDQUOTES}Caçadores de tempestades{ENDQUOTES} STR_1087 :Filme em 3D: {ENDQUOTES}Caçadores do espaço{ENDQUOTES} STR_1088 :Modo intenso -STR_1089 :Berserk mode -STR_1090 :Haunted house mode -STR_1091 :Circus show mode -STR_1092 :Downward launch -STR_1093 :Crooked house mode -STR_1094 :Freefall drop mode -STR_1095 :Continuous circuit block sectioned mode -STR_1096 :Powered launch (without passing station) -STR_1097 :Powered launch block sectioned mode -STR_1098 :Moving to end of {POP16}{STRINGID} -STR_1099 :Waiting for passengers at {POP16}{STRINGID} -STR_1100 :Waiting to depart {POP16}{STRINGID} -STR_1101 :Departing {POP16}{STRINGID} +STR_1089 :Modo frenético +STR_1090 :Modo casa mal-assombrada +STR_1091 :Modo circo +STR_1092 :Lançamento para baixo +STR_1093 :Modo casa maluca +STR_1094 :Modo queda livre +STR_1095 :Modo de circuito contínuo com blocos seccionados +STR_1096 :Lançamento motorizado (sem passar pela estação) +STR_1097 :Modo de lançamento motorizado com blocos seccionados +STR_1098 :Movendo para o fim de {POP16}{STRINGID} +STR_1099 :Esperando passageiros em {POP16}{STRINGID} +STR_1100 :Esperando sair {POP16}{STRINGID} +STR_1101 :Partindo {POP16}{STRINGID} STR_1102 :Viajando a {VELOCITY} STR_1103 :Chegando a {POP16}{STRINGID} -STR_1104 :Unloading passengers at {POP16}{STRINGID} +STR_1104 :Desembarcando passageiros em {POP16}{STRINGID} STR_1105 :Viajando a {VELOCITY} STR_1106 :Falhando! STR_1107 :Quebrado! @@ -1119,9 +1119,9 @@ STR_1113 :Mostrando filme STR_1114 :Rotacionando STR_1115 :Operando STR_1116 :Operando -STR_1117 :Doing circus show +STR_1117 :Executando Circo STR_1118 :Operando -STR_1119 :Waiting for cable lift +STR_1119 :Esperando cabo de elevação STR_1120 :Viajando a {VELOCITY} STR_1121 :Terminando STR_1122 :Aguardando passageiros @@ -1130,7 +1130,7 @@ STR_1124 :Começando STR_1125 :Operando STR_1126 :Terminando STR_1127 :Desembarcando passageiros -STR_1128 :Parado pelo bloco dos freios +STR_1128 :Parado pelos freios bloqueadores STR_1129 :Todos os veículos com as mesmas cores STR_1130 :Diferentes cores por {STRINGID} STR_1131 :Diferentes cores por veículos @@ -1143,11 +1143,11 @@ STR_1137 :{SMALLFONT}{BLACK}Selecione a cor adicional 1 STR_1138 :{SMALLFONT}{BLACK}Selecione a cor adicional 2 STR_1139 :{SMALLFONT}{BLACK}Selecione a cor do suporte das estruturas STR_1140 :{SMALLFONT}{BLACK}Selecione a opção do esquema de cor do veículo -STR_1141 :{SMALLFONT}{BLACK}Selecione o veiculo/Trem para modificar +STR_1141 :{SMALLFONT}{BLACK}Selecione o veiculo/trem para modificar STR_1142 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1143 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRINGID} STR_1144 :Impossível contruir/mover a entrada para essa atração... -STR_1145 :Impossível contruir/mover a saida para essa atração... +STR_1145 :Impossível contruir/mover a saída para essa atração... STR_1146 :Entrada ainda não construida STR_1147 :Saida ainda não construida STR_1148 :Um quarto de carga @@ -1155,9 +1155,9 @@ STR_1149 :Metade de carga STR_1150 :Três quartos de carga STR_1151 :Carga total STR_1152 :Qualquer carga -STR_1153 :Height Marks on Ride Tracks -STR_1154 :Height Marks on Land -STR_1155 :Height Marks on Paths +STR_1153 :Marcas de altura nas Pistas dos Brinquedos +STR_1154 :Marcas de altura no Terreno +STR_1155 :Marcas de altura nos Caminhos STR_1156 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1157 :{TICK}{MOVE_X}{SMALLFONT}{STRINGID} STR_1158 :Impossível remover isto... @@ -1175,15 +1175,15 @@ STR_1169 :(Nenhum) STR_1170 :{STRING} STR_1171 :{RED}Fechado - - STR_1172 :{YELLOW}{STRINGID} - - -STR_1173 :{SMALLFONT}{BLACK}Build footpaths and queue lines -STR_1174 :Banner sign in the way -STR_1175 :Can't build this on sloped footpath -STR_1176 :Can't build footpath here... -STR_1177 :Can't remove footpath from here... -STR_1178 :Land slope unsuitable -STR_1179 :Footpath in the way +STR_1173 :{SMALLFONT}{BLACK}Construir calçadas e filas de espera +STR_1174 :Banner está no caminho +STR_1175 :Impossível construir isto na calçada inclinada +STR_1176 :Impossível construir calçada aqui... +STR_1177 :Impossível remover calçada daqui... +STR_1178 :Inclinação de terreno imprópria +STR_1179 :Calçada está no caminho STR_1180 :Impossível construir isto debaixo de água! -STR_1181 :Caminhos +STR_1181 :Calçadas STR_1182 :Tipo STR_1183 :Direção STR_1184 :Inclinação @@ -1191,46 +1191,46 @@ STR_1185 :{SMALLFONT}{BLACK}Direção STR_1186 :{SMALLFONT}{BLACK}inclinação para baixo STR_1187 :{SMALLFONT}{BLACK}Nível STR_1188 :{SMALLFONT}{BLACK}inclinação para cima -STR_1189 :{SMALLFONT}{BLACK}Construct the selected footpath section -STR_1190 :{SMALLFONT}{BLACK}Remove previous footpath section +STR_1189 :{SMALLFONT}{BLACK}Construir a seção de calçada selecionada +STR_1190 :{SMALLFONT}{BLACK}Remover a seção de calçada selecionada STR_1191 :{BLACK}{STRINGID} STR_1192 :{OUTLINE}{RED}{STRINGID} STR_1193 :{WINDOW_COLOUR_2}{STRINGID} STR_1194 :Fechado STR_1195 :Executar teste STR_1196 :Aberto -STR_1197 :Enguiçou -STR_1198 :Quebrado! -STR_1199 :{COMMA16} person on ride -STR_1200 :{COMMA16} people on ride -STR_1201 :Nobody in queue line -STR_1202 :1 person in queue line -STR_1203 :{COMMA16} people in queue line -STR_1204 :{COMMA16} minute queue time -STR_1205 :{COMMA16} minutes queue time -STR_1206 :{WINDOW_COLOUR_2}Wait for: -STR_1207 :{WINDOW_COLOUR_2}Leave if another train arrives at station -STR_1208 :{WINDOW_COLOUR_2}Leave if another boat arrives at station -STR_1209 :{SMALLFONT}{BLACK}Select whether should wait for passengers before departing -STR_1210 :{SMALLFONT}{BLACK}Select whether should leave if another vehicle arrives at the same station -STR_1211 :{WINDOW_COLOUR_2}Minimum waiting time: -STR_1212 :{WINDOW_COLOUR_2}Maximum waiting time: -STR_1213 :{SMALLFONT}{BLACK}Select minimum length of time to wait before departing -STR_1214 :{SMALLFONT}{BLACK}Select maximum length of time to wait before departing -STR_1215 :{WINDOW_COLOUR_2}Synchronise with adjacent stations -STR_1216 :{SMALLFONT}{BLACK}Select whether to synchronise departure with all adjacent stations (for 'racing') -STR_1217 :{COMMA16} seconds +STR_1197 :Quebrado +STR_1198 :Bateu! +STR_1199 :{COMMA16} pessoa na atração +STR_1200 :{COMMA16} pessoas na atração +STR_1201 :Ninguém na fila +STR_1202 :1 pessoa na fila +STR_1203 :{COMMA16} pessoas na fila de espera +STR_1204 :{COMMA16} minuto de fila de espera +STR_1205 :{COMMA16} minutos de fila de espera +STR_1206 :{WINDOW_COLOUR_2}Esperar por: +STR_1207 :{WINDOW_COLOUR_2}Sair se outro trem chegar na estação +STR_1208 :{WINDOW_COLOUR_2}Sair se outro barco chegar na estação +STR_1209 :{SMALLFONT}{BLACK}Selecione se deve esperar por passageiros antes de sair +STR_1210 :{SMALLFONT}{BLACK}Selecione se deve sair se outro veículo chegar na mesma estação +STR_1211 :{WINDOW_COLOUR_2}Tempo mínimo de espera: +STR_1212 :{WINDOW_COLOUR_2}Tempo máximo de espera: +STR_1213 :{SMALLFONT}{BLACK}Selecione o tempo mínimo de espera antes de sair +STR_1214 :{SMALLFONT}{BLACK}Selecione o tempo máximo de espera antes de sair +STR_1215 :{WINDOW_COLOUR_2}Sincronizar com estações adjacentes +STR_1216 :{SMALLFONT}{BLACK}Selecione para sincronizar saída com todas estações adjacentes (para corrida) +STR_1217 :{COMMA16} segundos STR_1218 :{BLACK}{SMALLUP} STR_1219 :{BLACK}{SMALLDOWN} -STR_1220 :Somente Saida +STR_1220 :Somente Saída STR_1221 :Sem entrada STR_1222 :Sem saída STR_1223 :{SMALLFONT}{BLACK}Atrações de Transporte -STR_1224 :{SMALLFONT}{BLACK}Atrações Suaves/Calmas +STR_1224 :{SMALLFONT}{BLACK}Atrações Tranquilas STR_1225 :{SMALLFONT}{BLACK}Montanhas-Russas STR_1226 :{SMALLFONT}{BLACK}Atrações Emocionantes STR_1227 :{SMALLFONT}{BLACK}Atrações Aquáticas -STR_1228 :{SMALLFONT}{BLACK}Lojas, Barracas & Stands +STR_1228 :{SMALLFONT}{BLACK}Lojas e Barracas STR_1229 :trem STR_1230 :trens STR_1231 :Trem @@ -1330,7 +1330,7 @@ STR_1324 :{COMMA16} curso STR_1325 :{COMMA16} cursos STR_1326 :Curso {COMMA16} STR_1327 :{SMALLFONT}{BLACK}Rotacionar objetos em 90{DEGREE} -STR_1328 :Nível da terra necessário +STR_1328 :Necessário nivelar terreno STR_1329 :{WINDOW_COLOUR_2}Velocidade de lançamento: STR_1330 :{SMALLFONT}{BLACK}Velocidade máxima quando sair da estação STR_1331 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} @@ -1342,60 +1342,60 @@ STR_1336 :{STRINGID} - Estação {POP16}{COMMA16} Entrada STR_1337 :{STRINGID} - Saida{POP16}{POP16} STR_1338 :{STRINGID} - Estação {POP16}{COMMA16} Saida STR_1339 :{BLACK}Nenhum resultado de teste ainda... -STR_1340 :{WINDOW_COLOUR_2}Vel. Max.: {BLACK}{VELOCITY} -STR_1341 :{WINDOW_COLOUR_2}Ride time: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1340 :{WINDOW_COLOUR_2}Vel. Máx.: {BLACK}{VELOCITY} +STR_1341 :{WINDOW_COLOUR_2}Duração da atração: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1342 :{DURATION} STR_1343 :{DURATION} / -STR_1344 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1344 :{WINDOW_COLOUR_2}Comprimento da atração: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1345 :{LENGTH} STR_1346 :{LENGTH} / -STR_1347 :{WINDOW_COLOUR_2}Average speed: {BLACK}{VELOCITY} -STR_1348 :{WINDOW_COLOUR_2}Max. positive vertical G's: {BLACK}{COMMA2DP32}g -STR_1349 :{WINDOW_COLOUR_2}Max. positive vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1350 :{WINDOW_COLOUR_2}Max. negative vertical G's: {BLACK}{COMMA2DP32}g -STR_1351 :{WINDOW_COLOUR_2}Max. negative vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1352 :{WINDOW_COLOUR_2}Max. lateral G's: {BLACK}{COMMA2DP32}g -STR_1353 :{WINDOW_COLOUR_2}Max. lateral G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1354 :{WINDOW_COLOUR_2}Highest drop height: {BLACK}{LENGTH} -STR_1355 :{WINDOW_COLOUR_2}Drops: {BLACK}{COMMA16} -STR_1356 :{WINDOW_COLOUR_2}Inversions: {BLACK}{COMMA16} -STR_1357 :{WINDOW_COLOUR_2}Holes: {BLACK}{COMMA16} -STR_1358 :{WINDOW_COLOUR_2}Total 'air' time: {BLACK}{COMMA2DP32}secs -STR_1359 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minute -STR_1360 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minutes -STR_1361 :Can't change speed... -STR_1362 :Can't change launch speed... -STR_1363 :Too high for supports! -STR_1364 :Supports for track above can't be extended any further! -STR_1365 :In-line Twist (left) -STR_1366 :In-line Twist (right) -STR_1367 :Half Loop -STR_1368 :Half Corkscrew (left) -STR_1369 :Half Corkscrew (right) -STR_1370 :Barrel Roll (left) -STR_1371 :Barrel Roll (right) -STR_1372 :Launched Lift Hill -STR_1373 :Large Half Loop (left) -STR_1374 :Large Half Loop (right) -STR_1375 :Upper Transfer -STR_1376 :Lower Transfer -STR_1377 :Heartline Roll (left) -STR_1378 :Heartline Roll (right) -STR_1379 :Reverser (left) -STR_1380 :Reverser (right) -STR_1381 :Curved Lift Hill (left) -STR_1382 :Curved Lift Hill (right) -STR_1383 :Quarter Loop +STR_1347 :{WINDOW_COLOUR_2}Velocidade Média: {BLACK}{VELOCITY} +STR_1348 :{WINDOW_COLOUR_2}Máx. G vertical positivo: {BLACK}{COMMA2DP32}g +STR_1349 :{WINDOW_COLOUR_2}Máx. G vertical positivo: {OUTLINE}{RED}{COMMA2DP32}g +STR_1350 :{WINDOW_COLOUR_2}Máx. G vertical negativo: {BLACK}{COMMA2DP32}g +STR_1351 :{WINDOW_COLOUR_2}Máx. G vertical negativo: {OUTLINE}{RED}{COMMA2DP32}g +STR_1352 :{WINDOW_COLOUR_2}Máx. G lateral: {BLACK}{COMMA2DP32}g +STR_1353 :{WINDOW_COLOUR_2}Máx. G lateral: {OUTLINE}{RED}{COMMA2DP32}g +STR_1354 :{WINDOW_COLOUR_2}Queda mais alta: {BLACK}{LENGTH} +STR_1355 :{WINDOW_COLOUR_2}Quedas: {BLACK}{COMMA16} +STR_1356 :{WINDOW_COLOUR_2}Inversões: {BLACK}{COMMA16} +STR_1357 :{WINDOW_COLOUR_2}Túneis: {BLACK}{COMMA16} +STR_1358 :{WINDOW_COLOUR_2}'Tempo no Ar' Total: {BLACK}{COMMA2DP32}segs +STR_1359 :{WINDOW_COLOUR_2}Tempo de espera: {BLACK}{COMMA16} minuto +STR_1360 :{WINDOW_COLOUR_2}Tempo de espera: {BLACK}{COMMA16} minutos +STR_1361 :Impossível mudar velocidade... +STR_1362 :Impossível mudar velocidade de lançamento... +STR_1363 :Muito alto para os suportes! +STR_1364 :Suportes do trilho acima não podem ser mais extendidos! +STR_1365 :Torção em Linha Reta (esquerda) +STR_1366 :Torção em Linha Reta (direita) +STR_1367 :Meio Loop +STR_1368 :Meio Parafuso (esquerda) +STR_1369 :Meio Parafuso (direita) +STR_1370 :Tonneau de Barril (esquerda) +STR_1371 :Tonneau de Barril (direita) +STR_1372 :Subida de elevação lançada +STR_1373 :Meio Loop Grande (esquerda) +STR_1374 :Meio Loop Grande (direita) +STR_1375 :Transferir para cima +STR_1376 :Transferir para baixo +STR_1377 :Giro Linha do Coração (esquerda) +STR_1378 :Giro Linha do Coração (direita) +STR_1379 :Reversor (esquerda) +STR_1380 :Reversor (direita) +STR_1381 :Subida em curva (esquerda) +STR_1382 :Subida em curva (direita) +STR_1383 :Um quarto de Loop STR_1384 :{YELLOW}{STRINGID} -STR_1385 :{SMALLFONT}{BLACK}Other track configurations +STR_1385 :{SMALLFONT}{BLACK}Outras configurações de trilho STR_1386 :Especial... -STR_1387 :Can't change land type... +STR_1387 :Impossível mudar tipo de terreno STR_1388 :{OUTLINE}{GREEN}+ {CURRENCY} STR_1389 :{OUTLINE}{RED}- {CURRENCY} STR_1390 :{CURRENCY2DP} STR_1391 :{RED}{CURRENCY2DP} STR_1392 :{SMALLFONT}{BLACK}Visão da atração -STR_1393 :{SMALLFONT}{BLACK}Opções e detalhes do veiculo +STR_1393 :{SMALLFONT}{BLACK}Opções e detalhes do veículo STR_1394 :{SMALLFONT}{BLACK}Opções de operação STR_1395 :{SMALLFONT}{BLACK}Opções de manutenção STR_1396 :{SMALLFONT}{BLACK}Opções de esquema de cor @@ -1408,40 +1408,40 @@ STR_1402 :{SMALLFONT}{BLACK}Construir ou mover a entrada da atração STR_1403 :{SMALLFONT}{BLACK}Construir ou mover a saída da atração STR_1404 :{SMALLFONT}{BLACK}Rotacionar 90{DEGREE} STR_1405 :{SMALLFONT}{BLACK}Imagem espelhada -STR_1406 :{SMALLFONT}{BLACK}Alternar cenário on / off (se disponível para este projeto) +STR_1406 :{SMALLFONT}{BLACK}Liga/Desliga cenário (se disponível para este projeto) STR_1407 :{WINDOW_COLOUR_2}Construir isto... STR_1408 :{WINDOW_COLOUR_2}Custo: {BLACK}{CURRENCY} STR_1409 :Entrada/Saída Plataforma STR_1410 :Torre Vertical STR_1411 :{STRINGID} no caminho -STR_1412 :{WINDOW_COLOUR_3}Data logging not available for this type of ride -STR_1413 :{WINDOW_COLOUR_3}Data logging will start when next {STRINGID} leaves {STRINGID} +STR_1412 :{WINDOW_COLOUR_3}O registro de dados não estão disponíveis para este tipo de atração +STR_1413 :{WINDOW_COLOUR_3}O registro de dados vai começar quando o próximo {STRINGID} sair de {STRINGID} STR_1414 :{SMALLFONT}{BLACK}{DURATION} STR_1415 :{WINDOW_COLOUR_2}Velocidade STR_1416 :{WINDOW_COLOUR_2}Altitude -STR_1417 :{WINDOW_COLOUR_2}Vert.G's -STR_1418 :{WINDOW_COLOUR_2}Lat.G's +STR_1417 :{WINDOW_COLOUR_2}G vertical +STR_1418 :{WINDOW_COLOUR_2}G lateral STR_1419 :{SMALLFONT}{BLACK}{VELOCITY} STR_1420 :{SMALLFONT}{BLACK}{LENGTH} STR_1421 :{SMALLFONT}{BLACK}{COMMA16}g -STR_1422 :{SMALLFONT}{BLACK}Logging data from {POP16}{STRINGID} -STR_1423 :{SMALLFONT}{BLACK}Caminho da fila -STR_1424 :{SMALLFONT}{BLACK}Trajeto -STR_1425 :Trajeto +STR_1422 :{SMALLFONT}{BLACK}Obtendo dados de {POP16}{STRINGID} +STR_1423 :{SMALLFONT}{BLACK}Fila de espera +STR_1424 :{SMALLFONT}{BLACK}Calçada +STR_1425 :Calçada STR_1426 :Fila de espera STR_1427 :{WINDOW_COLOUR_2}Clientes: {BLACK}{COMMA32} por hora STR_1428 :{WINDOW_COLOUR_2}Preço de entrada: STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} -STR_1430 :Livre +STR_1430 :Grátis STR_1431 :Andando -STR_1432 :Rumo a {STRINGID} -STR_1433 :Filas para {STRINGID} +STR_1432 :Indo para {STRINGID} +STR_1433 :Em fila para {STRINGID} STR_1434 :Afogando -STR_1435 :Em {STRINGID} -STR_1436 :In {STRINGID} -STR_1437 :At {STRINGID} +STR_1435 :No {STRINGID} +STR_1436 :Dentro {STRINGID} +STR_1437 :Em {STRINGID} STR_1438 :Sentando -STR_1439 :(select location) +STR_1439 :(selecione localização) STR_1440 :Cortando grama STR_1441 :Varrendo calçada STR_1442 :Esvaziando lixeira @@ -1457,22 +1457,22 @@ STR_1451 :{STRINGID}{NEWLINE}({STRINGID}) STR_1452 :Nome do Visitante STR_1453 :Digite o nome para este visitante: STR_1454 :Não é possivel nomear o visitante... -STR_1455 :Nome invalido para o visitante +STR_1455 :Nome inválido para o visitante STR_1456 :{WINDOW_COLOUR_2}Dinheiro gasto: {BLACK}{CURRENCY2DP} STR_1457 :{WINDOW_COLOUR_2}Dinheiro no bolso: {BLACK}{CURRENCY2DP} STR_1458 :{WINDOW_COLOUR_2}Tempo no parque: {BLACK}{REALTIME} STR_1459 :Estilo da pista -STR_1460 :{SMALLFONT}{BLACK}'U' shaped open track -STR_1461 :{SMALLFONT}{BLACK}'O' shaped enclosed track -STR_1462 :Too steep for lift hill +STR_1460 :{SMALLFONT}{BLACK}Pista aberta em forma de 'U' +STR_1461 :{SMALLFONT}{BLACK}Pista fechada em forma de 'O' +STR_1462 :Muito íngreme para uma subida de elevação STR_1463 :Visitantes -STR_1464 :Hélice cima (pequeno) -STR_1465 :Hélice cima (grande) -STR_1466 :Hélice baixo (pequeno) -STR_1467 :Hélice baixo (grande) +STR_1464 :Espiral para cima (pequeno) +STR_1465 :Espiral para cima (grande) +STR_1466 :Espiral para baixo (pequeno) +STR_1467 :Espiral para baixo (grande) STR_1468 :Funcionários -STR_1469 :Ride must start and end with stations -STR_1470 :Station not long enough +STR_1469 :Atração deve começar e finalizar com estações +STR_1470 :Estação não é longa o suficiente STR_1471 :{WINDOW_COLOUR_2}Velocidade: STR_1472 :{SMALLFONT}{BLACK}Velocidade desta atração STR_1473 :{WINDOW_COLOUR_2}Classificação de emoção: {BLACK}{COMMA2DP32} ({STRINGID}) @@ -1482,17 +1482,17 @@ STR_1476 :{WINDOW_COLOUR_2}Classificação de intensidade: {BLACK}Indisponív STR_1477 :{WINDOW_COLOUR_2}Classificação de intensidade: {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) STR_1478 :{WINDOW_COLOUR_2}Classificação de náuseas: {BLACK}{COMMA2DP32} ({STRINGID}) STR_1479 :{WINDOW_COLOUR_2}Classificação de náuseas: {BLACK}Indisponível -STR_1480 :{SMALLFONT}{OPENQUOTES}Eu não posso pagar{STRINGID}{ENDQUOTES} +STR_1480 :{SMALLFONT}{OPENQUOTES}Eu não posso pagar {STRINGID}{ENDQUOTES} STR_1481 :{SMALLFONT}{OPENQUOTES}Eu gastei todo o meu dinheiro{ENDQUOTES} STR_1482 :{SMALLFONT}{OPENQUOTES}Eu me sinto mal{ENDQUOTES} STR_1483 :{SMALLFONT}{OPENQUOTES}Eu me sinto muito mal{ENDQUOTES} STR_1484 :{SMALLFONT}{OPENQUOTES}Eu quero ir em algo mais emocionante do que {STRINGID}{ENDQUOTES} STR_1485 :{SMALLFONT}{OPENQUOTES}{STRINGID} parece muito intenso para mim{ENDQUOTES} STR_1486 :{SMALLFONT}{OPENQUOTES}Eu não terminei meu {STRINGID} ainda{ENDQUOTES} -STR_1487 :{SMALLFONT}{OPENQUOTES}Basta olhar para {STRINGID} para me sentir mal{ENDQUOTES} -STR_1488 :{SMALLFONT}{OPENQUOTES}Eu não estou pagando muito para ir em {STRINGID}{ENDQUOTES} +STR_1487 :{SMALLFONT}{OPENQUOTES}Só de olhar para {STRINGID} já me sento mal{ENDQUOTES} +STR_1488 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso para ir em {STRINGID}{ENDQUOTES} STR_1489 :{SMALLFONT}{OPENQUOTES}Eu quero ir para casa{ENDQUOTES} -STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} é realmente bom preço{ENDQUOTES} +STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} tem um preço bom{ENDQUOTES} STR_1491 :{SMALLFONT}{OPENQUOTES}Eu já tenho {STRINGID}{ENDQUOTES} STR_1492 :{SMALLFONT}{OPENQUOTES}Não posso pagar {STRINGID}{ENDQUOTES} STR_1493 :{SMALLFONT}{OPENQUOTES}Eu não estou com fome{ENDQUOTES} @@ -1506,107 +1506,107 @@ STR_1500 :{SMALLFONT}{OPENQUOTES}Eu estou com fome{ENDQUOTES} STR_1501 :{SMALLFONT}{OPENQUOTES}Eu estou com sede{ENDQUOTES} STR_1502 :{SMALLFONT}{OPENQUOTES}Eu preciso ir ao banheiro{ENDQUOTES} STR_1503 :{SMALLFONT}{OPENQUOTES}Eu não consigo encontrar {STRINGID}{ENDQUOTES} -STR_1504 :{SMALLFONT}{OPENQUOTES}Eu não estou pagando muito de usar {STRINGID}{ENDQUOTES} -STR_1505 :{SMALLFONT}{OPENQUOTES}Eu não estou indo em {STRINGID} enquanto está chovendo{ENDQUOTES} -STR_1506 :{SMALLFONT}{OPENQUOTES}O lixo aqui é muito ruim{ENDQUOTES} +STR_1504 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso para usar {STRINGID}{ENDQUOTES} +STR_1505 :{SMALLFONT}{OPENQUOTES}Eu não vou em {STRINGID} enquanto está chovendo{ENDQUOTES} +STR_1506 :{SMALLFONT}{OPENQUOTES}A limpeza aqui é muito ruim{ENDQUOTES} STR_1507 :{SMALLFONT}{OPENQUOTES}Eu não estou encontrando a saída do parque{ENDQUOTES} STR_1508 :{SMALLFONT}{OPENQUOTES}Eu quero sair{STRINGID}{ENDQUOTES} STR_1509 :{SMALLFONT}{OPENQUOTES}Eu quero sair do {STRINGID}{ENDQUOTES} -STR_1510 :{SMALLFONT}{OPENQUOTES}Eu não estou indo em {STRINGID} - Não é seguro{ENDQUOTES} +STR_1510 :{SMALLFONT}{OPENQUOTES}Eu não vou em {STRINGID} - Não é seguro{ENDQUOTES} STR_1511 :{SMALLFONT}{OPENQUOTES}Este caminho é nojento{ENDQUOTES} STR_1512 :{SMALLFONT}{OPENQUOTES}Está lotado aqui{ENDQUOTES} STR_1513 :{SMALLFONT}{OPENQUOTES}O vandalismo aqui é muito ruim{ENDQUOTES} STR_1514 :{SMALLFONT}{OPENQUOTES}Excelente cenário!{ENDQUOTES} STR_1515 :{SMALLFONT}{OPENQUOTES}Este parque é realmente limpo e arrumado{ENDQUOTES} -STR_1516 :{SMALLFONT}{OPENQUOTES}As fontes de salto são ótimas{ENDQUOTES} +STR_1516 :{SMALLFONT}{OPENQUOTES}As fontes saltitantes são ótimas{ENDQUOTES} STR_1517 :{SMALLFONT}{OPENQUOTES}A música é agradável aqui{ENDQUOTES} -STR_1518 :{SMALLFONT}{OPENQUOTES}Este balão de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1519 :{SMALLFONT}{OPENQUOTES}Este brinquedo pelúcia de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1520 :{SMALLFONT}{OPENQUOTES}Este mapa do parque de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1521 :{SMALLFONT}{OPENQUOTES}Esta foto na atração de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1522 :{SMALLFONT}{OPENQUOTES}Este guarda-chuva de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1523 :{SMALLFONT}{OPENQUOTES}Esta bebida de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1524 :{SMALLFONT}{OPENQUOTES}Este hambúrguer de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1525 :{SMALLFONT}{OPENQUOTES}Estas batatas fritas de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1526 :{SMALLFONT}{OPENQUOTES}Este sorvete de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1527 :{SMALLFONT}{OPENQUOTES}Este algodão-doce de {STRINGID} tem um bom preço{ENDQUOTES} +STR_1518 :{SMALLFONT}{OPENQUOTES}Este balão de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1519 :{SMALLFONT}{OPENQUOTES}Este brinquedo de pelúcia de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1520 :{SMALLFONT}{OPENQUOTES}Este mapa do parque de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1521 :{SMALLFONT}{OPENQUOTES}Esta foto em {STRINGID} tem um preço bom{ENDQUOTES} +STR_1522 :{SMALLFONT}{OPENQUOTES}Este guarda-chuva de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1523 :{SMALLFONT}{OPENQUOTES}Esta bebida de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1524 :{SMALLFONT}{OPENQUOTES}Este hambúrguer de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1525 :{SMALLFONT}{OPENQUOTES}Estas batatas fritas de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1526 :{SMALLFONT}{OPENQUOTES}Este sorvete de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1527 :{SMALLFONT}{OPENQUOTES}Este algodão-doce de {STRINGID} tem um preço bom{ENDQUOTES} STR_1528 : STR_1529 : STR_1530 : -STR_1531 :{SMALLFONT}{OPENQUOTES}Esta pizza de {STRINGID} tem um bom preço{ENDQUOTES} +STR_1531 :{SMALLFONT}{OPENQUOTES}Esta pizza de {STRINGID} tem um preço bom{ENDQUOTES} STR_1532 : -STR_1533 :{SMALLFONT}{OPENQUOTES}Esta pipoca de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1534 :{SMALLFONT}{OPENQUOTES}Este cachorro quente de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1535 :{SMALLFONT}{OPENQUOTES}Este tentáculo de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1536 :{SMALLFONT}{OPENQUOTES}Este chapéu de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1537 :{SMALLFONT}{OPENQUOTES}Esta maça do amor de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1538 :{SMALLFONT}{OPENQUOTES}Esta camiseta de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1539 :{SMALLFONT}{OPENQUOTES}Esta rosquinha de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1540 :{SMALLFONT}{OPENQUOTES}Este café de {STRINGID} tem um bom preço{ENDQUOTES} +STR_1533 :{SMALLFONT}{OPENQUOTES}Esta pipoca de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1534 :{SMALLFONT}{OPENQUOTES}Este cachorro quente de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1535 :{SMALLFONT}{OPENQUOTES}Este tentáculo de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1536 :{SMALLFONT}{OPENQUOTES}Este chapéu de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1537 :{SMALLFONT}{OPENQUOTES}Esta maçã do amor de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1538 :{SMALLFONT}{OPENQUOTES}Esta camiseta de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1539 :{SMALLFONT}{OPENQUOTES}Esta rosquinha de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1540 :{SMALLFONT}{OPENQUOTES}Este café de {STRINGID} tem um preço bom{ENDQUOTES} STR_1541 : -STR_1542 :{SMALLFONT}{OPENQUOTES}Este frango frito de {STRINGID} tem um bom preço{ENDQUOTES} -STR_1543 :{SMALLFONT}{OPENQUOTES}Esta limonada de {STRINGID} tem um bom preço{ENDQUOTES} +STR_1542 :{SMALLFONT}{OPENQUOTES}Este frango frito de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1543 :{SMALLFONT}{OPENQUOTES}Esta limonada de {STRINGID} tem um preço bom{ENDQUOTES} STR_1544 : STR_1545 : STR_1546 : STR_1547 : STR_1548 : STR_1549 : -STR_1550 :{SMALLFONT}{OPENQUOTES}Wow!{ENDQUOTES} -STR_1551 :{SMALLFONT}{OPENQUOTES}I have the strangest feeling someone is watching me{ENDQUOTES} -STR_1552 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a balloon from {STRINGID}{ENDQUOTES} -STR_1553 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a cuddly toy from {STRINGID}{ENDQUOTES} -STR_1554 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a park map from {STRINGID}{ENDQUOTES} -STR_1555 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1556 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an umbrella from {STRINGID}{ENDQUOTES} -STR_1557 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a drink from {STRINGID}{ENDQUOTES} -STR_1558 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a burger from {STRINGID}{ENDQUOTES} -STR_1559 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for chips from {STRINGID}{ENDQUOTES} -STR_1560 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an ice cream from {STRINGID}{ENDQUOTES} -STR_1561 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for candyfloss from {STRINGID}{ENDQUOTES} +STR_1550 :{SMALLFONT}{OPENQUOTES}Uau!{ENDQUOTES} +STR_1551 :{SMALLFONT}{OPENQUOTES}Estou com a sensação estranha de que alguém está me observando{ENDQUOTES} +STR_1552 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um balão de {STRINGID}{ENDQUOTES} +STR_1553 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um brinquedo de pelúcia de {STRINGID}{ENDQUOTES} +STR_1554 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um mapa de {STRINGID}{ENDQUOTES} +STR_1555 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma foto de {STRINGID}{ENDQUOTES} +STR_1556 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um guarda-chuva {STRINGID}{ENDQUOTES} +STR_1557 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma bebida de {STRINGID}{ENDQUOTES} +STR_1558 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um hambúrguer de {STRINGID}{ENDQUOTES} +STR_1559 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma batata frita de {STRINGID}{ENDQUOTES} +STR_1560 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um sorvete de {STRINGID}{ENDQUOTES} +STR_1561 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por algodão doce de {STRINGID}{ENDQUOTES} STR_1562 : STR_1563 : STR_1564 : -STR_1565 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for pizza from {STRINGID}{ENDQUOTES} +STR_1565 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma pizza de {STRINGID}{ENDQUOTES} STR_1566 : -STR_1567 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for popcorn from {STRINGID}{ENDQUOTES} -STR_1568 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a hot dog from {STRINGID}{ENDQUOTES} -STR_1569 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for tentacle from {STRINGID}{ENDQUOTES} -STR_1570 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a hat from {STRINGID}{ENDQUOTES} -STR_1571 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a toffee apple from {STRINGID}{ENDQUOTES} -STR_1572 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a T-shirt from {STRINGID}{ENDQUOTES} -STR_1573 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a doughnut from {STRINGID}{ENDQUOTES} -STR_1574 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for coffee from {STRINGID}{ENDQUOTES} +STR_1567 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma pipoca de {STRINGID}{ENDQUOTES} +STR_1568 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um cachorro-quente de {STRINGID}{ENDQUOTES} +STR_1569 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um tentáculo de {STRINGID}{ENDQUOTES} +STR_1570 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um chapéu de {STRINGID}{ENDQUOTES} +STR_1571 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma maçã do amor de {STRINGID}{ENDQUOTES} +STR_1572 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma camiseta de {STRINGID}{ENDQUOTES} +STR_1573 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um donut de {STRINGID}{ENDQUOTES} +STR_1574 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um café de {STRINGID}{ENDQUOTES} STR_1575 : -STR_1576 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fried chicken from {STRINGID}{ENDQUOTES} -STR_1577 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for lemonade from {STRINGID}{ENDQUOTES} +STR_1576 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um frango frito de {STRINGID}{ENDQUOTES} +STR_1577 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma limonada de {STRINGID}{ENDQUOTES} STR_1578 : STR_1579 : STR_1580 : STR_1581 : STR_1582 : STR_1583 : -STR_1584 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1585 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1586 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1587 :{SMALLFONT}{OPENQUOTES}This pretzel from {STRINGID} is really good value{ENDQUOTES} -STR_1588 :{SMALLFONT}{OPENQUOTES}This hot chocolate from {STRINGID} is really good value{ENDQUOTES} -STR_1589 :{SMALLFONT}{OPENQUOTES}This iced tea from {STRINGID} is really good value{ENDQUOTES} -STR_1590 :{SMALLFONT}{OPENQUOTES}This funnel cake from {STRINGID} is really good value{ENDQUOTES} -STR_1591 :{SMALLFONT}{OPENQUOTES}These sunglasses from {STRINGID} are really good value{ENDQUOTES} -STR_1592 :{SMALLFONT}{OPENQUOTES}These beef noodles from {STRINGID} are really good value{ENDQUOTES} -STR_1593 :{SMALLFONT}{OPENQUOTES}These fried rice noodles from {STRINGID} are really good value{ENDQUOTES} -STR_1594 :{SMALLFONT}{OPENQUOTES}This wonton soup from {STRINGID} is really good value{ENDQUOTES} -STR_1595 :{SMALLFONT}{OPENQUOTES}This meatball soup from {STRINGID} is really good value{ENDQUOTES} -STR_1596 :{SMALLFONT}{OPENQUOTES}This fruit juice from {STRINGID} is really good value{ENDQUOTES} -STR_1597 :{SMALLFONT}{OPENQUOTES}This soybean milk from {STRINGID} is really good value{ENDQUOTES} -STR_1598 :{SMALLFONT}{OPENQUOTES}This sujongkwa from {STRINGID} is really good value{ENDQUOTES} -STR_1599 :{SMALLFONT}{OPENQUOTES}This sub sandwich from {STRINGID} is really good value{ENDQUOTES} -STR_1600 :{SMALLFONT}{OPENQUOTES}This cookie from {STRINGID} is really good value{ENDQUOTES} +STR_1584 :{SMALLFONT}{OPENQUOTES}Esta foto de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1585 :{SMALLFONT}{OPENQUOTES}Esta foto de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1586 :{SMALLFONT}{OPENQUOTES}Esta foto de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1587 :{SMALLFONT}{OPENQUOTES}Este pretzel de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1588 :{SMALLFONT}{OPENQUOTES}Este chocolate quente de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1589 :{SMALLFONT}{OPENQUOTES}Este chá gelado de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1590 :{SMALLFONT}{OPENQUOTES}Este bolo de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1591 :{SMALLFONT}{OPENQUOTES}Estes óculos de sol de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1592 :{SMALLFONT}{OPENQUOTES}Este macarrão de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1593 :{SMALLFONT}{OPENQUOTES}Este arroz frito de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1594 :{SMALLFONT}{OPENQUOTES}Esta sopa de wonton de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1595 :{SMALLFONT}{OPENQUOTES}Esta sopa de almôndegas de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1596 :{SMALLFONT}{OPENQUOTES}Este suco de frutas {STRINGID} tem um preço bom{ENDQUOTES} +STR_1597 :{SMALLFONT}{OPENQUOTES}Este leite de soja de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1598 :{SMALLFONT}{OPENQUOTES}Este sujongkwa de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1599 :{SMALLFONT}{OPENQUOTES}Este sanduíche de {STRINGID} tem um preço bom{ENDQUOTES} +STR_1600 :{SMALLFONT}{OPENQUOTES}Este cookie de {STRINGID} tem um preço bom{ENDQUOTES} STR_1601 : STR_1602 : STR_1603 : -STR_1604 :{SMALLFONT}{OPENQUOTES}This roast sausage from {STRINGID} are really good value{ENDQUOTES} +STR_1604 :{SMALLFONT}{OPENQUOTES}Esta linguiça grelhada {STRINGID} tem um preço bom{ENDQUOTES} STR_1605 : STR_1606 : STR_1607 : @@ -1618,27 +1618,27 @@ STR_1612 : STR_1613 : STR_1614 : STR_1615 : -STR_1616 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1617 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1618 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1619 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a pretzel from {STRINGID}{ENDQUOTES} -STR_1620 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for hot chocolate from {STRINGID}{ENDQUOTES} -STR_1621 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for iced tea from {STRINGID}{ENDQUOTES} -STR_1622 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a funnel cake from {STRINGID}{ENDQUOTES} -STR_1623 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sunglasses from {STRINGID}{ENDQUOTES} -STR_1624 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for beef noodles from {STRINGID}{ENDQUOTES} -STR_1625 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fried rice noodles from {STRINGID}{ENDQUOTES} -STR_1626 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for wonton soup from {STRINGID}{ENDQUOTES} -STR_1627 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for meatball soup from {STRINGID}{ENDQUOTES} -STR_1628 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fruit juice from {STRINGID}{ENDQUOTES} -STR_1629 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for soybean milk from {STRINGID}{ENDQUOTES} -STR_1630 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sujongkwa from {STRINGID}{ENDQUOTES} -STR_1631 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a sub sandwich from {STRINGID}{ENDQUOTES} -STR_1632 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a cookie from {STRINGID}{ENDQUOTES} +STR_1616 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma foto em {STRINGID}{ENDQUOTES} +STR_1617 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma foto em {STRINGID}{ENDQUOTES} +STR_1618 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma foto em {STRINGID}{ENDQUOTES} +STR_1619 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um pretzel de {STRINGID}{ENDQUOTES} +STR_1620 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um chocolate quente de {STRINGID}{ENDQUOTES} +STR_1621 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um chá gelado de {STRINGID}{ENDQUOTES} +STR_1622 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um bolo de {STRINGID}{ENDQUOTES} +STR_1623 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um óculos de sol de {STRINGID}{ENDQUOTES} +STR_1624 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um macarrão de {STRINGID}{ENDQUOTES} +STR_1625 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um arroz frito de {STRINGID}{ENDQUOTES} +STR_1626 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma sopa de wonton de {STRINGID}{ENDQUOTES} +STR_1627 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma sopa de almôndegas de {STRINGID}{ENDQUOTES} +STR_1628 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um suco de frutas de {STRINGID}{ENDQUOTES} +STR_1629 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um leite de soja de {STRINGID}{ENDQUOTES} +STR_1630 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um sujongkwa de {STRINGID}{ENDQUOTES} +STR_1631 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um sanduíche de {STRINGID}{ENDQUOTES} +STR_1632 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por um cookie de {STRINGID}{ENDQUOTES} STR_1633 : STR_1634 : STR_1635 : -STR_1636 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a roast sausage from {STRINGID}{ENDQUOTES} +STR_1636 :{SMALLFONT}{OPENQUOTES}Eu não vou pagar tudo isso por uma linguiça grelhada de {STRINGID}{ENDQUOTES} STR_1637 : STR_1638 : STR_1639 : @@ -1650,15 +1650,15 @@ STR_1644 : STR_1645 : STR_1646 : STR_1647 : -STR_1648 :{SMALLFONT}{OPENQUOTES}Help! Put me down!{ENDQUOTES} -STR_1649 :{SMALLFONT}{OPENQUOTES}I'm running out of cash!{ENDQUOTES} -STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! A new ride being built!{ENDQUOTES} -STR_1651 :{SMALLFONT}{OPENQUOTES}Nice ride! But not as good as the Phoenix...{ENDQUOTES} -STR_1652 :{SMALLFONT}{OPENQUOTES}I'm so excited - It's an Intamin ride!{ENDQUOTES} -STR_1653 :{SMALLFONT}{OPENQUOTES}...and here we are on {STRINGID}!{ENDQUOTES} -STR_1654 :{WINDOW_COLOUR_2}Recent thoughts: -STR_1655 :{SMALLFONT}{BLACK}Construct footpath on land -STR_1656 :{SMALLFONT}{BLACK}Construct bridge or tunnel footpath +STR_1648 :{SMALLFONT}{OPENQUOTES}Socorro! Me solte!{ENDQUOTES} +STR_1649 :{SMALLFONT}{OPENQUOTES}Estou ficando sem dinheiro!{ENDQUOTES} +STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! Uma nova atração está sendo construída!{ENDQUOTES} +STR_1651 :{SMALLFONT}{OPENQUOTES}Atração legal! Mas não tão boa quanto a Phoenix...{ENDQUOTES} +STR_1652 :{SMALLFONT}{OPENQUOTES}Estou tão animado - É uma atração da Intamin!{ENDQUOTES} +STR_1653 :{SMALLFONT}{OPENQUOTES}...e aqui estamos no {STRINGID}!{ENDQUOTES} +STR_1654 :{WINDOW_COLOUR_2}Pensamentos recentes: +STR_1655 :{SMALLFONT}{BLACK}Construir caminho no terreno +STR_1656 :{SMALLFONT}{BLACK}Construir ponte ou túnel de caminho STR_1657 :{WINDOW_COLOUR_2}Atração preferida STR_1658 :{WINDOW_COLOUR_2}intensidade: {BLACK}menor que {COMMA16} STR_1659 :{WINDOW_COLOUR_2}intensidade: {BLACK}entre {COMMA16} and {COMMA16} @@ -1675,37 +1675,37 @@ STR_1669 :{WINDOW_COLOUR_2}Satisfação: {BLACK}{COMMA16}% STR_1670 :{WINDOW_COLOUR_2}Total de clientes: {BLACK}{COMMA32} STR_1671 :{WINDOW_COLOUR_2}Lucro total: {BLACK}{CURRENCY2DP} STR_1672 :Freios -STR_1673 :Spinning Control Toggle Track +STR_1673 :Alternar controle de giro na pista STR_1674 :Velocidade do freio STR_1675 :{POP16}{VELOCITY} -STR_1676 :{SMALLFONT}{BLACK}Set speed limit for brakes +STR_1676 :{SMALLFONT}{BLACK}Escolher limite de velocidade para os freios STR_1677 :{WINDOW_COLOUR_2}Popularidade: {BLACK}Desconhecido STR_1678 :{WINDOW_COLOUR_2}Popularidade: {BLACK}{COMMA16}% -STR_1679 :Hélice Cima (esquerda) -STR_1680 :Hélice Cima (direita) -STR_1681 :Hélice Baixo (esqueda) -STR_1682 :Hélice Baixo (direita) +STR_1679 :Espiral para Cima (esquerda) +STR_1680 :Espiral para Cima (direita) +STR_1681 :Espiral para Baixo (esqueda) +STR_1682 :Espiral para Baixo (direita) STR_1683 :Tamanho da base 2 x 2 STR_1684 :Tamanho da base 4 x 4 STR_1685 :Tamanho da base 2 x 4 STR_1686 :Tamanho da base 5 x 1 STR_1687 :Respingo da água STR_1688 :Tamanho da base 4 x 1 -STR_1689 :Block brakes +STR_1689 :Freios Bloqueadores 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_1691 :{WINDOW_COLOUR_2} Custo: {BLACK}{CURRENCY} +STR_1692 :{WINDOW_COLOUR_2} Custo: {BLACK}de {CURRENCY} STR_1693 :{SMALLFONT}{BLACK}Visitantes STR_1694 :{SMALLFONT}{BLACK}Funcionários -STR_1695 :{SMALLFONT}{BLACK}Rendimentos e gastos -STR_1696 :{SMALLFONT}{BLACK}Informação para os clientes -STR_1697 :Cannot place these on queue line area -STR_1698 :Can only place these on queue area +STR_1695 :{SMALLFONT}{BLACK}Receita e gastos +STR_1696 :{SMALLFONT}{BLACK}Informação do cliente +STR_1697 :Impossível colocar estes na fila de espera +STR_1698 :Somente possível colocar estes na fila de espera STR_1699 :Muitas pessoas no jogo -STR_1700 :Contratar novo Faz-Tudo -STR_1701 :Contratar novo Mecânico -STR_1702 :Contratar novo Segurança -STR_1703 :Contratar novo Animador +STR_1700 :Contratar novo faxineiro +STR_1701 :Contratar novo mecânico +STR_1702 :Contratar novo segurança +STR_1703 :Contratar novo animador STR_1704 :Impossível contratar novos funcionários... STR_1705 :{SMALLFONT}{BLACK}Demitir este funcionário STR_1706 :{SMALLFONT}{BLACK}Mover essa pessao para um novo local @@ -1713,22 +1713,22 @@ STR_1707 :Muitos funcionários no jogo STR_1708 :{SMALLFONT}{BLACK}Definir área de patrulha do funcionário STR_1709 :Demitir funcionário STR_1710 :Sim -STR_1711 :{WINDOW_COLOUR_1}Are you sure you want to sack {STRINGID}? +STR_1711 :{WINDOW_COLOUR_1}Tem certeza que quer demitir {STRINGID}? STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Varrer calçadas STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Regar jardins STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Esvaziar lixeiras -STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Cortar Gramas -STR_1716 :Nome invalido para o park -STR_1717 :Impossível renomear o park... +STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Cortar gramas +STR_1716 :Nome inválido para o parque +STR_1717 :Impossível renomear o parque... STR_1718 :Nome do Parque STR_1719 :Digite o nome para o parque: STR_1720 :{SMALLFONT}{BLACK}Nome do parque -STR_1721 :Park fechado -STR_1722 :Park aberto -STR_1723 :Impossível abrir o park... -STR_1724 :Impossível fechar o park... -STR_1725 :Impossível comprar Can't buy região... -STR_1726 :Região não está a venda! +STR_1721 :Parque fechado +STR_1722 :Parque aberto +STR_1723 :Impossível abrir o parque... +STR_1724 :Impossível fechar o parque... +STR_1725 :Impossível comprar região... +STR_1726 :Região não está à venda! STR_1727 :Direitos de construção não está à venda! STR_1728 :Não pode comprar os direitos de construção aqui... STR_1729 :Os terrenos não são propriedade do parque! @@ -1744,42 +1744,42 @@ STR_1738 :Impossível alterar o número de voltas... STR_1739 :Corrida ganha pelo visitante {INT32} STR_1740 :Corrida ganha por {STRINGID} STR_1741 :Ainda não construido ! -STR_1742 :{WINDOW_COLOUR_2}Max. pessoas na atração: +STR_1742 :{WINDOW_COLOUR_2}Máx. pessoas na atração: STR_1743 :{SMALLFONT}{BLACK}Número máximo permitido de pessoas na atração por vez STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1745 :{COMMA16} STR_1746 :Impossível alterar isto... STR_1747 :{WINDOW_COLOUR_2}Tempo limite: -STR_1748 :{SMALLFONT}{BLACK}Time limit for ride +STR_1748 :{SMALLFONT}{BLACK}Tempo limite na atração STR_1749 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{DURATION} 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_1751 :Não é possível mudar o tempo limite na atração... +STR_1752 :{SMALLFONT}{BLACK}Mostrar listas de visitantes individuais no parque +STR_1753 :{SMALLFONT}{BLACK}Mostrar lista resumida de visitantes no parque STR_1754 :{BLACK}{COMMA16} visitantes STR_1755 :{BLACK}{COMMA16} visitante STR_1756 :{WINDOW_COLOUR_2}Preço de entrada: -STR_1757 :{WINDOW_COLOUR_2}Confiabilidade: {MOVE_X}{255}{BLACK}{COMMA16}% +STR_1757 :{WINDOW_COLOUR_2}Confiança: {MOVE_X}{255}{BLACK}{COMMA16}% STR_1758 :{SMALLFONT}{BLACK}Modo de construção STR_1759 :{SMALLFONT}{BLACK}Modo de movimentação -STR_1760 :{SMALLFONT}{BLACK}Modo de Preenchiment +STR_1760 :{SMALLFONT}{BLACK}Modo de Preenchimento STR_1761 :{SMALLFONT}{BLACK}Construir labirinto nessa direção STR_1762 :Cachoeiras STR_1763 :Corredeiras -STR_1764 :Log Bumps -STR_1765 :On-ride photo section -STR_1766 :Reverser turntable -STR_1767 :Spinning tunnel -STR_1768 :Can't change number of swings... -STR_1769 :{WINDOW_COLOUR_2}Number of swings: -STR_1770 :{SMALLFONT}{BLACK}Number of complete swings +STR_1764 :Obstáculo de troncos +STR_1765 :Seção de fotos na atração +STR_1766 :Mesa reversora +STR_1767 :Túnel Giratório +STR_1768 :Não é possível mudar o número de balanços... +STR_1769 :{WINDOW_COLOUR_2}Número de balanços: +STR_1770 :{SMALLFONT}{BLACK}Número de balanços completos STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1772 :{COMMA16} -STR_1773 :Only one on-ride photo section allowed per ride -STR_1774 :Only one cable lift hill allowed per ride +STR_1773 :Somente uma seção de fotos é permitida por atração +STR_1774 :Somente uma subida com cabo de elevação é permitida por atração STR_1775 :Desligado STR_1776 :Ligado -STR_1777 :{WINDOW_COLOUR_2}Música: +STR_1777 :{WINDOW_COLOUR_2}Música da atração STR_1778 :{STRINGID} - - STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Fantasia de panda STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Fantasia de tigre @@ -1795,23 +1795,23 @@ STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Fantasia de pirata STR_1790 :{SMALLFONT}{BLACK}Selecione a cor do uniforme para este tipo de funcionário STR_1791 :{WINDOW_COLOUR_2}Cor do uniforme: STR_1792 :Respondendo a chamada de quebra da {STRINGID} -STR_1793 :Rumo ao {STRINGID} para uma inspecção -STR_1794 :Reparando a {STRINGID} +STR_1793 :Rumo a {STRINGID} para uma inspeção +STR_1794 :Reparando {STRINGID} STR_1795 :Respondendo a chamada do rádio -STR_1796 :Esta quebrado e requer conserto +STR_1796 :Está quebrado e requer conserto STR_1797 :Esta opção não pode ser alterada para esta atração STR_1798 :Turbilhão STR_1799 :{POP16}{POP16}{POP16}{POP16}{POP16}{CURRENCY2DP} STR_1800 :Segurança cortada -STR_1801 :Restrições presas fechadas -STR_1802 :Restrições presas abertas +STR_1801 :Travas presas fechadas +STR_1802 :Travas presas abertas STR_1803 :Portas emperradas fechadas STR_1804 :Portas emperradas abertas -STR_1805 :Veículo em mal funcionamento +STR_1805 :Veículo em mau funcionamento STR_1806 :Falha nos freios STR_1807 :Falha nos controles STR_1808 :{WINDOW_COLOUR_2}Última quebra: {BLACK}{STRINGID} -STR_1809 :{WINDOW_COLOUR_2}Atualmente quebrado: {OUTLINE}{RED}{STRINGID} +STR_1809 :{WINDOW_COLOUR_2}Quebra atual: {OUTLINE}{RED}{STRINGID} STR_1810 :{WINDOW_COLOUR_2}Transportando: STR_1811 :Impossível construir isto aqui... STR_1812 :{SMALLFONT}{BLACK}{STRINGID} @@ -1861,21 +1861,21 @@ STR_1855 :{WINDOW_COLOUR_2}Construído: {BLACK}{COMMA16} Anos atrás STR_1856 :{WINDOW_COLOUR_2}Lucro por item vendido: {BLACK}{CURRENCY2DP} STR_1857 :{WINDOW_COLOUR_2}Prejuízo por item vendido: {BLACK}{CURRENCY2DP} STR_1858 :{WINDOW_COLOUR_2}Custo: {BLACK}{CURRENCY2DP} por mês -STR_1859 :Faz-Tudo +STR_1859 :Faxineiros STR_1860 :Mecânicos STR_1861 :Seguranças STR_1862 :Animadores -STR_1863 :Faz-Tudo +STR_1863 :Faxineiro STR_1864 :Mecânico STR_1865 :Segurança STR_1866 :Animador STR_1867 :{BLACK}{COMMA16} {STRINGID} -STR_1868 :Impossível alterar o numero de rotações... +STR_1868 :Impossível alterar o número de rotações... STR_1869 :{WINDOW_COLOUR_2}Número de rotações: STR_1870 :{SMALLFONT}{BLACK}Número de rotações completas STR_1871 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1872 :{COMMA16} -STR_1873 :{WINDOW_COLOUR_2}Rendimento: {BLACK}{CURRENCY2DP} por hora +STR_1873 :{WINDOW_COLOUR_2}Receita: {BLACK}{CURRENCY2DP} por hora STR_1874 :{WINDOW_COLOUR_2}Lucro: {BLACK}{CURRENCY2DP} por hora STR_1875 :{BLACK} {SPRITE}{BLACK} {STRINGID} STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Inspecionar Atrações @@ -1887,13 +1887,13 @@ STR_1881 :A cada 30 minutos STR_1882 :A cada 45 minutos STR_1883 :A cada hora STR_1884 :A cada 2 horas -STR_1885 :Numca +STR_1885 :Nunca STR_1886 :Inspecionando {STRINGID} STR_1887 :{WINDOW_COLOUR_2}Tempo desde a última inspeção: {BLACK}{COMMA16} minutos STR_1888 :{WINDOW_COLOUR_2}Tempo desde a última inspeção: {BLACK}mais de 4 horas STR_1889 :{WINDOW_COLOUR_2}Tempo ocioso: {MOVE_X}{255}{BLACK}{COMMA16}% -STR_1890 :{SMALLFONT}{BLACK}Selecione a frequência com um mecânico deve verificar esta atração -STR_1891 :No {STRINGID} parque ainda! +STR_1890 :{SMALLFONT}{BLACK}Selecione com qual frequência um mecânico deve verificar esta atração +STR_1891 :Sem {STRINGID} no parque ainda! # The following two strings were used to display an error when the disc was missing. # This has been replaced in OpenRCT2. STR_1892 : @@ -1904,13 +1904,13 @@ STR_1896 :{WINDOW_COLOUR_2}Receitas/Despesas STR_1897 :{WINDOW_COLOUR_2}Construções STR_1898 :{WINDOW_COLOUR_2}Func. das atrações STR_1899 :{WINDOW_COLOUR_2}Compra de terrenos -STR_1900 :{WINDOW_COLOUR_2}Landscaping +STR_1900 :{WINDOW_COLOUR_2}Paisagismo STR_1901 :{WINDOW_COLOUR_2}Entradas no parque STR_1902 :{WINDOW_COLOUR_2}Atrações STR_1903 :{WINDOW_COLOUR_2}Vendas das lojas STR_1904 :{WINDOW_COLOUR_2}Estoque das lojas STR_1905 :{WINDOW_COLOUR_2}Vendas de Comidas -STR_1906 :{WINDOW_COLOUR_2}Estoq. de Comidas +STR_1906 :{WINDOW_COLOUR_2}Estoque de Comidas STR_1907 :{WINDOW_COLOUR_2}Funcionários STR_1908 :{WINDOW_COLOUR_2}Marketing STR_1909 :{WINDOW_COLOUR_2}Pesquisa @@ -1931,65 +1931,65 @@ STR_1923 :{SMALLFONT}{BLACK}Mostrar Tutoriais STR_1924 :{SMALLFONT}{BLACK}Sair STR_1925 :Impossível colocar uma pessoa aqui... STR_1926 :{SMALLFONT} -STR_1927 :{YELLOW}{STRINGID} Quebrou -STR_1928 :{RED}{STRINGID} Bateu! -STR_1929 :{RED}{STRINGID} still hasn't been fixed{NEWLINE}Check where your mechanics are and consider organizing them better -STR_1930 :{SMALLFONT}{BLACK}Turn on/off tracking information for this guest - (If tracking is on, guest's movements will be reported in the message area) +STR_1927 :{YELLOW}{STRINGID} quebrou +STR_1928 :{RED}{STRINGID} bateu! +STR_1929 :{RED}{STRINGID} ainda não foi consertado{NEWLINE}Verifique aonde seus mecânicos estão e considere organizá-los melhor +STR_1930 :{SMALLFONT}{BLACK}Ligar/Desligar informações de rastreamento para este visitante - (Se o rastreamento está ligado, movimentos do visitante serão reportados na área de mensagem) STR_1931 :{STRINGID} entrou na fila de espera para {STRINGID} STR_1932 :{STRINGID} está no {STRINGID} STR_1933 :{STRINGID} esta no {STRINGID} STR_1934 :{STRINGID} saiu do {STRINGID} STR_1935 :{STRINGID} saiu do parque STR_1936 :{STRINGID} comprou {STRINGID} -STR_1937 :{SMALLFONT}{BLACK}Show information about the subject of this message -STR_1938 :{SMALLFONT}{BLACK}Show view of guest -STR_1939 :{SMALLFONT}{BLACK}Show view of staff member -STR_1940 :{SMALLFONT}{BLACK}Show happiness, energy, hunger etc. for this guest -STR_1941 :{SMALLFONT}{BLACK}Show which rides this guest has been on -STR_1942 :{SMALLFONT}{BLACK}Show financial information about this guest -STR_1943 :{SMALLFONT}{BLACK}Show guest's recent thoughts -STR_1944 :{SMALLFONT}{BLACK}Show items guest is carrying -STR_1945 :{SMALLFONT}{BLACK}Show orders and options for this staff member -STR_1946 :{SMALLFONT}{BLACK}Select costume for this entertainer -STR_1947 :{SMALLFONT}{BLACK}Show areas patrolled by selected staff type, and locate the nearest staff member -STR_1948 :{SMALLFONT}{BLACK}Hire a new staff member of the selected type +STR_1937 :{SMALLFONT}{BLACK}Mostrar informação sobre o assunto desta mensagem +STR_1938 :{SMALLFONT}{BLACK}Mostrar visão do visitante +STR_1939 :{SMALLFONT}{BLACK}Mostrar visão do funcionário +STR_1940 :{SMALLFONT}{BLACK}Mostrar felicidade, energia, fome etc. para este visitante +STR_1941 :{SMALLFONT}{BLACK}Mostrar em quais atrações este visitante esteve +STR_1942 :{SMALLFONT}{BLACK}Mostrar infomações financeiras deste visitante +STR_1943 :{SMALLFONT}{BLACK}Mostrar pensamentos recentes do visitante +STR_1944 :{SMALLFONT}{BLACK}Mostrar itens que o visitante está carregando +STR_1945 :{SMALLFONT}{BLACK}Mostrar pedidos e informações para este funcionário +STR_1946 :{SMALLFONT}{BLACK}Selecione fantasia para este animador +STR_1947 :{SMALLFONT}{BLACK}Mostrar áreas patrulhadas pelo tipo de funcionário selecionado, e localizar o funcionário mais próximo +STR_1948 :{SMALLFONT}{BLACK}Contratar novo funcionário do tipo selecionado STR_1949 :Resumo Financeiro STR_1950 :Gráfico Financeiro STR_1951 :Gráfico do Valor do Parque STR_1952 :Gráfico dos Lucros STR_1953 :Marketing STR_1954 :Financiamento de Pesquisa -STR_1955 :{WINDOW_COLOUR_2}Number of circuits: -STR_1956 :{SMALLFONT}{BLACK}Number of circuits of track per ride +STR_1955 :{WINDOW_COLOUR_2}Número de voltas: +STR_1956 :{SMALLFONT}{BLACK}Números de voltas por ingresso STR_1957 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1958 :{COMMA16} -STR_1959 :Can't change number of circuits... -STR_1960 :{WINDOW_COLOUR_2}Balloon price: -STR_1961 :{WINDOW_COLOUR_2}Cuddly Toy price: -STR_1962 :{WINDOW_COLOUR_2}Park Map price: -STR_1963 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_1964 :{WINDOW_COLOUR_2}Umbrella price: -STR_1965 :{WINDOW_COLOUR_2}Drink price: -STR_1966 :{WINDOW_COLOUR_2}Burger price: -STR_1967 :{WINDOW_COLOUR_2}Chips price: -STR_1968 :{WINDOW_COLOUR_2}Ice Cream price: -STR_1969 :{WINDOW_COLOUR_2}Candyfloss price: +STR_1959 :Impossível mudar o número de voltas... +STR_1960 :{WINDOW_COLOUR_2}Preço do balão: +STR_1961 :{WINDOW_COLOUR_2}Preço do brinquedo: +STR_1962 :{WINDOW_COLOUR_2}Preço do mapa do parque: +STR_1963 :{WINDOW_COLOUR_2}Preço da foto na atração: +STR_1964 :{WINDOW_COLOUR_2}Preço do guarda-chuva: +STR_1965 :{WINDOW_COLOUR_2}Preço da bebida: +STR_1966 :{WINDOW_COLOUR_2}Preço do hambúrguer: +STR_1967 :{WINDOW_COLOUR_2}Preço da batata frita: +STR_1968 :{WINDOW_COLOUR_2}Preço do sorvete: +STR_1969 :{WINDOW_COLOUR_2}Preço do algodão-doce: STR_1970 :{WINDOW_COLOUR_2} STR_1971 :{WINDOW_COLOUR_2} STR_1972 :{WINDOW_COLOUR_2} -STR_1973 :{WINDOW_COLOUR_2}Pizza price: +STR_1973 :{WINDOW_COLOUR_2}Preço da pizza: STR_1974 :{WINDOW_COLOUR_2} -STR_1975 :{WINDOW_COLOUR_2}Popcorn price: -STR_1976 :{WINDOW_COLOUR_2}Hot Dog price: -STR_1977 :{WINDOW_COLOUR_2}Tentacle price: -STR_1978 :{WINDOW_COLOUR_2}Hat price: -STR_1979 :{WINDOW_COLOUR_2}Toffee Apple price: -STR_1980 :{WINDOW_COLOUR_2}T-Shirt price: -STR_1981 :{WINDOW_COLOUR_2}Doughnut price: -STR_1982 :{WINDOW_COLOUR_2}Coffee price: +STR_1975 :{WINDOW_COLOUR_2}Preço da pipoca: +STR_1976 :{WINDOW_COLOUR_2}Preço do cachorro-quente: +STR_1977 :{WINDOW_COLOUR_2}Preço do tentáculo: +STR_1978 :{WINDOW_COLOUR_2}Preço do chapéu: +STR_1979 :{WINDOW_COLOUR_2}Preço da maçã do amor: +STR_1980 :{WINDOW_COLOUR_2}Preço da camiseta: +STR_1981 :{WINDOW_COLOUR_2}Preço do donut: +STR_1982 :{WINDOW_COLOUR_2}Preço do café: STR_1983 :{WINDOW_COLOUR_2} -STR_1984 :{WINDOW_COLOUR_2}Fried Chicken price: -STR_1985 :{WINDOW_COLOUR_2}Lemonade price: +STR_1984 :{WINDOW_COLOUR_2}Preço do frango frito: +STR_1985 :{WINDOW_COLOUR_2}Preço da limonada: STR_1986 :{WINDOW_COLOUR_2} STR_1987 :{WINDOW_COLOUR_2} STR_1988 :Balão @@ -2006,12 +2006,12 @@ STR_1998 :Lata Vazia STR_1999 :Lixo STR_2000 :Caixa de Hambúrguer Vazia STR_2001 :Pizza -STR_2002 :Voucher +STR_2002 :Cupom STR_2003 :Pipoca STR_2004 :Cachorro-quente STR_2005 :Tentáculo STR_2006 :Chapéu -STR_2007 :Maça do Amor +STR_2007 :Maçã do Amor STR_2008 :Camiseta STR_2009 :Donut STR_2010 :Café @@ -2034,12 +2034,12 @@ STR_2026 :Latas Vazias STR_2027 :Lixos STR_2028 :Caixas de Hambúrguer Vazias STR_2029 :Pizzas -STR_2030 :Vouchers +STR_2030 :Cupons STR_2031 :Pipocas STR_2032 :Cachorros-quentes STR_2033 :Tentáculos STR_2034 :Chapéus -STR_2035 :Maças do Amor +STR_2035 :Maçãs do Amor STR_2036 :Camisetas STR_2037 :Donuts STR_2038 :Cafés @@ -2057,17 +2057,17 @@ STR_2049 :uma bebida STR_2050 :um hambúrguer STR_2051 :uma batata frita STR_2052 :um sorvete -STR_2053 :algum algodão-Doce +STR_2053 :algum algodão-doce STR_2054 :uma lata vazia STR_2055 :algum lixo STR_2056 :uma caixa de hambúrguer vazia STR_2057 :uma pizza -STR_2058 :um voucher +STR_2058 :um cupom STR_2059 :alguma pipoca STR_2060 :um cachorro-quente STR_2061 :um tentáculo STR_2062 :um chapéu -STR_2063 :uma maça do amor +STR_2063 :uma maçã do amor STR_2064 :uma camiseta STR_2065 :um Donut STR_2066 :um café @@ -2075,7 +2075,7 @@ STR_2067 :um copo vazio STR_2068 :algum frango frito STR_2069 :alguma limonada STR_2070 :uma caixa vazia -STR_2071 :uma garafa vazia +STR_2071 :uma garrafa vazia STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Balão STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Brinquedo de Pelúcia STR_2074 :Mapa de {STRINGID} @@ -2090,12 +2090,12 @@ STR_2082 :Lata Vazia STR_2083 :lixo STR_2084 :Caixa de Hambúrguer Vazia STR_2085 :Pizza -STR_2086 :Voucher para {STRINGID} +STR_2086 :Cupom para {STRINGID} STR_2087 :Pipoca STR_2088 :Cachorro-Quente STR_2089 :Tentáculo STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Chapéu -STR_2091 :Maça do Amor +STR_2091 :Maçã do Amor STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Camiseta STR_2093 :Donut STR_2094 :Café @@ -2104,126 +2104,126 @@ STR_2096 :Frango Frito STR_2097 :Limonada STR_2098 :Caixa Vazia STR_2099 :Garafa Vazia -STR_2100 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2101 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2102 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2103 :{WINDOW_COLOUR_2}Pretzel price: -STR_2104 :{WINDOW_COLOUR_2}Hot Chocolate price: -STR_2105 :{WINDOW_COLOUR_2}Iced Tea price: -STR_2106 :{WINDOW_COLOUR_2}Funnel Cake price: -STR_2107 :{WINDOW_COLOUR_2}Sunglasses price: -STR_2108 :{WINDOW_COLOUR_2}Beef Noodles price: -STR_2109 :{WINDOW_COLOUR_2}Fried Rice Noodles price: -STR_2110 :{WINDOW_COLOUR_2}Wonton Soup price: -STR_2111 :{WINDOW_COLOUR_2}Meatball Soup price: -STR_2112 :{WINDOW_COLOUR_2}Fruit Juice price: -STR_2113 :{WINDOW_COLOUR_2}Soybean Milk price: -STR_2114 :{WINDOW_COLOUR_2}Sujongkwa price: -STR_2115 :{WINDOW_COLOUR_2}Sub Sandwich price: -STR_2116 :{WINDOW_COLOUR_2}Cookie price: +STR_2100 :{WINDOW_COLOUR_2}Preço da foto na atração: +STR_2101 :{WINDOW_COLOUR_2}Preço da foto na atração: +STR_2102 :{WINDOW_COLOUR_2}Preço da foto na atração: +STR_2103 :{WINDOW_COLOUR_2}Preço do pretzel: +STR_2104 :{WINDOW_COLOUR_2}Preço do chocolate quente: +STR_2105 :{WINDOW_COLOUR_2}Preço do chá gelado: +STR_2106 :{WINDOW_COLOUR_2}Preço do bolo: +STR_2107 :{WINDOW_COLOUR_2}Preço dos óculos: +STR_2108 :{WINDOW_COLOUR_2}Preço do macarrão: +STR_2109 :{WINDOW_COLOUR_2}Preço do arroz frito: +STR_2110 :{WINDOW_COLOUR_2}Preço da sopa de wonton: +STR_2111 :{WINDOW_COLOUR_2}Preço da sopa de almôndegas: +STR_2112 :{WINDOW_COLOUR_2}Preço do suco de frutas: +STR_2113 :{WINDOW_COLOUR_2}Preço do leite de soja: +STR_2114 :{WINDOW_COLOUR_2}Preço do sujongkwa: +STR_2115 :{WINDOW_COLOUR_2}Preço do sanduíche: +STR_2116 :{WINDOW_COLOUR_2}Preço do cookie: STR_2117 :{WINDOW_COLOUR_2} STR_2118 :{WINDOW_COLOUR_2} STR_2119 :{WINDOW_COLOUR_2} -STR_2120 :{WINDOW_COLOUR_2}Roast Sausage price: +STR_2120 :{WINDOW_COLOUR_2}Preço da linguiça grelhada: STR_2121 :{WINDOW_COLOUR_2} -STR_2122 :On-Ride Photo -STR_2123 :On-Ride Photo -STR_2124 :On-Ride Photo +STR_2122 :Foto na Atração +STR_2123 :Foto na Atração +STR_2124 :Foto na Atração STR_2125 :Pretzel STR_2126 :Chocolate Quente STR_2127 :Chá Gelado -STR_2128 :Funnel Cake -STR_2129 :Óculos de sol -STR_2130 :Beef Noodles -STR_2131 :Fried Rice Noodles -STR_2132 :Wonton Soup -STR_2133 :Meatball Soup -STR_2134 :Suco de fruta -STR_2135 :Soybean Milk +STR_2128 :Bolo +STR_2129 :Óculos de Sol +STR_2130 :Macarrão +STR_2131 :Arroz Frito +STR_2132 :Sopa de Wonton +STR_2133 :Sopa de Almôndegas +STR_2134 :Suco de frutas +STR_2135 :Leite de Soja STR_2136 :Sujongkwa -STR_2137 :Sub Sandwich +STR_2137 :Sanduíche STR_2138 :Cookie -STR_2139 :Empty Bowl -STR_2140 :Empty Drink Carton -STR_2141 :Empty Juice Cup -STR_2142 :Roast Sausage -STR_2143 :Empty Bowl -STR_2144 :On-Ride Photos -STR_2145 :On-Ride Photos -STR_2146 :On-Ride Photos +STR_2139 :Tigela vazia +STR_2140 :Copo de bebiba vazio +STR_2141 :Copo de suco vazio +STR_2142 :Linguiça Grelhada +STR_2143 :Tigela vazia +STR_2144 :Fotos na Atração +STR_2145 :Fotos na Atração +STR_2146 :Fotos na Atração STR_2147 :Pretzels -STR_2148 :Hot Chocolates +STR_2148 :Chocolates Quente STR_2149 :Chás Gelados -STR_2150 :Funnel Cakes -STR_2151 :Sunglasses -STR_2152 :Beef Noodles -STR_2153 :Fried Rice Noodles -STR_2154 :Wonton Soups -STR_2155 :Meatball Soups -STR_2156 :Fruit Juices -STR_2157 :Soybean Milks +STR_2150 :Bolos +STR_2151 :Óculos de Sol +STR_2152 :Macarrões +STR_2153 :Arrozes Fritos +STR_2154 :Sopas de Wonton +STR_2155 :Sopas de Almôndegas +STR_2156 :Sucos de Frutas +STR_2157 :Leites de Soja STR_2158 :Sujongkwa -STR_2159 :Sub Sandwiches +STR_2159 :Sanduíches STR_2160 :Cookies -STR_2161 :Empty Bowls -STR_2162 :Empty Drink Cartons -STR_2163 :Empty Juice cups -STR_2164 :Roast Sausages -STR_2165 :Empty Bowls -STR_2166 :an On-Ride Photo -STR_2167 :an On-Ride Photo -STR_2168 :an On-Ride Photo -STR_2169 :a Pretzel -STR_2170 :a Hot Chocolate -STR_2171 :an Iced Tea -STR_2172 :a Funnel Cake -STR_2173 :a pair of Sunglasses -STR_2174 :some Beef Noodles -STR_2175 :some Fried Rice Noodles -STR_2176 :some Wonton Soup -STR_2177 :some Meatball Soup -STR_2178 :a Fruit Juice -STR_2179 :some Soybean Milk -STR_2180 :some Sujongkwa -STR_2181 :a Sub Sandwich -STR_2182 :a Cookie -STR_2183 :an Empty Bowl -STR_2184 :an Empty Drink Carton -STR_2185 :an Empty Juice Cup -STR_2186 :a Roast Sausage -STR_2187 :an Empty Bowl -STR_2188 :On-Ride Photo of {STRINGID} -STR_2189 :On-Ride Photo of {STRINGID} -STR_2190 :On-Ride Photo of {STRINGID} +STR_2161 :Tigelas vazias +STR_2162 :Copos de bebida vazios +STR_2163 :Copos de suco vazios +STR_2164 :Linguiças Grelhadas +STR_2165 :Tigelas vazias +STR_2166 :uma Foto na Atração +STR_2167 :uma Foto na Atração +STR_2168 :uma Foto na Atração +STR_2169 :um Pretzel +STR_2170 :um Chocolate Quente +STR_2171 :um Chá Gelado +STR_2172 :um Bolo +STR_2173 :um par de Óculos de Sol +STR_2174 :um pouco de Macarrão +STR_2175 :um pouco de Arroz Frito +STR_2176 :um pouco de Sopa de Wonton +STR_2177 :um pouco de Sopa de Almôndegas +STR_2178 :um Suco de Frutas +STR_2179 :um pouco de Leite de Soja +STR_2180 :um pouco de Sujongkwa +STR_2181 :um Sanduíche +STR_2182 :um Cookie +STR_2183 :uma Tigela Vazia +STR_2184 :um Copo de Bebida Vazio +STR_2185 :um Copo de Suco Vazio +STR_2186 :uma Linguiça Grelhada +STR_2187 :uma Tegela Vazia +STR_2188 :Foto na Atração {STRINGID} +STR_2189 :Foto na Atração {STRINGID} +STR_2190 :Foto na Atração {STRINGID} STR_2191 :Pretzel -STR_2192 :Hot Chocolate -STR_2193 :Iced Tea -STR_2194 :Funnel Cake -STR_2195 :Sunglasses -STR_2196 :Beef Noodles -STR_2197 :Fried Rice Noodles -STR_2198 :Wonton Soup -STR_2199 :Meatball Soup -STR_2200 :Fruit Juice -STR_2201 :Soybean Milk +STR_2192 :Chocolate Quente +STR_2193 :Chá Gelado +STR_2194 :Bolo +STR_2195 :Óculos de Sol +STR_2196 :Macarrão +STR_2197 :Arroz Frito +STR_2198 :Sopa de Wonton +STR_2199 :Sopa de Almôndegas +STR_2200 :Suco de Frutas +STR_2201 :Leite de Soja STR_2202 :Sujongkwa -STR_2203 :Sub Sandwich +STR_2203 :Sanduiche STR_2204 :Cookie -STR_2205 :Empty Bowl -STR_2206 :Empty Drink Carton -STR_2207 :Empty Juice Cup -STR_2208 :Roast Sausage -STR_2209 :Empty Bowl -STR_2210 :{SMALLFONT}{BLACK}Exibir a lista de faz-tudo no parque -STR_2211 :{SMALLFONT}{BLACK}Exibir a lista de mecanicos no parque +STR_2205 :Tigela Vazia +STR_2206 :Copo de Bebida Vazio +STR_2207 :Copo de Suco Vazio +STR_2208 :Linguiça Frita +STR_2209 :Tigela Vazia +STR_2210 :{SMALLFONT}{BLACK}Exibir a lista de faxineiros no parque +STR_2211 :{SMALLFONT}{BLACK}Exibir a lista de mecânicos no parque STR_2212 :{SMALLFONT}{BLACK}Exibir a lista de seguranças no parque STR_2213 :{SMALLFONT}{BLACK}Exibir a lista de animadores no parque -STR_2214 :Construction not possible while game is paused! +STR_2214 :Impossível construir enquanto o jogo está pausado! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F -STR_2218 :{RED}{STRINGID} on {STRINGID} hasn't returned to the {STRINGID} yet!{NEWLINE}Check whether it is stuck or has stalled -STR_2219 :{RED}{COMMA16} people have died in an accident on {STRINGID} +STR_2218 :{RED}{STRINGID} em {STRINGID} não voltou à {STRINGID} ainda!{NEWLINE}Verifique se está preso ou parado +STR_2219 :{RED}{COMMA16} pessoas morreram em um acidente em {STRINGID} STR_2220 :{WINDOW_COLOUR_2}Classificação do Parque: {BLACK}{COMMA16} STR_2221 :{SMALLFONT}{BLACK}Classificação do Parque: {COMMA16} STR_2222 :{SMALLFONT}{BLACK}{STRINGID} @@ -2232,12 +2232,12 @@ STR_2224 :{WINDOW_COLOUR_2}Dinheiro: {BLACK}{CURRENCY2DP} STR_2225 :{WINDOW_COLOUR_2}Dinheiro: {RED}{CURRENCY2DP} STR_2226 :{WINDOW_COLOUR_2}Valor do parque: {BLACK}{CURRENCY} STR_2227 :{WINDOW_COLOUR_2}Valor da empresa: {BLACK}{CURRENCY} -STR_2228 :{WINDOW_COLOUR_2}Last month's profit from food/drink and{NEWLINE}merchandise sales: {BLACK}{CURRENCY} -STR_2229 :Slope up to vertical -STR_2230 :Vertical track -STR_2231 :Holding brake for drop -STR_2232 :Cable lift hill -STR_2233 :{SMALLFONT}{BLACK}Park information +STR_2228 :{WINDOW_COLOUR_2}Lucro do último mês de comida/bebida e{NEWLINE}vendas de mercadoria: {BLACK}{CURRENCY} +STR_2229 :Subir na vertical +STR_2230 :Pista vertical +STR_2231 :Freio que segura para queda +STR_2232 :Cabo de elevação +STR_2233 :{SMALLFONT}{BLACK}Informação do Parque STR_2234 :Mensagens Recentes STR_2235 :{SMALLFONT}{STRINGID} {STRINGID} STR_2236 :Janeiro @@ -2258,7 +2258,7 @@ STR_2250 :{BABYBLUE}Novo Cenário/Tematização disponível agora:{NEWLINE}{S STR_2251 :Somente pode ser construído sobre os caminhos! STR_2252 :Somente pode ser construído através de caminhos! STR_2253 :Atrações de Transporte -STR_2254 :Atrações Suaves/Calmas +STR_2254 :Atrações Tranquilas STR_2255 :Montanhas-Russas STR_2256 :Atrações Emocionantes STR_2257 :Atrações Aquáticas @@ -2283,7 +2283,7 @@ STR_2275 :{SMALLFONT}{BLACK}Mostrar financiamento e opções para pesquisa e STR_2276 :{SMALLFONT}{BLACK}Mostrar estado das pesquisa e desenvolvimentos STR_2277 :Desconhecido STR_2278 :Atrações de Transporte -STR_2279 :Atrações Suaves/Calmas +STR_2279 :Atrações Tranquilas STR_2280 :Montanhas-Russas STR_2281 :Atrações Emocionantes STR_2282 :Atrações Aquáticas @@ -2294,27 +2294,27 @@ STR_2286 :Projetando STR_2287 :Completando Projeto STR_2288 :Desconhecido STR_2289 :{STRINGID} {STRINGID} -STR_2290 :{SMALLFONT}{BLACK}{STRINGID} {STRINGID} +STR_2290 : STR_2291 :Selecione o cenário para novo jogo -STR_2292 :{WINDOW_COLOUR_2}Rides been on: +STR_2292 :{WINDOW_COLOUR_2}Atrações em que esteve: STR_2293 :{BLACK} Nada -STR_2294 :{SMALLFONT}{BLACK}Change base land style -STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land -STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} paid to enter park -STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} ride -STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} rides -STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} item of food -STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} items of food -STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drink -STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drinks -STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenir -STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenirs -STR_2305 :Track design files -STR_2306 :Save track design -STR_2307 :Select {STRINGID} design -STR_2308 :{STRINGID} Track Designs -STR_2309 :Install New Track Design -STR_2310 :Build custom design +STR_2294 :{SMALLFONT}{BLACK}Mudar estilo da base do terreno +STR_2295 :{SMALLFONT}{BLACK}Mudar bordas verticais do terreno +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} pagou para entrar no parque +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} atração +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} atrações +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} item de comida +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} itens de comida +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} bebida +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} bebidas +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} lembrança +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastou em {BLACK}{COMMA16} lembranças +STR_2305 :Arquivos de projetos de pista +STR_2306 :Salvar projeto de pista +STR_2307 :Selecionar projeto de {STRINGID} +STR_2308 :{STRINGID} Projetos de Pista +STR_2309 :Instalar Novo Projeto de Pista +STR_2310 :Construir projeto personalizado STR_2311 :{WINDOW_COLOUR_2}Classificação de emoção: {BLACK}{COMMA2DP32} (approx.) STR_2312 :{WINDOW_COLOUR_2}Classificação de intensidade rating: {BLACK}{COMMA2DP32} (approx.) STR_2313 :{WINDOW_COLOUR_2}Classificação de náuseas: {BLACK}{COMMA2DP32} (approx.) @@ -2325,12 +2325,12 @@ STR_2317 : STR_2318 : STR_2319 : STR_2320 : -STR_2321 :{WINDOW_COLOUR_2}Number of rides/attractions: {BLACK}{COMMA16} +STR_2321 :{WINDOW_COLOUR_2}Número de atrações: {BLACK}{COMMA16} STR_2322 :{WINDOW_COLOUR_2}Funcionário: {BLACK}{COMMA16} -STR_2323 :{WINDOW_COLOUR_2}Park size: {BLACK}{COMMA32}m{SQUARED} -STR_2324 :{WINDOW_COLOUR_2}Park size: {BLACK}{COMMA32}sq.ft. +STR_2323 :{WINDOW_COLOUR_2}Tamanho do parque: {BLACK}{COMMA32}m{SQUARED} +STR_2324 :{WINDOW_COLOUR_2}Tamanho do parque: {BLACK}{COMMA32}sq.ft. STR_2325 :{SMALLFONT}{BLACK}Comprar terreno para extender o parque -STR_2326 :{SMALLFONT}{BLACK}Comprar os direitos de construção para permitir a construção acima ou abaixo da terra fora do parque +STR_2326 :{SMALLFONT}{BLACK}Comprar os direitos de construção para permitir a construção acima ou abaixo do terreno fora do parque STR_2327 :Opções STR_2328 :{WINDOW_COLOUR_2}Moeda: STR_2329 :{WINDOW_COLOUR_2}Distância e Velocidade: @@ -2339,14 +2339,14 @@ STR_2331 :{WINDOW_COLOUR_2}Marcadores Altura: STR_2332 :Unidades STR_2333 :Som STR_2334 :Libras ({POUND}) -STR_2335 :Dolar ($) +STR_2335 :Dólar ($) STR_2336 :Franco (F) -STR_2337 :Deutschmark (DM) +STR_2337 :Marco Alemão(DM) STR_2338 :Yen ({YEN}) STR_2339 :Peseta (Pts) STR_2340 :Lira (L) -STR_2341 :Guilders (fl.) -STR_2342 :Krona (kr) +STR_2341 :Florim Neerlandês (fl.) +STR_2342 :Coroa Sueca(kr) STR_2343 :Euros ({EURO}) STR_2344 :Imperial STR_2345 :Métrica @@ -2364,12 +2364,12 @@ STR_2356 :{WINDOW_COLOUR_2}Atrações Inspecionadas: {BLACK}{COMMA16} STR_2357 :Casa STR_2358 :Unidades STR_2359 :Valores Reais -STR_2360 :{WINDOW_COLOUR_2}Resolução de Tela: -STR_2361 :Landscape Smoothing -STR_2362 :{SMALLFONT}{BLACK}Toggle landscape tile edge smoothing on/off -STR_2363 :Gridlines on Landscape -STR_2364 :{SMALLFONT}{BLACK}Toggle gridlines on landscape on/off -STR_2365 :The bank refuses to increase your loan! +STR_2360 :Resolução de Tela: +STR_2361 :Suavizar Terreno +STR_2362 :{SMALLFONT}{BLACK}Liga/Desliga suavização do azulejo do terreno +STR_2363 :Grades no terreno +STR_2364 :{SMALLFONT}{BLACK}Liga/Desliga grades no terreno +STR_2365 :O banco se recusa a aumentar seu empréstimo! STR_2366 :Celsius ({DEGREE}C) STR_2367 :Fahrenheit ({DEGREE}F) STR_2368 :Nenhum @@ -2382,37 +2382,37 @@ STR_2374 :Alto STR_2375 :Muito alto STR_2376 :Extremo STR_2377 :Ultra Extremo -STR_2378 :{SMALLFONT}{BLACK}Adjust smaller area of land -STR_2379 :{SMALLFONT}{BLACK}Adjust larger area of land -STR_2380 :{SMALLFONT}{BLACK}Adjust smaller area of water -STR_2381 :{SMALLFONT}{BLACK}Adjust larger area of water -STR_2382 :Terra +STR_2378 :{SMALLFONT}{BLACK}Ajusta uma área menor de terreno +STR_2379 :{SMALLFONT}{BLACK}Ajusta uma área maior de terreno +STR_2380 :{SMALLFONT}{BLACK}Ajusta uma área menor de água +STR_2381 :{SMALLFONT}{BLACK}Ajusta uma área maior de água +STR_2382 :Terreno STR_2383 :Água STR_2384 :{WINDOW_COLOUR_2}Seu objetivo: STR_2385 :{BLACK}Nenhum -STR_2386 :{BLACK}To have at least {COMMA16} guests in your park at the end of {MONTHYEAR}, with a park rating of at least 600 -STR_2387 :{BLACK}To achieve a park value of at least {POP16}{POP16}{CURRENCY} at the end of {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} -STR_2388 :{BLACK}Have Fun! -STR_2389 :{BLACK}Build the best {STRINGID} you can! -STR_2390 :{BLACK}To have 10 different types of roller coasters operating in your park, each with an excitement value of at least 6.00 -STR_2391 :{BLACK}To have at least {COMMA16} guests in your park. You must not let the park rating drop below 700 at any time! -STR_2392 :{BLACK}To achieve a monthly income from ride tickets of at least {POP16}{POP16}{CURRENCY} -STR_2393 :{BLACK}To have 10 different types of roller coasters operating in your park, each with a minimum length of {LENGTH}, and an excitement rating of at least 7.00 -STR_2394 :{BLACK}To finish building all 5 of the partially built roller coasters in this park, designing them to achieve excitement ratings of at least {POP16}{POP16}{COMMA2DP32} each -STR_2395 :{BLACK}To repay your loan and achieve a park value of at least {POP16}{POP16}{CURRENCY} -STR_2396 :{BLACK}To achieve a monthly profit from food, drink and merchandise sales of at least {POP16}{POP16}{CURRENCY} +STR_2386 :{BLACK}Ter pelo menos {COMMA16} visitantes em seu parque até o fim de {MONTHYEAR}, com classificação de parque de pelo menos 600 +STR_2387 :{BLACK}Alcançar um valor do parque de pelo menos {POP16}{POP16}{CURRENCY} até o fim de {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} +STR_2388 :{BLACK}Divirta-se! +STR_2389 :{BLACK}Construir o melhor {STRINGID} que puder! +STR_2390 :{BLACK}Ter 10 tipos de montanha-russa diferentes operando em seu parque, cada uma com um valor de emoção de pelo menos 6.00 +STR_2391 :{BLACK}Ter pelo menos {COMMA16} visitantes em seu parque. Você não pode deixar a classificação de parque abaixo de 700 em momento algum! +STR_2392 :{BLACK}Alcançar uma receita mensal de ingressos de atrações de pelo menos {POP16}{POP16}{CURRENCY} +STR_2393 :{BLACK}Ter 10 tipos de montanha-russa diferentes operando em seu parque, cada uma com um comprimento mínimo de {LENGTH}, e um valor de emoção de no mínimo 7.00 +STR_2394 :{BLACK}Terminar de construir todas as 5 montanhas-russas parcialmente construídas neste parque, projetando-as para alcançar um valor de emoção de pelo menos {POP16}{POP16}{COMMA2DP32} cada +STR_2395 :{BLACK}Pagar o empréstimo e alcançar um valor do parque de pelo menos {POP16}{POP16}{CURRENCY} +STR_2396 :{BLACK}Alcançar um lucro mensal de comida, bebida e vendas de mercadorias de pelo menos {POP16}{POP16}{CURRENCY} STR_2397 :Nenhum -STR_2398 :Number of guests at a given date -STR_2399 :Park value at a given date -STR_2400 :Have fun -STR_2401 :Build the best ride you can -STR_2402 :Build 10 roller coasters -STR_2403 :Number of guests in park -STR_2404 :Monthly income from ride tickets -STR_2405 :Build 10 roller coasters of a given length -STR_2406 :Finish building 5 roller coasters -STR_2407 :Repay loan and achieve a given park value -STR_2408 :Monthly profit from food/merchandise +STR_2398 :Número de visitantes numa data estabelecida +STR_2399 :Valor do parque numa data estabelecida +STR_2400 :Divirta-se +STR_2401 :Construa a melhor atração que puder +STR_2402 :Construa 10 montanhas-russas +STR_2403 :Número de visitantes no parque +STR_2404 :Receita mensal de ingressos de atrações +STR_2405 :Construa 10 montanhas-russas com um comprimento estebelecido +STR_2406 :Termine de construir 5 montanhas-russas +STR_2407 :Pague o empréstimo e alcance um valor do parque estebelecido +STR_2408 :Lucro mensal de comida/mercadoria STR_2409 :{WINDOW_COLOUR_2}Campanhas de marketing em operação STR_2410 :{BLACK}Nenhum STR_2411 :{WINDOW_COLOUR_2}Campanhas de marketing disponíveis @@ -2428,16 +2428,16 @@ STR_2420 :Meia-entrada para {STRINGID} STR_2421 :Gratuito {STRINGID} STR_2422 :Campanha publicitária para {STRINGID} STR_2423 :Campanha publicitária para {STRINGID} -STR_2424 :{WINDOW_COLOUR_2}Cupões para entrada gratuita no parque -STR_2425 :{WINDOW_COLOUR_2}Cupões para entrada gratuitas em atrações em especial -STR_2426 :{WINDOW_COLOUR_2}Cupões para meia-entrada para o parque -STR_2427 :{WINDOW_COLOUR_2}Cupões para comida ou bebida de graça +STR_2424 :{WINDOW_COLOUR_2}Cupons de entrada gratuita no parque +STR_2425 :{WINDOW_COLOUR_2}Cupons de entrada gratuita em uma atração em especial +STR_2426 :{WINDOW_COLOUR_2}Cupons de meia-entrada para o parque +STR_2427 :{WINDOW_COLOUR_2}Cupons de comida ou bebida gratuita STR_2428 :{WINDOW_COLOUR_2}Campanha publicitária para o parque STR_2429 :{WINDOW_COLOUR_2}Campanha publicitária para uma atração em especial -STR_2430 :{BLACK}Cupões de entrada gratuita para {STRINGID} -STR_2431 :{BLACK}Cupões para entrada gratuita na atração {STRINGID} -STR_2432 :{BLACK}Cupões de meia-entrada para {STRINGID} -STR_2433 :{BLACK}Cupões de graça{STRINGID} +STR_2430 :{BLACK}Cupons de entrada gratuita para {STRINGID} +STR_2431 :{BLACK}Cupons de entrada gratuita na atração {STRINGID} +STR_2432 :{BLACK}Cupons de meia-entrada para {STRINGID} +STR_2433 :{BLACK}Cupons de {STRINGID} grátis STR_2434 :{BLACK}Campanha publicitária para {STRINGID} STR_2435 :{BLACK}Campanha publicitária para {STRINGID} STR_2436 :1 semana @@ -2450,12 +2450,12 @@ STR_2442 : STR_2443 :{WINDOW_COLOUR_2}Custo por semana: {BLACK}{CURRENCY2DP} STR_2444 :{WINDOW_COLOUR_2}Custo total: {BLACK}{CURRENCY2DP} STR_2445 :Comece esta campanha de marketing -STR_2446 :{YELLOW}Your marketing campaign for free entry to the park has finished -STR_2447 :{YELLOW}Your marketing campaign for free rides on {STRINGID} has finished -STR_2448 :{YELLOW}Your marketing campaign for half-price entry to the park has finished -STR_2449 :{YELLOW}Your marketing campaign for free {STRINGID} has finished -STR_2450 :{YELLOW}Your advertising campaign for the park has finished -STR_2451 :{YELLOW}Your advertising campaign for {STRINGID} has finished +STR_2446 :{YELLOW}Sua campanha de marketing para entrada gratuita no parque terminou +STR_2447 :{YELLOW}Sua campanha de marketing para entrada gratuita em {STRINGID} terminou +STR_2448 :{YELLOW}Sua campanha de marketing para meia-entrada para o parque terminou +STR_2449 :{YELLOW}Sua campanha de marketing para {STRINGID} grátis terminou +STR_2450 :{YELLOW}Sua campanha publicitária para o parque terminou +STR_2451 :{YELLOW}Sua campanha publicitária para {STRINGID} terminou STR_2452 :{WINDOW_COLOUR_2}Dinheiro (menos empréstimo): {BLACK}{CURRENCY2DP} STR_2453 :{WINDOW_COLOUR_2}Dinheiro (menos empréstimo): {RED}{CURRENCY2DP} STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - @@ -2475,60 +2475,60 @@ STR_2467 :{SMALLFONT}{BLACK}Mostrar objetivos para este jogo STR_2468 :{SMALLFONT}{BLACK}Mostrar prêmios recentes que este parque recebeu STR_2469 :{SMALLFONT}{BLACK}Escolha um nível de pesquisa e desenvolvimento STR_2470 :{SMALLFONT}{BLACK}Pesquisar novas atrações de transporte -STR_2471 :{SMALLFONT}{BLACK}Pesquisar novas atrações Suaves/Calmas +STR_2471 :{SMALLFONT}{BLACK}Pesquisar novas atrações tranquilas STR_2472 :{SMALLFONT}{BLACK}Pesquisar novas montanhas-russas STR_2473 :{SMALLFONT}{BLACK}Pesquisar novas atrações emocionantes STR_2474 :{SMALLFONT}{BLACK}Pesquisar novas atrações aquáticas STR_2475 :{SMALLFONT}{BLACK}Pesquisar novas lojas e barracas STR_2476 :{SMALLFONT}{BLACK}Pesquisar novos cenários e tematizações STR_2477 :{SMALLFONT}{BLACK}Selecione o modo de operação para esta atração -STR_2478 :{SMALLFONT}{BLACK}Show graph of velocity against time -STR_2479 :{SMALLFONT}{BLACK}Show graph of altitude against time -STR_2480 :{SMALLFONT}{BLACK}Show graph of vertical acceleration against time -STR_2481 :{SMALLFONT}{BLACK}Show graph of lateral acceleration against time -STR_2482 :{SMALLFONT}{BLACK}Profit: {CURRENCY} per week, Park Value: {CURRENCY} +STR_2478 :{SMALLFONT}{BLACK}Mostrar gráfico de Velocidade X Tempo +STR_2479 :{SMALLFONT}{BLACK}Mostrar gráfico de Altitude X Tempo +STR_2480 :{SMALLFONT}{BLACK}Mostrar gráfico de Aceleração Vertical X Tempo +STR_2481 :{SMALLFONT}{BLACK}Mostrar gráfico de Aceleração Lateral X Tempo +STR_2482 :{SMALLFONT}{BLACK}Lucro: {CURRENCY} por semana, Valor do Parque: {CURRENCY} STR_2483 :{WINDOW_COLOUR_2}Lucro semanal: {BLACK}+{CURRENCY2DP} STR_2484 :{WINDOW_COLOUR_2}Lucro semanal: {RED}{CURRENCY2DP} STR_2485 :Controles STR_2486 :Geral STR_2487 :Exibir nomes 'reais' para os visitantes -STR_2488 :{SMALLFONT}{BLACK}Alternar entre exibir nomes 'reais' para os visitantes e numeros de visitantes +STR_2488 :{SMALLFONT}{BLACK}Alternar entre exibir nomes 'reais' para os visitantes e números de visitantes STR_2489 :Teclas de atalho... STR_2490 :Atalhos do teclado STR_2491 :Redefinir teclas STR_2492 :{SMALLFONT}{BLACK}Redefinir todos os atalhos de teclado para as configurações padrão -STR_2493 :Close top-most window -STR_2494 :Close all floating windows -STR_2495 :Cancel construction mode -STR_2496 :Pause game -STR_2497 :Zoom view out -STR_2498 :Zoom view in -STR_2499 :Rotate view clockwise -STR_2500 :Rotate construction object -STR_2501 :Underground view toggle -STR_2502 :Remove base land toggle -STR_2503 :Remove vertical land toggle -STR_2504 :See-through rides toggle -STR_2505 :See-through scenery toggle -STR_2506 :Invisible supports toggle -STR_2507 :Invisible people toggle -STR_2508 :Height marks on land toggle -STR_2509 :Height marks on ride tracks toggle -STR_2510 :Height marks on paths toggle -STR_2511 :Adjust land -STR_2512 :Adjust water -STR_2513 :Build scenery -STR_2514 :Build paths -STR_2515 :Build new ride -STR_2516 :Show financial information -STR_2517 :Show research information -STR_2518 :Show rides list -STR_2519 :Show park information -STR_2520 :Show guest list -STR_2521 :Show staff list -STR_2522 :Show recent messages -STR_2523 :Show map -STR_2524 :Screenshot +STR_2493 :Fechar janela do topo +STR_2494 :Fechar todas as janelas +STR_2495 :Cancelar modo construção +STR_2496 :Pausar jogo +STR_2497 :Afastar vista +STR_2498 :Aproximar vista +STR_2499 :Rotacionar vista no sentido horário +STR_2500 :Rotacionar objeto de construção +STR_2501 :Vista subterrânea +STR_2502 :Terreno base invisível +STR_2503 :Terreno vertical invisível +STR_2504 :Brinquedos invisíveis +STR_2505 :Cenários invisíveis +STR_2506 :Suportes invisíveis +STR_2507 :Pessoas invisíveis +STR_2508 :Marcas de altura no terreno +STR_2509 :Marcas de altura nos trilhos +STR_2510 :Marcas de altura nos caminhos +STR_2511 :Ajustar terreno +STR_2512 :Ajustar água +STR_2513 :Construir cenário +STR_2514 :Construir caminhos +STR_2515 :Construir nova atração +STR_2516 :Mostrar informações financeiras +STR_2517 :Mostrar informações de pesquisa +STR_2518 :Mostrar lista de atrações +STR_2519 :Mostrar informação do parque +STR_2520 :Mostrar lista de visitantes +STR_2521 :Mostrar lista de funcionários +STR_2522 :Mostrar mensagens recentes +STR_2523 :Mostrar mapa +STR_2524 :Captura de tela ### The following need to be reordered to match SDL_keycode layout. STR_2525 :??? STR_2526 :??? @@ -2685,11 +2685,11 @@ STR_2676 :??? STR_2677 :??? STR_2678 :??? STR_2679 :??? -STR_2680 :All research complete -STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} +STR_2680 :Todas as pesquisas completas +STR_2681 :{MEDIUMFONT}{BLACK}Incrementa seu dinheiro em {CURRENCY} STR_2682 : STR_2683 : -STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive +STR_2684 :{SMALLFONT}{BLACK}Um grande grupo de visitantes está chegando STR_2685 :Parâmetros de ruído simples STR_2686 :{WINDOW_COLOUR_2}Baixo: STR_2687 :{WINDOW_COLOUR_2}Alto: @@ -2712,7 +2712,7 @@ STR_2703 :A cada 15 minutos STR_2704 :A cada 30 minutos STR_2705 :A cada hora STR_2706 :Nunca -STR_2707 :Abrir nova janela +STR_2707 :Usar janela do sistema operacional STR_2708 :{WINDOW_COLOUR_1}Você tem certeza que quer sobrescrever {STRINGID}? STR_2709 :Sobrescrever STR_2710 :Tipo de nome para o arquivo. @@ -2723,8 +2723,8 @@ STR_2714 :- STR_2715 :. STR_2716 :/ STR_2717 :' -STR_2718 :(cima) -STR_2719 :(novo arquivo) +STR_2718 :Voltar Pasta +STR_2719 :Novo Arquivo STR_2720 :{UINT16}seg STR_2721 :{UINT16}segs STR_2722 :{UINT16}min:{UINT16}seg @@ -2743,7 +2743,7 @@ STR_2734 :{COMMA16}mph STR_2735 :{COMMA16}km/h STR_2736 :{MONTH}, Ano {COMMA16} STR_2737 :{STRINGID} {MONTH}, Ano {COMMA16} -STR_2738 :Musíca da tela de início +STR_2738 :Música da tela de início STR_2739 :Nenhum STR_2740 :RollerCoaster Tycoon 1 STR_2741 :RollerCoaster Tycoon 2 @@ -2763,9 +2763,9 @@ STR_2753 :Cortar grama STR_2754 :Regar plantas STR_2755 :Consertar vandalismo STR_2756 :Remover vomitos -STR_2757 :Forçar Sol -STR_2758 :Forçar Chuva -STR_2759 :Zero Clearance +STR_2757 : +STR_2758 : +STR_2759 :Apuramento Zero STR_2760 :+{CURRENCY} STR_2761 : STR_2762 : @@ -2781,71 +2781,71 @@ STR_2771 :Velocidade de Jogo mais lento STR_2772 :Velocidade de Jogo mais rápido STR_2773 :Janela STR_2774 :Tela Inteira -STR_2775 :Tela Inteira (área de trabalho) -STR_2776 :Linguagem +STR_2775 :Tela Inteira (janela sem borda) +STR_2776 :Idioma STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} -STR_2779 :Viewport #{COMMA16} -STR_2780 :Extra viewport +STR_2779 :Janela de Exibição #{COMMA16} +STR_2780 :Janela de Exibição Grande # End of new strings STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} STR_2782 :SHIFT + STR_2783 :CTRL + STR_2784 :Mudar atalho do teclado -STR_2785 :{WINDOW_COLOUR_2}Press new shortcut key for:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} -STR_2786 :{SMALLFONT}{BLACK}Click on shortcut description to select new key +STR_2785 :{WINDOW_COLOUR_2}Pressione uma nova tecla de atalho para:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2786 :{SMALLFONT}{BLACK}Clique na descrição do atalho para selecionar uma nova tecla STR_2787 :{WINDOW_COLOUR_2}Valor do parque: {BLACK}{CURRENCY} STR_2788 :{WINDOW_COLOUR_2}Parabéns !{NEWLINE}{BLACK}Você alcançou seu objetivo com o valor da empresa de {CURRENCY} ! STR_2789 :{WINDOW_COLOUR_2}Você falhou no seu objetivo ! -STR_2790 :Digite o nome do gráfico do cenário -STR_2791 :Digite o nome -STR_2792 :Por favor, insira o seu nome para o gráfico do cenário: +STR_2790 :Inserir nome na lista de cenário +STR_2791 :Inserir nome +STR_2792 :Por favor, insira o seu nome {NEWLINE}para a lista de cenário: STR_2793 :{SMALLFONT}(Completado por {STRINGID}) -STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY} -STR_2795 :Sort -STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed +STR_2794 :{WINDOW_COLOUR_2}Completado por: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} com o valor da empresa de: {BLACK}{CURRENCY} +STR_2795 :Organizar +STR_2796 :{SMALLFONT}{BLACK}Organiza lista de atrações usando o tipo de informação exibida STR_2797 :Move a tela quando o ponteiro estiver na borda da tela STR_2798 :{SMALLFONT}{BLACK}Selecione se deseja mover a tela quando o ponteiro do mouse estiver na borda da tela -STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments -STR_2800 :{WINDOW_COLOUR_2}Total admissions: {BLACK}{COMMA32} -STR_2801 :{WINDOW_COLOUR_2}Income from admissions: {BLACK}{CURRENCY2DP} +STR_2799 :{SMALLFONT}{BLACK}Visualiza ou muda atribuições de teclas de controle +STR_2800 :{WINDOW_COLOUR_2}Total de ingressos: {BLACK}{COMMA32} +STR_2801 :{WINDOW_COLOUR_2}Receita dos ingressos: {BLACK}{CURRENCY2DP} STR_2802 :Mapa -STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map -STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map +STR_2803 :{SMALLFONT}{BLACK}Mostrar estes visitantes destacadoss no mapa +STR_2804 :{SMALLFONT}{BLACK}Mostrar estes funcionários destacados no mapa STR_2805 :{SMALLFONT}{BLACK}Exibir o mapa do parque -STR_2806 :{RED}Guests are complaining about the disgusting state of the paths in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2807 :{RED}Guests are complaining about the amount of litter in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2808 :{RED}Guests are complaining about the vandalism in your park{NEWLINE}Check where your security guards are and consider organising them better -STR_2809 :{RED}Guests are hungry and can't find anywhere to buy food -STR_2810 :{RED}Guests are thirsty and can't find anywhere to buy drinks -STR_2811 :{RED}Guests are complaining because they can't find the toilets in your park -STR_2812 :{RED}Guests are getting lost or stuck{NEWLINE}Check whether the layout of your footpaths needs improving to help the guests find their way around -STR_2813 :{RED}Your park entrance fee is too high!{NEWLINE}Reduce your entrance fee or improve the value of the park to attract more guests -STR_2814 :{WINDOW_COLOUR_2}O maior prêmio de parque desarrumado -STR_2815 :{WINDOW_COLOUR_2}O maior prêmio de parque arrumado +STR_2806 :{RED}Os visitantes estão reclamando sobre o estado nojento dos caminhos de seu parque{NEWLINE}Verifique aonde seus faxineiros estão e considere organizá-los melhor +STR_2807 :{RED}Os visitantes estão reclamando sobre a quatidade de lixo em seu parque{NEWLINE}Verifique aonde seus faxineiros estão e considere organizá-los melhor +STR_2808 :{RED}Os visitantes estão reclamando sobre o vandalismo em seu parque{NEWLINE}Verifique aonde seus seguranças estão e considere organizá-los melhor +STR_2809 :{RED}Os visitantes estão com fome e não conseguem encontrar nenhum lugar para comprar comida +STR_2810 :{RED}Os visitantes estão com sede e não conseguem encontrar nenhum lugar para combrar bebidas +STR_2811 :{RED}Os visitantes estão reclamando porque não conseguem encontrar banheiros em seu parque +STR_2812 :{RED}Os visitantes estão ficando perdidos ou presos{NEWLINE}Verifique se o traçado de suas calçadas precisam melhorar para ajudar os visitantes a encontrarem seu rumo +STR_2813 :{RED}O preço do ingresso do parque está muito caro!{NEWLINE}Diminua ou melhore o valor do parque para atrair mais visitantes +STR_2814 :{WINDOW_COLOUR_2}Prêmio de parque mais desarrumado +STR_2815 :{WINDOW_COLOUR_2}Prêmio de parque mais arrumado STR_2816 :{WINDOW_COLOUR_2}Prêmio para o parque com as melhores montanhas-russas -STR_2817 :{WINDOW_COLOUR_2}Prêmio do parque com melhor valor -STR_2818 :{WINDOW_COLOUR_2}Prêmio do mais belo parque -STR_2819 :{WINDOW_COLOUR_2}Prêmio do parque com pior valor -STR_2820 :{WINDOW_COLOUR_2}Prêmio do parque mais seguro -STR_2821 :{WINDOW_COLOUR_2}Prêmio da melhor equipe -STR_2822 :{WINDOW_COLOUR_2}Prêmio da melhor comida de parque -STR_2823 :{WINDOW_COLOUR_2}Prêmio da pior comida de parque -STR_2824 :{WINDOW_COLOUR_2}Prêmio dos melhores banheiro de parque -STR_2825 :{WINDOW_COLOUR_2}Prêmio do parque mais decepcionante -STR_2826 :{WINDOW_COLOUR_2}Prêmio das melhores atrações aquáticas -STR_2827 :{WINDOW_COLOUR_2}Prêmio das melhores atrações customizadas -STR_2828 :{WINDOW_COLOUR_2}Prêmio do mais deslumbrante esquema de cor da atração -STR_2829 :{WINDOW_COLOUR_2}Prêmio do formato do parque mais confuso -STR_2830 :{WINDOW_COLOUR_2}Prêmio das melhores atrações suaves/calmas +STR_2817 :{WINDOW_COLOUR_2}Prêmio de parque com melhor valor +STR_2818 :{WINDOW_COLOUR_2}Prêmio de parque mais bonito +STR_2819 :{WINDOW_COLOUR_2}Prêmio de parque com pior valor +STR_2820 :{WINDOW_COLOUR_2}Prêmio de parque mais seguro +STR_2821 :{WINDOW_COLOUR_2}Prêmio de melhores funcionários +STR_2822 :{WINDOW_COLOUR_2}Prêmio de melhor comida de parque +STR_2823 :{WINDOW_COLOUR_2}Prêmio de pior comida de parque +STR_2824 :{WINDOW_COLOUR_2}Prêmio de melhores banheiros de parque +STR_2825 :{WINDOW_COLOUR_2}Prêmio de parque mais decepcionante +STR_2826 :{WINDOW_COLOUR_2}Prêmio de melhores atrações aquáticas +STR_2827 :{WINDOW_COLOUR_2}Prêmio de melhores atrações personalizadas +STR_2828 :{WINDOW_COLOUR_2}Prêmio de atração com esquema de cor mais deslumbrante +STR_2829 :{WINDOW_COLOUR_2}Prêmio de parque com traçado mais confuso +STR_2830 :{WINDOW_COLOUR_2}Prêmio de melhores atrações tranquilas STR_2831 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque mais desarrumado do país'! STR_2832 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque mais arrumado do país'! STR_2833 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com as melhores montanhas-russas'! STR_2834 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com o melhor valor do país "! -STR_2835 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O mais belo parque do país'! +STR_2835 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque mais bonito do país'! STR_2836 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com o pior valor do país'! STR_2837 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque mais seguro do país'! -STR_2838 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com a melhor equipe'! +STR_2838 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com os melhores funcionários'! STR_2839 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com a melhor comida do país'! STR_2840 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com a pior comida do país'! STR_2841 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com as melhores instalações sanitárias do país'! @@ -2853,91 +2853,91 @@ STR_2842 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque mais decepci STR_2843 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com as melhores atrações aquáticas do país'! STR_2844 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com as melhores atrações customizadas'! STR_2845 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com a escolha de esquemas de cores mais deslumbrante'! -STR_2846 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com o formato mais confuso'! -STR_2847 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com as melhores atrações suaves/calmas'! +STR_2846 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com o traçado mais confuso'! +STR_2847 :{TOPAZ}Seu parque recebeu um prêmio por ser 'O parque com as melhores atrações tranquilas'! STR_2848 :{WINDOW_COLOUR_2}Não há prêmios recentes -STR_2849 :New scenario installed successfully -STR_2850 :New track design installed successfully -STR_2851 :Scenario already installed -STR_2852 :Track design already installed -STR_2853 :Forbidden by the local authority! -STR_2854 :{RED}Guests can't get to the entrance of {STRINGID} !{NEWLINE}Construct a path to the entrance -STR_2855 :{RED}{STRINGID} has no path leading from its exit !{NEWLINE}Construct a path from the ride exit +STR_2849 :Novo cenário instalado com sucesso +STR_2850 :Novo projeto de pista instalado com sucesso +STR_2851 :Cenário já instalado +STR_2852 :Projeto de pista já instalado +STR_2853 :Proibido por autoridades locais! +STR_2854 :{RED}Os visitantes não conseguem entrar em {STRINGID} !{NEWLINE}Construa um caminho para a entrada +STR_2855 :{RED}{STRINGID} não tem um caminho de saída !{NEWLINE}Construa um caminho a partir da saída da atração STR_2856 :{WINDOW_COLOUR_2}Tutorial -STR_2857 :{WINDOW_COLOUR_2}(Press a key or mouse button to take control) +STR_2857 :{WINDOW_COLOUR_2}(Pressione uma tecla ou botão do mouse para controlar) STR_2858 :Impossível começar uma campanha de marketing... -STR_2859 :Another instance of OpenRCT2 is already running -STR_2860 :Infogrames Interactive credits... -STR_2861 :{WINDOW_COLOUR_2}Licensed to Infogrames Interactive Inc. -STR_2862 :Music acknowledgements... -STR_2863 :Music acknowledgements -STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) non copyright +STR_2859 :Um outro exemplar de OpenRCT2 já está executando +STR_2860 :Créditos de Infogrames Interactive... +STR_2861 :{WINDOW_COLOUR_2}Licenciado para Infogrames Interactive Inc. +STR_2862 :Reconhecimentos de música... +STR_2863 :Reconhecimentos de música +STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) sem direitos autorais STR_2865 :{WINDOW_COLOUR_2}Heyken's Serenade: (J.Heyken) British Standard Music Coy; GEMA, BRITICO -STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Composer unknown) Copyright Control +STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Composer unknown) Controle de Direitos Autorais STR_2867 :{WINDOW_COLOUR_2}Wedding Journey: (Traditional) -STR_2868 :{WINDOW_COLOUR_2}Tales from the Vienna Woods: (Johann Strauss) non copyright +STR_2868 :{WINDOW_COLOUR_2}Tales from the Vienna Woods: (Johann Strauss) sem direitos autorais STR_2869 :{WINDOW_COLOUR_2}Slavonic Dance: (Traditional) STR_2870 :{WINDOW_COLOUR_2}Das Alpenhorn: (Traditional) STR_2871 :{WINDOW_COLOUR_2}The Blond Sailor: (Traditional) -STR_2872 :{WINDOW_COLOUR_2}Overture - Poet and Peasant: (Suppe) non copyright -STR_2873 :{WINDOW_COLOUR_2}Waltz Medley: (Johann Strauss) non copyright +STR_2872 :{WINDOW_COLOUR_2}Overture - Poet and Peasant: (Suppe) sem direitos autorais +STR_2873 :{WINDOW_COLOUR_2}Waltz Medley: (Johann Strauss) sem direitos autorais STR_2874 :{WINDOW_COLOUR_2}Bella Bella Bimba: (Traditional) -STR_2875 :{WINDOW_COLOUR_2}Original recordings (P) 1976 C.J.Mears Organization, used with consent -STR_2876 :{WINDOW_COLOUR_2}RollerCoaster Tycoon 2 Title Music: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2877 :{WINDOW_COLOUR_2}Dodgems Beat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2878 :{WINDOW_COLOUR_2}Mid Summer's Heat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2879 :{WINDOW_COLOUR_2}Pharaoh's Tomb: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2880 :{WINDOW_COLOUR_2}Caesar's March: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2881 :{WINDOW_COLOUR_2}Drifting To Heaven: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2882 :{WINDOW_COLOUR_2}Invaders: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2883 :{WINDOW_COLOUR_2}Eternal Toybox: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2884 :{WINDOW_COLOUR_2}Jungle Juice: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2885 :{WINDOW_COLOUR_2}Ninja's Noodles: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2886 :{WINDOW_COLOUR_2}Voyage to Andromeda: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2887 :{WINDOW_COLOUR_2}Brimble's Beat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2888 :{WINDOW_COLOUR_2}Atlantis: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2889 :{WINDOW_COLOUR_2}Wild West Kid: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2890 :{WINDOW_COLOUR_2}Vampire's Lair: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2891 :{WINDOW_COLOUR_2}Blockbuster: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2892 :{WINDOW_COLOUR_2}Airtime Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2893 :{WINDOW_COLOUR_2}Searchlight Rag: (Scott Joplin/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2894 :{WINDOW_COLOUR_2}Flight of Fantasy: (Steve Blenkinsopp) copyright {COPYRIGHT} Chris Sawyer -STR_2895 :{WINDOW_COLOUR_2}Big Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2896 :{WINDOW_COLOUR_2}Hypothermia: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2897 :{WINDOW_COLOUR_2}Last Sleigh Ride: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2898 :{WINDOW_COLOUR_2}Pipes of Glencairn: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2899 :{WINDOW_COLOUR_2}Traffic Jam: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2875 :{WINDOW_COLOUR_2}Gravações originais (P) 1976 C.J.Mears Organization, usado com consentimento +STR_2876 :{WINDOW_COLOUR_2}RollerCoaster Tycoon 2 Title Music: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2877 :{WINDOW_COLOUR_2}Dodgems Beat: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2878 :{WINDOW_COLOUR_2}Mid Summer's Heat: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2879 :{WINDOW_COLOUR_2}Pharaoh's Tomb: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2880 :{WINDOW_COLOUR_2}Caesar's March: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2881 :{WINDOW_COLOUR_2}Drifting To Heaven: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2882 :{WINDOW_COLOUR_2}Invaders: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2883 :{WINDOW_COLOUR_2}Eternal Toybox: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2884 :{WINDOW_COLOUR_2}Jungle Juice: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2885 :{WINDOW_COLOUR_2}Ninja's Noodles: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2886 :{WINDOW_COLOUR_2}Voyage to Andromeda: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2887 :{WINDOW_COLOUR_2}Brimble's Beat: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2888 :{WINDOW_COLOUR_2}Atlantis: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2889 :{WINDOW_COLOUR_2}Wild West Kid: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2890 :{WINDOW_COLOUR_2}Vampire's Lair: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2891 :{WINDOW_COLOUR_2}Blockbuster: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2892 :{WINDOW_COLOUR_2}Airtime Rock: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2893 :{WINDOW_COLOUR_2}Searchlight Rag: (Scott Joplin/Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2894 :{WINDOW_COLOUR_2}Flight of Fantasy: (Steve Blenkinsopp) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2895 :{WINDOW_COLOUR_2}Big Rock: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2896 :{WINDOW_COLOUR_2}Hypothermia: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2897 :{WINDOW_COLOUR_2}Last Sleigh Ride: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2898 :{WINDOW_COLOUR_2}Pipes of Glencairn: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2899 :{WINDOW_COLOUR_2}Traffic Jam: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer STR_2900 :{WINDOW_COLOUR_2} -STR_2901 :{WINDOW_COLOUR_2}(Samples courtesy of Spectrasonics {ENDQUOTES}Liquid Grooves{ENDQUOTES}) +STR_2901 :{WINDOW_COLOUR_2}(Amostras Grátis de Spectrasonics {ENDQUOTES}Liquid Grooves{ENDQUOTES}) STR_2902 :{WINDOW_COLOUR_2}Toccata: (C.M.Widor, played by Peter James Adcock) recording {COPYRIGHT} Chris Sawyer -STR_2903 :{WINDOW_COLOUR_2}Space Rock: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2904 :{WINDOW_COLOUR_2}Manic Mechanic: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2905 :{WINDOW_COLOUR_2}Techno Torture: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2906 :{WINDOW_COLOUR_2}Sweat Dreams: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer -STR_2907 :{WINDOW_COLOUR_2}What shall we do with the Drunken Sailor: (Anon/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2903 :{WINDOW_COLOUR_2}Space Rock: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2904 :{WINDOW_COLOUR_2}Manic Mechanic: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2905 :{WINDOW_COLOUR_2}Techno Torture: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2906 :{WINDOW_COLOUR_2}Sweat Dreams: (Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer +STR_2907 :{WINDOW_COLOUR_2}What shall we do with the Drunken Sailor: (Anon/Allister Brimble) direitos autorais {COPYRIGHT} Chris Sawyer STR_2908 :{WINDOW_COLOUR_2}Infogrames Interactive -STR_2909 :{WINDOW_COLOUR_2}Senior Producer: Thomas J. Zahorik -STR_2910 :{WINDOW_COLOUR_2}Executive Producer: Bill Levay -STR_2911 :{WINDOW_COLOUR_2}Senior Marketing Product Manager: Scott Triola -STR_2912 :{WINDOW_COLOUR_2}V.P. of Product Development: Scott Walker -STR_2913 :{WINDOW_COLOUR_2}General Manager: John Hurlbut -STR_2914 :{WINDOW_COLOUR_2}Director of Quality Assurance: Michael Craighead -STR_2915 :{WINDOW_COLOUR_2}Q.A. Certification Manager: Kurt Boutin -STR_2916 :{WINDOW_COLOUR_2}Q.A. Certification Lead: Mark Huggins -STR_2917 :{WINDOW_COLOUR_2}Testers: Dena Irene Fitzgerald, Scott Rollins, Christopher McPhail +STR_2909 :{WINDOW_COLOUR_2}Produtor Sênior: Thomas J. Zahorik +STR_2910 :{WINDOW_COLOUR_2}Produtor Executivo: Bill Levay +STR_2911 :{WINDOW_COLOUR_2}Gerente de Produtos de Marketing Sênior: Scott Triola +STR_2912 :{WINDOW_COLOUR_2}Vice-Presidente de Desenvolvimento de Produto: Scott Walker +STR_2913 :{WINDOW_COLOUR_2}Gerente Geral: John Hurlbut +STR_2914 :{WINDOW_COLOUR_2}Diretor de Garantia de Qualidade: Michael Craighead +STR_2915 :{WINDOW_COLOUR_2}Gerente de Certificação de Garantia de Qualidade: Kurt Boutin +STR_2916 :{WINDOW_COLOUR_2}Líder de Certificação de Garantia de Qualidade: Mark Huggins +STR_2917 :{WINDOW_COLOUR_2}Testadores: Dena Irene Fitzgerald, Scott Rollins, Christopher McPhail STR_2918 :{WINDOW_COLOUR_2}Clif McClure, Erik Maramaldi, Erik Jeffery -STR_2919 :{WINDOW_COLOUR_2}Director of Marketing: Ann Marie Bland -STR_2920 :{WINDOW_COLOUR_2}Manager of Creative Services: Steve Martin -STR_2921 :{WINDOW_COLOUR_2}Manager of Editorial & Documentation Services: Elizabeth Mackney -STR_2922 :{WINDOW_COLOUR_2}Graphic Designer: Paul Anselmi +STR_2919 :{WINDOW_COLOUR_2}Diretor de Marketing: Ann Marie Bland +STR_2920 :{WINDOW_COLOUR_2}Gerente de Serviços Criativos: Steve Martin +STR_2921 :{WINDOW_COLOUR_2}Gerente de Serviços Editoriais e Documentação: Elizabeth Mackney +STR_2922 :{WINDOW_COLOUR_2}Designer Gráfico: Paul Anselmi STR_2923 :{WINDOW_COLOUR_2}Copywriter: Kurt Carlson -STR_2924 :{WINDOW_COLOUR_2}Special Thanks to: Peter Matiss -STR_2925 :{WINDOW_COLOUR_2}Engineering Specialist: Ken Edwards -STR_2926 :{WINDOW_COLOUR_2}Engineering Services Manager: Luis Rivas -STR_2927 :{WINDOW_COLOUR_2}Lead Compatibility Analyst: Geoffrey Smith -STR_2928 :{WINDOW_COLOUR_2}Compatibility Analysts: Jason Cordero, Burke McQuinn, Kim Jardin -STR_2929 :{WINDOW_COLOUR_2}Lead Tester: Daniel Frisoli -STR_2930 :{WINDOW_COLOUR_2}Senior Tester: Matt Pantaleoni +STR_2924 :{WINDOW_COLOUR_2}Agradecimentos Especiais à: Peter Matiss +STR_2925 :{WINDOW_COLOUR_2}Especialista em Engenharia: Ken Edwards +STR_2926 :{WINDOW_COLOUR_2}Gerende de Serviços de Engenharia: Luis Rivas +STR_2927 :{WINDOW_COLOUR_2}Líder de Análistas de Compatibilidade: Geoffrey Smith +STR_2928 :{WINDOW_COLOUR_2}Analistas de Compatibilidade: Jason Cordero, Burke McQuinn, Kim Jardin +STR_2929 :{WINDOW_COLOUR_2}Testador Líder: Daniel Frisoli +STR_2930 :{WINDOW_COLOUR_2}Testador Sênior: Matt Pantaleoni STR_2931 :{WINDOW_COLOUR_2} STR_2932 :{WINDOW_COLOUR_2} STR_2933 :{WINDOW_COLOUR_2} @@ -2978,31 +2978,31 @@ STR_2967 : STR_2968 : STR_2969 : STR_2970 : -STR_2971 :Main colour scheme -STR_2972 :Alternative colour scheme 1 -STR_2973 :Alternative colour scheme 2 -STR_2974 :Alternative colour scheme 3 -STR_2975 :{SMALLFONT}{BLACK}Select which colour scheme to change, or paint ride with -STR_2976 :{SMALLFONT}{BLACK}Paint an individual area of this ride using the selected colour scheme -STR_2977 :Staff member name -STR_2978 :Enter new name for this member of staff: -STR_2979 :Can't name staff member... -STR_2980 :Too many banners in game -STR_2981 :{RED}No entry - - -STR_2982 :Banner text -STR_2983 :Enter new text for this banner: -STR_2984 :Can't set new text for banner... +STR_2971 :Esquema de cor principal +STR_2972 :Esquema de cor alternativo 1 +STR_2973 :Esquema de cor alternativo 2 +STR_2974 :Esquema de cor alternativo 3 +STR_2975 :{SMALLFONT}{BLACK}Selecione qual esquema de cor mudar, ou usar para pintar atração +STR_2976 :{SMALLFONT}{BLACK}Pintar uma área individual desta atração usando o esquema de cor selecionado +STR_2977 :Nome do Funcionário +STR_2978 :Inserir novo nove para este funcionário: +STR_2979 :Impossível nomear funcionário... +STR_2980 :Muitos banners no jogo +STR_2981 :{RED}Entrada Proibida - - +STR_2982 :Texto do banner +STR_2983 :Insira um novo texto para este banner: +STR_2984 :Impossível definir novo texto para banner... STR_2985 :Banner -STR_2986 :{SMALLFONT}{BLACK}Change text on banner -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_2992 :Sign text -STR_2993 :Enter new text for this sign: -STR_2994 :{SMALLFONT}{BLACK}Change text on sign -STR_2995 :{SMALLFONT}{BLACK}Demolish this sign +STR_2986 :{SMALLFONT}{BLACK}Muda o texto no banner +STR_2987 :{SMALLFONT}{BLACK}Define este banner como "Entrada Proibida" para visitantes +STR_2988 :{SMALLFONT}{BLACK}Demole este banner +STR_2989 :{SMALLFONT}{BLACK}Selecione a cor principal +STR_2990 :{SMALLFONT}{BLACK}Selecione a cor do texto +STR_2991 :Placa +STR_2992 :Texto da Placa +STR_2993 :Insira um novo texto para esta placa: +STR_2994 :{SMALLFONT}{BLACK}Muda o texto na placa +STR_2995 :{SMALLFONT}{BLACK}Demole esta placa STR_2996 :{BLACK}ABC STR_2997 :{GREY}ABC STR_2998 :{WHITE}ABC @@ -3017,146 +3017,146 @@ STR_3006 :{PALEGOLD}ABC STR_3007 :{LIGHTPINK}ABC STR_3008 :{PEARLAQUA}ABC STR_3009 :{PALESILVER}ABC -STR_3010 :Unable to load file... -STR_3011 :File contains invalid data -STR_3012 :Dodgems beat style -STR_3013 :Fairground organ style -STR_3014 :Roman fanfare style -STR_3015 :Oriental style -STR_3016 :Martian style -STR_3017 :Jungle drums style -STR_3018 :Egyptian style -STR_3019 :Toyland style +STR_3010 :Incapaz de carregar arquivo... +STR_3011 :Arquivo contém dados inválidos +STR_3012 :Estilo Carrinho de Bate-Bate +STR_3013 :Estilo Orgão de Parque de Diversões +STR_3014 :Estilo Fanfarra Romana +STR_3015 :Estilo Oriental +STR_3016 :Estilo Marciano +STR_3017 :Estilo Bateria da Selva +STR_3018 :Estilo Egípcio +STR_3019 :Estilo Brinquedolândia STR_3020 : -STR_3021 :Space style -STR_3022 :Horror style -STR_3023 :Techno style -STR_3024 :Gentle style -STR_3025 :Summer style -STR_3026 :Water style -STR_3027 :Wild west style -STR_3028 :Jurassic style -STR_3029 :Rock style -STR_3030 :Ragtime style -STR_3031 :Fantasy style -STR_3032 :Rock style 2 -STR_3033 :Ice style -STR_3034 :Snow style -STR_3035 :Custom music 1 -STR_3036 :Custom music 2 -STR_3037 :Medieval style -STR_3038 :Urban style -STR_3039 :Organ style -STR_3040 :Mechanical style -STR_3041 :Modern style -STR_3042 :Pirates style -STR_3043 :Rock style 3 -STR_3044 :Candy style -STR_3045 :{SMALLFONT}{BLACK}Select style of music to play -STR_3046 :This ride cannot be modified -STR_3047 :Local authority forbids demolition or modifications to this ride -STR_3048 :Marketing campaigns forbidden by local authority -STR_3049 :Golf hole A -STR_3050 :Golf hole B -STR_3051 :Golf hole C -STR_3052 :Golf hole D -STR_3053 :Golf hole E +STR_3021 :Estilo Espaço +STR_3022 :Estilo Horror +STR_3023 :Estilo Techno +STR_3024 :Estilo Suave/Calmo +STR_3025 :Estilo Verão +STR_3026 :Estilo Água +STR_3027 :Estilo Oeste Selvagem +STR_3028 :Estilo Jurássico +STR_3029 :Estilo Rock +STR_3030 :Estilo Raggae +STR_3031 :Estilo Fantasia +STR_3032 :Estilo Rock 2 +STR_3033 :Estilo Gelo +STR_3034 :Estilo Neve +STR_3035 :Música Pesonalizada 1 +STR_3036 :Música Pesonalizada 2 +STR_3037 :Estilo Medieval +STR_3038 :Estilo Urbano +STR_3039 :Estilo Orgão +STR_3040 :Estilo Mecânico +STR_3041 :Estilo Moderno +STR_3042 :Estilo Piratas +STR_3043 :Estilo Rock 3 +STR_3044 :Estilo Doce +STR_3045 :{SMALLFONT}{BLACK}Selecione o estilo de música para tocar +STR_3046 :Esta atração não pode ser modificada +STR_3047 :Autoridades locais proíbem a demolição ou modificações nesta atração +STR_3048 :Campanhas de marketing proibidas pelas autoridades locais +STR_3049 :Buraco de golfe A +STR_3050 :Buraco de golfe B +STR_3051 :Buraco de golfe C +STR_3052 :Buraco de golfe D +STR_3053 :Buraco de golfe E STR_3054 :Carregando... STR_3055 :Branco STR_3056 :Translúcido STR_3057 :{WINDOW_COLOUR_2}Marcador de Construção: -STR_3058 :Brick walls -STR_3059 :Hedges -STR_3060 :Ice blocks -STR_3061 :Wooden fences -STR_3062 :{SMALLFONT}{BLACK}Standard roller coaster track -STR_3063 :{SMALLFONT}{BLACK}Water channel (track submerged) -STR_3064 :Beginner Parks -STR_3065 :Challenging Parks -STR_3066 :Expert Parks -STR_3067 :{OPENQUOTES}Real{ENDQUOTES} Parks -STR_3068 :Other Parks -STR_3069 :Top Section -STR_3070 :Slope to Level -STR_3071 :{WINDOW_COLOUR_2}Same price throughout park -STR_3072 :{SMALLFONT}{BLACK}Select whether this price is used throughout the entire park -STR_3073 :{RED}WARNING: Your park rating has dropped below 700 !{NEWLINE}If you haven't raised the park rating in 4 weeks, your park will be closed down -STR_3074 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have 3 weeks to raise the park rating -STR_3075 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have only 2 weeks to raise the park rating, or your park will be closed down -STR_3076 :{RED}FINAL WARNING: Your park rating is still below 700 !{NEWLINE}In just 7 days your park will be closed down unless you can raise the rating -STR_3077 :{RED}CLOSURE NOTICE: Your park has been closed down ! -STR_3078 :Plain entrance -STR_3079 :Wooden entrance -STR_3080 :Canvas tent entrance -STR_3081 :Castle entrance (grey) -STR_3082 :Castle entrance (brown) -STR_3083 :Jungle entrance -STR_3084 :Log cabin entrance -STR_3085 :Classical/Roman entrance -STR_3086 :Abstract entrance -STR_3087 :Snow/Ice entrance -STR_3088 :Pagoda entrance -STR_3089 :Space entrance -STR_3090 :{SMALLFONT}{BLACK}Select style of entrance, exit, and station -STR_3091 :You are not allowed to remove this section! -STR_3092 :You are not allowed to move or modify the station for this ride! +STR_3058 :Parede de Tijolos +STR_3059 :Sebes +STR_3060 :Blocos de Gelo +STR_3061 :Cercas de Madeira +STR_3062 :{SMALLFONT}{BLACK}Pista de montanha-russa padrão +STR_3063 :{SMALLFONT}{BLACK}Canal d'água (pista submersa) +STR_3064 :Parques para Iniciantes +STR_3065 :Parques Desafiadores +STR_3066 :Parques para Especialistas +STR_3067 :Parques {OPENQUOTES}Reais{ENDQUOTES} +STR_3068 :Outros Parques +STR_3069 :Seção Superior +STR_3070 :Nivelar +STR_3071 :{WINDOW_COLOUR_2}Mesmo preço em todo o parque +STR_3072 :{SMALLFONT}{BLACK}Selecione se este preço deve ser usado em todo o parque +STR_3073 :{RED}AVISO: A classificação de seu parque está abaixo de 700 !{NEWLINE}Se você não aumentar a classificação de parque em 4 semanas, seu parque será fechado +STR_3074 :{RED}AVISO: A classificação de seu parque ainda está abaixo de 700 !{NEWLINE}Você tem 3 semanas para aumentar a classificação de parque +STR_3075 :{RED}AVISO: A classificação de seu parque ainda está abaixo de 700 !{NEWLINE}Você tem só 2 semanas para aumentar a classificação de parque, ou seu parque será fechado +STR_3076 :{RED}AVISO FINAL: A classificação de seu parque ainda está abaixo de 700 !{NEWLINE} Em 7 dias seu parque será fechado, a não ser que você consiga melhorar a classificação +STR_3077 :{RED}ANÚNCIO DE ENCERRAMENTO: Seu parque foi fechado ! +STR_3078 :Entrada Simples +STR_3079 :Entrada de Madeira +STR_3080 :Entrada de Lona +STR_3081 :Entrada de Castelo (cinza) +STR_3082 :Entrada de Castelo (marrom) +STR_3083 :Entrada da Selva +STR_3084 :Entrada de Cabana feita de toros +STR_3085 :Entrada Clássica/Romana +STR_3086 :Entrada Abstrata +STR_3087 :Entrada de Neve/Gelo +STR_3088 :Entrada de Templo +STR_3089 :Entrada do Espaço +STR_3090 :{SMALLFONT}{BLACK}Selecione o estilo de entrada, saída e estação +STR_3091 :Você não tem permissão para remover esta seção! +STR_3092 :Você não tem permissão para mover ou modificar a estação desta atração! STR_3093 :{WINDOW_COLOUR_2}Favorito: {BLACK}{STRINGID} STR_3094 :N/A -STR_3095 :{WINDOW_COLOUR_2}Lift hill chain speed: +STR_3095 :{WINDOW_COLOUR_2}Velocidade da Corrente: STR_3096 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} -STR_3097 :{SMALLFONT}{BLACK}Select lift hill chain speed -STR_3098 :Can't change lift hill speed... -STR_3099 :{SMALLFONT}{BLACK}Select colour -STR_3100 :{SMALLFONT}{BLACK}Select second colour -STR_3101 :{SMALLFONT}{BLACK}Select third colour -STR_3102 :{SMALLFONT}{BLACK}Re-paint coloured scenery on landscape -STR_3103 :Can't re-paint this... -STR_3104 :{SMALLFONT}{BLACK}List rides -STR_3105 :{SMALLFONT}{BLACK}List shops and stalls -STR_3106 :{SMALLFONT}{BLACK}List information kiosks and other guest facilities +STR_3097 :{SMALLFONT}{BLACK}Selecione a velocidade da corrente de elevação +STR_3098 :Impossível mudar a velocidade da corrente de elevação +STR_3099 :{SMALLFONT}{BLACK}Selecionar cor +STR_3100 :{SMALLFONT}{BLACK}Selecionar segunda cor +STR_3101 :{SMALLFONT}{BLACK}Selecionar terceira cor +STR_3102 :{SMALLFONT}{BLACK}Repintar cenário colorível no terreno +STR_3103 :Impossível repintar isto... +STR_3104 :{SMALLFONT}{BLACK}Listar atrações +STR_3105 :{SMALLFONT}{BLACK}Listar lojas e barracas +STR_3106 :{SMALLFONT}{BLACK}Listar quiosque de informações e outras instalações STR_3107 :Fechar STR_3108 :Testar STR_3109 :Abrir -STR_3110 :{WINDOW_COLOUR_2}Block Sections: {BLACK}{COMMA16} -STR_3111 :{SMALLFONT}{BLACK}Click on design to build it -STR_3112 :{SMALLFONT}{BLACK}Click on design to rename or delete it -STR_3113 :Select a different design -STR_3114 :{SMALLFONT}{BLACK}Go back to design selection window -STR_3115 :{SMALLFONT}{BLACK}Save track design -STR_3116 :{SMALLFONT}{BLACK}Save track design (Not possible until ride has been tested and statistics have been generated) -STR_3117 :{BLACK}Calling mechanic... -STR_3118 :{BLACK}{STRINGID} is heading for the ride -STR_3119 :{BLACK}{STRINGID} is fixing the ride -STR_3120 :{SMALLFONT}{BLACK}Locate nearest available mechanic, or mechanic fixing ride -STR_3121 :Unable to locate mechanic, or all nearby mechanics are busy -STR_3122 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guest -STR_3123 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guests -STR_3124 :Broken {STRINGID} -STR_3125 :{WINDOW_COLOUR_2}Excitement Factor: {BLACK}+{COMMA16}% -STR_3126 :{WINDOW_COLOUR_2}Intensity Factor: {BLACK}+{COMMA16}% -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_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) -STR_3135 :{RED}(Vehicle design unavailable - Ride performance may be affected) -STR_3136 :Warning: This design will be built with an alternative vehicle type and may not perform as expected -STR_3137 :Select Nearby Scenery -STR_3138 :Reset Selection -STR_3139 :Cable lift unable to work in this operating mode -STR_3140 :Cable lift hill must start immediately after station -STR_3141 :Multi-circuit per ride not possible with cable lift hill +STR_3110 :{WINDOW_COLOUR_2}Secções de Bloco: {BLACK}{COMMA16} +STR_3111 :{SMALLFONT}{BLACK}Clique no projeto para construí-lo +STR_3112 :{SMALLFONT}{BLACK}Clique no projeto para renomear ou deletá-lo +STR_3113 :Selecionar um projeto diferente +STR_3114 :{SMALLFONT}{BLACK}Voltar para a janela de seleção de projetos +STR_3115 :{SMALLFONT}{BLACK}Salvar projeto de pista +STR_3116 :{SMALLFONT}{BLACK}Salvar projeto de pista (Não é possível até que a atração seja testada e as estatísticas sejam geradas) +STR_3117 :{BLACK}Chamando mecânico... +STR_3118 :{BLACK}{STRINGID} indo até a atração +STR_3119 :{BLACK}{STRINGID} consertando atração +STR_3120 :{SMALLFONT}{BLACK}Localizar o mecânico mais perto disponível, ou mecânico consertando atração +STR_3121 :Não foi possível localizar mecânicos, ou todos os mecânicos próximos estão ocupados +STR_3122 :{WINDOW_COLOUR_2}Atração favorita de: {BLACK}{COMMA16} visitante +STR_3123 :{WINDOW_COLOUR_2}Atração favorita de: {BLACK}{COMMA16} visitantes +STR_3124 :{STRINGID} Quebrado +STR_3125 :{WINDOW_COLOUR_2}Fator de emoção: {BLACK}+{COMMA16}% +STR_3126 :{WINDOW_COLOUR_2}Fator de intensidade: {BLACK}+{COMMA16}% +STR_3127 :{WINDOW_COLOUR_2}Fator de Nausea: {BLACK}+{COMMA16}% +STR_3128 :Salvar Projeto de Pista +STR_3129 :Salvar Projeto de Pista com Cenário +STR_3130 :Salvar +STR_3131 :Cancelar +STR_3132 :{BLACK}Clique nos itens do cenário para selecioná-los e salvar junto com o projeto de pista... +STR_3133 :Impossível construir isto nesta inclinação +STR_3134 :{RED}(Projeto inclui cenário que está indisponível) +STR_3135 :{RED}(Estilo de veículo indisponível - Performance da atração pode ser afetada) +STR_3136 :Aviso: Este projeto será construido com um tipo alternativo de veículo e pode não funcionar como o esperado +STR_3137 :Selecionar Cenários Próximos +STR_3138 :Reiniciar Seleção +STR_3139 :Cabo de elevação não funciona neste modo de operação +STR_3140 :Cabo de elevação deve estar imediatamente após a estação +STR_3141 :Várias voltas por ingresso não é possível com o cabo de elevação STR_3142 :{WINDOW_COLOUR_2}Capacidade: {BLACK}{STRINGID} -STR_3143 :{SMALLFONT}{BLACK}Mostrar pessoa no mapa +STR_3143 :{SMALLFONT}{BLACK}Mostrar pessoas no mapa STR_3144 :{SMALLFONT}{BLACK}Mostrar atrações e barracas no mapa -STR_3145 :{SMALLFONT}{BLACK}Scroll {STRINGID} esqueda +STR_3145 :{SMALLFONT}{BLACK}Scroll {STRINGID} esquerda STR_3146 :{SMALLFONT}{BLACK}Scroll {STRINGID} direita STR_3147 :{SMALLFONT}{BLACK}Scroll {STRINGID} esquerda rápido STR_3148 :{SMALLFONT}{BLACK}Scroll {STRINGID} direita rápido -STR_3149 :{SMALLFONT}{BLACK}Scroll {STRINGID} esqueda/direita +STR_3149 :{SMALLFONT}{BLACK}Scroll {STRINGID} esquerda/direita STR_3150 :{SMALLFONT}{BLACK}Scroll {STRINGID} cima STR_3151 :{SMALLFONT}{BLACK}Scroll {STRINGID} baixo STR_3152 :{SMALLFONT}{BLACK}Scroll {STRINGID} cima rápido @@ -3169,130 +3169,130 @@ STR_3158 :gráfico STR_3159 :lista STR_3160 : STR_3161 : -STR_3162 :Unable to allocate enough memory -STR_3163 :Installing new data: -STR_3164 :{BLACK}{COMMA16} selected (maximum {COMMA16}) +STR_3162 :Não é possível alocar memória necessária +STR_3163 :Instalando novos dados: +STR_3164 :{BLACK}{COMMA16} selecionado(s) (no máximo {COMMA16}) STR_3165 : STR_3166 :{BLACK}(ID: -STR_3167 :{WINDOW_COLOUR_2}Includes: {BLACK}{COMMA16} objects -STR_3168 :{WINDOW_COLOUR_2}Text: {BLACK}{STRINGID} -STR_3169 :Data for the following object not found: -STR_3170 :Not enough space for graphics -STR_3171 :Too many objects of this type selected -STR_3172 :The following object must be selected first: {STRING} -STR_3173 :This object is currently in use -STR_3174 :This object is required by another object -STR_3175 :This object is always required -STR_3176 :Unable to select this object -STR_3177 :Unable to de-select this object -STR_3178 :At least one path object must be selected -STR_3179 :At least one ride vehicle/attraction object must be selected -STR_3180 :Invalid selection of objects -STR_3181 :Object Selection - {STRINGID} -STR_3182 :Park entrance type must be selected -STR_3183 :Water type must be selected -STR_3184 :Ride Vehicles/Attractions -STR_3185 :Small Scenery -STR_3186 :Large Scenery -STR_3187 :Walls/Fences -STR_3188 :Path Signs -STR_3189 :Footpaths -STR_3190 :Path Extras -STR_3191 :Scenery Groups -STR_3192 :Park Entrance -STR_3193 :Water -STR_3194 :Scenario Description -STR_3195 :Invention List -STR_3196 :{WINDOW_COLOUR_2}Research Group: {BLACK}{STRINGID} -STR_3197 :{WINDOW_COLOUR_2}Items pre-invented at start of game: -STR_3198 :{WINDOW_COLOUR_2}Items to invent during game: -STR_3199 :Random Shuffle -STR_3200 :{SMALLFONT}{BLACK}Randomly shuffle the list of items to invent during the game -STR_3201 :Object Selection -STR_3202 :Landscape Editor -STR_3203 :Invention List Set Up -STR_3204 :Options Selection -STR_3205 :Objective Selection -STR_3206 :Save Scenario -STR_3207 :Roller Coaster Designer -STR_3208 :Track Designs Manager -STR_3209 :Back to Previous Step: -STR_3210 :Forward to Next Step: -STR_3211 :{WINDOW_COLOUR_2}Map size: +STR_3167 :{WINDOW_COLOUR_2}Inclui: {BLACK}{COMMA16} objetos +STR_3168 :{WINDOW_COLOUR_2}Texto: {BLACK}{STRINGID} +STR_3169 :Dados dos objetos seguintes não encontrados: +STR_3170 :Espaço insuficiente para gráficos +STR_3171 :Muitos objetos deste tipo selecionados +STR_3172 :O objeto seguinte deve ser selecionado primeiro: {STRING} +STR_3173 :Este objeto está atualmente em uso +STR_3174 :Este objeto é requisitado por outro objeto +STR_3175 :Este objeto é sempre requisitado +STR_3176 :Impossível selecionar este objeto +STR_3177 :Impossível desselecionar este objeto +STR_3178 :Pelo menos um caminho deve ser selecionado +STR_3179 :Pelo menos um objeto de atração/veículo deve ser selecionado +STR_3180 :Seleção de objetos inválida +STR_3181 :Seleção de Objetos - {STRINGID} +STR_3182 :Tipo de entrada do parque deve ser selecionado +STR_3183 :Tipo de água dele ser selecionado +STR_3184 :Atrações/Veículos +STR_3185 :Cenário Pequeno +STR_3186 :Cenário Grande +STR_3187 :Muros/Cercas +STR_3188 :Placa para Caminho +STR_3189 :Calçadas +STR_3190 :Caminhos Extras +STR_3191 :Grupo de Cenários +STR_3192 :Entrada do Parque +STR_3193 :Água +STR_3194 :Descrição do Cenário +STR_3195 :Lista de Invenções +STR_3196 :{WINDOW_COLOUR_2}Grupo de Pesquisa: {BLACK}{STRINGID} +STR_3197 :{WINDOW_COLOUR_2}Itens pré-inventados no começo do jogo: +STR_3198 :{WINDOW_COLOUR_2}Itens a serem inventados durante o jogo: +STR_3199 :Aleatório +STR_3200 :{SMALLFONT}{BLACK}Escolhe aleatóriamente a lista de itens a serem inventados durante o jogo +STR_3201 :Seleção de Objeto +STR_3202 :Editor de Paisagem +STR_3203 :Montar Lista de Invenções +STR_3204 :Seleção de Opções +STR_3205 :Seleção de Objetivos +STR_3206 :Salvar Cenário +STR_3207 :Construtor de Montanha-Russa +STR_3208 :Gerenciador de Projetos de Pista +STR_3209 :Voltar para o Passo Anterior: +STR_3210 :Avançar para o Próximo Passo: +STR_3211 :{WINDOW_COLOUR_2}Tamanho do Mapa: STR_3212 :{POP16}{COMMA16} x {PUSH16}{COMMA16} -STR_3213 :Can't decrease map size any further -STR_3214 :Can't increase map size any further -STR_3215 :Too close to edge of map -STR_3216 :{SMALLFONT}{BLACK}Select park-owned land etc. -STR_3217 :Land Owned -STR_3218 :Construction Rights Owned -STR_3219 :Land For Sale -STR_3220 :Construction Rights For Sale -STR_3221 :{SMALLFONT}{BLACK}Set land to be owned by the park -STR_3222 :{SMALLFONT}{BLACK}Set construction rights only to be owned by the park -STR_3223 :{SMALLFONT}{BLACK}Set land to be available to purchase by the park -STR_3224 :{SMALLFONT}{BLACK}Set construction rights to be available to purchase by the park -STR_3225 :{SMALLFONT}{BLACK}Toggle on/off building a random cluster of objects around the selected position -STR_3226 :{SMALLFONT}{BLACK}Build park entrance -STR_3227 :Too many park entrances! -STR_3228 :{SMALLFONT}{BLACK}Set starting positions for people -STR_3229 :Block Brakes cannot be used directly after station -STR_3230 :Block Brakes cannot be used directly after each other -STR_3231 :Block Brakes cannot be used directly after the top of this lift hill -STR_3232 :Options - Financial -STR_3233 :Options - Guests -STR_3234 :Options - Park -STR_3235 :{SMALLFONT}{BLACK}Show financial options -STR_3236 :{SMALLFONT}{BLACK}Show guest options -STR_3237 :{SMALLFONT}{BLACK}Show park options -STR_3238 :No Money -STR_3239 :{SMALLFONT}{BLACK}Make this park a 'no money' park with no financial restrictions +STR_3213 :Impossível diminuir ainda mais o tamanho do mapa +STR_3214 :Impossível aumentar ainda mais o tamanho do mapa +STR_3215 :Muito perto da borda do mapa +STR_3216 :{SMALLFONT}{BLACK}Selecionar terreno do parque e etc +STR_3217 :Terreno Comprado +STR_3218 :Direitos Comprados +STR_3219 :Terreno à venda +STR_3220 :Direitos à venda +STR_3221 :{SMALLFONT}{BLACK}Define terreno já comprado pelo parque +STR_3222 :{SMALLFONT}{BLACK}Define direitos de construção já comprados pelo parque +STR_3223 :{SMALLFONT}{BLACK}Define terreno disponível para comprar pelo parque +STR_3224 :{SMALLFONT}{BLACK}Define direitos de construção disponíveis para comprar pelo parque +STR_3225 :{SMALLFONT}{BLACK}Liga/Desliga a construção aleatória de uma porção de objetos em volta da posição selecionada +STR_3226 :{SMALLFONT}{BLACK}Construir entrada do parque +STR_3227 :Muitas entradas de parque +STR_3228 :{SMALLFONT}{BLACK}Definir posição inicial para pessoas +STR_3229 :Freios Bloqueadores não podem ser usados diretamente depois da estação +STR_3230 :Freios Bloqueadores não podem ser usados diretamente um após o outro +STR_3231 :Freios Bloqueadores não podem ser usados diretamente após a corrente de elevação +STR_3232 :Opções - Financeiro +STR_3233 :Opções - Visitantes +STR_3234 :Opções - Parque +STR_3235 :{SMALLFONT}{BLACK}Mostrar opções financeiras +STR_3236 :{SMALLFONT}{BLACK}Mostrar opções de visitante +STR_3237 :{SMALLFONT}{BLACK}Mostrar opções do parque +STR_3238 :Não necessita dinheiro +STR_3239 :{SMALLFONT}{BLACK}Fazer este parque sem restrições financeiras STR_3240 :{WINDOW_COLOUR_2}Dinheiro inicial: STR_3241 :{WINDOW_COLOUR_2}Empréstimo inicial: -STR_3242 :{WINDOW_COLOUR_2}Maximum loan size: -STR_3243 :{WINDOW_COLOUR_2}Annual interest rate: -STR_3244 :Forbid marketing campaigns -STR_3245 :{SMALLFONT}{BLACK}Forbid advertising, promotional schemes, and other marketing campaigns +STR_3242 :{WINDOW_COLOUR_2}Empréstimo máximo: +STR_3243 :{WINDOW_COLOUR_2}Taxa de juros anual: +STR_3244 :Proibir campanhas de marketing +STR_3245 :{SMALLFONT}{BLACK}Proibir publicidade, esquemas promocionais, e outras campanhas de marketing STR_3246 :{WINDOW_COLOUR_2}{CURRENCY} STR_3247 :{WINDOW_COLOUR_2}{COMMA16}% -STR_3248 :Can't increase initial cash any further! -STR_3249 :Can't reduce initial cash any further! -STR_3250 :Can't increase initial loan any further! -STR_3251 :Can't reduce initial loan any further! -STR_3252 :Can't increase maximum loan size any further! -STR_3253 :Can't reduce maximum loan size any further! -STR_3254 :Can't increase interest rate any further! -STR_3255 :Can't reduce interest rate any further! -STR_3256 :Guests prefer less intense rides -STR_3257 :{SMALLFONT}{BLACK}Select whether guests should generally prefer less intense rides only -STR_3258 :Guests prefer more intense rides -STR_3259 :{SMALLFONT}{BLACK}Select whether guests should generally prefer more intense rides only -STR_3260 :{WINDOW_COLOUR_2}Cash per guest (average): -STR_3261 :{WINDOW_COLOUR_2}Guests initial happiness: -STR_3262 :{WINDOW_COLOUR_2}Guests initial hunger: -STR_3263 :{WINDOW_COLOUR_2}Guests initial thirst: -STR_3264 :Can't increase this any further! -STR_3265 :Can't reduce this any further! -STR_3266 :{SMALLFONT}{BLACK}Select how this park charges for entrance and rides -STR_3267 :Forbid tree removal -STR_3268 :{SMALLFONT}{BLACK}Forbid tall trees being removed -STR_3269 :Forbid landscape changes -STR_3270 :{SMALLFONT}{BLACK}Forbid any changes to the landscape +STR_3248 :Impossível aumentar ainda mais o dinheiro inicial! +STR_3249 :Impossível reduzir ainda mais o dinheiro inicial! +STR_3250 :Impossível aumentar ainda mais o empréstimo inicial! +STR_3251 :Impossível reduzir ainda mais o empréstimo inicial! +STR_3252 :Impossível aumentar ainda mais o tamanho do empréstimo! +STR_3253 :Impossível diminuir ainda mais o tamanho do empréstimo! +STR_3254 :Impossível aumentar ainda mais a taxa de juros! +STR_3255 :Impossível diminuir ainda mais a taxa de juros! +STR_3256 :Visitantes preferem atrações menos intensas +STR_3257 :{SMALLFONT}{BLACK}Selecionar se os visitantes geralmente preferem somente atrações menos intensas +STR_3258 :Visitantes preferem atrações mais intensas +STR_3259 :{SMALLFONT}{BLACK}Selecionar se os visitantes geralmente preferem somente atrações mais intensas +STR_3260 :{WINDOW_COLOUR_2}Dinheiro por visitante (em média): +STR_3261 :{WINDOW_COLOUR_2}Felicidade inicial dos visitantes: +STR_3262 :{WINDOW_COLOUR_2}Fome inicial dos visitantes: +STR_3263 :{WINDOW_COLOUR_2}Sede inicial dos visitantes: +STR_3264 :Impossível aumentar isto ainda mais! +STR_3265 :Impossível diminuir isto ainda mais! +STR_3266 :{SMALLFONT}{BLACK}Selecionar como este parque cobra por entrada e atrações +STR_3267 :Proibir remoção de árvores +STR_3268 :{SMALLFONT}{BLACK}Proibir que árvores altas sejam removidas +STR_3269 :Proibir mudança na paisagem +STR_3270 :{SMALLFONT}{BLACK}Proibir qualquer mudança na paisagem STR_3271 :Proibir construção alta STR_3272 :{SMALLFONT}{BLACK}Proibir qualquer construção alta STR_3273 :Classificação do parque com alto nível de dificuldade -STR_3274 :{SMALLFONT}{BLACK}Fazer p valor da classificação do parque mais desafiador +STR_3274 :{SMALLFONT}{BLACK}Fazer o valor de classificação do parque mais desafiador STR_3275 :Geração de visitantes com maior nível de dificuldade STR_3276 :{SMALLFONT}{BLACK}Tornar mais difícil atrair clientes para o parque STR_3277 :{WINDOW_COLOUR_2}Custo para comprar terreno: -STR_3278 :{WINDOW_COLOUR_2}Custo para comprar os direitos de construção: -STR_3279 :Entrada gratuita no parque / Pagamento por atrações -STR_3280 :Pague para entrar no Parque / Atrações gratuitas +STR_3278 :{WINDOW_COLOUR_2}Custo para comprar direitos: +STR_3279 :Entrada gratuita / Atrações pagas +STR_3280 :Entrada paga / Atrações gratuitas STR_3281 :{WINDOW_COLOUR_2}Preço de entrada: STR_3282 :{SMALLFONT}{BLACK}Selecione o objetivo e nome do parque STR_3283 :{SMALLFONT}{BLACK}Selecione as atrações a serem preservadas STR_3284 :Seleção de Objetivo -STR_3285 :Atrações Conservadas +STR_3285 :Atrações Preservadas STR_3286 :{SMALLFONT}{BLACK}Selecione o objetivo para este cenário STR_3287 :{WINDOW_COLOUR_2}Objetivo: STR_3288 :{SMALLFONT}{BLACK}Selecione o clima @@ -3302,78 +3302,78 @@ STR_3291 :Morno STR_3292 :Quente e seco STR_3293 :Frio STR_3294 :Mudar... -STR_3295 :{SMALLFONT}{BLACK}Change name of park -STR_3296 :{SMALLFONT}{BLACK}Change name of scenario -STR_3297 :{SMALLFONT}{BLACK}Change detail notes about park / scenario -STR_3298 :{WINDOW_COLOUR_2}Park Name: {BLACK}{STRINGID} -STR_3299 :{WINDOW_COLOUR_2}Park/Scenario Details: -STR_3300 :{WINDOW_COLOUR_2}Scenario Name: {BLACK}{STRINGID} -STR_3301 :{WINDOW_COLOUR_2}Objective Date: +STR_3295 :{SMALLFONT}{BLACK}Mudar nome do parque +STR_3296 :{SMALLFONT}{BLACK}Mudar nome do cenário +STR_3297 :{SMALLFONT}{BLACK}Mudar notas detalhadas sobre o parque / cenário +STR_3298 :{WINDOW_COLOUR_2}Nome do Parque: {BLACK}{STRINGID} +STR_3299 :{WINDOW_COLOUR_2}Detalhes do Parque/Cenário: +STR_3300 :{WINDOW_COLOUR_2}Nome do Cenário: {BLACK}{STRINGID} +STR_3301 :{WINDOW_COLOUR_2}Objetivo de Data: STR_3302 :{WINDOW_COLOUR_2}{MONTHYEAR} -STR_3303 :{WINDOW_COLOUR_2}Numero de visitantes: +STR_3303 :{WINDOW_COLOUR_2}Número de visitantes: STR_3304 :{WINDOW_COLOUR_2}Valor do parque: -STR_3305 :{WINDOW_COLOUR_2}Monthly income: -STR_3306 :{WINDOW_COLOUR_2}Monthly profit: -STR_3307 :{WINDOW_COLOUR_2}Minimum length: -STR_3308 :{WINDOW_COLOUR_2}Excitement rating: +STR_3305 :{WINDOW_COLOUR_2}Receita Mensal: +STR_3306 :{WINDOW_COLOUR_2}Lucro Mensal: +STR_3307 :{WINDOW_COLOUR_2}Comprimento Mínimo: +STR_3308 :{WINDOW_COLOUR_2}Classificação de emoção: STR_3309 :{WINDOW_COLOUR_2}{COMMA16} STR_3310 :{WINDOW_COLOUR_2}{LENGTH} STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} -STR_3312 :{WINDOW_COLOUR_2}Rides/attractions under a preservation order: +STR_3312 :{WINDOW_COLOUR_2}Atrações em ordem de preservação: STR_3313 :Nome do Cenário STR_3314 :Digite o nome para o cenário: STR_3315 :Detalhes do Parque/Cenário STR_3316 :Digite a descrição para o cenário: -STR_3317 :No details yet -STR_3318 :{SMALLFONT}{BLACK}Select which group this scenario appears in -STR_3319 :{WINDOW_COLOUR_2}Scenario Group: -STR_3320 :Unable to save scenario file... -STR_3321 :New objects installed successfully -STR_3322 :{WINDOW_COLOUR_2}Objective: {BLACK}{STRINGID} -STR_3323 :Missing object data, ID: -STR_3324 :Requires Add-On Pack: -STR_3325 :Requires an Add-On Pack -STR_3326 :{WINDOW_COLOUR_2}(no image) -STR_3327 :Starting positions for people not set -STR_3328 :Can't advance to next editor stage... -STR_3329 :Park entrance not yet built -STR_3330 :Park must own some land -STR_3331 :Path from park entrance to map edge either not complete or too complex - Path must be single-width with as few junctions and corners as possible -STR_3332 :Park entrance is the wrong way round or has no path leading to the map edge -STR_3333 :Export plug-in objects with saved games -STR_3334 :{SMALLFONT}{BLACK}Select whether to save any additional plug-in object data required (add-in data not supplied with the main product) in saved game or scenario files, allowing them to be loaded by someone who doesn't have the additional object data -STR_3335 :Roller Coaster Designer - Select Ride Types & Vehicles -STR_3336 :Track Designs Manager - Select Ride Type +STR_3317 :Sem detalhes ainda +STR_3318 :{SMALLFONT}{BLACK}Selecione em qual grupo este cenário aparece +STR_3319 :{WINDOW_COLOUR_2}Grupo de Cenário: +STR_3320 :Não é possível salvar arquivo de cenário... +STR_3321 :Novos objetos instalados com sucesso +STR_3322 :{WINDOW_COLOUR_2}Objetivo: {BLACK}{STRINGID} +STR_3323 :Dado de objeto faltando, ID: +STR_3324 :Requer Pacotes de Expansão: {STRINGID} +STR_3325 :Requer um Pacote de Expansão +STR_3326 :{WINDOW_COLOUR_2}(sem imagem) +STR_3327 :Posição inicial de pessoas não definida +STR_3328 :Impossível avançar para o próximo estágio do editor... +STR_3329 :Entrada do parque ainda não construída +STR_3330 :O parque deve ter um pouco de terreno +STR_3331 :Caminho da entrada do parque a borda do mapa incompleta ou muito complexo - O caminho deve ter uma largura simples (um quadrado) com poucos cruzamentos e esquinas +STR_3332 :Entrada do parque está ao contrário ou não tem caminho até a borda do mapa +STR_3333 :Exportar plug-in de objetos com jogos salvos +STR_3334 :{SMALLFONT}{BLACK}Selecione se deve salvar requerimento de qualquer plug-in de objeto adicional (dados adicionais não fornecidos no produto principal) nos dados de jogo salvo ou cenário, permitindo que sejam carregados por alguém que não tenha dados de objeto adicional +STR_3335 :Construtor de Montanha-Russa - Selecione o Tipo de Veículo e Atração +STR_3336 :Gerenciador de Projetos de Pista - Selecione o Tipo de Atração STR_3337 : -STR_3338 :{BLACK}Custom-designed layout -STR_3339 :{BLACK}{COMMA16} design available, or custom-designed layout -STR_3340 :{BLACK}{COMMA16} designs available, or custom-designed layout +STR_3338 :{BLACK}Projeto com Traçado Personalizado +STR_3339 :{BLACK}{COMMA16} projeto disponível, ou projeto com traçado personalizado +STR_3340 :{BLACK}{COMMA16} projetos disponíveis, ou projeto com traçado personalizado STR_3341 :{SMALLFONT}{BLACK}Ferramentas de Jogo STR_3342 :Editor de Cenário STR_3343 :Converter Jogo Salvo em Cenário -STR_3344 :Designer de Montanha-Russa -STR_3345 :Gerenciamento de Designs de Pista -STR_3346 :Can't save track design... -STR_3347 :Ride is too large, contains too many elements, or scenery is too spread out +STR_3344 :Construtor de Montanha-Russa +STR_3345 :Gerenciador de Projetos de Pista +STR_3346 :Impossível salvar projeto de pista... +STR_3347 :Atração é muito grande, contém muitos elementos, ou o cenários é muito espalhado STR_3348 :Renomear STR_3349 :Deletar -STR_3350 :Track design name -STR_3351 :Enter new name for this track design: -STR_3352 :Can't rename track design... -STR_3353 :New name contains invalid characters -STR_3354 :Another file exists with this name, or file is write-protected -STR_3355 :File is write-protected or locked -STR_3356 :Delete File -STR_3357 :{WINDOW_COLOUR_2}Are you sure you want to permanently delete {STRINGID} ? -STR_3358 :Can't delete track design... -STR_3359 :{BLACK}No track designs of this type -STR_3360 :Warning! -STR_3361 :Too many track designs of this type - Some will not be listed. +STR_3350 :Nome do projeto de pista +STR_3351 :Insira um novo nome para este projeto de pista: +STR_3352 :Impossível renomear projeto de pista... +STR_3353 :Novo nome contém caracteres inválidos +STR_3354 :Existe outro arquivo com este nome, ou o arquivo é protegido contra gravação +STR_3355 :Arquivo protegido contra gravação ou trancado +STR_3356 :Deletar Arquivo +STR_3357 :{WINDOW_COLOUR_2}Tem certeza que deseja deletar {STRINGID} permanentemente ? +STR_3358 :Impossível deletar projeto de pista... +STR_3359 :{BLACK}Nenhum projeto de pista deste tipo de atração +STR_3360 :Aviso! +STR_3361 :Muitos projetos de pista deste tipo de atração - Alguns não serão listados. STR_3362 : STR_3363 : -STR_3364 :Advanced -STR_3365 :{SMALLFONT}{BLACK}Allow selection of individual items of scenery in addition to scenery groups -STR_3366 :{BLACK}= Ride +STR_3364 :Avançado +STR_3365 :{SMALLFONT}{BLACK}Permite seleção de itens individuais do cenário, além dos grupos de cenário +STR_3366 :{BLACK}= Atração STR_3367 :{BLACK}= Barraca de Comida STR_3368 :{BLACK}= Barraca de Bebida STR_3369 :{BLACK}= Barraca de Lembrança @@ -3391,62 +3391,62 @@ STR_3380 :Impossível instalar este projeto de pista... STR_3381 :O arquivo não é compatível ou contém dados inválidos STR_3382 :Cópia de arquivo falhou STR_3383 :Selecione um novo nome para o projeto da pista -STR_3384 :An existing track design already has this name - Please select a new name for this design: +STR_3384 :Um projeto de pista com este nome já existe - Por favor selecione um novo nome para este projeto: STR_3385 :Tutorial Iniciante STR_3386 :Tutorial de Atrações Customizadas -STR_3387 :Tutorial de construção de Montanha-Russas +STR_3387 :Tutorial de Construção de Montanha-Russas STR_3388 :Impossível alterar para o modo selecionado STR_3389 :Impossível selecionar o item adicional de cenário... STR_3390 :Muitos itens selecionados # Start of tutorial strings. Not used at the moment, so not necessary to translate. -STR_3391 :{SMALLFONT}{BLACK}Here is our park - Let's have a quick look around... -STR_3392 :{SMALLFONT}{BLACK}Holding down the RIGHT mouse button and moving the mouse is the quickest way to move the view... -STR_3393 :{SMALLFONT}{BLACK}To view more of the park, you can zoom the view out using the icon at the top of the screen... -STR_3394 :{SMALLFONT}{BLACK}You can also rotate the view in 90 degree steps... -STR_3395 :{SMALLFONT}{BLACK}Building anything at this scale is a bit difficult, so let's zoom the view back in again... -STR_3396 :{SMALLFONT}{BLACK}Let's build a simple ride to get the park started... -STR_3397 :{SMALLFONT}{BLACK}The white 'ghost' image shows where the ride will be built. We'll move the pointer to select the position then click to build it... -STR_3398 :{SMALLFONT}{BLACK}Rides need an entrance and an exit. We'll move the pointer to a square on the edge of the ride and then click to build first the entrance and then the exit... -STR_3399 :{SMALLFONT}{BLACK}We need to build footpaths to allow guests to reach our new ride... -STR_3400 :{SMALLFONT}{BLACK}For the path to the ride entrance we'll use a special 'queue line' path... -STR_3401 :{SMALLFONT}{BLACK}For the exit path, just an 'ordinary' path will do... -STR_3402 :{SMALLFONT}{BLACK}Right, lets open the ride! To open the ride we click the flag icon on the ride window and select 'open'... -STR_3403 :{SMALLFONT}{BLACK}But where are the guests? -STR_3404 :{SMALLFONT}{BLACK}Oh - The park is still closed! Right - Let's open it... -STR_3405 :{SMALLFONT}{BLACK}While we're waiting for our first guests, let's build some scenery... -STR_3406 :{SMALLFONT}{BLACK}Here's our empty park. We're going to build a simple custom-designed ride... -STR_3407 :{SMALLFONT}{BLACK}First we need to choose a starting position... -STR_3408 :{SMALLFONT}{BLACK}The section of track we've just built is a 'station platform', to allow guests to get on and off the ride... -STR_3409 :{SMALLFONT}{BLACK}We'll extend the platform a bit by adding a couple more station platform sections... -STR_3410 :{SMALLFONT}{BLACK}The icons at the top of the construction window let you choose different track pieces to add... -STR_3411 :{SMALLFONT}{BLACK}We'll select a left-hand curve... -STR_3412 :{SMALLFONT}{BLACK}The curve hasn't been built yet, but the white ghost image shows where it will be built. Clicking the large 'build this' icon actually builds the track... -STR_3413 :{SMALLFONT}{BLACK}Now we want to build straight track, so we click the straight track icon... -STR_3414 :{SMALLFONT}{BLACK}Now that the circuit is complete, we need to build the ride entrance and exit... -STR_3415 :{SMALLFONT}{BLACK}Let's test our ride to check it works... -STR_3416 :{SMALLFONT}{BLACK}White it's being tested, we'll build the queue line and exit path... -STR_3417 :{SMALLFONT}{BLACK}OK - Let's open the park and the ride... -STR_3418 :{SMALLFONT}{BLACK}Our new ride isn't very exciting - Perhaps we should add some scenery? -STR_3419 :{SMALLFONT}{BLACK}To build scenery above other scenery or in mid-air, hold down the SHIFT key and move the mouse to select the height... -STR_3420 :{SMALLFONT}{BLACK}Some types of scenery can be re-painted after it's built... -STR_3421 :{SMALLFONT}{BLACK}Let's add some music to the ride... -STR_3422 :{SMALLFONT}{BLACK}Let's build a roller coaster ! -STR_3423 :{SMALLFONT}{BLACK}There are loads of pre-designed coasters, but we're going to build our own custom design... -STR_3424 :{SMALLFONT}{BLACK}That's the station platform built. Now we need a lift hill... -STR_3425 :{SMALLFONT}{BLACK}Roller coaster trains aren't powered, so a 'chain lift' is needed to pull the train up the first hill... -STR_3426 :{SMALLFONT}{BLACK}That's the lift hill complete - Now for the first drop... -STR_3427 :{SMALLFONT}{BLACK}Those curves are a bad idea - The riders will be flung to the sides by the lateral G forces as the train hurtles around... -STR_3428 :{SMALLFONT}{BLACK}Banking the curves will improve the ride - Riders will be pushed down into their seats instead of flung to the sides... -STR_3429 :{SMALLFONT}{BLACK}No - That won't work! Look at the height marks - The second hill is taller than the lift hill... -STR_3430 :{SMALLFONT}{BLACK}To ensure the train makes it around, each hill should be slightly smaller than the previous one... -STR_3431 :{SMALLFONT}{BLACK}That's better - Our train should make it up that hill now! Let's try some more twisted track... -STR_3432 :{SMALLFONT}{BLACK}We need to slow the train before the final curve and station, so let's add some brakes... -STR_3433 :{SMALLFONT}{BLACK}And finally we'll add 'block brakes', which allow two trains to operate more safely on the circuit... -STR_3434 :{SMALLFONT}{BLACK}Let's test the ride and see if it works! -STR_3435 :{SMALLFONT}{BLACK}Great - It worked! Let's add the footpaths and let guests onto our new roller coaster... -STR_3436 :{SMALLFONT}{BLACK}While waiting for our first riders, we could customise the ride a bit... +STR_3391 :{SMALLFONT}{BLACK}Aqui está nosso parque - Vamos dar uma olhada rápida... +STR_3392 :{SMALLFONT}{BLACK}Segurar o botão DIREITO do mouse e mover o mouse é a maneira mais rápida de mover a vista... +STR_3393 :{SMALLFONT}{BLACK}Para vizualizar mais do parque, você pode afastar o zoom usando o ícone no topo da tela... +STR_3394 :{SMALLFONT}{BLACK}Você também pode rotacionar a visão em incrementos de 90 graus... +STR_3395 :{SMALLFONT}{BLACK}Construir qualquer coisa nesta escala é um pouco difícil, então vamos ampliar a visão novamente... +STR_3396 :{SMALLFONT}{BLACK}Vamos construir uma atração simples para iniciar o parque... +STR_3397 :{SMALLFONT}{BLACK}A imagem 'transparente' mostra onde a atração será construído. Vamos mover o ponteiro para selecionar a posição e então clicar para construir... +STR_3398 :{SMALLFONT}{BLACK}Atrações precisam de uma entrada e uma saída. Vamos mover o ponteiro para um quadrado na borda da atração e clicar para construir primeiro a entrada e depois a saída... +STR_3399 :{SMALLFONT}{BLACK}Precisamos construir caminhos para permitir que os visitantes cheguem à nossa nova atração... +STR_3400 :{SMALLFONT}{BLACK}Para o caminho até a entrada da atração, vamos usar um caminho especial de 'fila de espera'... +STR_3401 :{SMALLFONT}{BLACK}Para o caminho de saída, um caminho 'comum' servirá... +STR_3402 :{SMALLFONT}{BLACK}Certo, vamos abrir a atração! Para abrir a atração clicamos no ícone de bandeira na janela da atração e selecionamos 'abrir'... +STR_3403 :{SMALLFONT}{BLACK}Mas onde estão os visitantes? +STR_3404 :{SMALLFONT}{BLACK}Oh - O parque ainda está fechado! Certo - Vamos abri-lo... +STR_3405 :{SMALLFONT}{BLACK}Enquanto esperamos por nossos primeiros visitantes, vamos construir alguns cenários... +STR_3406 :{SMALLFONT}{BLACK}Aqui está nosso parque vazio. Vamos construir uma atração personalizada simples... +STR_3407 :{SMALLFONT}{BLACK}Primeiro vamos selecionar uma posição inicial... +STR_3408 :{SMALLFONT}{BLACK}A seção de pista que nós acabamos de construir é a 'plataforma de estação', que permite os visitantes entrarem e sairem da atração... +STR_3409 :{SMALLFONT}{BLACK}Vamos extender a plataforma um pouco acrescentando mais algumas seções de plataforma de estação... +STR_3410 :{SMALLFONT}{BLACK}Os icones no topo da janela de construção permitem escolher pedaços de pista diferentes para adicionar... +STR_3411 :{SMALLFONT}{BLACK}Vamos selecionar uma curva para a esquerda... +STR_3412 :{SMALLFONT}{BLACK}A curva não foi construída ainda, mas imagem 'transparente' mostra onde será construída. Clicar no ícone grande'construir isso' faz a seção de pista ser construída... +STR_3413 :{SMALLFONT}{BLACK}Agora vamos construir uma pista reta, então clicamos no ícone de pista reta... +STR_3414 :{SMALLFONT}{BLACK}Agora que o circuíto está completa, nós precisamos construir a entrada e a saída da atração... +STR_3415 :{SMALLFONT}{BLACK}Vamos testar nossa atração pra ver se funciona... +STR_3416 :{SMALLFONT}{BLACK}Enquanto está sendo testada, vamos construir a fila de espera e o caminho de saída... +STR_3417 :{SMALLFONT}{BLACK}OK - Vamos abrir o parque e a atração... +STR_3418 :{SMALLFONT}{BLACK}Nossa nova atração não é muito emocionante - Talvez devêssemos adicionar alguns cenários? +STR_3419 :{SMALLFONT}{BLACK}Para construir um cenário em cima de outro cenário ou no ar, segure a tecla SHIFT e mova o mouse para escolher a altura... +STR_3420 :{SMALLFONT}{BLACK}Alguns tipos de cenário podem ser repintados depois de construído... +STR_3421 :{SMALLFONT}{BLACK}Vamos adicionar um pouco de música na atração... +STR_3422 :{SMALLFONT}{BLACK}Vamos construir uma montanha-russa ! +STR_3423 :{SMALLFONT}{BLACK}Existem muitas montanhas pré-fabricadas, mas nós vamos construir nosso próprio projeto personalizado... +STR_3424 :{SMALLFONT}{BLACK}Esta é a plataforma de estação construída. Agora vamos fazer a subida... +STR_3425 :{SMALLFONT}{BLACK}Os trens de montanha-russa não são motorizados, então uma 'corrente de elevação' é necessária para puxar o trem para cima da nossa primeira subida... +STR_3426 :{SMALLFONT}{BLACK}Está é a subida de elevação completa - Agora a primeira queda... +STR_3427 :{SMALLFONT}{BLACK}Essas curvas não são uma boa ideia - Os passageiros serão arremessados para o lado pela forca G lateral assim que o trem der a volta... +STR_3428 :{SMALLFONT}{BLACK}Inclinar as curvas irá melhorar a atração - Passageiros serão empurrados para baixo no assento ao invés de serem arremessados para os lados... +STR_3429 :{SMALLFONT}{BLACK}Não - Isto não vai funcionar! Olhe as marcar de altura - A segunda subida é mais alta que a subida de elevação... +STR_3430 :{SMALLFONT}{BLACK}Para ter certeza que o trem percorrerá o percurso, cada subida deve ser um pouco menor que a anterior... +STR_3431 :{SMALLFONT}{BLACK}Assim está melhor - Agora nosso trem conseguirá subir esta colina! Vamos tentar alguns trilhos mais retorcidos... +STR_3432 :{SMALLFONT}{BLACK}Nós precisamos diminuir a velocidade do trem antes da curva final e da estação, então vamos adicionar alguns freios... +STR_3433 :{SMALLFONT}{BLACK}E finalmente adicionaremos os 'freios bloqueadores', que permite dois trens no circuito operarem com mais segurança... +STR_3434 :{SMALLFONT}{BLACK}Vamos testar e ver se funciona! +STR_3435 :{SMALLFONT}{BLACK}Ótimo - funcionou! Vamos adicionar os caminhos e deixar as pessoas entrarem na nossa nova montanha-russa... +STR_3436 :{SMALLFONT}{BLACK}Enquanto esperamos os nossos primeiros passageiros, podíamos personalizar a atração um pouco... # End of tutorial strings -STR_3437 :{SMALLFONT}{BLACK}Clear large areas of scenery from landscape +STR_3437 :{SMALLFONT}{BLACK}Limpar grandes áreas de cenário na paisagem STR_3438 :Impossível remover todos os cenários a partir daqui... STR_3439 :Limpar Cenário STR_3440 :Página 1 @@ -3456,36 +3456,37 @@ STR_3443 :Página 4 STR_3444 :Página 5 STR_3445 :Definir a Área de Patrulha STR_3446 :Cancelar a Área de Patrulha + # New strings, cleaner STR_5120 :Finanças STR_5121 :Pesquisas -STR_5122 :Select rides by track type (like in RCT1) +STR_5122 :Selecionar atrações por tipo de pista (como no RCT1) STR_5123 :Renovar atrações STR_5124 : -STR_5125 :All destructable -STR_5126 :Random title music -STR_5127 :{SMALLFONT}{BLACK}Disable land elevation -STR_5128 :Selection size -STR_5129 :Enter selection size between {COMMA16} and {COMMA16} -STR_5130 :Map size -STR_5131 :Enter map size between {COMMA16} and {COMMA16} +STR_5125 :Tudo destruível +STR_5126 :Música de título aleatória +STR_5127 :{SMALLFONT}{BLACK}Enquanto arrastando, pinta a paisagem ao invés de mudar a elevação +STR_5128 :Tamanho da seleção +STR_5129 :Insira o tamanho da seleção entre {COMMA16} e {COMMA16} +STR_5130 :Tamanho do mapa +STR_5131 :Insira o tamanho do mapa entre {COMMA16} e {COMMA16} STR_5132 :Consertar todas as atrações -STR_5133 :{SMALLFONT}{BLACK}Adjust smaller area of land rights -STR_5134 :{SMALLFONT}{BLACK}Adjust larger area of land rights -STR_5135 :{SMALLFONT}{BLACK}Buy land rights and construction rights -STR_5136 :Land rights -STR_5137 :Allow lift hill and launch speeds{NEWLINE}up to {VELOCITY} +STR_5133 :{SMALLFONT}{BLACK}Ajustar área menor de direitos de terreno +STR_5134 :{SMALLFONT}{BLACK}Ajustar área maior de direitos de terreno +STR_5135 :{SMALLFONT}{BLACK}Comprar direitos de terreno e direitos de construção +STR_5136 :Direitos de terreno +STR_5137 :Destrava os limites de operação STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} STR_5139 :{WHITE}{STRINGID} -STR_5140 :Disable brakes failure -STR_5141 :Disable all breakdowns -STR_5142 :Normal Speed -STR_5143 :Quick Speed -STR_5144 :Fast Speed -STR_5145 :Turbo Speed -STR_5146 :Hyper Speed +STR_5140 :Desativar falhas nos freios +STR_5141 :Desativar todas as quebras +STR_5142 :Velocidade Normal +STR_5143 :Velocidade Rápida +STR_5144 :Velocidade Muito Rápida +STR_5145 :Velocidade Turbo +STR_5146 :Hiper Velocidade STR_5147 :Trapaças -STR_5148 :{SMALLFONT}{BLACK}Change the game speed +STR_5148 :{SMALLFONT}{BLACK}Mudar velocidade do jogo STR_5149 :{SMALLFONT}{BLACK}Exibir opções de trapaça STR_5150 :Habilitar ferramentas de depuração STR_5151 :, @@ -3494,7 +3495,7 @@ STR_5153 :Editar Temas... STR_5154 :Exibição por Hardware STR_5155 :Permitir o teste de atrações incompletas STR_5156 :{SMALLFONT}{BLACK}Permite testar a maioria dos tipos de atrações, mesmo quando a atração está inacabada, não se aplica bloquear os modos seccionados -STR_5157 :Unlock all prices +STR_5157 :Destravar todos os preços STR_5158 :Sair para o menu STR_5159 :Sair do OpenRCT2 STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, Ano {POP16}{COMMA16} @@ -3502,133 +3503,133 @@ STR_5161 :Formato da Data: STR_5162 :Dia/Mês/Ano STR_5163 :Mês/Dia/Ano STR_5164 :Nome do canal do Twitch -STR_5165 :Name peeps after followers -STR_5166 :{SMALLFONT}{BLACK}Will name peeps after channel's Twitch followers -STR_5167 :Track follower peeps -STR_5168 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after channel's Twitch followers -STR_5169 :Name peeps after people in Twitch chat -STR_5170 :{SMALLFONT}{BLACK}Will name peeps after people in Twitch chat -STR_5171 :Track chat peeps -STR_5172 :{SMALLFONT}{BLACK}Will turn on tracking information for guests named after Twitch chat participants -STR_5173 :Pull Twitch chat as news -STR_5174 :{SMALLFONT}{BLACK}Will use Twitch chat messages preceded by !news for in game notifications -STR_5175 :Input the name of your Twitch channel -STR_5176 :Habilita integração com Twitch -STR_5177 :Modo tela inteira: +STR_5165 :Usar nome dos seguidores +STR_5166 :{SMALLFONT}{BLACK}Usa o nome dos seguidores do seu canal no Twitch nos visitantes +STR_5167 :Rastrear visitantes seguidores +STR_5168 :{SMALLFONT}{BLACK}Liga a informação de rastreamento dos visitantes com nome igual aos dos seguidores do seu canal no Twitch +STR_5169 :Usar nome das pessoas no chat do Twitch +STR_5170 :{SMALLFONT}{BLACK}Usa o nome das pessoas no chat do Twitch nos visitantes +STR_5171 :Rastrear visitantes do chat +STR_5172 :{SMALLFONT}{BLACK}Liga a informação de rastreamento dos visitantes com nome igual aos das pessoas do chat do Twitch +STR_5173 :Mostrar chat do Twitch como notícias +STR_5174 :{SMALLFONT}{BLACK}Usará as mensagens do chat do Twitch precedido por !news nas notificações dentro do jogo +STR_5175 :Insira o nome do seu canal no Twitch +STR_5176 :Habilitar integração com Twitch +STR_5177 :Modo de tela: STR_5178 :{SMALLFONT}{BLACK}Mostrar trapaças financeiras STR_5179 :{SMALLFONT}{BLACK}Mostrar trapaças de visitantes STR_5180 :{SMALLFONT}{BLACK}Mostrar trapaças do parque STR_5181 :{SMALLFONT}{BLACK}Mostrar trapaças das atrações STR_5182 :{INT32} -STR_5183 :Base height -STR_5184 :Enter base height between {COMMA16} and {COMMA16} -STR_5185 :Water level -STR_5186 :Enter water level between {COMMA16} and {COMMA16} +STR_5183 :Altura da base +STR_5184 :Insira altura da base entre {COMMA16} e {COMMA16} +STR_5185 :Nível da água +STR_5186 :Insira o nível da água entre {COMMA16} e {COMMA16} STR_5187 :Finanças STR_5188 :Nova Campanha STR_5189 :Pesquisa STR_5190 :Mapa -STR_5191 :Viewport -STR_5192 :Recent News -STR_5193 :Land +STR_5191 :Janela de Exibição +STR_5192 :Notícias Recentes +STR_5193 :Terreno STR_5194 :Água -STR_5195 :Clear Scenery -STR_5196 :Land Rights -STR_5197 :Scenery -STR_5198 :Footpath -STR_5199 :Ride Construction -STR_5200 :Track Design Place -STR_5201 :New Ride -STR_5202 :Track Design Selection -STR_5203 :Ride -STR_5204 :Ride List -STR_5205 :Guest -STR_5206 :Guest List -STR_5207 :Staff -STR_5208 :Staff List +STR_5195 :Limpar Cenário +STR_5196 :Direitos de Terreno +STR_5197 :Cenário +STR_5198 :Calçada +STR_5199 :Construção de Atração +STR_5200 :Local do Projeto de Pista +STR_5201 :Nova Atração +STR_5202 :Seleção de Projeto de Pista +STR_5203 :Atração +STR_5204 :Lista de Atrações +STR_5205 :Visitantes +STR_5206 :Lista de Visitantes +STR_5207 :Funcionário +STR_5208 :Lista de Funcionários STR_5209 :Banner -STR_5210 :Object Selection -STR_5211 :Invention List -STR_5212 :Scenario Options -STR_5213 :Objective Options -STR_5214 :Map Generation -STR_5215 :Track Design Manager -STR_5216 :Track Design Manager List -STR_5217 :Cheats -STR_5218 :Themes -STR_5219 :Options -STR_5220 :Keyboard Shortcuts -STR_5221 :Change Keyboard Shortcut -STR_5222 :Load/Save -STR_5223 :Save Prompt -STR_5224 :Demolish Ride Prompt -STR_5225 :Fire Staff Prompt -STR_5226 :Track Delete Prompt -STR_5227 :Save Overwrite Prompt -STR_5228 :{SMALLFONT}{BLACK}Main UI -STR_5229 :{SMALLFONT}{BLACK}Park -STR_5230 :{SMALLFONT}{BLACK}Tools -STR_5231 :{SMALLFONT}{BLACK}Rides and Peeps -STR_5232 :{SMALLFONT}{BLACK}Editors -STR_5233 :{SMALLFONT}{BLACK}Miscellaneous -STR_5234 :{SMALLFONT}{BLACK}Prompts -STR_5235 :{SMALLFONT}{BLACK}Settings -STR_5236 :Window: -STR_5237 :Palette: -STR_5238 :Current Theme: -STR_5239 :Duplicate -STR_5240 :Enter a name for the theme -STR_5241 :Can't change this theme -STR_5242 :Theme name already exists -STR_5243 :Invalid characters used -STR_5244 :Themes -STR_5245 :Top Toolbar -STR_5246 :Bottom Toolbar -STR_5247 :Track Editor Bottom Toolbar -STR_5248 :Scenario Editor Bottom Toolbar -STR_5249 :Title Menu Buttons -STR_5250 :Title Exit Button -STR_5251 :Title Options Button -STR_5252 :Title Scenario Selection -STR_5253 :Park Information -STR_5254 :Create -STR_5255 :{SMALLFONT}{BLACK}Create a new title sequence from scratch -STR_5256 :Create a new theme to make changes to -STR_5257 :{SMALLFONT}{BLACK}Create a new theme based on the current one -STR_5258 :{SMALLFONT}{BLACK}Delete the current theme -STR_5259 :{SMALLFONT}{BLACK}Rename the current theme -STR_5260 :Giant Screenshot -STR_5261 :Filter +STR_5210 :Seleção de Objetos +STR_5211 :Lista de Invenções +STR_5212 :Opções de Cenário +STR_5213 :Opções de Objetivo +STR_5214 :Gerador de Mapa +STR_5215 :Gerenciador de Projeto de Pista +STR_5216 :Lista de Gerenciador de Projeto de Pista +STR_5217 :Trapaças +STR_5218 :Temas +STR_5219 :Opções +STR_5220 :Atalhos de Teclado +STR_5221 :Mudar Atalhos de Teclado +STR_5222 :Carregar/Salvar +STR_5223 :Pop-up de Salvamento +STR_5224 :Pop-up de Demolição de Atração +STR_5225 :Pop-up de Demissão de Funcionários +STR_5226 :Pop-up de Exclusão de Pista +STR_5227 :Pop-up de Salvamento Sobrescrito +STR_5228 :{SMALLFONT}{BLACK}Interface de Usuário Principal +STR_5229 :{SMALLFONT}{BLACK}Parque +STR_5230 :{SMALLFONT}{BLACK}Ferramentas +STR_5231 :{SMALLFONT}{BLACK}Atrações e Visitantes +STR_5232 :{SMALLFONT}{BLACK}Editores +STR_5233 :{SMALLFONT}{BLACK}Variados +STR_5234 :{SMALLFONT}{BLACK}Pop-ups +STR_5235 :{SMALLFONT}{BLACK}Configurações +STR_5236 :Janela: +STR_5237 :Paleta: +STR_5238 :Tema Atual: +STR_5239 :Duplicar +STR_5240 :Insita um nome para o tema +STR_5241 :Impossível mudar este tema +STR_5242 :Já existe um tema com este nome +STR_5243 :Caracteres inválidos usados +STR_5244 :Temas +STR_5245 :Barra de Ferramentas Superior +STR_5246 :Barra de Ferramentas Inferior +STR_5247 :Barra Inferior do Editor de Pista +STR_5248 :Barra Inferior do Editor de Cernário +STR_5249 :Botões do Menu do Jogo +STR_5250 :Botão de Saída do Jogo +STR_5251 :Botão de Opções do Jogo +STR_5252 :Seleção de Cenários do Jogo +STR_5253 :Informações do Parque +STR_5254 :Criar +STR_5255 :{SMALLFONT}{BLACK}Cria uma nova sequência de título a partir de um rascunho +STR_5256 :Criar um novo tema para fazer mudanças +STR_5257 :{SMALLFONT}{BLACK}Cria um novo tema baseado no atual +STR_5258 :{SMALLFONT}{BLACK}Deleta tema atual +STR_5259 :{SMALLFONT}{BLACK}Renomeia tema atual +STR_5260 :Captura Gigante de Tela +STR_5261 :Filtrar STR_5262 :Wacky Worlds STR_5263 :Time Twister -STR_5264 :Custom -STR_5265 :{SMALLFONT}{BLACK}Select which content sources are visible -STR_5266 :{SMALLFONT}{BLACK}Display -STR_5267 :{SMALLFONT}{BLACK}Culture and Units -STR_5268 :{SMALLFONT}{BLACK}Audio -STR_5269 :{SMALLFONT}{BLACK}Controls and interface -STR_5270 :{SMALLFONT}{BLACK}Miscellaneous +STR_5264 :Personalizar +STR_5265 :{SMALLFONT}{BLACK}Selecione quais fontes de conteúdo são visíveis +STR_5266 :{SMALLFONT}{BLACK}Exibição +STR_5267 :{SMALLFONT}{BLACK}Idioma e Unidades +STR_5268 :{SMALLFONT}{BLACK}Áudio +STR_5269 :{SMALLFONT}{BLACK}Controles e interface +STR_5270 :{SMALLFONT}{BLACK}Variados STR_5271 :{SMALLFONT}{BLACK}Twitch -STR_5272 :{SMALLFONT}{BLACK}Small Scenery -STR_5273 :{SMALLFONT}{BLACK}Large Scenery -STR_5274 :{SMALLFONT}{BLACK}Footpath -STR_5275 :Search for Objects -STR_5276 :Enter the name of an object to search for -STR_5277 :Claro +STR_5272 :{SMALLFONT}{BLACK}Cenário Pequeno +STR_5273 :{SMALLFONT}{BLACK}Cenário Grande +STR_5274 :{SMALLFONT}{BLACK}Calçada +STR_5275 :Procurar por Objetos +STR_5276 :Insira o nome do objeto que deseja procurar +STR_5277 :Limpar STR_5278 :Modo sandbox ativado STR_5279 :Modo sandbox desativado -STR_5280 :{SMALLFONT}{BLACK}Allow editing land ownership settings through the Map window and other options that are normally restricted to the Scenario Editor -STR_5281 :{SMALLFONT}{BLACK}Features -STR_5282 :RCT1 Ride Open/Close Lights -STR_5283 :RCT1 Park Open/Close Lights -STR_5284 :RCT1 Scenario Selection Font +STR_5280 :{SMALLFONT}{BLACK}Permite editar configurações de posse de terreno através da janela do mapa e outras opções que normalmente são restritas no Editor de Cenário +STR_5281 :{SMALLFONT}{BLACK}Características +STR_5282 :Luzes de Abrir/Fechar Atração do RCT1 +STR_5283 :Luzes de Abrir/Fechar Parque do RCT1 +STR_5284 :Fonte de Seleção de Cenário do RCT1 STR_5285 :EXPLODIR!! -STR_5286 :{SMALLFONT}{BLACK}Explodir alguns visitantes +STR_5286 :{SMALLFONT}{BLACK}Exploda alguns visitantes STR_5287 :Atração já está quebrada STR_5288 :Atração está fechada -STR_5289 :Indisponível quebra para essa atração +STR_5289 :Quebras indisponíveis para essa atração STR_5290 :Consertar atração -STR_5291 :Impossível forçar quebra +STR_5291 :Impossível forçar a quebra STR_5292 :{SMALLFONT}{BLACK}Forçar quebra STR_5293 :{SMALLFONT}{BLACK}Fechar atração STR_5294 :{SMALLFONT}{BLACK}Testar atração @@ -3637,11 +3638,11 @@ STR_5296 :{SMALLFONT}{BLACK}Fechar parque STR_5297 :{SMALLFONT}{BLACK}Abrir parque STR_5298 :{RED}{STRINGID} STR_5299 :{LIGHTPINK}{STRINGID} -STR_5300 :{SMALLFONT}{BLACK}Quick fire staff +STR_5300 :{SMALLFONT}{BLACK}Demitir funcionários rapidamente STR_5301 :{MEDIUMFONT}{BLACK}Limpar seu empréstimo STR_5302 :Limpar empréstimo -STR_5303 :Allow building in pause mode -STR_5304 :Sequencia de Títulos: +STR_5303 :Permitir construir com jogo pausado +STR_5304 :Sequência de Títulos: STR_5305 :RollerCoaster Tycoon 1 STR_5306 :RollerCoaster Tycoon 1 (AA) STR_5307 :RollerCoaster Tycoon 1 (AA + LL) @@ -3650,8 +3651,8 @@ STR_5309 :OpenRCT2 STR_5310 :Aleatório STR_5311 :{SMALLFONT}{BLACK}Ferramentas de depuração STR_5312 :Exibir console -STR_5313 :Exibir inspetor de título -STR_5314 :Inspetor de título +STR_5313 :Exibir inspetor de azulejo +STR_5314 :Inspetor de azulejo STR_5315 :Grama STR_5316 :Areia STR_5317 :Sujeira @@ -3676,10 +3677,10 @@ STR_5335 :Entrada da atração STR_5336 :Saida da atração STR_5337 :Entrada do parque STR_5338 :Tipo de elemento -STR_5339 :Altura da base -STR_5340 :Altura de passagem +STR_5339 :{SMALLFONT}{BLACK}Altura da base +STR_5340 :{SMALLFONT}{BLACK}Altura de segurança STR_5341 :Bandeiras -STR_5342 :Escolha o titulo do mapa +STR_5342 :Escolha o azulejo do mapa STR_5343 :Colocar automaticamente funcionários STR_5344 :Log de mudanças STR_5345 :Trapaça financeira @@ -3687,65 +3688,65 @@ STR_5346 :Trapaça do visitante STR_5347 :Trapaça da atração STR_5348 :Trapaça do parque STR_5349 :{SMALLFONT}{BLACK}Todas as Atrações -STR_5350 :Max +STR_5350 :Máx STR_5351 :Min STR_5352 :{BLACK}Felicidade: STR_5353 :{BLACK}Energia: STR_5354 :{BLACK}Fome: STR_5355 :{BLACK}Sede: STR_5356 :{BLACK}Náusea: -STR_5357 :{BLACK}Tolerância a náusea +STR_5357 :{BLACK}Tolerância a náusea: STR_5358 :{BLACK}Banheiro: -STR_5359 :Remove os visitantes +STR_5359 :Remover visitantes STR_5360 :{SMALLFONT}{BLACK}Remove todos os visitantes do mapa -STR_5361 :{BLACK}De a todos os visitantes: +STR_5361 :{BLACK}Dar a todos os visitantes: STR_5362 :{BLACK}Intensidade preferida: STR_5363 :Maior que 1 STR_5364 :Menor que 15 STR_5365 :{BLACK}Vel. dos funcionários: STR_5366 :Normal STR_5367 :Rápido -STR_5368 :Redefinir o status de acidente +STR_5368 :Redefinir status de acidente STR_5369 :Parâmetros do parque... STR_5370 :{SMALLFONT}{BLACK}Clique nesse botão para modificar os parâmetros {NEWLINE}do parque com restrições,{NEWLINE}geração de visitantes e dinheiro. -STR_5371 :Object Selection +STR_5371 :Seleção de Objetos STR_5372 :Inverter seleção do botão direito do mouse STR_5373 :Nome {STRINGID} STR_5374 :Data {STRINGID} STR_5375 :{UP} STR_5376 :{DOWN} -STR_5377 :{SMALLFONT}{BLACK}Saves -STR_5378 :{SMALLFONT}{BLACK}Script -STR_5379 :{SMALLFONT}{BLACK}Skip to next wait command -STR_5380 :{SMALLFONT}{BLACK}Start playing title sequence -STR_5381 :{SMALLFONT}{BLACK}Stop playing title sequence -STR_5382 :{SMALLFONT}{BLACK}Restart title sequence -STR_5383 :{SMALLFONT}{BLACK}Create a new title sequence based on the current one -STR_5384 :{SMALLFONT}{BLACK}Delete the current title sequence -STR_5385 :{SMALLFONT}{BLACK}Rename the current title sequence -STR_5386 :{SMALLFONT}{BLACK}Insert a new command -STR_5387 :{SMALLFONT}{BLACK}Edit the selected command -STR_5388 :{SMALLFONT}{BLACK}Delete the selected command -STR_5389 :{SMALLFONT}{BLACK}Skip to the selected command in the title sequence -STR_5390 :{SMALLFONT}{BLACK}Move the selected command down -STR_5391 :{SMALLFONT}{BLACK}Move the selected command up -STR_5392 :{SMALLFONT}{BLACK}Add a save to the title sequence -STR_5393 :{SMALLFONT}{BLACK}Remove the selected save from the title sequence -STR_5394 :{SMALLFONT}{BLACK}Rename the selected save -STR_5395 :{SMALLFONT}{BLACK}Load the selected save in game -STR_5396 :{SMALLFONT}{BLACK}Reload the title sequence if changes have been made to it outside of the game -STR_5397 :Can only be used on the title screen -STR_5398 :Cannot edit title sequence while it's playing -STR_5399 :Press the stop button to continue editing +STR_5377 :{SMALLFONT}{BLACK}Jogos Salvos +STR_5378 :{SMALLFONT}{BLACK}Roteiro +STR_5379 :{SMALLFONT}{BLACK}Pula para o próximo comando de espera +STR_5380 :{SMALLFONT}{BLACK}Executa sequência de título +STR_5381 :{SMALLFONT}{BLACK}Para sequência de título +STR_5382 :{SMALLFONT}{BLACK}Reinicia sequência de título +STR_5383 :{SMALLFONT}{BLACK}Cria uma nova sequência de título baseada na atual +STR_5384 :{SMALLFONT}{BLACK}Deleta a sequência de título atual +STR_5385 :{SMALLFONT}{BLACK}Renomeia a sequência de título atual +STR_5386 :{SMALLFONT}{BLACK}Insere um novo comando +STR_5387 :{SMALLFONT}{BLACK}Edita o comando selecionado +STR_5388 :{SMALLFONT}{BLACK}Deleta o comando selecionado +STR_5389 :{SMALLFONT}{BLACK}Pula para o comando selecionado na sequência de título +STR_5390 :{SMALLFONT}{BLACK}Move o comando selecionado para cima +STR_5391 :{SMALLFONT}{BLACK}Move o comando selecionado para baixo +STR_5392 :{SMALLFONT}{BLACK}Adiciona um jogo salvo à sequência de título +STR_5393 :{SMALLFONT}{BLACK}Remove o jogo salvo selecionado da sequência de título +STR_5394 :{SMALLFONT}{BLACK}Renomeia o jogo salvo selecionado +STR_5395 :{SMALLFONT}{BLACK}Carrega o jogo salvo selecionado no jogo +STR_5396 :{SMALLFONT}{BLACK}Recarrega a sequência de título se mudanças foram feitas fora do jogo +STR_5397 :Só pode ser usando na tela de título +STR_5398 :Impossível editar sequência de título enquanto estiver executando +STR_5399 :Aperte o botão de parar para continuar editando STR_5400 :Impossível alterar esta sequência de título -STR_5401 :Criar uma nova sequência de título para fazer alterações para +STR_5401 :Criar uma nova sequência de título para fazer alterações STR_5402 :Falha ao carregar a sequência do título -STR_5403 :Não pode haver nenhuma carga, comando de espera ou uma gravação pode ser inválida +STR_5403 :Pode haver nenhuma carga, comando de espera ou uma gravação pode ser inválida STR_5404 :Este nome já existe -STR_5405 :Insira um nome para o salvar +STR_5405 :Insira um nome para a gravação STR_5406 :Insira um nome para a sequência de título STR_5407 :Adicionar -STR_5408 :Remoder +STR_5408 :Remover STR_5409 :Inserir STR_5410 :Editar STR_5411 :Recarregar @@ -3753,33 +3754,33 @@ STR_5412 :Ir para STR_5413 :Carregar STR_5414 :Carregar{MOVE_X}{87}Six Flags Magic Mountain.SC6 STR_5415 :Carregar{MOVE_X}{87}{STRING} -STR_5416 :Carregar{MOVE_X}{87}Salvar não selecionado -STR_5417 :localização +STR_5416 :Carregar{MOVE_X}{87}Jogo salvo não selecionado +STR_5417 :Localização STR_5418 :Localização{MOVE_X}{87}{COMMA16} {COMMA16} STR_5419 :Rotacionar STR_5420 :Rotacionar{MOVE_X}{87}{COMMA16} STR_5421 :Ampliar STR_5422 :Ampliar{MOVE_X}{87}{COMMA16} -STR_5423 :Aguarde -STR_5424 :Wait{MOVE_X}{87}{COMMA16} +STR_5423 :Aguardar +STR_5424 :Aguardar{MOVE_X}{87}{COMMA16} STR_5425 :Reiniciar STR_5426 :Fim STR_5427 :Cordenadas: -STR_5428 :Rotações anti-horário: +STR_5428 :Rotações anti-horárias: STR_5429 :Nível de ampliação: STR_5430 :Segundos de espera: STR_5431 :Salvar para carregar: STR_5432 :Comando: STR_5433 :Sequências de título -STR_5434 :Command Editor -STR_5435 :Rename save +STR_5434 :Editor de Comando +STR_5435 :Renomear jogo salvo STR_5436 :Editar a sequência de título... -STR_5437 :Salvar não selecionado +STR_5437 :Jogo salvo não selecionado STR_5438 :Impossível fazer mudanças enquanto editor de comando está aberto STR_5439 :Um comando de espera com pelo menos 4 segundos é necessário com um comando de reinicialização -STR_5440 :Minimizar tela inteira quando perder o faco +STR_5440 :Minimizar tela inteira quando perder o foco STR_5441 :{SMALLFONT}{BLACK}Identificar as atrações por tipo de pista,{NEWLINE}assim os veículos podem ser alterados {NEWLINE}depois, como no RCT1. -STR_5442 :Forças a classificação do parque: +STR_5442 :Forçar a classificação do parque: STR_5443 :Velocidade{MOVE_X}{87}{STRINGID} STR_5444 :Velocidade: STR_5445 :Velocidade @@ -3811,7 +3812,7 @@ STR_5470 :Desloca mapa para esquerda STR_5471 :Desloca mapa para baixo STR_5472 :Desloca mapa para direita STR_5473 :Ciclo dia / noite -STR_5474 :Exibie texto nos banners em letras maiúsculas +STR_5474 :Exibe texto nos banners em letras maiúsculas STR_5475 :{COMMA16} semanas STR_5476 :Hardware STR_5477 :Renderização do mapa @@ -3825,7 +3826,7 @@ STR_5484 :{BLACK}({COMMA16} semana restante) STR_5485 :{SMALLFONT}{STRING} STR_5486 :{BLACK}{COMMA16} STR_5487 :{SMALLFONT}{BLACK}Exibir as mensagens recentes -STR_5488 :Entrada proibida +STR_5488 :Sem entrada (Somente no OpenRCT2!) STR_5489 :{SMALLFONT}{BLACK}Mostrar apenas os visitantes monitorados STR_5490 :Desativar som quando perder o foco STR_5491 :Lista de Invenções @@ -3837,20 +3838,20 @@ STR_5496 :Jogador: STR_5497 :Ping: STR_5498 :Lista de Servidores STR_5499 :Nome do Jogador: -STR_5500 :Adic. Servidor +STR_5500 :Adicionar Servidor STR_5501 :Iniciar Servidor STR_5502 :Multijogador STR_5503 :Digite o nome do servidor ou o endereço de IP: STR_5504 :{SMALLFONT}{BLACK}Exibir o estado do multijogador STR_5505 :Impossível se conectar ao servidor. STR_5506 :Os Visistantes ignoram as intensidades -STR_5507 :Faz-Tudo corta a grama por padrão +STR_5507 :Faxineiro corta a grama por padrão STR_5508 :Carregamento de arquivos com checksums incorreto STR_5509 :{SMALLFONT}{BLACK}Permitir o carregamento de cenários e jogos salvos que possuam checksum incorreto, como os cenários do demo e jogos salvos danificados. STR_5510 :Dispositivo de som padrão STR_5511 :(DESCONHECIDO) STR_5512 :Salvar Jogo Como -STR_5513 :(Rapido) salvar jogo +STR_5513 :(Rápido) salvar jogo STR_5514 :Desativar vandalismo STR_5515 :{SMALLFONT}{BLACK}Parar o vandalismo dos visitantes no seu parque quando eles estão com raiva STR_5516 :{SMALLFONT}{BLACK}Preto @@ -3861,14 +3862,14 @@ STR_5520 :{SMALLFONT}{BLACK}Roxo claro STR_5521 :{SMALLFONT}{BLACK}Roxo brilhante STR_5522 :{SMALLFONT}{BLACK}Azul escuro STR_5523 :{SMALLFONT}{BLACK}Azul claro -STR_5524 :{SMALLFONT}{BLACK}Azul Gelo -STR_5525 :{SMALLFONT}{BLACK}Azul esverdeado -STR_5526 :{SMALLFONT}{BLACK}Turquesa +STR_5524 :{SMALLFONT}{BLACK}Azul gelo +STR_5525 :{SMALLFONT}{BLACK}Água escura +STR_5526 :{SMALLFONT}{BLACK}Água clara STR_5527 :{SMALLFONT}{BLACK}Verde saturado STR_5528 :{SMALLFONT}{BLACK}Verde escuro -STR_5529 :{SMALLFONT}{BLACK}Moss green -STR_5530 :{SMALLFONT}{BLACK}Bright green -STR_5531 :{SMALLFONT}{BLACK}Olive green +STR_5529 :{SMALLFONT}{BLACK}Verde musgo +STR_5530 :{SMALLFONT}{BLACK}Verde brilhante +STR_5531 :{SMALLFONT}{BLACK}Verde oliva STR_5532 :{SMALLFONT}{BLACK}Verde oliva escuro STR_5533 :{SMALLFONT}{BLACK}Amarelo brilhante STR_5534 :{SMALLFONT}{BLACK}Amarelo @@ -3890,11 +3891,662 @@ STR_5549 :Ano/Mês/Dia STR_5550 :{POP16}{POP16}Ano {COMMA16}, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} STR_5551 :Ano/Mês/Dia STR_5552 :{POP16}{POP16}Ano {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} -STR_5553 :Pausar o jogo quando a Steam estiver aberta sobrepondo +STR_5553 :Pausar jogo quando a Steam estiver sobrepondo STR_5554 :{SMALLFONT}{BLACK}Habilitar ferramenta de montanha -STR_5555 :Exibir veiculos de outros tipos de atrações +STR_5555 :Exibir veículos de outras atrações STR_5556 :Remover Jogador -STR_5557 :Manter conectado após dessincronização (Multijogador) +STR_5557 :Ficar conectado após dessincronização (Multijogador) +STR_5558 :Reinicie o jogo para esta configuração ter efeito +STR_5559 :Inspeções de 10 min +STR_5560 :{SMALLFONT}{BLACK}Define o tempo de inspeção para 'A cada 10 minutos' em todas as atrações +STR_5561 :Falhou ao carregar idioma +STR_5562 :AVISO! +STR_5563 :Esta característica está atualmente instável, tome um cuidado maior. +STR_5564 :Inserir Elemento Corrompido +STR_5565 :{SMALLFONT}{BLACK}Insere um elemento de mapa corrompido no topo do quadrado. Isto irá esconder qualquer elemento acima do elemento corrompido. +STR_5566 :Senha: +STR_5567 :Promover +STR_5568 :Senha Requerida +STR_5569 :Este servidor requer uma senha +STR_5570 :Buscar Servidores +STR_5571 :Entrar no Jogo +STR_5572 :Adicionar aos Favoritos +STR_5573 :Remover dos Favoritos +STR_5574 :Nome do Servidor: +STR_5575 :Máximo de Jogadores: +STR_5576 :Porta: +STR_5577 :Won Sul-Coreano(W) +STR_5578 :Rublo Russo (R) +STR_5579 :Fator escalar da janela: +STR_5580 :Coroa Tcheca (Kc) +STR_5581 :Mostrar FPS +STR_5582 :Manter ponteiro do mouse dentro da janela +STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} +STR_5584 :SI +STR_5585 :{SMALLFONT}{BLACK}Destrava limites de operação na atração, permitindo coisas como corrente de elevação com {VELOCITY} +STR_5586 :Abrir automaticamente lojas e barracas +STR_5587 :{SMALLFONT}{BLACK}Quando habilitado, lojas e barracas serão abertas automaticamente depois de contruí-las +STR_5588 :{SMALLFONT}{BLACK}Jogar com outros jogadores +STR_5589 :Configurações de Notificação +STR_5590 :Prêmios do parque +STR_5591 :A campanha de marketing terminou +STR_5592 :Avisos do parque +STR_5593 :Avisos de classificação do parque +STR_5594 :Atração quebrou +STR_5595 :Atração bateu +STR_5596 :Avisos de atração +STR_5597 :Atração / Cernário pesquisado +STR_5598 :Avisos de visitantes +STR_5599 :Visitante está perdido +STR_5600 :Visitante saiu do parque +STR_5601 :Visitante está esperando na fila para atração +STR_5602 :Visitante está na atração +STR_5603 :Visitante saiu da atração +STR_5604 :Visitante comprou um item +STR_5605 :Visitante usou uma instalação +STR_5606 :Visitante morreu +STR_5607 :{SMALLFONT}{BLACK}Força remoção do elemento de mapa selecionado. +STR_5608 :AB +STR_5609 :AS +STR_5610 :{SMALLFONT}{BLACK}Remove o elemento de mapa atual selecionado. Isto irá forçar a remoção dele, então nenhum dinheiro será gasto/ganho. Use com cuidado. +STR_5611 :F +STR_5612 :{SMALLFONT}{BLACK}Bandeira fantasma +STR_5613 :Q +STR_5614 :{SMALLFONT}{BLACK}Bandeira quebrada +STR_5615 :U +STR_5616 :{SMALLFONT}{BLACK}Último elemento para a bandeira do azulejo +STR_5617 :{SMALLFONT}{BLACK}Move elemento selecionado para cima. +STR_5618 :{SMALLFONT}{BLACK}Move elemento selecionado para baixo. +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 :Parques {OPENQUOTES}Reais{ENDQUOTES} +STR_5626 :Outros parques +STR_5627 :Agrupar lista de cenário por: +STR_5628 :Origem do jogo +STR_5629 :Nível de dificuldade +STR_5630 :Habilitar destravamento de cenários +STR_5631 :Parques Originais Baixados (DLC) +STR_5632 :Construa seu próprio... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Dinheiro gasto: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Comandos executados: {BLACK}{COMMA16} +STR_5637 :Não é possível fazer isto... +STR_5638 :Permissão negada +STR_5639 :{SMALLFONT}{BLACK}Mostrar lista de jogadores +STR_5640 :{SMALLFONT}{BLACK}Gerenciar grupos +STR_5641 :Grupo Padrão: +STR_5642 :Grupo: +STR_5643 :Adicionar Grupo +STR_5644 :Remover Grupo +STR_5645 :Bate-Papo +STR_5646 :Terraform +STR_5647 :Alternar Pausa +STR_5648 :Definir Nível da Água +STR_5649 :Criar Atração +STR_5650 :Remover Atração +STR_5651 :Construir Atração +STR_5652 :Propriedades da Atração +STR_5653 :Cenário +STR_5654 :Calçada +STR_5655 :Visitante +STR_5656 :Funcionário +STR_5657 :Propriedades do Parque +STR_5658 :Financiamento do Parque +STR_5659 :Expulsar Jogador +STR_5660 :Modificar Grupos +STR_5661 :Definir Grupo do Jogador +STR_5662 :N/A +STR_5663 :Limpar Paisagem +STR_5664 :Trapaças +STR_5701 :{WINDOW_COLOUR_2}Última ação: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Localizar ação mais recente do jogador +STR_5703 :Não é possível expulsar o anfitrião +STR_5704 :Última Ação: +STR_5705 :Impossível definir para este grupo +STR_5706 :Impossível remover grupo que os jogadores pertencem +STR_5707 :Este grupo não pode ser modificado +STR_5708 :Impossível remover grupo que o anfitrião pertence +STR_5709 :Renomear Grupo +STR_5710 :Nome do grupo +STR_5711 :Insira um novo nome para este grupo: +STR_5712 :Impossível modificar permissão que não é sua +STR_5713 :Expulsar Jogador +STR_5714 :Mostrar janela de opções +STR_5715 :Novo Jogo +STR_5716 :Não é permitido no modo multijogador +# For identifying client network version in server list window +STR_5717 :Versão da rede: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Versão da rede: {STRING} +STR_5719 :Ensolarado +STR_5720 :Parcialmente Nublado +STR_5721 :Nublado +STR_5722 :Chuva +STR_5723 :Chuva Forte +STR_5724 :Tempestade +STR_5725 :{BLACK}Forçar clima: +STR_5726 :{SMALLFONT}{BLACK}Define o clima atual no parque +STR_5727 :Qualidade da escala +STR_5728 :Requer opção de exibição de hardware +STR_5729 :{SMALLFONT}{BLACK}Requer opção de exibição de hardware +STR_5730 :Vizinho mais próximo +STR_5731 :Linear +STR_5732 :Anisotrópica +STR_5733 :Usar escala NN em escalas inteiras +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Renderizando +STR_5735 :Estado da Rede +STR_5736 :Jogador +STR_5737 :Fechado, {COMMA16} pessoa ainda está na atração +STR_5738 :Fechado, {COMMA16} pessoas ainda estão na atração +STR_5739 :{WINDOW_COLOUR_2}Clientes na atração: {BLACK}{COMMA16} +STR_5740 :Campanhas de marketing sem fim +STR_5741 :{SMALLFONT}{BLACK}Campanhas de marketing nunca acabam +STR_5742 :Autenticando ... +STR_5743 :Conectando ... +STR_5744 :Resolvendo ... +STR_5745 :Dessincronização de rede detectada +STR_5746 :Desconectado +STR_5747 :Desconectado: {STRING} +STR_5748 :Expulso +STR_5749 :Saia do servidor! +STR_5750 :Conexão Fechada +STR_5751 :Sem dados +STR_5752 :{OUTLINE}{RED}{STRING} se desconectou +STR_5753 :{OUTLINE}{RED}{STRING} se desconectou ({STRING}) +STR_5754 :Nome de Jogador Ruim +STR_5755 :Versão de Software Incorreta +STR_5756 :Senha Ruim +STR_5757 :Servidor Cheio +STR_5758 :{OUTLINE}{GREEN}{STRING} entrou no jogo +STR_5759 :Baixando mapa ... ({INT32} / {INT32}) +STR_5760 :Dólar de Hong Kong (HK$) +STR_5761 :Dólar de New Taiwan (NT$) +STR_5762 :Yuan Chinês(CN{YEN}) +STR_5763 :Todos os arquivos +STR_5764 :Tipo de atração inválida +STR_5765 :Não é possível editar atração de tipo inválido +STR_5766 : +STR_5767 :Receita +STR_5768 :Clientes totais +STR_5769 :Lucro total +STR_5770 :Clientes por hora +STR_5771 :Custo de operação +STR_5772 :Idade +STR_5773 :Clientes totais: {COMMA32} +STR_5774 :Lucro total: {CURRENCY2DP} +STR_5775 :Clientes: {COMMA32} por hora +STR_5776 :Construído: Este Ano +STR_5777 :Construído: Ano Passado +STR_5778 :Construído: {COMMA16} Anos Atrás +STR_5779 :Receita: {CURRENCY2DP} por hora +STR_5780 :Custo de operação: {CURRENCY2DP} por hora +STR_5781 :Custo de operação: Desconhecido +STR_5782 :Você está conectado. Pressione '{STRING}' para conversar. +STR_5783 :{WINDOW_COLOUR_2}Cenário Trancado +STR_5784 :{BLACK}Complete os cenários anteriores para destravar este cenário. +STR_5785 :Impossível renomear grupo... +STR_5786 :Nome de grupo inválido +STR_5787 :{COMMA32} jogadores online +STR_5788 :Intervalo de inspeção padrão: +STR_5789 :Desabilitar efeitos de relâmpago +STR_5790 :{SMALLFONT}{BLACK}Ativa preço estilo RCT1{NEWLINE}(atrações e entradas ambos pagos) +STR_5791 :{SMALLFONT}{BLACK}Define a confiança de todas as atrações em 100%{NEWLINE}e reinicia a data de construção para "este ano" +STR_5792 :{SMALLFONT}{BLACK}Conserta todos as atrações quebradas +STR_5793 :{SMALLFONT}{BLACK}Reinicia o histórico de acidentes de uma atração,{NEWLINE}então visitantes não irão reclamar que não é seguro +STR_5794 :{SMALLFONT}{BLACK}Alguns cenários desabilitam a edição de algumas{NEWLINE}das atrações que já estão no parque.{NEWLINE}Esta trapaça desliga a restrição +STR_5795 :{SMALLFONT}{BLACK}Visitantes andam em todas as atrações do parque{NEWLINE}mesmo se a intensidade for extremamente alta +STR_5796 :{SMALLFONT}{BLACK}Força o parque a abrir ou fechar +STR_5797 :{SMALLFONT}{BLACK}Desliga a mudança de clima e{NEWLINE}congela no clima selecionado +STR_5798 :{SMALLFONT}{BLACK}Permite construir no modo pausado +STR_5799 :{SMALLFONT}{BLACK}Desabilita quebras nas atrações e acidentes causados por falha nos freios +STR_5800 :{SMALLFONT}{BLACK}Previne atrações de quebrar + +############# +# Scenarios # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :No meio da floresta, construa um próspero parque temático numa grande área aberta. + + +STR_SCNR :Dynamite Dunes +STR_PARK :Dynamite Dunes +STR_DTLS :Construído no meio do deserto, este parque temático contém apenas uma montanha-russa, mas tem espaço para expansão. + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Partindo do zero, construa um parque temático em torno de um grande lago. + + +STR_SCNR :Diamond Heights +STR_PARK :Diamond Heights +STR_DTLS :O Diamond Heights já é um parque temático de sucesso com excelentes brinquedos. Desenvolva-o para dobrar seu valor. + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Converta os belos jardins do Evergreen num própero parque temático. + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Desenvolva o pequeno parque de diversões da Bumbly Beach, transformando-o num próspero parque temático. + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Algumas ilhas formam a base para este novo parque. + + +STR_SCNR :Katie's Dreamland +STR_PARK :Katie's Dreamland +STR_DTLS :Um pequeno parque temático com alguns briquedos e espaço para expansão - Seu objetivo é dobrar o valor do parque. + + +STR_SCNR :Pokey Park +STR_PARK :Pokey Park +STR_DTLS :Um pequeno e limitado parque de diversões que requer mais expansão. + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :Um parque com algumas atrações aquáticas ótimas que requer expansão. + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Converta uma grande mina abandonada de ponto turístico em um parque temático. + + +STR_SCNR :Karts & Coasters +STR_PARK :Karts & Coasters +STR_DTLS :Um grande parque escondido na floresta, somente com pistas de karts e montanhas-russas de madeira. + + +STR_SCNR :Mel's World +STR_PARK :Mel's World +STR_DTLS :Este parque temático tem algumas atrações modernas bem projetadas e muito espaço para expansão. + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :Nas florestas montanhosas de Mystic Mountain, construa um parque temático do zero. + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Converta a atração turística Ruínas Egípcias em um próspero parque temático + + +STR_SCNR :Crumbly Woods +STR_PARK :Crumbly Woods +STR_DTLS :Um grande parque com atrações bem projetadas porém muito velhas - Substitua as atrações velhas ou adicione novas para tornar o parque mais popular. + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :Converta o cais desta cidade sonolenta em uma atração próspera. + + +STR_SCNR :Lightning Peaks +STR_PARK :Lightning Peaks +STR_DTLS :As belas montanhas de Lightning Peaks são populares com andarilhos e turistas - Use a área disponível para atrair uma nova clientela em busca de emoção. + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :Um parque bem estabelecido, que possui alguns problemas. + + +STR_SCNR :Rainbow Valley +STR_PARK :Rainbow Valley +STR_DTLS :A autoridade local de Rainbow Valley não permite mudanças no terreno ou remover as árvores, mas você deve desenvolver a área em um grande parque temático. + + +STR_SCNR :Thunder Rock +STR_PARK :Thunder Rock +STR_DTLS :Thunder Rock fica no meio de um deserto e atrai muitos turistas - Use o espaço disponível para construir atrações e atrair mais pessoas. + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :Apenas por diversão! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Transforme os penhascos à beira-mar em um parque de diversões próspero. + + +STR_SCNR :Three Monkeys Park +STR_PARK :Three Monkeys Park +STR_DTLS :No centro deste grande parque em crescimento está a grande montanha-russa de aço de corrida tripla. + + +STR_SCNR :Canary Mines +STR_PARK :Canary Mines +STR_DTLS :Esta mina abandonada já tem os ingredientes de uma atração turística com sua ferrovia em miniatura e um par de montanhas-russas de querda vertical. + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :Uma velha ponte redundante é sua para transformar em um parque de diversões. + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Cobrindo terra em ambos os lados de uma estrada, este parque já tem vários brinquedos em operação. + + +STR_SCNR :Haunted Harbor +STR_PARK :Haunted Harbor +STR_DTLS :A autoridade local concordou em vender barato o terreno para este pequeno parque litorâneo, com a condição de que certos brinquedos são preservados. + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :Este castelo é todo seu para transformar em um parque temático. + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :Este parque futurísta tem muito espaço para novas atrações em sua paisagem alienígena. + + +STR_SCNR :Gentle Glen +STR_PARK :Gentle Glen +STR_DTLS :A população local prefere atrações calmas e relaxantes, então é seu trabalho expandir este parque para suprir o gosto dela. + + +STR_SCNR :Jolly Jungle +STR_PARK :Jolly Jungle +STR_DTLS :Selva adentro jaz uma grande área pronta para ser transformada em um parque temático. + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :Uma série de lagos íngremes formam a base para este novo parque. + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :Este parque ancião tem muitas atrações históricas mas está muito endividado. + + +STR_SCNR :Magic Quarters +STR_PARK :Magic Quarters +STR_DTLS :Uma grande área foi limpa e parcialmente tematizada pronta para você desenvolver um parque temático. + + +STR_SCNR :Fruit Farm +STR_PARK :Fruit Farm +STR_DTLS :Uma próspera fazenda de frutas contruiu uma ferrovia para acelerar sua receita, seu trabalho é transforma-la em um parque de diversões desenvolvido. + + +STR_SCNR :Butterfly Dam +STR_PARK :Butterfly Dam +STR_DTLS :A área envolta de uma barragem está diponível para você desenvolver um parque de diversões. + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :Um vasto desfiladeiro é todo seu para transformar em um parque temático. + + +STR_SCNR :Thunderstorm Park +STR_PARK :Thunderstorm Park +STR_DTLS :O clima é tão molhado aqui que uma pirâmide gigantesca foi construída para permitir que alguns brinquedos fossem construídos cobertos. + + +STR_SCNR :Harmonic Hills +STR_PARK :Harmonic Hills +STR_DTLS :A autoridade local não te permite construir acima da altura das árvores neste parque. + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Desenvolva um parque com tema romano adicionando brinquedos e montanhas-russas. + + +STR_SCNR :Swamp Cove +STR_PARK :Swamp Cove +STR_DTLS :Construído parcialmente em uma série de pequenas ilhas, este parque já tem um par de grandes montanhas-russas como sua peça cental. + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Construa um parque para apelar às pessoas locais buscadoras de emoção de alta intensidade. + + +STR_SCNR :Utopia Park +STR_PARK :Utopia Park +STR_DTLS :Um oasis no meio de um deserto fornece uma oportunidade incomum de construir um parque de diversões. + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Repleto de vegetação e delapidado, você consegue fazer este parque de diversões que já foi grande ressurgir? + + +STR_SCNR :Fiasco Forest +STR_PARK :Fiasco Forest +STR_DTLS :Cheio de brinquedos perigosos e mal projetados, você tem um orçamento muito limitado, tempo para consertar os problemas e transformar este parque. + + +STR_SCNR :Pickle Park +STR_PARK :Pickle Park +STR_DTLS :A autoridade local não permite qualquer tipo de campanha publicitária ou promoções, então este parque deve ser um sucesso só pela reputação. + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :Uma corrida de obstáculos quádrupla é a peça central deste parque em expansão. + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Tranforme esta pedreira abandonada em um lugar para atrair turistas caçadores de emoções. + + +STR_SCNR :Coaster Crazy +STR_PARK :Coaster Crazy +STR_DTLS :Você tem fundos limitados mas tempo ilimitado para transformar esta área montanhosa em um vasto parque de montanha-russa. + + +STR_SCNR :Urban Park +STR_PARK :Urban Park +STR_DTLS :Um parque minúsculo fez um acordo com a cidade vizinha para permitir a expansão através da própria cidade. + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :Um grande parque de jardim precisa ser transformado em um próspero parque temático. + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :Uma coleção de icebergs faz um ambiente frio para este ambicioso parque temático. + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :Um vulcão dormente é o ambiente para este desafio de construção de montanha-russa. + + +STR_SCNR :Arid Heights +STR_PARK :Arid Heights +STR_DTLS :Livre de qualquer limite financeiro,seu desafio é desenvolver este parque desértico enquanto mantém os visitantes felizes. + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Sua tarefa é construir um parque repleto de montanhas-russas no meio das Razor Rocks. + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :Um grande lago numa cratera anciã é o ambiente para este parque. + + +STR_SCNR :Vertigo Views +STR_PARK :Vertigo Views +STR_DTLS :Este grande parque já tem uma excelente montanha-russa hiper, mas sua tarefa é aumentar massivamente seu lucro. + + +STR_SCNR :Paradise Pier 2 +STR_PARK :Paradise Pier 2 +STR_DTLS :Paradise Pier expandiu sua rede de passarelas sobre o mar, e sua tarefa é expandir o parque para usar o espaço extra. + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :Esta enseada à beira-mar é o ambiente para este desafio de construção de montanha-russa. + + +STR_SCNR :Good Knight Park +STR_PARK :Good Knight Park +STR_DTLS :Um castelo com um par de montanhas-russas precisa ser desenvolvido em um parque temático maior. + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :Um parque que tem boa parte de seus caminhos e montanhas-russas subterrâneos. + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :Um vale cheio de geleira é seu para desenvolver um parque temático. + + +STR_SCNR :Crazy Craters +STR_PARK :Crazy Craters +STR_DTLS :Em um mundo muito distante onde dinheiro não é necessário, você deve construir um centro de entretenimento para manter as pessoas felizes. + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Cinco montanhas-russas requerem ser terminadas neste parque desértico. + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :Neste parque história só é permitico construir atrações com estilo antigo. + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Desenvolva este parque alienígena para maximizar seu lucro. + + +STR_SCNR :Sunny Swamps +STR_PARK :Sunny Swamps +STR_DTLS :Este parque de diversões bem tematizado já tem vários brinquedos e muito espaço para expansão. + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :Um parque assustador com uma montanha-russa gigantesca como peça central. + + +STR_SCNR :Thunder Rocks +STR_PARK :Thunder Rocks +STR_DTLS :Dois grandes pedaços de pedra saem da areia, sobre os quais o início de um parque temático é contruído. + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :Neste grante parque você deve projetar e construir dez grandes montanhas-russas. + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :Uma longa ilha fina fornece um cenário desafiador para construir uma seleção de montanhas-russas. + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :Uma paisagem congelante precisa ser transformada em um parque temático próspero. + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :Um parque desértico com algumas montanhas-russas projetadas com inteligencia é seu para expandir. + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :Neste parque minúsculo você deve terminar de construir cinco montanhas-russas existentes. + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :Um grande parque com um novo sistema de transporte envolta de sua borda. + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :Esta grande ilha é toda sua para desenvolver um parque de diversões. + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :Um gigante arranha-céu abandonado é a oportunidade única para um desenvolvedor de parque temático. + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :Esta área urbana é toda sua para desenvolver um parque de diversões. + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :Um grande parque empacotado com muitos brinquedos precisa de melhoras. + + +STR_SCNR :Venus Ponds +STR_PARK :Venus Ponds +STR_DTLS :Em um planeta distante, esta área precisa ser transformada em um parque temático. + + +STR_SCNR :Micro Park +STR_PARK :Micro Park +STR_DTLS :Tente criar o menor parque mais lucrativo do mundo. + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : ##################### # Rides/attractions # @@ -3904,4 +4556,4 @@ STR_5557 :Manter conectado após dessincronização (Multijogador) [CONDORRD] STR_NAME :Condor STR_DESC :Montando em arreios especiais sob a pista, os passageiros experimentarão a sensação de voar pelo ar em uma estrutura na forma de Condor -STR_CPTY :4 passageiros por carro \ No newline at end of file +STR_CPTY :4 passageiros por carro diff --git a/data/language/spanish_sp.txt b/data/language/spanish_sp.txt index 787a788e5f..9d859217a1 100644 --- a/data/language/spanish_sp.txt +++ b/data/language/spanish_sp.txt @@ -1,99 +1,99 @@ -# STR_XXXX part is read and XXXX becomes the string id number. +# STR_XXXX part is read and XXXX becomes the string id number. STR_1672 # Everything after the colon and before the new line will be saved as the string. # Use # at the beginning of a line to leave a comment. STR_0000 : STR_0001 :{STRINGID} {COMMA16} -STR_0002 :Spiral Roller Coaster -STR_0003 :Stand-up Roller Coaster -STR_0004 :Suspended Swinging Coaster -STR_0005 :Inverted Roller Coaster -STR_0006 :Junior Roller Coaster -STR_0007 :Miniature Railway -STR_0008 :Monorail -STR_0009 :Mini Suspended Coaster -STR_0010 :Boat Ride -STR_0011 :Wooden Wild Mouse -STR_0012 :Steeplechase -STR_0013 :Car Ride -STR_0014 :Launched Freefall -STR_0015 :Bobsleigh Coaster -STR_0016 :Observation Tower -STR_0017 :Looping Roller Coaster -STR_0018 :Dinghy Slide -STR_0019 :Mine Train Coaster -STR_0020 :Chairlift -STR_0021 :Corkscrew Roller Coaster -STR_0022 :Maze -STR_0023 :Spiral Slide -STR_0024 :Go Karts -STR_0025 :Log Flume -STR_0026 :River Rapids -STR_0027 :Dodgems -STR_0028 :Pirate Ship -STR_0029 :Swinging Inverter Ship -STR_0030 :Food Stall -STR_0031 :Unknown Stall (1D) -STR_0032 :Drink Stall -STR_0033 :Unknown Stall (1F) -STR_0034 :Shop -STR_0035 :Merry-Go-Round -STR_0036 :Unknown Stall (22) -STR_0037 :Information Kiosk -STR_0038 :Toilets -STR_0039 :Ferris Wheel -STR_0040 :Motion Simulator -STR_0041 :3D Cinema +STR_0002 :Montaña Rusa Espiral +STR_0003 :Montaña Rusa En Pie +STR_0004 :Montaña Rusa Colgante +STR_0005 :Montaña Rusa Invertida +STR_0006 :Montaña Rusa Infantil +STR_0007 :Tren Miniatura +STR_0008 :Monorraíl +STR_0009 :Mini Montaña Rusa Suspendida +STR_0010 :Paseo en bote +STR_0011 :Ratón Loco de Madera +STR_0012 :Carrera Ciega +STR_0013 :Atracción de coches +STR_0014 :Caída Libre Propulsada +STR_0015 :Montaña Rusa Bobsleigh +STR_0016 :Torre de Observación +STR_0017 :Montaña Rusa con Rizo +STR_0018 :Botes deslizantes +STR_0019 :Montaña Rusa Minitrén +STR_0020 :Telesilla +STR_0021 :Montaña Rusa Sacacorchos +STR_0022 :Laberinto +STR_0023 :Tobogán en Espiral +STR_0024 :Go-Karts +STR_0025 :Leños de agua +STR_0026 :Río Rápido +STR_0027 :Coches de Choque +STR_0028 :Barco Pirata +STR_0029 :Barco Balancín Invertido +STR_0030 :Puesto de comida +STR_0031 :Puesto Desconocido (1D) +STR_0032 :Puesto de Bebidas +STR_0033 :Puesto Desconocido (1F) +STR_0034 :Tienda +STR_0035 :Tiovivo +STR_0036 :Puesto Desconocido (22) +STR_0037 :Quiosco de Información +STR_0038 :Baños +STR_0039 :Rueda Gigante +STR_0040 :Simulador de Movimiento +STR_0041 :Cine 3D STR_0042 :Top Spin -STR_0043 :Space Rings -STR_0044 :Reverse Freefall Coaster -STR_0045 :Lift -STR_0046 :Vertical Drop Roller Coaster -STR_0047 :Cash Machine +STR_0043 :Anillos Espaciales +STR_0044 :Montaña Rusa Invertida +STR_0045 :Elevador +STR_0046 :Montaña Rusa Caída Vertical +STR_0047 :Cajero Automático STR_0048 :Twist -STR_0049 :Haunted House -STR_0050 :First Aid Room -STR_0051 :Circus Show -STR_0052 :Ghost Train -STR_0053 :Steel Twister Roller Coaster -STR_0054 :Wooden Roller Coaster -STR_0055 :Side-Friction Roller Coaster -STR_0056 :Wild Mouse -STR_0057 :Multi-Dimension Roller Coaster -STR_0058 :Unknown Ride (38) -STR_0059 :Flying Roller Coaster -STR_0060 :Unknown Ride (3A) -STR_0061 :Virginia Reel -STR_0062 :Splash Boats -STR_0063 :Mini Helicopters -STR_0064 :Lay-down Roller Coaster -STR_0065 :Suspended Monorail -STR_0066 :Unknown Ride (40) -STR_0067 :Reverser Roller Coaster -STR_0068 :Heartline Twister Coaster +STR_0049 :Casa Encantada +STR_0050 :Sala de primeros auxilios +STR_0051 :Circo +STR_0052 :Tren fantasma +STR_0053 :Montaña Rusa En Pie Tornado +STR_0054 :Montaña Rusa de Madera +STR_0055 :Montaña de fricción lateral +STR_0056 :Ratón Loco +STR_0057 :Montaña Rusa Multi-Dimensión +STR_0058 :Atracc. Desconocida (38) +STR_0059 :Montaña Rusa Volante +STR_0060 :Atracc. Desconocida (3A) +STR_0061 :Danza de Virginia +STR_0062 :Botes de Salpicadura +STR_0063 :Mini Helicópteros +STR_0064 :Montaña Rusa Fija +STR_0065 :Monorraíl suspendido +STR_0066 :Atracc. Desconocida (40) +STR_0067 :Montaña Rusa Inversora +STR_0068 :Mt. Rusa Tornado Medio STR_0069 :Mini Golf -STR_0070 :Giga Coaster -STR_0071 :Roto-Drop -STR_0072 :Flying Saucers -STR_0073 :Crooked House -STR_0074 :Monorail Cycles -STR_0075 :Compact Inverted Coaster -STR_0076 :Water Coaster -STR_0077 :Air Powered Vertical Coaster -STR_0078 :Inverted Hairpin Coaster -STR_0079 :Magic Carpet -STR_0080 :Submarine Ride -STR_0081 :River Rafts -STR_0082 :Unknown Ride (50) +STR_0070 :Gigamontaña Rusa +STR_0071 :Caída Giratoria +STR_0072 :Platillos Voladores +STR_0073 :Casa Inclinada +STR_0074 :Bicis Monoraíl +STR_0075 :Montaña Rusa Compacta +STR_0076 :Montaña Rusa de Agua +STR_0077 :Montaña Rusa Vertical de Aire +STR_0078 :Horquilla invertida +STR_0079 :Alfombra Mágica +STR_0080 :Viaje Submarino +STR_0081 :Balsas de Río +STR_0082 :Atracc. Desconocida (50) STR_0083 :Enterprise -STR_0084 :Unknown Ride (52) -STR_0085 :Unknown Ride (53) -STR_0086 :Unknown Ride (54) -STR_0087 :Unknown Ride (55) -STR_0088 :Inverted Impulse Coaster -STR_0089 :Mini Roller Coaster -STR_0090 :Mine Ride -STR_0091 :Unknown Ride (59) -STR_0092 :LIM Launched Roller Coaster +STR_0084 :Atracc. Desconocida (52) +STR_0085 :Atracc. Desconocida (53) +STR_0086 :Atracc. Desconocida (54) +STR_0087 :Atracc. Desconocida (55) +STR_0088 :Montaña Rusa Impulso Inverso +STR_0089 :Mini Montaña Rusa +STR_0090 :Trenes Mineros +STR_0091 :Atracc. Desconocida (59) +STR_0092 :Montaña Rusa Impulso MLI STR_0093 : STR_0094 : STR_0095 : @@ -513,31 +513,31 @@ STR_0508 : STR_0509 : STR_0510 : STR_0511 : -STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. -STR_0513 :A looping roller coaster where the riders ride in a standing position -STR_0514 :Trains suspended beneath the roller coaster track swing out to the side around corners -STR_0515 :A steel roller coaster with trains that are held beneath the track, with many complex and twisting track elements -STR_0516 :A gentle roller coaster for people who haven't yet got the courage to face the larger rides -STR_0517 :Passengers ride in miniature trains along a narrow-gauge railway track -STR_0518 :Passengers travel in electric trains along a monorail track -STR_0519 :Passengers ride in small cars hanging beneath the single-rail track, swinging freely from side to side around corners -STR_0520 :A dock platform where guests can drive/row personal watercraft on a body of water -STR_0521 :A fast and twisting roller coaster with tight turns and steep drops. Intensity is bound to be high. -STR_0522 :A smaller roller coaster where the riders sit above the track with no car around them -STR_0523 :Riders travel slowly in powered vehicles along a track-based route -STR_0524 :Freefall car is pneumatically launched up a tall steel tower and then allowed to freefall down -STR_0525 :Riders career down a twisting track guided only by the curvature and banking of the semi-circular track -STR_0526 :Passengers travel in a rotating observation cabin which travels up a tall tower -STR_0527 :A smooth steel-tracked roller coaster capable of vertical loops -STR_0528 :Riders travel in inflatable dinghies down a twisting semi-circular or completely enclosed tube track -STR_0529 :Mine train themed roller coaster trains career along steel roller coaster track made to look like old railway track -STR_0530 :Cars hang from a steel cable which runs continuously from one end of the ride to the other and back again -STR_0531 :A compact steel-tracked roller coaster where the train travels through corkscrews and loops +STR_0512 :Una montaña rusa pequeña de acero con una subida en espiral y vagones con asientos en línea. +STR_0513 :Una montaña rusa en el que los pasajeros permanecen de pie. +STR_0514 :Los vagones suspendidos bajo los raíles se balancean hacia los lados en las curvas. +STR_0515 :Los pasajeros se sientan en asientos suspendidos bajo la vía y corren por rizos gigantes, giros y grandes caídas. +STR_0516 :Una montaña rusa más suave para la gente que no tiene el valor de afrontar las grandes montañas rusas. +STR_0517 :Los pasajeros viajan en trenes diminutos sobre una pequeña vía. +STR_0518 :Los pasajeros viajan en trenes eléctricos sobre una vía monorraíl +STR_0519 :Los pasajeros se colocan boca abajo en unos vagones especiales en ésta montaña rusa. +STR_0520 :Una plataforma de muelle donde los pasajeros pueden conducir botes sobre el agua. +STR_0521 :Una montaña rusa rápida con curvas cerradas y fuertes caídas. La intensidad es muy alta. +STR_0522 :Pequeña montaña rusa en donde los pasajeros se montan en unos vagones que recorren un monoraíl. +STR_0523 :Los pasajeros viajan lentamente en vehículos autopropulsados sobre una vía +STR_0524 :Un vagón es lanzado en un neumático a lo alto de una elevada torre de acero, cayendo libremente. +STR_0525 :Los pasajeros viajan por unas vías retorcidas en vagones tipo bobsleigh guiados únicamente por la curvatura y los peraltes de la vía semicircular. +STR_0526 :Los pasajeros viajan en una cabina de observación giratoria que se desplaza hacia arriba en una torre alta. +STR_0527 :Una montaña rusa de acero capaz de rizos verticales +STR_0528 :Los pasajeros viajan en botes hinchables por tubos semicirculares o totalmente cerrados. +STR_0529 :El tren de la mina corre por una vía de acero que recuerda las viejas vías del tren. +STR_0530 :Asientos colgados de un cable de acero viajan contínuamente desde un extremo a otro del recorrido +STR_0531 :Una montaña rusa compacta de acero donde los vagones circulan por rizos y sacachorscos. STR_0532 : STR_0533 : -STR_0534 :Self-drive petrol-engined go karts -STR_0535 :Log-shaped boats travel along a water channel, splashing down steep slopes to soak the riders -STR_0536 :Circular boats meander along a wide water channel, splashing through waterfalls and thrilling riders through foaming rapids +STR_0534 :Go-Karts autopropulsados con gasolina. +STR_0535 :Barcos con forma de tronco que viajan por un canal de agua, salpicando hasta empapar a los pasajeros. +STR_0536 :Botes circulares viajan a lo largo de un canal de agua ancho, salpicando a través de cascadas y paseos emocionantes a través de rápidos espumantes. STR_0537 : STR_0538 : STR_0539 : @@ -555,55 +555,55 @@ STR_0550 : STR_0551 : STR_0552 : STR_0553 : -STR_0554 :The car is accelerated out of the station along a long level track using Linear Induction Motors, then heads straight up a vertical spike of track, freefalling back down to return to the station -STR_0555 :Guests ride in an elevator up or down a vertical tower to get from one level to another -STR_0556 :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_0554 :El vagón acelera saliendo de la estación usando Motores Lineales Inductivos, pasando a una zona del trayecto vertical y cayendo libremente hasta volver a la estación. +STR_0555 :Los pasajeros suben o bajan en un ascensor para acceder a distintos niveles de una torre vertical. +STR_0556 :Vagones superanchos descienden completamente verticalmente para una experiencia definitiva. STR_0557 : STR_0558 : STR_0559 : STR_0560 : STR_0561 : -STR_0562 :Powered cars travel along a multi-level track past spooky scenery and special effects -STR_0563 :Sitting in comfortable trains with only simple lap restraints riders enjoy giant smooth drops and twisting track as well as plenty of 'air time' over the hills -STR_0564 :Running on wooden track, this coaster is fast, rough, noisy, and gives an 'out of control' riding experience with plenty of 'air time' -STR_0565 :A simple wooden roller coaster capable of only gentle slopes and turns, where the cars are only kept on the track by side friction wheels and gravity -STR_0566 :Individual roller coaster cars zip around a tight zig-zag layout of track with sharp corners and short sharp drops -STR_0567 :Sitting in seats suspended either side of the track, riders are pitched head-over-heels while they plunge down steep drops and travel through various inversions +STR_0562 :Vagones autopropulsados viajan a lo largo de una pista multinivel pasando por paisajes fantasmagóricos y efectos especiales. +STR_0563 :Los pasajeros permanecen de pie en unos vagones con sujeciones especiales atravesando caídas y múltiples inversiones. +STR_0564 :Esta montaña rusa, construida en madera, es rápida, rústica, ruidosa y ofrece una experiencia 'fuera de control' con muchos 'vuelos'. +STR_0565 :Una montaña rusa de madera con suaves caídas y giros, donde los vagones se mantienen en la vía mediante ruedas laterales de fricción y la gravedad. +STR_0566 :Los vagones individuales giran en un tramo de vía en estrecho zig-zag con curvas y caídas bruscas. +STR_0567 :Los pasajeros, sentados en sillas suspendidas a ambos lados de la vía son colgados cabeza abajo mientras sufren bruscas zambullidas y varias inversiones. STR_0568 : -STR_0569 :Riding in special harnesses below the track, riders experience the feeling of flight as they swoop through the air +STR_0569 :Los pasajeros están sentados confortablemente bajo la vía sintiendo una experiencia de casi-vuelo. STR_0570 : -STR_0571 :Circular cars spin around as they travel along the zig-zagging wooden track -STR_0572 :Large capacity boats travel along a wide water channel, propelled up slopes by a conveyer belt, accelerating down steep slopes to soak the riders with a gaint splash -STR_0573 :Powered helicoper shaped cars running on a steel track, controlled by the pedalling of the riders -STR_0574 :Riders are held in special harnesses in a lying-down position, travlling through twisted track and inversions either on their backs or facing the ground -STR_0575 :Powered trains hanging from a single rail transport people around the park +STR_0571 :Vagones circulares que rebotan mientras corren sobre la pista de madera en zig-zag. +STR_0572 :Botes de gran capacidad viajan por un amplio canal, los cuales son impulsados por una cinta transportadora para después caer y hacer grandes salpicaduras. +STR_0573 :Vagones con forma de helicópteros corren por una vía de acero controlados por los pedales de los pasajeros. +STR_0574 :Los pasajeros están sujetos por unos arneses cara abajo +STR_0575 :Trenes monorraíl suspendidos transportan a la gente por el parque. STR_0576 : -STR_0577 :Bogied cars run on wooden tracks, turning around on special reversing sections -STR_0578 :Cars run along track enclosed by circular hoops, traversing steep drops and heartline twists +STR_0577 :Vagones que corren por una vía de madera girando en secciones especiales de inversión. +STR_0578 :Los vagones circulan por vías formando aros y recorriendo bruscas caídas y giros. STR_0579 : -STR_0580 :A giant steel roller coaster capable of smooth drops and hills of over 300ft -STR_0581 :A ring of seats is pulled to the top of a tall tower while gently rotating, then allowed to free-fall down, stopping gently at the bottom using magnetic brakes +STR_0580 :Una montaña rusa gigante capaz de caídas suaves y subidas de más de 300 pies. +STR_0581 :Un anillo de asientos es arrastrado a lo alto de una torre mientras gira, y después cae libremente hasta detenerse suavemente usando unos frenos magnéticos. STR_0582 : STR_0583 : -STR_0584 :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders -STR_0585 :Riders sit in pairs of seats suspended beneath the track as they loop and twist through tight inversions -STR_0586 :Boat shaped cars run on roller coaster track to allow twisting curves and steep drops, splashing down into sections of water for gentle river sections -STR_0587 :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station -STR_0588 :Individual cars run beneath a zig-zagging track with hairpin turns and sharp drops +STR_0584 :Bicicletas especiales que viajan sobre un monoraíl, impulsadas por el pedaleo. +STR_0585 :Los pasajeros se sientan en parejas atravesando rizos e inversiones. +STR_0586 :Los vagones en forma de bote volante corren por el recorrido de la montaña rusa, con curvas cerradas y caídas pronunciadas, pasando por zonas de agua. +STR_0587 :Tras un excitante lanzamiento el vagón corre por una vía vertical hasta el tope y baja vertical por el otro lado. +STR_0588 :Vagones individuales corren bajo una vía zig-zagueante STR_0589 : -STR_0590 :Riders ride in a submerged submarine through an underwater course -STR_0591 :Raft-shaped boats gently meander around a river track +STR_0590 :Los pasajeros viajan en un submarino sumergido que viaja sobre una ruta submarina. +STR_0591 :Barcos en forma de balsa viajan suavemente sobre un río. STR_0592 : STR_0593 : STR_0594 : STR_0595 : STR_0596 : STR_0597 : -STR_0598 :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track -STR_0599 :A compact roller coaster with individual cars and smooth twisting drops -STR_0600 :Powered mine trains career along a smooth and twisted track layout +STR_0598 :Los vagones de la montaña rusa invertida aceleran saliendo del andén y tomando un tramo de vía vertical, entonces vuelven marcha atrás pasando por el andén y subiendo por otro tramo de vía vertical. +STR_0599 :Una montaña rusa compacta con vagones individuales y caídas y giros suaves. +STR_0600 :Trenes mineros autopropulsados corren a lo largo de una vía enredada. STR_0601 : -STR_0602 :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions +STR_0602 :Los vagones se aceleran por los motores lineales de inducción STR_0603 :Visitante {INT32} STR_0604 :Visitante {INT32} STR_0605 :Visitante {INT32} @@ -769,76 +769,76 @@ STR_0764 :Visitante {INT32} STR_0765 :Visitante {INT32} STR_0766 :Visitante {INT32} STR_0767 :Visitante {INT32} -STR_0768 :Handyman {INT32} -STR_0769 :Mechanic {INT32} -STR_0770 :Security Guard {INT32} -STR_0771 :Entertainer {INT32} -STR_0772 :Unnamed park{POP16}{POP16} -STR_0773 :Unnamed park{POP16}{POP16} -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_0779 :1st -STR_0780 :2nd -STR_0781 :3rd -STR_0782 :4th -STR_0783 :5th -STR_0784 :6th -STR_0785 :7th -STR_0786 :8th -STR_0787 :9th -STR_0788 :10th -STR_0789 :11th -STR_0790 :12th -STR_0791 :13th -STR_0792 :14th -STR_0793 :15th -STR_0794 :16th -STR_0795 :17th -STR_0796 :18th -STR_0797 :19th -STR_0798 :20th -STR_0799 :21st -STR_0800 :22nd -STR_0801 :23rd -STR_0802 :24th -STR_0803 :25th -STR_0804 :26th -STR_0805 :27th -STR_0806 :28th -STR_0807 :29th -STR_0808 :30th -STR_0809 :31st -STR_0810 :Jan -STR_0811 :Feb -STR_0812 :Mar -STR_0813 :Apr -STR_0814 :May -STR_0815 :Jun -STR_0816 :Jul -STR_0817 :Aug -STR_0818 :Sep -STR_0819 :Oct -STR_0820 :Nov -STR_0821 :Dec -STR_0822 :Unable to access graphic data file -STR_0823 :Missing or inaccessible data file +STR_0768 :Jardinero {INT32} +STR_0769 :Mecánico {INT32} +STR_0770 :Guardia {INT32} +STR_0771 :Animador {INT32} +STR_0772 :Parque sin nombre{POP16}{POP16} +STR_0773 :Parque sin nombre{POP16}{POP16} +STR_0774 :Parque sin nombre{POP16}{POP16} +STR_0775 :Parque sin nombre{POP16}{POP16} +STR_0776 :Parque sin nombre{POP16}{POP16} +STR_0777 :Parque sin nombre{POP16}{POP16} +STR_0778 :Señal +STR_0779 :1 +STR_0780 :2 +STR_0781 :3 +STR_0782 :4 +STR_0783 :5 +STR_0784 :6 +STR_0785 :7 +STR_0786 :8 +STR_0787 :9 +STR_0788 :10 +STR_0789 :11 +STR_0790 :12 +STR_0791 :13 +STR_0792 :14 +STR_0793 :15 +STR_0794 :16 +STR_0795 :17 +STR_0796 :18 +STR_0797 :19 +STR_0798 :20 +STR_0799 :21 +STR_0800 :22 +STR_0801 :23 +STR_0802 :24 +STR_0803 :25 +STR_0804 :26 +STR_0805 :27 +STR_0806 :28 +STR_0807 :29 +STR_0808 :30 +STR_0809 :31 +STR_0810 :ene +STR_0811 :feb +STR_0812 :mar +STR_0813 :abr +STR_0814 :may +STR_0815 :jun +STR_0816 :jul +STR_0817 :ago +STR_0818 :sep +STR_0819 :oct +STR_0820 :nov +STR_0821 :dic +STR_0822 :No se pudo acceder al archivo de datos de gráficos +STR_0823 :Archivo faltante o inaccesible 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_0834 :{SMALLFONT}{BLACK}Disk and game options -STR_0835 :Game initialisation failed -STR_0836 :Unable to start game in a minimised state -STR_0837 :Unable to initialise graphics system +STR_0825 :Este nombre ya está usado +STR_0826 :Demasiados nombres están usados +STR_0827 :No hay suficiente dinero - requiere {CURRENCY2DP} +STR_0828 :{SMALLFONT}{BLACK}Cerrar ventana +STR_0829 :{SMALLFONT}{BLACK}Título de la ventana - Arrastra para moverla +STR_0830 :{SMALLFONT}{BLACK}Acercar zoom +STR_0831 :{SMALLFONT}{BLACK}Alejar zoom +STR_0832 :{SMALLFONT}{BLACK}Rota la cámara 90{DEGREE} en el sentido de las agujas del reloj +STR_0833 :{SMALLFONT}{BLACK}Pausar juego +STR_0834 :{SMALLFONT}{BLACK}Opciones de juego +STR_0835 :Falló la inicialización del juego +STR_0836 :No se ha podido iniciar el juego en estado minimizado +STR_0837 :No se ha podido iniciar el sistema gráfico STR_0838 : STR_0839 :{UINT16} x {UINT16} STR_0840 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{UINT16} x {UINT16} @@ -849,17 +849,17 @@ STR_0843 : STR_0844 : STR_0845 : STR_0846 : -STR_0847 :About 'OpenRCT2' +STR_0847 :Sobre 'OpenRCT2' STR_0848 :RollerCoaster Tycoon 2 STR_0849 :{WINDOW_COLOUR_2}Version 2.01.028 -STR_0850 :{WINDOW_COLOUR_2}Copyright {COPYRIGHT} 2002 Chris Sawyer, all rights reserved -STR_0851 :{WINDOW_COLOUR_2}Designed and programmed by Chris Sawyer -STR_0852 :{WINDOW_COLOUR_2}Graphics by Simon Foster -STR_0853 :{WINDOW_COLOUR_2}Sound and music by Allister Brimble -STR_0854 :{WINDOW_COLOUR_2}Additional sounds recorded by David Ellis -STR_0855 :{WINDOW_COLOUR_2}Representation by Jacqui Lyons at Marjacq Ltd. -STR_0856 :{WINDOW_COLOUR_2}Thanks to: -STR_0857 :{WINDOW_COLOUR_2}Peter James Adcock, Joe Booth, and John Wardley +STR_0850 :{WINDOW_COLOUR_2} {COPYRIGHT} 2002 Chris Sawyer, todos los derechos reservados +STR_0851 :{WINDOW_COLOUR_2}Diseñado y programado por Chris Sawyer +STR_0852 :{WINDOW_COLOUR_2}Gráficos de Simon Foster +STR_0853 :{WINDOW_COLOUR_2}Sonidos y música de Allister Brimble +STR_0854 :{WINDOW_COLOUR_2}Sonidos adicionales grabados por David Ellis +STR_0855 :{WINDOW_COLOUR_2}Representación por Jacqui Lyons at Marjacq Ltd. +STR_0856 :{WINDOW_COLOUR_2}Agradecimientos: +STR_0857 :{WINDOW_COLOUR_2}Peter James Adcock, Joe Booth, y John Wardley STR_0858 :{WINDOW_COLOUR_2} STR_0859 :{WINDOW_COLOUR_2} STR_0860 :{WINDOW_COLOUR_2} @@ -879,85 +879,85 @@ STR_0873 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0874 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0875 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} STR_0876 :{BLACK}{DOWN} -STR_0877 :Too low ! -STR_0878 :Too high ! -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_0877 :¡Demasiado bajo! +STR_0878 :¡Demasiado alto! +STR_0879 :No se puede bajar el terreno... +STR_0880 :No se puede elevar el terreno... +STR_0881 :Un objeto interfiere +STR_0882 :Cargar Partida +STR_0883 :Guardar Partida +STR_0884 :Cargar paisaje +STR_0885 :Guardar paisaje +STR_0886 :Salir del juego +STR_0887 :Salir del editor de escenarios +STR_0888 :Salir del editor de Montañas Rusas +STR_0889 :Salir del editor de Vías STR_0890 :SCR{COMMA16}.BMP -STR_0891 :Screenshot -STR_0892 :Screenshot saved to disk as '{STRINGID}' -STR_0893 :Screenshot failed ! -STR_0894 :Landscape data area full ! -STR_0895 :Can't build partly above and partly below ground -STR_0896 :{POP16}{POP16}{STRINGID} Construction -STR_0897 :Direction -STR_0898 :{SMALLFONT}{BLACK}Left-hand curve -STR_0899 :{SMALLFONT}{BLACK}Right-hand curve -STR_0900 :{SMALLFONT}{BLACK}Left-hand curve (small radius) -STR_0901 :{SMALLFONT}{BLACK}Right-hand curve (small radius) -STR_0902 :{SMALLFONT}{BLACK}Left-hand curve (very small radius) -STR_0903 :{SMALLFONT}{BLACK}Right-hand curve (very small radius) -STR_0904 :{SMALLFONT}{BLACK}Left-hand curve (large radius) -STR_0905 :{SMALLFONT}{BLACK}Right-hand curve (large radius) -STR_0906 :{SMALLFONT}{BLACK}Straight -STR_0907 :Slope -STR_0908 :Roll/Banking -STR_0909 :Seat Rot. -STR_0910 :{SMALLFONT}{BLACK}Roll for left-hand curve -STR_0911 :{SMALLFONT}{BLACK}Roll for right-hand curve -STR_0912 :{SMALLFONT}{BLACK}No roll -STR_0913 :{SMALLFONT}{BLACK}Move to previous section -STR_0914 :{SMALLFONT}{BLACK}Move to next section -STR_0915 :{SMALLFONT}{BLACK}Construct the selected section -STR_0916 :{SMALLFONT}{BLACK}Remove the highlighted section +STR_0891 :Tomar captura de pantalla +STR_0892 :Captura de pantalla guardada como '{STRINGID}' +STR_0893 :¡No se pudo tomar la Captura de pantalla! +STR_0894 :¡Datos de paisaje lleno! +STR_0895 :No se puede construir una parte arriba y otra bajo tierra +STR_0896 :{POP16}{POP16}Construcción de {STRINGID} +STR_0897 :Dirección +STR_0898 :{SMALLFONT}{BLACK}Curva izquierda +STR_0899 :{SMALLFONT}{BLACK}Curva derecha +STR_0900 :{SMALLFONT}{BLACK}Curva izquierda (pequeño) +STR_0901 :{SMALLFONT}{BLACK}Curva derecha (pequeño) +STR_0902 :{SMALLFONT}{BLACK}Curva izquierda (muy pequeño) +STR_0903 :{SMALLFONT}{BLACK}Curva derecha (muy pequeño) +STR_0904 :{SMALLFONT}{BLACK}Curva izquierda (grande) +STR_0905 :{SMALLFONT}{BLACK}Curva derecha (grande) +STR_0906 :{SMALLFONT}{BLACK}Recto +STR_0907 :Inclinación +STR_0908 :Peralte +STR_0909 :Rot. Asto. +STR_0910 :{SMALLFONT}{BLACK}Peraltar hacia la izquierda +STR_0911 :{SMALLFONT}{BLACK}Peraltar hacia la derecha +STR_0912 :{SMALLFONT}{BLACK}Sin peralte +STR_0913 :{SMALLFONT}{BLACK}Resalta el tramo anterior +STR_0914 :{SMALLFONT}{BLACK}Resalta el tramo posterior +STR_0915 :{SMALLFONT}{BLACK}Construir tramo +STR_0916 :{SMALLFONT}{BLACK}Elimina el tramo resaltado STR_0917 :{SMALLFONT}{BLACK}Vertical drop -STR_0918 :{SMALLFONT}{BLACK}Steep slope down -STR_0919 :{SMALLFONT}{BLACK}Slope down -STR_0920 :{SMALLFONT}{BLACK}Level -STR_0921 :{SMALLFONT}{BLACK}Slope up -STR_0922 :{SMALLFONT}{BLACK}Steep slope up +STR_0918 :{SMALLFONT}{BLACK}Cuesta abajo pronunciada +STR_0919 :{SMALLFONT}{BLACK}Cuesta abajo +STR_0920 :{SMALLFONT}{BLACK}Nivelado +STR_0921 :{SMALLFONT}{BLACK}Cuesta arriba +STR_0922 :{SMALLFONT}{BLACK}Cuesta arriba pronunciada STR_0923 :{SMALLFONT}{BLACK}Vertical rise -STR_0924 :{SMALLFONT}{BLACK}Helix down -STR_0925 :{SMALLFONT}{BLACK}Helix up -STR_0926 :Can't remove this... -STR_0927 :Can't construct this here... -STR_0928 :{SMALLFONT}{BLACK}Chain lift, to pull cars up slopes -STR_0929 :'S' Bend (left) -STR_0930 :'S' Bend (right) -STR_0931 :Vertical Loop (left) -STR_0932 :Vertical Loop (right) -STR_0933 :Raise or lower land first -STR_0934 :Ride entrance in the way -STR_0935 :Ride exit in the way -STR_0936 :Park entrance in the way -STR_0937 :{SMALLFONT}{BLACK}View options -STR_0938 :{SMALLFONT}{BLACK}Adjust land height and slope -STR_0939 :Underground/Inside View -STR_0940 :Remove Base Land -STR_0941 :Remove Vertical Faces -STR_0942 :See-Through Rides -STR_0943 :See-Through Scenery -STR_0944 :Save -STR_0945 :Don't Save +STR_0924 :{SMALLFONT}{BLACK}Hélice abajo +STR_0925 :{SMALLFONT}{BLACK}Hélice arriba +STR_0926 :No se puede quitar esto... +STR_0927 :No puede construir esto aquí... +STR_0928 :{SMALLFONT}{BLACK}Cadena elevadora para propulsar coches por una pendiente. +STR_0929 :Curva 'S' (izquierda) +STR_0930 :Curva 'S' (derecha) +STR_0931 :Vuelta vertical (izquierda) +STR_0932 :Vuelta vertical (derecha) +STR_0933 :Sube o baja el terreno primero +STR_0934 :Entrada de atracción interfiere +STR_0935 :Salida de atracción interfiere +STR_0936 :Entrada del parque interfiere +STR_0937 :{SMALLFONT}{BLACK}Opciones de visualización +STR_0938 :{SMALLFONT}{BLACK}Movimientos de tierra +STR_0939 :Vista subterránea +STR_0940 :Tierra invisible +STR_0941 :Acantilados invisibles +STR_0942 :Atracciones invisibles +STR_0943 :Decorado invisible +STR_0944 :Guardar +STR_0945 :No guardar STR_0946 :Cancelar -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_0953 :Load Landscape +STR_0947 :¿Guardar antes de cargar una nueva partida? +STR_0948 :¿Guardar antes de salir? +STR_0949 :¿Guardar antes de salir? +STR_0950 :Cargar Partida +STR_0951 :Salir del juego +STR_0952 :Salir del juego +STR_0953 :Cargar paisaje STR_0954 : -STR_0955 :{SMALLFONT}{BLACK}Select seat rotation angle for this track section +STR_0955 :{SMALLFONT}{BLACK}Angulo de rotación de asciento en este tramo STR_0956 :-180{DEGREE} STR_0957 :-135{DEGREE} STR_0958 :-90{DEGREE} @@ -976,637 +976,637 @@ STR_0970 :+450{DEGREE} STR_0971 :+495{DEGREE} STR_0972 :Cancelar STR_0973 :OK -STR_0974 :Rides -STR_0975 :Shops and Stalls -STR_0976 :Toilets and Information Kiosks -STR_0977 :New Transport Rides -STR_0978 :New Gentle Rides -STR_0979 :New Roller Coasters -STR_0980 :New Thrill Rides -STR_0981 :New Water Rides -STR_0982 :New Shops & Stalls -STR_0983 :Research & Development +STR_0974 :Atracciones +STR_0975 :Tiendas y puestos +STR_0976 :Aseos y Quioscos de información +STR_0977 :Nueva atracción de transporte +STR_0978 :Nueva atracción suave +STR_0979 :Nueva montaña rusa +STR_0980 :Nueva atracción intensa +STR_0981 :Nueva atracción acuática +STR_0982 :Nueva tienda o puesto +STR_0983 :Investigación + Desarrollo STR_0984 :{WINDOW_COLOUR_2}{UP}{BLACK} {CURRENCY2DP} STR_0985 :{WINDOW_COLOUR_2}{DOWN}{BLACK} {CURRENCY2DP} STR_0986 :{BLACK}{CURRENCY2DP} -STR_0987 :Too many rides/attractions -STR_0988 :Can't create new ride/attraction... +STR_0987 :Demasiados atracciones/juegos +STR_0988 :No se puede crear una nueva atracción STR_0989 :{STRINGID} -STR_0990 :{SMALLFONT}{BLACK}Construction -STR_0991 :Station platform -STR_0992 :{SMALLFONT}{BLACK}Demolish entire ride/attraction -STR_0993 :Demolish ride/attraction -STR_0994 :Demolish -STR_0995 :{WINDOW_COLOUR_1}Are you sure you want to completely demolish {STRINGID}? -STR_0996 :Overall view -STR_0997 :{SMALLFONT}{BLACK}View selection -STR_0998 :No more stations allowed on this ride -STR_0999 :Requires a station platform -STR_1000 :Track is not a complete circuit -STR_1001 :Track unsuitable for type of train -STR_1002 :Can't open {POP16}{POP16}{POP16}{STRINGID}... -STR_1003 :Can't test {POP16}{POP16}{POP16}{STRINGID}... -STR_1004 :Can't close {POP16}{POP16}{POP16}{STRINGID}... -STR_1005 :Can't start construction on {POP16}{POP16}{POP16}{STRINGID}... -STR_1006 :Must be closed first -STR_1007 :Unable to create enough vehicles -STR_1008 :{SMALLFONT}{BLACK}Open, close, or test ride/attraction -STR_1009 :{SMALLFONT}{BLACK}Open or close all rides/attractions -STR_1010 :{SMALLFONT}{BLACK}Open or close park -STR_1011 :Close all -STR_1012 :Open all -STR_1013 :Close park -STR_1014 :Open park -STR_1015 :Unable to operate with more than one station platform in this mode -STR_1016 :Unable to operate with less than two stations in this mode -STR_1017 :Can't change operating mode... -STR_1018 :Can't make changes... -STR_1019 :Can't make changes... -STR_1020 :Can't make changes... +STR_0990 :{SMALLFONT}{BLACK}Construcción +STR_0991 :Andén +STR_0992 :{SMALLFONT}{BLACK}Demoler completamente esta atracción +STR_0993 :Demoler atracción +STR_0994 :Demoler +STR_0995 :{WINDOW_COLOUR_1}¿Estás seguro de demoler completamente {STRINGID}? +STR_0996 :Vista general +STR_0997 :{SMALLFONT}{BLACK}Selección de vista +STR_0998 :No se permiten más estaciones en esta atracción +STR_0999 :Requiere un andén de estación +STR_1000 :El trayecto no completa un circuito +STR_1001 :Trayecto no adecuado para este tipo de tren +STR_1002 :No se puede abrir {POP16}{POP16}{POP16}{STRINGID}... +STR_1003 :No se puede probar {POP16}{POP16}{POP16}{STRINGID}... +STR_1004 :No se puede cerrar {POP16}{POP16}{POP16}{STRINGID}... +STR_1005 :No se puede iniciar construcción en {POP16}{POP16}{POP16}{STRINGID}... +STR_1006 :Debe ser cerrado antes +STR_1007 :No se puede crear suficientes vehículos +STR_1008 :{SMALLFONT}{BLACK}Abrir, cerrar o probar esta atracción +STR_1009 :{SMALLFONT}{BLACK}Abrir o cerrar todas las atracciones +STR_1010 :{SMALLFONT}{BLACK}Abrir o cerrar el parque +STR_1011 :Cerrar todo +STR_1012 :Abrir todo +STR_1013 :Cerrar parque +STR_1014 :Abrir parque +STR_1015 :No se puede operar con más de una estación en este modo +STR_1016 :No se puede operar con menos de dos estaciones en este modo +STR_1017 :No se puede cambiar el modo de funcionamiento... +STR_1018 :No se pueden hacer cambios... +STR_1019 :No se pueden hacer cambios... +STR_1020 :No se pueden hacer cambios... STR_1021 :{POP16}{POP16}{POP16}{POP16}{STRINGID} -STR_1022 :{POP16}{POP16}{POP16}{COMMA16} car per train -STR_1023 :{POP16}{POP16}{POP16}{COMMA16} cars per train -STR_1024 :{COMMA16} car per train -STR_1025 :{COMMA16} cars per train -STR_1026 :Station platform too long! -STR_1027 :{SMALLFONT}{BLACK}Locate this on Main View -STR_1028 :Off edge of map! -STR_1029 :Cannot build partly above and partly below water! -STR_1030 :Can only build this underwater! -STR_1031 :Can't build this underwater! -STR_1032 :Can only build this on water! -STR_1033 :Can only build this above ground! -STR_1034 :Can only build this on land! -STR_1035 :Local authority won't allow construction above tree-height! -STR_1036 :Load Game -STR_1037 :Load Landscape -STR_1038 :Convert saved game to scenario -STR_1039 :Install new track design -STR_1040 :Save Game -STR_1041 :Save Scenario -STR_1042 :Save Landscape -STR_1043 :OpenRCT2 Saved Game -STR_1044 :OpenRCT2 Scenario File -STR_1045 :OpenRCT2 Landscape File -STR_1046 :OpenRCT2 Track Design File -STR_1047 :Game save failed! -STR_1048 :Scenario save failed! -STR_1049 :Landscape save failed! -STR_1050 :Failed to load...{NEWLINE}File contains invalid data! -STR_1051 :Invisible Supports -STR_1052 :Invisible People -STR_1053 :{SMALLFONT}{BLACK}Rides/attractions in park -STR_1054 :{SMALLFONT}{BLACK}Name ride/attraction -STR_1055 :{SMALLFONT}{BLACK}Name person -STR_1056 :{SMALLFONT}{BLACK}Name staff member -STR_1057 :Ride/attraction name -STR_1058 :Enter new name for this ride/attraction: -STR_1059 :Can't rename ride/attraction... -STR_1060 :Invalid ride/attraction name -STR_1061 :Normal mode -STR_1062 :Continuous circuit mode -STR_1063 :Reverse-Incline launched shuttle mode -STR_1064 :Powered launch (passing station) -STR_1065 :Shuttle mode -STR_1066 :Boat hire mode -STR_1067 :Upward launch -STR_1068 :Rotating lift mode -STR_1069 :Station to station mode -STR_1070 :Single ride per admission -STR_1071 :Unlimited rides per admission -STR_1072 :Maze mode -STR_1073 :Race mode -STR_1074 :Bumper-car mode -STR_1075 :Swing mode -STR_1076 :Shop stall mode -STR_1077 :Rotation mode -STR_1078 :Forward rotation -STR_1079 :Backward rotation -STR_1080 :Film: {ENDQUOTES}Avenging aviators{ENDQUOTES} -STR_1081 :3D film: {ENDQUOTES}Mouse tails{ENDQUOTES} -STR_1082 :Space rings mode -STR_1083 :Beginners mode -STR_1084 :LIM-powered launch -STR_1085 :Film: {ENDQUOTES}Thrill riders{ENDQUOTES} -STR_1086 :3D film: {ENDQUOTES}Storm chasers{ENDQUOTES} -STR_1087 :3D film: {ENDQUOTES}Space raiders{ENDQUOTES} -STR_1088 :Intense mode -STR_1089 :Berserk mode -STR_1090 :Haunted house mode -STR_1091 :Circus show mode -STR_1092 :Downward launch -STR_1093 :Crooked house mode -STR_1094 :Freefall drop mode -STR_1095 :Continuous circuit block sectioned mode -STR_1096 :Powered launch (without passing station) -STR_1097 :Powered launch block sectioned mode -STR_1098 :Moving to end of {POP16}{STRINGID} -STR_1099 :Waiting for passengers at {POP16}{STRINGID} -STR_1100 :Waiting to depart {POP16}{STRINGID} -STR_1101 :Departing {POP16}{STRINGID} -STR_1102 :Travelling at {VELOCITY} -STR_1103 :Arriving at {POP16}{STRINGID} -STR_1104 :Unloading passengers at {POP16}{STRINGID} -STR_1105 :Travelling at {VELOCITY} -STR_1106 :Crashing! -STR_1107 :Crashed! -STR_1108 :Travelling at {VELOCITY} -STR_1109 :Swinging -STR_1110 :Rotating -STR_1111 :Rotating -STR_1112 :Operating -STR_1113 :Showing film -STR_1114 :Rotating -STR_1115 :Operating -STR_1116 :Operating -STR_1117 :Doing circus show -STR_1118 :Operating -STR_1119 :Waiting for cable lift -STR_1120 :Travelling at {VELOCITY} -STR_1121 :Stopping -STR_1122 :Waiting for passengers -STR_1123 :Waiting to start -STR_1124 :Starting -STR_1125 :Operating -STR_1126 :Stopping -STR_1127 :Unloading passengers -STR_1128 :Stopped by block brakes -STR_1129 :All vehicles in same colours -STR_1130 :Different colours per {STRINGID} -STR_1131 :Different colours per vehicle -STR_1132 :Vehicle {POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} -STR_1133 :Vehicle {POP16}{COMMA16} +STR_1022 :{POP16}{POP16}{POP16}{COMMA16} vagón por tren +STR_1023 :{POP16}{POP16}{POP16}{COMMA16} vagones por tren +STR_1024 :{COMMA16} vagón por tren +STR_1025 :{COMMA16} vagones por tren +STR_1026 :¡Andén demasiado largo! +STR_1027 :{SMALLFONT}{BLACK}Localizar esto en la Vista Principal. +STR_1028 :¡Fuera del borde del mapa! +STR_1029 :¡No se puede construir parte dentro y fuera del agua! +STR_1030 :¡Sólo se puede construir bajo el agua! +STR_1031 :¡No se puede construir esto bajo el agua! +STR_1032 :¡Sólo puede construirse en el agua! +STR_1033 :¡Sólo puede construirse encima del suelo! +STR_1034 :¡Sólo puede construirse en el suelo! +STR_1035 :¡Las autoridades locales prohíben las construcciones altas! +STR_1036 :Cargar Partida +STR_1037 :Cargar paisaje +STR_1038 :Convertir partida guardada en escenario +STR_1039 :Instalar nuevo diseño de vía +STR_1040 :Guardar Partida +STR_1041 :Guardar escenario +STR_1042 :Guardar paisaje +STR_1043 :OpenRCT2 Juegos guardados +STR_1044 :OpenRCT2 Archivo de Escenario +STR_1045 :OpenRCT2 Archivo de Paisaje +STR_1046 :OpenRCT2 Archivo de diseño de vía +STR_1047 :¡Guardar partida falló! +STR_1048 :¡Guardar escenario falló! +STR_1049 :¡Guardar paisaje falló! +STR_1050 :Falló al cargar...{NEWLINE}¡El archivo contiene datos inválidos! +STR_1051 :Soportes invisibles +STR_1052 :Visitantes invisibles +STR_1053 :{SMALLFONT}{BLACK}Atracciones en el parque +STR_1054 :{SMALLFONT}{BLACK}Nombrar atracción +STR_1055 :{SMALLFONT}{BLACK}Nombrar persona +STR_1056 :{SMALLFONT}{BLACK}Nombrar empleado +STR_1057 :Nombre de atracción +STR_1058 :Escribe el nombre de esta atracción: +STR_1059 :No se pudo renombrar la atracción... +STR_1060 :Nombre de atracción no válido +STR_1061 :Modo normal +STR_1062 :Modo circuito contínuo +STR_1063 :Modo lanzamiento invertido +STR_1064 :Modo lanzamiento impulsado (pasar estación) +STR_1065 :Modo lanzadera +STR_1066 :Modo alquiler de barcos +STR_1067 :Lanzamiento ascendente +STR_1068 :Modo elevación giratoria +STR_1069 :Modo estación a estación +STR_1070 :Un paseo por admisión +STR_1071 :Paseos ilimitados por admisión +STR_1072 :Modo laberinto +STR_1073 :Modo carrera +STR_1074 :Modo coches de choque +STR_1075 :Modo balanceo +STR_1076 :Modo tienda de parada +STR_1077 :Modo rotación +STR_1078 :Rotación hacia adelante +STR_1079 :Rotación hacia atrás +STR_1080 :Película: {ENDQUOTES}Aviadores emocionados{ENDQUOTES} +STR_1081 :Película 3D: {ENDQUOTES}Colas de ratón{ENDQUOTES} +STR_1082 :Modo anillos espaciales +STR_1083 :Modo principiante +STR_1084 :Lanzamiento impulsado por MLI +STR_1085 :Película: {ENDQUOTES}Pasajeros emocionados{ENDQUOTES} +STR_1086 :Película 3D: {ENDQUOTES}Cazadores de tormenta{ENDQUOTES} +STR_1087 :Película 3D: {ENDQUOTES}Invasores del espacio{ENDQUOTES} +STR_1088 :Modo intenso +STR_1089 :Modo frenético +STR_1090 :Modo casa encantada +STR_1091 :Modo show de circo +STR_1092 :Lanzamiento hacia abajo +STR_1093 :Modo de casa torcida +STR_1094 :Modo caída libre +STR_1095 :Modo circuito contínuo con secciones de bloque +STR_1096 :Lanzamiento impulsado (sin pasar estación) +STR_1097 :Modo lanzamiento impulsado seccionado +STR_1098 :Moviéndose al final de {POP16}{STRINGID} +STR_1099 :Esperando pasajeros en {POP16}{STRINGID} +STR_1100 :Esperando para salir de {POP16}{STRINGID} +STR_1101 :Saliendo de {POP16}{STRINGID} +STR_1102 :Moviéndose a {VELOCITY} +STR_1103 :Llegando a la {POP16}{STRINGID} +STR_1104 :Descargando pasajeros en {POP16}{STRINGID} +STR_1105 :Viajando a {VELOCITY} +STR_1106 :¡Estrellandose! +STR_1107 :¡Accidentado! +STR_1108 :Viajando a {VELOCITY} +STR_1109 :Balanceándose +STR_1110 :Rotando +STR_1111 :Rotando +STR_1112 :Operando +STR_1113 :Reproduciendo película +STR_1114 :Rotando +STR_1115 :Operando +STR_1116 :Operando +STR_1117 :Haciendo espectáculo de circo +STR_1118 :Operando +STR_1119 :Esperando al cable de elevación +STR_1120 :Viajando a {VELOCITY} +STR_1121 :Deteniendose +STR_1122 :Esperando pasajeros +STR_1123 :Esperando para iniciar +STR_1124 :Iniciando +STR_1125 :Operando +STR_1126 :Deteniendose +STR_1127 :Descargando pasajeros +STR_1128 :Detenido por bloque de frenado +STR_1129 :Todos los vagones del mismo color +STR_1130 :Diferentes colores por {STRINGID} +STR_1131 :Diferentes colores por vagón +STR_1132 :Vagón {POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} +STR_1133 :Vagón {POP16}{COMMA16} STR_1134 :{POP16}{POP16}{POP16}{POP16}{POP16}{STRINGID} {COMMA16} STR_1135 :{STRINGID} {COMMA16} -STR_1136 :{SMALLFONT}{BLACK}Select main colour -STR_1137 :{SMALLFONT}{BLACK}Select additional colour 1 -STR_1138 :{SMALLFONT}{BLACK}Select additional colour 2 -STR_1139 :{SMALLFONT}{BLACK}Select support structure colour -STR_1140 :{SMALLFONT}{BLACK}Select vehicle colour scheme option -STR_1141 :{SMALLFONT}{BLACK}Select which vehicle/train to modify +STR_1136 :{SMALLFONT}{BLACK}Seleccionar color principal +STR_1137 :{SMALLFONT}{BLACK}Seleccionar color adicional 1 +STR_1138 :{SMALLFONT}{BLACK}Seleccionar color adicional 2 +STR_1139 :{SMALLFONT}{BLACK}Seleccionar color de los soportes +STR_1140 :{SMALLFONT}{BLACK}Selecciona el esquema de color de los vagones +STR_1141 :{SMALLFONT}{BLACK}Selecciona que vehículo/tren modificar STR_1142 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1143 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRINGID} -STR_1144 :Can't build/move entrance for this ride/attraction... -STR_1145 :Can't build/move exit for this ride/attraction... -STR_1146 :Entrance not yet built -STR_1147 :Exit not yet built -STR_1148 :Quarter load -STR_1149 :Half load -STR_1150 :Three-quarter load -STR_1151 :Full load -STR_1152 :Any load -STR_1153 :Height Marks on Ride Tracks -STR_1154 :Height Marks on Land -STR_1155 :Height Marks on Paths +STR_1144 :No se puede construir/mover la entrada de esta atracción... +STR_1145 :No se puede construir/mover la salida de esta atracción... +STR_1146 :Aún no se ha construido una entrada +STR_1147 :Aún no se ha construido una salida +STR_1148 :Un cuarto de carga +STR_1149 :Media carga +STR_1150 :Tres cuartos de carga +STR_1151 :Carga completa +STR_1152 :Cualquier carga +STR_1153 :Marcas de altura en atracciones +STR_1154 :Marcas de altura en el suelo +STR_1155 :Marcas de altura en senderos STR_1156 :{MOVE_X}{SMALLFONT}{STRINGID} STR_1157 :{TICK}{MOVE_X}{SMALLFONT}{STRINGID} -STR_1158 :Can't remove this... -STR_1159 :{SMALLFONT}{BLACK}Place scenery, gardens, and other accessories -STR_1160 :{SMALLFONT}{BLACK}Create/adjust lakes & water -STR_1161 :Can't position this here... +STR_1158 :No se puede quitar esto... +STR_1159 :{SMALLFONT}{BLACK}Crear decorado, jardines y otros accesorios +STR_1160 :{SMALLFONT}{BLACK}Crear lagos y ajustar agua +STR_1161 :No se puede posicionar esto aquí... STR_1162 :{OUTLINE}{TOPAZ}{STRINGID} -STR_1163 :{STRINGID}{NEWLINE}(Right-Click to Modify) -STR_1164 :{STRINGID}{NEWLINE}(Right-Click to Remove) +STR_1163 :{STRINGID}{NEWLINE}(Clic derecho para modificar) +STR_1164 :{STRINGID}{NEWLINE}(Clic derecho para quitar) 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_1169 :(None) +STR_1166 :No se puede bajar el nivel de agua... +STR_1167 :No se puede subir el nivel del agua... +STR_1168 :Opciones +STR_1169 :(Ninguno) STR_1170 :{STRING} -STR_1171 :{RED}Closed - - +STR_1171 :{RED}Cerrada - - STR_1172 :{YELLOW}{STRINGID} - - -STR_1173 :{SMALLFONT}{BLACK}Build footpaths and queue lines -STR_1174 :Banner sign in the way -STR_1175 :Can't build this on sloped footpath -STR_1176 :Can't build footpath here... -STR_1177 :Can't remove footpath from here... -STR_1178 :Land slope unsuitable -STR_1179 :Footpath in the way -STR_1180 :Can't build this underwater! -STR_1181 :Footpaths -STR_1182 :Type -STR_1183 :Direction -STR_1184 :Slope -STR_1185 :{SMALLFONT}{BLACK}Direction -STR_1186 :{SMALLFONT}{BLACK}Slope down -STR_1187 :{SMALLFONT}{BLACK}Level -STR_1188 :{SMALLFONT}{BLACK}Slope up -STR_1189 :{SMALLFONT}{BLACK}Construct the selected footpath section -STR_1190 :{SMALLFONT}{BLACK}Remove previous footpath section +STR_1173 :{SMALLFONT}{BLACK}Construir senderos +STR_1174 :Cartel de señal interfiere +STR_1175 :No se puede construir esto sobre una pendiente +STR_1176 :No se puede construir este camino aquí... +STR_1177 :No se puede quitar este camino de aquí... +STR_1178 :Pendiente del terreno no apto +STR_1179 :Camino interfiere +STR_1180 :¡No se puede construir bajo el agua! +STR_1181 :Senderos +STR_1182 :Tipo +STR_1183 :Dirección +STR_1184 :Inclinación +STR_1185 :{SMALLFONT}{BLACK}Dirección +STR_1186 :{SMALLFONT}{BLACK}Cuesta abajo +STR_1187 :{SMALLFONT}{BLACK}Nivel del suelo +STR_1188 :{SMALLFONT}{BLACK}Cuesta arriba +STR_1189 :{SMALLFONT}{BLACK}Construye el camino seleccionado +STR_1190 :{SMALLFONT}{BLACK}Eliminar la sección de camino previo STR_1191 :{BLACK}{STRINGID} STR_1192 :{OUTLINE}{RED}{STRINGID} STR_1193 :{WINDOW_COLOUR_2}{STRINGID} -STR_1194 :Closed -STR_1195 :Test Run -STR_1196 :Open -STR_1197 :Broken Down -STR_1198 :Crashed! -STR_1199 :{COMMA16} person on ride -STR_1200 :{COMMA16} people on ride -STR_1201 :Nobody in queue line -STR_1202 :1 person in queue line -STR_1203 :{COMMA16} people in queue line -STR_1204 :{COMMA16} minute queue time -STR_1205 :{COMMA16} minutes queue time -STR_1206 :{WINDOW_COLOUR_2}Wait for: -STR_1207 :{WINDOW_COLOUR_2}Leave if another train arrives at station -STR_1208 :{WINDOW_COLOUR_2}Leave if another boat arrives at station -STR_1209 :{SMALLFONT}{BLACK}Select whether should wait for passengers before departing -STR_1210 :{SMALLFONT}{BLACK}Select whether should leave if another vehicle arrives at the same station -STR_1211 :{WINDOW_COLOUR_2}Minimum waiting time: -STR_1212 :{WINDOW_COLOUR_2}Maximum waiting time: -STR_1213 :{SMALLFONT}{BLACK}Select minimum length of time to wait before departing -STR_1214 :{SMALLFONT}{BLACK}Select maximum length of time to wait before departing -STR_1215 :{WINDOW_COLOUR_2}Synchronise with adjacent stations -STR_1216 :{SMALLFONT}{BLACK}Select whether to synchronise departure with all adjacent stations (for 'racing') -STR_1217 :{COMMA16} seconds +STR_1194 :Cerrado +STR_1195 :En pruebas +STR_1196 :Abierto +STR_1197 :Averiado +STR_1198 :¡Accidentado! +STR_1199 :{COMMA16} persona en la atracción +STR_1200 :{COMMA16} personas en la atracción +STR_1201 :Ninguna persona en cola +STR_1202 :1 persona en cola +STR_1203 :{COMMA16} personas en cola +STR_1204 :{COMMA16} minuto en cola +STR_1205 :{COMMA16} minutos en cola +STR_1206 :{WINDOW_COLOUR_2}Esperar a: +STR_1207 :{WINDOW_COLOUR_2}Partir si otro tren llega a la estación +STR_1208 :{WINDOW_COLOUR_2}Partir si otro bote llega a la estación +STR_1209 :{SMALLFONT}{BLACK}Selecciona si se debe esperar cierta carga de pasajeros antes de partir. +STR_1210 :{SMALLFONT}{BLACK}Seleccionar si se debe partir si otro vehículo llega a la misma estación. +STR_1211 :{WINDOW_COLOUR_2}Tiempo de espera mínimo: +STR_1212 :{WINDOW_COLOUR_2}Tiempo de espera máximo: +STR_1213 :{SMALLFONT}{BLACK}Selecciona el tiempo de espera mínimo antes de partir +STR_1214 :{SMALLFONT}{BLACK}Selecciona el tiempo de espera máximo antes de partir +STR_1215 :{WINDOW_COLOUR_2}Sincronizar con estaciones adyacentes +STR_1216 :{SMALLFONT}{BLACK}Selecciona si deseas sincronizar esta estación con otras estaciones adyacentes a esta estación. +STR_1217 :{COMMA16} segundos STR_1218 :{BLACK}{SMALLUP} STR_1219 :{BLACK}{SMALLDOWN} -STR_1220 :Exit only -STR_1221 :No entrance -STR_1222 :No exit -STR_1223 :{SMALLFONT}{BLACK}Transport rides -STR_1224 :{SMALLFONT}{BLACK}Gentle rides -STR_1225 :{SMALLFONT}{BLACK}Roller coasters -STR_1226 :{SMALLFONT}{BLACK}Thrill rides -STR_1227 :{SMALLFONT}{BLACK}Water rides -STR_1228 :{SMALLFONT}{BLACK}Shops & stalls -STR_1229 :train -STR_1230 :trains -STR_1231 :Train -STR_1232 :Trains -STR_1233 :{COMMA16} train -STR_1234 :{COMMA16} trains -STR_1235 :Train {COMMA16} -STR_1236 :boat -STR_1237 :boats -STR_1238 :Boat -STR_1239 :Boats -STR_1240 :{COMMA16} boat -STR_1241 :{COMMA16} boats -STR_1242 :Boat {COMMA16} -STR_1243 :track -STR_1244 :tracks -STR_1245 :Track -STR_1246 :Tracks -STR_1247 :{COMMA16} track -STR_1248 :{COMMA16} tracks -STR_1249 :Track {COMMA16} -STR_1250 :docking platform -STR_1251 :docking platforms -STR_1252 :Docking platform -STR_1253 :Docking platforms -STR_1254 :{COMMA16} docking platform -STR_1255 :{COMMA16} docking platforms -STR_1256 :Docking platform {COMMA16} -STR_1257 :station -STR_1258 :stations -STR_1259 :Station -STR_1260 :Stations -STR_1261 :{COMMA16} station -STR_1262 :{COMMA16} stations -STR_1263 :Station {COMMA16} -STR_1264 :car -STR_1265 :cars -STR_1266 :Car -STR_1267 :Cars -STR_1268 :{COMMA16} car -STR_1269 :{COMMA16} cars -STR_1270 :Car {COMMA16} -STR_1271 :building -STR_1272 :buildings -STR_1273 :Building -STR_1274 :Buildings -STR_1275 :{COMMA16} building -STR_1276 :{COMMA16} buildings -STR_1277 :Building {COMMA16} -STR_1278 :structure -STR_1279 :structures -STR_1280 :Structure -STR_1281 :Structures -STR_1282 :{COMMA16} structure -STR_1283 :{COMMA16} structures -STR_1284 :Structure {COMMA16} -STR_1285 :ship -STR_1286 :ships -STR_1287 :Ship -STR_1288 :Ships -STR_1289 :{COMMA16} ship -STR_1290 :{COMMA16} ships -STR_1291 :Ship {COMMA16} -STR_1292 :cabin -STR_1293 :cabins -STR_1294 :Cabin -STR_1295 :Cabins -STR_1296 :{COMMA16} cabin -STR_1297 :{COMMA16} cabins -STR_1298 :Cabin {COMMA16} -STR_1299 :wheel -STR_1300 :wheels -STR_1301 :Wheel -STR_1302 :Wheels -STR_1303 :{COMMA16} wheel -STR_1304 :{COMMA16} wheels -STR_1305 :Wheel {COMMA16} -STR_1306 :ring -STR_1307 :rings -STR_1308 :Ring -STR_1309 :Rings -STR_1310 :{COMMA16} ring -STR_1311 :{COMMA16} rings -STR_1312 :Ring {COMMA16} -STR_1313 :player -STR_1314 :players -STR_1315 :Player -STR_1316 :Players -STR_1317 :{COMMA16} player -STR_1318 :{COMMA16} players -STR_1319 :Player {COMMA16} -STR_1320 :course -STR_1321 :courses -STR_1322 :Course -STR_1323 :Courses -STR_1324 :{COMMA16} course -STR_1325 :{COMMA16} courses -STR_1326 :Course {COMMA16} -STR_1327 :{SMALLFONT}{BLACK}Rotate objects by 90{DEGREE} -STR_1328 :Level land required -STR_1329 :{WINDOW_COLOUR_2}Launch speed: -STR_1330 :{SMALLFONT}{BLACK}Maximum speed when leaving station +STR_1220 :Sólo salida +STR_1221 :No hay entrada +STR_1222 :No hay salida +STR_1223 :{SMALLFONT}{BLACK}Atracciones de transporte +STR_1224 :{SMALLFONT}{BLACK}Atracciones suave +STR_1225 :{SMALLFONT}{BLACK}Montañas rusas +STR_1226 :{SMALLFONT}{BLACK}Atracciones intensas +STR_1227 :{SMALLFONT}{BLACK}Atracciones de agua +STR_1228 :{SMALLFONT}{BLACK}Tiendas y puestos +STR_1229 :tren +STR_1230 :trenes +STR_1231 :Tren +STR_1232 :Trenes +STR_1233 :{COMMA16} tren +STR_1234 :{COMMA16} trenes +STR_1235 :Tren {COMMA16} +STR_1236 :bote +STR_1237 :botes +STR_1238 :Bote +STR_1239 :Botes +STR_1240 :{COMMA16} bote +STR_1241 :{COMMA16} botes +STR_1242 :Bote {COMMA16} +STR_1243 :vía +STR_1244 :vías +STR_1245 :Vía +STR_1246 :Vías +STR_1247 :{COMMA16} vía +STR_1248 :{COMMA16} vías +STR_1249 :Vía {COMMA16} +STR_1250 :plataforma de acoplamiento +STR_1251 :plataformas de acoplamiento +STR_1252 :Plataforma de acoplamiento +STR_1253 :Plataformas de acoplamiento +STR_1254 :{COMMA16} plataforma de acoplamiento +STR_1255 :{COMMA16} plataformas de acoplamiento +STR_1256 :Plataforma de acoplamiento {COMMA16} +STR_1257 :la estación +STR_1258 :estaciones +STR_1259 :Estación +STR_1260 :Estaciones +STR_1261 :{COMMA16} estación +STR_1262 :{COMMA16} estaciones +STR_1263 :Estación {COMMA16} +STR_1264 :carro +STR_1265 :carros +STR_1266 :Carro +STR_1267 :Carros +STR_1268 :{COMMA16} carro +STR_1269 :{COMMA16} carros +STR_1270 :Carro {COMMA16} +STR_1271 :edificio +STR_1272 :edificios +STR_1273 :Edificio +STR_1274 :Edificios +STR_1275 :{COMMA16} edificio +STR_1276 :{COMMA16} edificios +STR_1277 :Edificio {COMMA16} +STR_1278 :estructura +STR_1279 :estructuras +STR_1280 :Estructura +STR_1281 :Estructuras +STR_1282 :{COMMA16} estructura +STR_1283 :{COMMA16} estructuras +STR_1284 :Estructura {COMMA16} +STR_1285 :barco +STR_1286 :barcos +STR_1287 :Barco +STR_1288 :Barcos +STR_1289 :{COMMA16} barco +STR_1290 :{COMMA16} barcos +STR_1291 :Barco {COMMA16} +STR_1292 :cabina +STR_1293 :cabinas +STR_1294 :Cabina +STR_1295 :Cabinas +STR_1296 :{COMMA16} cabina +STR_1297 :{COMMA16} cabinas +STR_1298 :Cabina {COMMA16} +STR_1299 :rueda +STR_1300 :ruedas +STR_1301 :Rueda +STR_1302 :Ruedas +STR_1303 :{COMMA16} rueda +STR_1304 :{COMMA16} ruedas +STR_1305 :Rueda {COMMA16} +STR_1306 :tono +STR_1307 :tonos +STR_1308 :Tono +STR_1309 :Tonos +STR_1310 :{COMMA16} tono +STR_1311 :{COMMA16} tonos +STR_1312 :Tono {COMMA16} +STR_1313 :jugador +STR_1314 :jugadores +STR_1315 :Jugador +STR_1316 :Jugadores +STR_1317 :{COMMA16} jugador +STR_1318 :{COMMA16} jugadores +STR_1319 :Jugador {COMMA16} +STR_1320 :curso +STR_1321 :cursos +STR_1322 :Curso +STR_1323 :Cursos +STR_1324 :{COMMA16} curso +STR_1325 :{COMMA16} cursos +STR_1326 :Curso {COMMA16} +STR_1327 :{SMALLFONT}{BLACK}Rotar objetos en 90{DEGREE} +STR_1328 :Terreno llano requerido +STR_1329 :{WINDOW_COLOUR_2}Velocidad de lanzamiento: +STR_1330 :{SMALLFONT}{BLACK}Velocidad máxima al salir de la estación STR_1331 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} STR_1332 :{VELOCITY} STR_1333 :{STRINGID} - {STRINGID}{POP16} STR_1334 :{STRINGID} - {STRINGID} {COMMA16} -STR_1335 :{STRINGID} - Entrance{POP16}{POP16} -STR_1336 :{STRINGID} - Station {POP16}{COMMA16} Entrance -STR_1337 :{STRINGID} - Exit{POP16}{POP16} -STR_1338 :{STRINGID} - Station {POP16}{COMMA16} Exit -STR_1339 :{BLACK}No test results yet... -STR_1340 :{WINDOW_COLOUR_2}Max. speed: {BLACK}{VELOCITY} -STR_1341 :{WINDOW_COLOUR_2}Ride time: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1335 :{STRINGID} - Entrada{POP16}{POP16} +STR_1336 :{STRINGID} - Estación {POP16}{COMMA16} Entrada +STR_1337 :{STRINGID} - Salidad{POP16}{POP16} +STR_1338 :{STRINGID} - Estación {POP16}{COMMA16} Salida +STR_1339 :{BLACK}No hay resultados de prueba aún... +STR_1340 :{WINDOW_COLOUR_2}Velocidad máxima: {BLACK}{VELOCITY} +STR_1341 :{WINDOW_COLOUR_2}Tiempo de viaje: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1342 :{DURATION} STR_1343 :{DURATION} / -STR_1344 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} +STR_1344 :{WINDOW_COLOUR_2}Longitud de viaje: {BLACK}{STRINGID}{STRINGID}{STRINGID}{STRINGID} STR_1345 :{LENGTH} STR_1346 :{LENGTH} / -STR_1347 :{WINDOW_COLOUR_2}Average speed: {BLACK}{VELOCITY} -STR_1348 :{WINDOW_COLOUR_2}Max. positive vertical G's: {BLACK}{COMMA2DP32}g -STR_1349 :{WINDOW_COLOUR_2}Max. positive vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1350 :{WINDOW_COLOUR_2}Max. negative vertical G's: {BLACK}{COMMA2DP32}g -STR_1351 :{WINDOW_COLOUR_2}Max. negative vertical G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1352 :{WINDOW_COLOUR_2}Max. lateral G's: {BLACK}{COMMA2DP32}g -STR_1353 :{WINDOW_COLOUR_2}Max. lateral G's: {OUTLINE}{RED}{COMMA2DP32}g -STR_1354 :{WINDOW_COLOUR_2}Highest drop height: {BLACK}{LENGTH} -STR_1355 :{WINDOW_COLOUR_2}Drops: {BLACK}{COMMA16} +STR_1347 :{WINDOW_COLOUR_2}Velocidad media: {BLACK}{VELOCITY} +STR_1348 :{WINDOW_COLOUR_2}Aceleración máx. vertical positiva: {BLACK}{COMMA2DP32}g +STR_1349 :{WINDOW_COLOUR_2}Aceleración máx. vertical positiva: {OUTLINE}{RED}{COMMA2DP32}g +STR_1350 :{WINDOW_COLOUR_2}Aceleración máx. vertical negativa: {BLACK}{COMMA2DP32}g +STR_1351 :{WINDOW_COLOUR_2}Aceleración máx. vertical negativa: {OUTLINE}{RED}{COMMA2DP32}g +STR_1352 :{WINDOW_COLOUR_2}Aceleración máx. lateral: {BLACK}{COMMA2DP32}g +STR_1353 :{WINDOW_COLOUR_2}Aceleración máx. lateral: {OUTLINE}{RED}{COMMA2DP32}g +STR_1354 :{WINDOW_COLOUR_2}Altura de la mayor caída: {BLACK}{LENGTH} +STR_1355 :{WINDOW_COLOUR_2}Caídas: {BLACK}{COMMA16} STR_1356 :{WINDOW_COLOUR_2}Inversions: {BLACK}{COMMA16} -STR_1357 :{WINDOW_COLOUR_2}Holes: {BLACK}{COMMA16} -STR_1358 :{WINDOW_COLOUR_2}Total 'air' time: {BLACK}{COMMA2DP32}secs -STR_1359 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minute -STR_1360 :{WINDOW_COLOUR_2}Queue time: {BLACK}{COMMA16} minutes -STR_1361 :Can't change speed... -STR_1362 :Can't change launch speed... -STR_1363 :Too high for supports! -STR_1364 :Supports for track above can't be extended any further! -STR_1365 :In-line Twist (left) -STR_1366 :In-line Twist (right) -STR_1367 :Half Loop -STR_1368 :Half Corkscrew (left) -STR_1369 :Half Corkscrew (right) -STR_1370 :Barrel Roll (left) -STR_1371 :Barrel Roll (right) -STR_1372 :Launched Lift Hill -STR_1373 :Large Half Loop (left) -STR_1374 :Large Half Loop (right) -STR_1375 :Upper Transfer -STR_1376 :Lower Transfer -STR_1377 :Heartline Roll (left) -STR_1378 :Heartline Roll (right) -STR_1379 :Reverser (left) -STR_1380 :Reverser (right) -STR_1381 :Curved Lift Hill (left) -STR_1382 :Curved Lift Hill (right) -STR_1383 :Quarter Loop +STR_1357 :{WINDOW_COLOUR_2}Hoyos: {BLACK}{COMMA16} +STR_1358 :{WINDOW_COLOUR_2}Tiempo total de 'vuelo': {BLACK}{COMMA2DP32}secs +STR_1359 :{WINDOW_COLOUR_2}Tiempo de espera: {BLACK}{COMMA16} minuto +STR_1360 :{WINDOW_COLOUR_2}Tiempo de espera: {BLACK}{COMMA16} minutos +STR_1361 :No puedes cambiar la velocidad... +STR_1362 :No puedes cambiar la velocidad de lanzamiento... +STR_1363 :¡Muy alto para los soportes! +STR_1364 :¡Los soportes del tramo anterior no se pueden extender más! +STR_1365 :Giro en-línea (izquierda) +STR_1366 :Giro en-línea (derecha) +STR_1367 :Media vuelta +STR_1368 :Medio Sacacorcho (izq) +STR_1369 :Medio Sacacorcho (der) +STR_1370 :Tonel (izquierdo) +STR_1371 :Tonel (derecho) +STR_1372 :Subida propulsada +STR_1373 :Media vuelta larga (izq) +STR_1374 :Media vuelta larga (der) +STR_1375 :Transferencia superior +STR_1376 :Transferencia inferior +STR_1377 :Giro med. alt. (der) +STR_1378 :Giro med. alt. (izq) +STR_1379 :Inversor (izq) +STR_1380 :Inversor (der) +STR_1381 :Subida en curva (izq) +STR_1382 :Subida en curva (der) +STR_1383 :Cuarto de vuelta STR_1384 :{YELLOW}{STRINGID} -STR_1385 :{SMALLFONT}{BLACK}Other track configurations -STR_1386 :Special... -STR_1387 :Can't change land type... +STR_1385 :{SMALLFONT}{BLACK}Otros tipos de tramos +STR_1386 :Tramo especial... +STR_1387 :No se puede cambiar el tipo de tierra... STR_1388 :{OUTLINE}{GREEN}+ {CURRENCY} STR_1389 :{OUTLINE}{RED}- {CURRENCY} STR_1390 :{CURRENCY2DP} STR_1391 :{RED}{CURRENCY2DP} -STR_1392 :{SMALLFONT}{BLACK}View of ride/attraction -STR_1393 :{SMALLFONT}{BLACK}Vehicle details and options -STR_1394 :{SMALLFONT}{BLACK}Operating options -STR_1395 :{SMALLFONT}{BLACK}Maintenance options -STR_1396 :{SMALLFONT}{BLACK}Colour scheme options -STR_1397 :{SMALLFONT}{BLACK}Sound & music options -STR_1398 :{SMALLFONT}{BLACK}Measurements and test data -STR_1399 :{SMALLFONT}{BLACK}Graphs -STR_1400 :Entrance -STR_1401 :Exit -STR_1402 :{SMALLFONT}{BLACK}Build or move entrance to ride/attraction -STR_1403 :{SMALLFONT}{BLACK}Build or move exit from ride/attraction -STR_1404 :{SMALLFONT}{BLACK}Rotate 90{DEGREE} -STR_1405 :{SMALLFONT}{BLACK}Mirror image -STR_1406 :{SMALLFONT}{BLACK}Toggle scenery on/off (if available for this design) -STR_1407 :{WINDOW_COLOUR_2}Build this... -STR_1408 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY} -STR_1409 :Entry/Exit Platform -STR_1410 :Vertical Tower -STR_1411 :{STRINGID} in the way -STR_1412 :{WINDOW_COLOUR_3}Data logging not available for this type of ride -STR_1413 :{WINDOW_COLOUR_3}Data logging will start when next {STRINGID} leaves {STRINGID} +STR_1392 :{SMALLFONT}{BLACK}Vista de la atracción +STR_1393 :{SMALLFONT}{BLACK}Opciones de vehículos +STR_1394 :{SMALLFONT}{BLACK}Opciones de funcionamiento +STR_1395 :{SMALLFONT}{BLACK}Opciones de mantenimiento +STR_1396 :{SMALLFONT}{BLACK}Opciones de esquemas de color +STR_1397 :{SMALLFONT}{BLACK}Opciones de música y sonidos +STR_1398 :{SMALLFONT}{BLACK}Datos de tests y medidas +STR_1399 :{SMALLFONT}{BLACK}Gráficas +STR_1400 :Entrada +STR_1401 :Salida +STR_1402 :{SMALLFONT}{BLACK}Construir o mover entrada de atracción/juego +STR_1403 :{SMALLFONT}{BLACK}Construir o mover salida de atracción/juego +STR_1404 :{SMALLFONT}{BLACK}Rotar 90{DEGREE} +STR_1405 :{SMALLFONT}{BLACK}Rotar en Espejo +STR_1406 :{SMALLFONT}{BLACK}Muestra u oculta el decorado (si se encuentra disponible) +STR_1407 :{WINDOW_COLOUR_2}Construye esto... +STR_1408 :{WINDOW_COLOUR_2}Precio: {BLACK}{CURRENCY} +STR_1409 :Estación +STR_1410 :Sección vertical +STR_1411 :{STRINGID} en medio +STR_1412 :{WINDOW_COLOUR_3}Estadísticas no disponibles para este tipo de atracción +STR_1413 :{WINDOW_COLOUR_3}Las estadísticas comenzarán a registrarse cuando el {STRINGID} salga de la {STRINGID} STR_1414 :{SMALLFONT}{BLACK}{DURATION} -STR_1415 :{WINDOW_COLOUR_2}Velocity -STR_1416 :{WINDOW_COLOUR_2}Altitude -STR_1417 :{WINDOW_COLOUR_2}Vert.G's -STR_1418 :{WINDOW_COLOUR_2}Lat.G's +STR_1415 :{WINDOW_COLOUR_2}Velocidad +STR_1416 :{WINDOW_COLOUR_2}Altitud +STR_1417 :{WINDOW_COLOUR_2}Acel. Vert. +STR_1418 :{WINDOW_COLOUR_2}Acel. Lat. STR_1419 :{SMALLFONT}{BLACK}{VELOCITY} STR_1420 :{SMALLFONT}{BLACK}{LENGTH} STR_1421 :{SMALLFONT}{BLACK}{COMMA16}g -STR_1422 :{SMALLFONT}{BLACK}Logging data from {POP16}{STRINGID} -STR_1423 :{SMALLFONT}{BLACK}Queue line path -STR_1424 :{SMALLFONT}{BLACK}Footpath -STR_1425 :Footpath -STR_1426 :Queue Line -STR_1427 :{WINDOW_COLOUR_2}Customers: {BLACK}{COMMA32} per hour -STR_1428 :{WINDOW_COLOUR_2}Admission price: +STR_1422 :{SMALLFONT}{BLACK}Guardando datos de {POP16}{STRINGID} +STR_1423 :{SMALLFONT}{BLACK}Fila de espera +STR_1424 :{SMALLFONT}{BLACK}Sendero +STR_1425 :Sendero +STR_1426 :Línea de Espera +STR_1427 :{WINDOW_COLOUR_2}Clientes: {BLACK}{COMMA32} por hora +STR_1428 :{WINDOW_COLOUR_2}Precio de la entrada: STR_1429 :{POP16}{POP16}{POP16}{CURRENCY2DP} -STR_1430 :Free -STR_1431 :Walking -STR_1432 :Heading for {STRINGID} -STR_1433 :Queuing for {STRINGID} -STR_1434 :Drowning -STR_1435 :On {STRINGID} -STR_1436 :In {STRINGID} -STR_1437 :At {STRINGID} -STR_1438 :Sitting -STR_1439 :(select location) -STR_1440 :Mowing grass -STR_1441 :Sweeping footpath -STR_1442 :Emptying litter bin -STR_1443 :Watering gardens -STR_1444 :Watching {STRINGID} -STR_1445 :Watching construction of {STRINGID} -STR_1446 :Looking at scenery -STR_1447 :Leaving the park -STR_1448 :Watching new ride being constructed +STR_1430 :Gratis +STR_1431 :Caminando +STR_1432 :Yendo a {STRINGID} +STR_1433 :Esperando en {STRINGID} +STR_1434 :Ahogándose +STR_1435 :En {STRINGID} +STR_1436 :En {STRINGID} +STR_1437 :En {STRINGID} +STR_1438 :Sentado +STR_1439 :(selecciona nueva ubicación) +STR_1440 :Cortando césped +STR_1441 :Limpiando el suelo +STR_1442 :Vaciando papelera +STR_1443 :Regando plantas +STR_1444 :Mirando {STRINGID} +STR_1445 :Mirando construcción de {STRINGID} +STR_1446 :Observando el decorado +STR_1447 :Abandonando el parque +STR_1448 :Viendo construcción de atracción STR_1449 :{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1450 :{INLINE_SPRITE}{09}{20}{00}{00}{SPRITE} {STRINGID}{NEWLINE}({STRINGID}) STR_1451 :{STRINGID}{NEWLINE}({STRINGID}) -STR_1452 :Visitante's name -STR_1453 :Enter name for this guest: -STR_1454 :Can't name guest... -STR_1455 :Invalid name for guest -STR_1456 :{WINDOW_COLOUR_2}Cash spent: {BLACK}{CURRENCY2DP} -STR_1457 :{WINDOW_COLOUR_2}Cash in pocket: {BLACK}{CURRENCY2DP} -STR_1458 :{WINDOW_COLOUR_2}Time in park: {BLACK}{REALTIME} -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_1452 :Nombrar Visitante +STR_1453 :Escribe el nombre para este visitante: +STR_1454 :No se puede renombrar visitante... +STR_1455 :Nombre no válido para visitante +STR_1456 :{WINDOW_COLOUR_2}Dinero gastado: {BLACK}{CURRENCY2DP} +STR_1457 :{WINDOW_COLOUR_2}Dinero en el bolsillo: {BLACK}{CURRENCY2DP} +STR_1458 :{WINDOW_COLOUR_2}Tiempo en el parque: {BLACK}{REALTIME} +STR_1459 :Estilo Vía +STR_1460 :{SMALLFONT}{BLACK}Pista en forma de 'U' +STR_1461 :{SMALLFONT}{BLACK}Pista en forma de 'O' +STR_1462 :Demasiado enclinado para las cadenas de elevación. STR_1463 :Visitantes -STR_1464 :Helix up (small) -STR_1465 :Helix up (large) -STR_1466 :Helix down (small) -STR_1467 :Helix down (large) -STR_1468 :Staff -STR_1469 :Ride must start and end with stations -STR_1470 :Station not long enough -STR_1471 :{WINDOW_COLOUR_2}Speed: -STR_1472 :{SMALLFONT}{BLACK}Speed of this ride -STR_1473 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1474 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}Not yet available -STR_1475 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1476 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}Not yet available -STR_1477 :{WINDOW_COLOUR_2}Intensity rating: {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) -STR_1478 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} ({STRINGID}) -STR_1479 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}Not yet available -STR_1480 :{SMALLFONT}{OPENQUOTES}I can't afford {STRINGID}{ENDQUOTES} -STR_1481 :{SMALLFONT}{OPENQUOTES}I've spent all my money{ENDQUOTES} -STR_1482 :{SMALLFONT}{OPENQUOTES}I feel sick{ENDQUOTES} -STR_1483 :{SMALLFONT}{OPENQUOTES}I feel very sick{ENDQUOTES} -STR_1484 :{SMALLFONT}{OPENQUOTES}I want to go on something more thrilling than {STRINGID}{ENDQUOTES} -STR_1485 :{SMALLFONT}{OPENQUOTES}{STRINGID} looks too intense for me{ENDQUOTES} -STR_1486 :{SMALLFONT}{OPENQUOTES}I haven't finished my {STRINGID} yet{ENDQUOTES} -STR_1487 :{SMALLFONT}{OPENQUOTES}Just looking at {STRINGID} makes me feel sick{ENDQUOTES} -STR_1488 :{SMALLFONT}{OPENQUOTES}I'm not paying that much to go on {STRINGID}{ENDQUOTES} -STR_1489 :{SMALLFONT}{OPENQUOTES}I want to go home{ENDQUOTES} -STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} is really good value{ENDQUOTES} -STR_1491 :{SMALLFONT}{OPENQUOTES}I've already got {STRINGID}{ENDQUOTES} -STR_1492 :{SMALLFONT}{OPENQUOTES}I can't afford {STRINGID}{ENDQUOTES} -STR_1493 :{SMALLFONT}{OPENQUOTES}I'm not hungry{ENDQUOTES} -STR_1494 :{SMALLFONT}{OPENQUOTES}I'm not thirsty{ENDQUOTES} -STR_1495 :{SMALLFONT}{OPENQUOTES}Help! I'm drowning!{ENDQUOTES} -STR_1496 :{SMALLFONT}{OPENQUOTES}I'm lost!{ENDQUOTES} -STR_1497 :{SMALLFONT}{OPENQUOTES}{STRINGID} was great{ENDQUOTES} -STR_1498 :{SMALLFONT}{OPENQUOTES}I've been queuing for {STRINGID} for ages{ENDQUOTES} -STR_1499 :{SMALLFONT}{OPENQUOTES}I'm tired{ENDQUOTES} -STR_1500 :{SMALLFONT}{OPENQUOTES}I'm hungry{ENDQUOTES} -STR_1501 :{SMALLFONT}{OPENQUOTES}I'm thirsty{ENDQUOTES} -STR_1502 :{SMALLFONT}{OPENQUOTES}I need to go to the bathroom{ENDQUOTES} -STR_1503 :{SMALLFONT}{OPENQUOTES}I can't find {STRINGID}{ENDQUOTES} -STR_1504 :{SMALLFONT}{OPENQUOTES}I'm not paying that much to use {STRINGID}{ENDQUOTES} -STR_1505 :{SMALLFONT}{OPENQUOTES}I'm not going on {STRINGID} while it's raining{ENDQUOTES} -STR_1506 :{SMALLFONT}{OPENQUOTES}The litter here is really bad{ENDQUOTES} -STR_1507 :{SMALLFONT}{OPENQUOTES}I can't find the park exit{ENDQUOTES} -STR_1508 :{SMALLFONT}{OPENQUOTES}I want to get off {STRINGID}{ENDQUOTES} -STR_1509 :{SMALLFONT}{OPENQUOTES}I want to get out of {STRINGID}{ENDQUOTES} -STR_1510 :{SMALLFONT}{OPENQUOTES}I'm not going on {STRINGID} - It isn't safe{ENDQUOTES} -STR_1511 :{SMALLFONT}{OPENQUOTES}This path is disgusting{ENDQUOTES} -STR_1512 :{SMALLFONT}{OPENQUOTES}It's too crowded here{ENDQUOTES} -STR_1513 :{SMALLFONT}{OPENQUOTES}The vandalism here is really bad{ENDQUOTES} -STR_1514 :{SMALLFONT}{OPENQUOTES}Great scenery!{ENDQUOTES} -STR_1515 :{SMALLFONT}{OPENQUOTES}This park is really clean and tidy{ENDQUOTES} -STR_1516 :{SMALLFONT}{OPENQUOTES}The jumping fountains are great{ENDQUOTES} -STR_1517 :{SMALLFONT}{OPENQUOTES}The music is nice here{ENDQUOTES} -STR_1518 :{SMALLFONT}{OPENQUOTES}This balloon from {STRINGID} is really good value{ENDQUOTES} -STR_1519 :{SMALLFONT}{OPENQUOTES}This cuddly toy from {STRINGID} is really good value{ENDQUOTES} -STR_1520 :{SMALLFONT}{OPENQUOTES}This park map from {STRINGID} is really good value{ENDQUOTES} -STR_1521 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1522 :{SMALLFONT}{OPENQUOTES}This umbrella from {STRINGID} is really good value{ENDQUOTES} -STR_1523 :{SMALLFONT}{OPENQUOTES}This drink from {STRINGID} is really good value{ENDQUOTES} -STR_1524 :{SMALLFONT}{OPENQUOTES}This burger from {STRINGID} is really good value{ENDQUOTES} -STR_1525 :{SMALLFONT}{OPENQUOTES}These chips from {STRINGID} are really good value{ENDQUOTES} -STR_1526 :{SMALLFONT}{OPENQUOTES}This ice cream from {STRINGID} is really good value{ENDQUOTES} -STR_1527 :{SMALLFONT}{OPENQUOTES}This candyfloss from {STRINGID} is really good value{ENDQUOTES} +STR_1464 :Hélice arriba (pequeña) +STR_1465 :Hélice arriba (grande) +STR_1466 :Hélice abajo (pequeña) +STR_1467 :Hélice abajo (grande) +STR_1468 :Empleados +STR_1469 :La atracción debe comenzar y terminar con las estaciones. +STR_1470 :La estación no es lo suficientemente largo. +STR_1471 :{WINDOW_COLOUR_2}Velocidad: +STR_1472 :{SMALLFONT}{BLACK}Velocidad de esta atraccion +STR_1473 :{WINDOW_COLOUR_2}Nivel de emoción: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1474 :{WINDOW_COLOUR_2}Nivel de emoción: {BLACK}Aún no disponible +STR_1475 :{WINDOW_COLOUR_2}Nivel de intensidad: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1476 :{WINDOW_COLOUR_2}Nivel de intensidad: {BLACK}Aún no disponible +STR_1477 :{WINDOW_COLOUR_2}Nivel de intensidad: {OUTLINE}{RED}{COMMA2DP32} ({STRINGID}) +STR_1478 :{WINDOW_COLOUR_2}Nivel de náusea: {BLACK}{COMMA2DP32} ({STRINGID}) +STR_1479 :{WINDOW_COLOUR_2}Nivel de náusea: {BLACK}Aún no disponible +STR_1480 :{SMALLFONT}{OPENQUOTES}No puedo pagar para {STRINGID}{ENDQUOTES} +STR_1481 :{SMALLFONT}{OPENQUOTES}He gastado todo mi dinero{ENDQUOTES} +STR_1482 :{SMALLFONT}{OPENQUOTES}Me siento mareado{ENDQUOTES} +STR_1483 :{SMALLFONT}{OPENQUOTES}Me siento muy mareado{ENDQUOTES} +STR_1484 :{SMALLFONT}{OPENQUOTES}Quiero probar algo más arriesgado que {STRINGID}{ENDQUOTES} +STR_1485 :{SMALLFONT}{OPENQUOTES}{STRINGID} parece demasiado intenso para mí{ENDQUOTES} +STR_1486 :{SMALLFONT}{OPENQUOTES}Aún no he acabado mi {STRINGID}{ENDQUOTES} +STR_1487 :{SMALLFONT}{OPENQUOTES}Con sólo mirar {STRINGID} me marea{ENDQUOTES} +STR_1488 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto para subir a {STRINGID}{ENDQUOTES} +STR_1489 :{SMALLFONT}{OPENQUOTES}Quiero volver a casa{ENDQUOTES} +STR_1490 :{SMALLFONT}{OPENQUOTES}{STRINGID} es barato{ENDQUOTES} +STR_1491 :{SMALLFONT}{OPENQUOTES}Ya tengo {STRINGID}{ENDQUOTES} +STR_1492 :{SMALLFONT}{OPENQUOTES}No puedo pagar para {STRINGID}{ENDQUOTES} +STR_1493 :{SMALLFONT}{OPENQUOTES}No tengo hambre{ENDQUOTES} +STR_1494 :{SMALLFONT}{OPENQUOTES}No tengo sed{ENDQUOTES} +STR_1495 :{SMALLFONT}{OPENQUOTES}¡Ayuda!¡Me ahogo!{ENDQUOTES} +STR_1496 :{SMALLFONT}{OPENQUOTES}¡Me he perdido!{ENDQUOTES} +STR_1497 :{SMALLFONT}{OPENQUOTES}{STRINGID} ha sido estupendo{ENDQUOTES} +STR_1498 :{SMALLFONT}{OPENQUOTES}He esperado una eternidad en {STRINGID}{ENDQUOTES} +STR_1499 :{SMALLFONT}{OPENQUOTES}Estoy cansado{ENDQUOTES} +STR_1500 :{SMALLFONT}{OPENQUOTES}Tengo hambre{ENDQUOTES} +STR_1501 :{SMALLFONT}{OPENQUOTES}Estoy sediento{ENDQUOTES} +STR_1502 :{SMALLFONT}{OPENQUOTES}Tengo que ir al lavabo{ENDQUOTES} +STR_1503 :{SMALLFONT}{OPENQUOTES}No encuentro {STRINGID}{ENDQUOTES} +STR_1504 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por {STRINGID}{ENDQUOTES} +STR_1505 :{SMALLFONT}{OPENQUOTES}No voy a subir a {STRINGID} mientras llueve{ENDQUOTES} +STR_1506 :{SMALLFONT}{OPENQUOTES}Las papeleras aquí brillan por su ausencia{ENDQUOTES} +STR_1507 :{SMALLFONT}{OPENQUOTES}No puedo encontrar la salida{ENDQUOTES} +STR_1508 :{SMALLFONT}{OPENQUOTES}Quiero bajarme de {STRINGID}{ENDQUOTES} +STR_1509 :{SMALLFONT}{OPENQUOTES}Quiero salir de {STRINGID}{ENDQUOTES} +STR_1510 :{SMALLFONT}{OPENQUOTES}No voy a subir a {STRINGID}, no es seguro{ENDQUOTES} +STR_1511 :{SMALLFONT}{OPENQUOTES}Este camino es repugnante{ENDQUOTES} +STR_1512 :{SMALLFONT}{OPENQUOTES}Está atestado{ENDQUOTES} +STR_1513 :{SMALLFONT}{OPENQUOTES}El vandalismo es terrible{ENDQUOTES} +STR_1514 :{SMALLFONT}{OPENQUOTES}¡El paisaje es estupendo!{ENDQUOTES} +STR_1515 :{SMALLFONT}{OPENQUOTES}Este parque está realmente limpio y ordenado{ENDQUOTES} +STR_1516 :{SMALLFONT}{OPENQUOTES}Las fuentes saltarinas son estupendas{ENDQUOTES} +STR_1517 :{SMALLFONT}{OPENQUOTES}La música es agradable{ENDQUOTES} +STR_1518 :{SMALLFONT}{OPENQUOTES}Este Globo de {STRINGID} es barato{ENDQUOTES} +STR_1519 :{SMALLFONT}{OPENQUOTES}Este Juguetito de {STRINGID} es barato{{ENDQUOTES} +STR_1520 :{SMALLFONT}{OPENQUOTES}Este Mapa de {STRINGID} es barato{{ENDQUOTES} +STR_1521 :{SMALLFONT}{OPENQUOTES}Esta Foto de {STRINGID} es barato{{ENDQUOTES} +STR_1522 :{SMALLFONT}{OPENQUOTES}Este Paraguas de {STRINGID} es barato{{ENDQUOTES} +STR_1523 :{SMALLFONT}{OPENQUOTES}Esta Bebida de {STRINGID} es barata{{ENDQUOTES} +STR_1524 :{SMALLFONT}{OPENQUOTES}Esta Hamburguesa de {STRINGID} es barata{{ENDQUOTES} +STR_1525 :{SMALLFONT}{OPENQUOTES}Estas Papas Fritas de {STRINGID} son baratas{{ENDQUOTES} +STR_1526 :{SMALLFONT}{OPENQUOTES}Este Helado de {STRINGID} es barato{{ENDQUOTES} +STR_1527 :{SMALLFONT}{OPENQUOTES}Este Algodón de {STRINGID} es barato{{ENDQUOTES} STR_1528 : STR_1529 : STR_1530 : -STR_1531 :{SMALLFONT}{OPENQUOTES}This pizza from {STRINGID} is really good value{ENDQUOTES} +STR_1531 :{SMALLFONT}{OPENQUOTES}Esta Pizza de {STRINGID} es barato{ENDQUOTES} STR_1532 : -STR_1533 :{SMALLFONT}{OPENQUOTES}This popcorn from {STRINGID} is really good value{ENDQUOTES} -STR_1534 :{SMALLFONT}{OPENQUOTES}This hot dog from {STRINGID} is really good value{ENDQUOTES} -STR_1535 :{SMALLFONT}{OPENQUOTES}This tentacle from {STRINGID} is really good value{ENDQUOTES} -STR_1536 :{SMALLFONT}{OPENQUOTES}This hat from {STRINGID} is really good value{ENDQUOTES} -STR_1537 :{SMALLFONT}{OPENQUOTES}This candy apple from {STRINGID} is really good value{ENDQUOTES} -STR_1538 :{SMALLFONT}{OPENQUOTES}This T-shirt from {STRINGID} is really good value{ENDQUOTES} -STR_1539 :{SMALLFONT}{OPENQUOTES}This doughnut from {STRINGID} is really good value{ENDQUOTES} -STR_1540 :{SMALLFONT}{OPENQUOTES}This coffee from {STRINGID} is really good value{ENDQUOTES} +STR_1533 :{SMALLFONT}{OPENQUOTES}Estas Palomitas de {STRINGID} son baratas{ENDQUOTES} +STR_1534 :{SMALLFONT}{OPENQUOTES}Este Perrito de {STRINGID} es barato{ENDQUOTES} +STR_1535 :{SMALLFONT}{OPENQUOTES}Este Tentáculo de {STRINGID} es barato{ENDQUOTES} +STR_1536 :{SMALLFONT}{OPENQUOTES}Este Sombrero de {STRINGID} es barato{ENDQUOTES} +STR_1537 :{SMALLFONT}{OPENQUOTES}Esta Manzana de {STRINGID} es barata{ENDQUOTES} +STR_1538 :{SMALLFONT}{OPENQUOTES}Esta Camiseta de {STRINGID} es barata{ENDQUOTES} +STR_1539 :{SMALLFONT}{OPENQUOTES}Esta Rosquilla de {STRINGID} es barata{ENDQUOTES} +STR_1540 :{SMALLFONT}{OPENQUOTES}Este Café de {STRINGID} es barato{ENDQUOTES} STR_1541 : -STR_1542 :{SMALLFONT}{OPENQUOTES}This fried chicken from {STRINGID} is really good value{ENDQUOTES} -STR_1543 :{SMALLFONT}{OPENQUOTES}This lemonade from {STRINGID} is really good value{ENDQUOTES} +STR_1542 :{SMALLFONT}{OPENQUOTES}Este Pollo Frito de {STRINGID} es barato{ENDQUOTES} +STR_1543 :{SMALLFONT}{OPENQUOTES}Esta Limonada de {STRINGID} es barata{ENDQUOTES} STR_1544 : STR_1545 : STR_1546 : STR_1547 : STR_1548 : STR_1549 : -STR_1550 :{SMALLFONT}{OPENQUOTES}Wow!{ENDQUOTES} -STR_1551 :{SMALLFONT}{OPENQUOTES}I have the strangest feeling someone is watching me{ENDQUOTES} -STR_1552 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a balloon from {STRINGID}{ENDQUOTES} -STR_1553 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a cuddly toy from {STRINGID}{ENDQUOTES} -STR_1554 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a park map from {STRINGID}{ENDQUOTES} -STR_1555 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1556 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an umbrella from {STRINGID}{ENDQUOTES} -STR_1557 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a drink from {STRINGID}{ENDQUOTES} -STR_1558 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a burger from {STRINGID}{ENDQUOTES} -STR_1559 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for chips from {STRINGID}{ENDQUOTES} -STR_1560 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an ice cream from {STRINGID}{ENDQUOTES} -STR_1561 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for candyfloss from {STRINGID}{ENDQUOTES} +STR_1550 :{SMALLFONT}{OPENQUOTES}¡Wow!{ENDQUOTES} +STR_1551 :{SMALLFONT}{OPENQUOTES}Tengo la extraña sensación de que alguien me está observando{ENDQUOTES} +STR_1552 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Globo de {STRINGID}{ENDQUOTES} +STR_1553 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Juguetito de {STRINGID}{ENDQUOTES} +STR_1554 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Mapa de {STRINGID}{ENDQUOTES} +STR_1555 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Foto de {STRINGID}{ENDQUOTES} +STR_1556 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Paraguas de {STRINGID}{ENDQUOTES} +STR_1557 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Bebida de {STRINGID}{ENDQUOTES} +STR_1558 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Hamburguesa de {STRINGID}{ENDQUOTES} +STR_1559 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por las Papas Fritas de {STRINGID}{ENDQUOTES} +STR_1560 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el helado de {STRINGID}{ENDQUOTES} +STR_1561 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Algodón de {STRINGID}{ENDQUOTES} STR_1562 : STR_1563 : STR_1564 : -STR_1565 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for pizza from {STRINGID}{ENDQUOTES} +STR_1565 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Pizza de {STRINGID}{ENDQUOTES} STR_1566 : -STR_1567 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for popcorn from {STRINGID}{ENDQUOTES} -STR_1568 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a hot dog from {STRINGID}{ENDQUOTES} -STR_1569 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for tentacle from {STRINGID}{ENDQUOTES} -STR_1570 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a hat from {STRINGID}{ENDQUOTES} -STR_1571 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a candy apple from {STRINGID}{ENDQUOTES} -STR_1572 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a T-shirt from {STRINGID}{ENDQUOTES} -STR_1573 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a doughnut from {STRINGID}{ENDQUOTES} -STR_1574 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for coffee from {STRINGID}{ENDQUOTES} +STR_1567 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por las Palomitas de {STRINGID}{ENDQUOTES} +STR_1568 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Perrito de {STRINGID}{ENDQUOTES} +STR_1569 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Tentáculo de {STRINGID}{ENDQUOTES} +STR_1570 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Sombrero de {STRINGID}{ENDQUOTES} +STR_1571 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Manzana de {STRINGID}{ENDQUOTES} +STR_1572 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Camiseta de {STRINGID}{ENDQUOTES} +STR_1573 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Rosquilla de {STRINGID}{ENDQUOTES} +STR_1574 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Café de {STRINGID}{ENDQUOTES} STR_1575 : -STR_1576 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fried chicken from {STRINGID}{ENDQUOTES} -STR_1577 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for lemonade from {STRINGID}{ENDQUOTES} +STR_1576 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Pollo Frito de {STRINGID}{ENDQUOTES} +STR_1577 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Limonada de {STRINGID}{ENDQUOTES} STR_1578 : STR_1579 : STR_1580 : STR_1581 : STR_1582 : STR_1583 : -STR_1584 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1585 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1586 :{SMALLFONT}{OPENQUOTES}This on-ride photo from {STRINGID} is really good value{ENDQUOTES} -STR_1587 :{SMALLFONT}{OPENQUOTES}This pretzel from {STRINGID} is really good value{ENDQUOTES} -STR_1588 :{SMALLFONT}{OPENQUOTES}This hot chocolate from {STRINGID} is really good value{ENDQUOTES} -STR_1589 :{SMALLFONT}{OPENQUOTES}This iced tea from {STRINGID} is really good value{ENDQUOTES} -STR_1590 :{SMALLFONT}{OPENQUOTES}This funnel cake from {STRINGID} is really good value{ENDQUOTES} -STR_1591 :{SMALLFONT}{OPENQUOTES}These sunglasses from {STRINGID} are really good value{ENDQUOTES} -STR_1592 :{SMALLFONT}{OPENQUOTES}These beef noodles from {STRINGID} are really good value{ENDQUOTES} -STR_1593 :{SMALLFONT}{OPENQUOTES}These fried rice noodles from {STRINGID} are really good value{ENDQUOTES} -STR_1594 :{SMALLFONT}{OPENQUOTES}This wonton soup from {STRINGID} is really good value{ENDQUOTES} -STR_1595 :{SMALLFONT}{OPENQUOTES}This meatball soup from {STRINGID} is really good value{ENDQUOTES} -STR_1596 :{SMALLFONT}{OPENQUOTES}This fruit juice from {STRINGID} is really good value{ENDQUOTES} -STR_1597 :{SMALLFONT}{OPENQUOTES}This soybean milk from {STRINGID} is really good value{ENDQUOTES} -STR_1598 :{SMALLFONT}{OPENQUOTES}This sujongkwa from {STRINGID} is really good value{ENDQUOTES} -STR_1599 :{SMALLFONT}{OPENQUOTES}This sub sandwich from {STRINGID} is really good value{ENDQUOTES} -STR_1600 :{SMALLFONT}{OPENQUOTES}This cookie from {STRINGID} is really good value{ENDQUOTES} +STR_1584 :{SMALLFONT}{OPENQUOTES}Esta Foto de {STRINGID} es barata{ENDQUOTES} +STR_1585 :{SMALLFONT}{OPENQUOTES}Esta Foto de {STRINGID} es barata{ENDQUOTES} +STR_1586 :{SMALLFONT}{OPENQUOTES}Esta Foto de {STRINGID} es barata{ENDQUOTES} +STR_1587 :{SMALLFONT}{OPENQUOTES}Este Pretzel de {STRINGID} es barato{ENDQUOTES} +STR_1588 :{SMALLFONT}{OPENQUOTES}Este Chocolate de {STRINGID} es barato{ENDQUOTES} +STR_1589 :{SMALLFONT}{OPENQUOTES}Este Té de {STRINGID} es barato{ENDQUOTES} +STR_1590 :{SMALLFONT}{OPENQUOTES}Este Pastel de {STRINGID} es barato{ENDQUOTES} +STR_1591 :{SMALLFONT}{OPENQUOTES}Estas Gafas de {STRINGID} son baratas{ENDQUOTES} +STR_1592 :{SMALLFONT}{OPENQUOTES}Estos Fideos con carne de {STRINGID} son baratos{ENDQUOTES} +STR_1593 :{SMALLFONT}{OPENQUOTES}Este Arroz Frito de {STRINGID} son baratos{ENDQUOTES} +STR_1594 :{SMALLFONT}{OPENQUOTES}Esta Sopawonton de {STRINGID} es barata{ENDQUOTES} +STR_1595 :{SMALLFONT}{OPENQUOTES}Esta Sopa de Albóndigas de {STRINGID} es barata{ENDQUOTES} +STR_1596 :{SMALLFONT}{OPENQUOTES}Este Zumo de {STRINGID} es barato{ENDQUOTES} +STR_1597 :{SMALLFONT}{OPENQUOTES}Esta Leche Soja de {STRINGID} es barata{ENDQUOTES} +STR_1598 :{SMALLFONT}{OPENQUOTES}Este Sujeonggwa de {STRINGID} es barato{ENDQUOTES} +STR_1599 :{SMALLFONT}{OPENQUOTES}Este Sándwich de {STRINGID} es barato{ENDQUOTES} +STR_1600 :{SMALLFONT}{OPENQUOTES}Esta Galleta de {STRINGID} es barata{ENDQUOTES} STR_1601 : STR_1602 : STR_1603 : -STR_1604 :{SMALLFONT}{OPENQUOTES}This roast sausage from {STRINGID} are really good value{ENDQUOTES} +STR_1604 :{SMALLFONT}{OPENQUOTES}Esta Salchicha de {STRINGID} es barata{ENDQUOTES} STR_1605 : STR_1606 : STR_1607 : @@ -1618,27 +1618,27 @@ STR_1612 : STR_1613 : STR_1614 : STR_1615 : -STR_1616 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1617 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1618 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for an on-ride photo from {STRINGID}{ENDQUOTES} -STR_1619 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a pretzel from {STRINGID}{ENDQUOTES} -STR_1620 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for hot chocolate from {STRINGID}{ENDQUOTES} -STR_1621 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for iced tea from {STRINGID}{ENDQUOTES} -STR_1622 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a funnel cake from {STRINGID}{ENDQUOTES} -STR_1623 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sunglasses from {STRINGID}{ENDQUOTES} -STR_1624 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for beef noodles from {STRINGID}{ENDQUOTES} -STR_1625 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fried rice noodles from {STRINGID}{ENDQUOTES} -STR_1626 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for wonton soup from {STRINGID}{ENDQUOTES} -STR_1627 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for meatball soup from {STRINGID}{ENDQUOTES} -STR_1628 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for fruit juice from {STRINGID}{ENDQUOTES} -STR_1629 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for soybean milk from {STRINGID}{ENDQUOTES} -STR_1630 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for sujongkwa from {STRINGID}{ENDQUOTES} -STR_1631 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a sub sandwich from {STRINGID}{ENDQUOTES} -STR_1632 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a cookie from {STRINGID}{ENDQUOTES} +STR_1616 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Foto de {STRINGID}{ENDQUOTES} +STR_1617 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Foto de {STRINGID}{ENDQUOTES} +STR_1618 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Foto de {STRINGID}{ENDQUOTES} +STR_1619 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Pretzel de {STRINGID}{ENDQUOTES} +STR_1620 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Chocolate de {STRINGID}{ENDQUOTES} +STR_1621 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Té de {STRINGID}{ENDQUOTES} +STR_1622 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Pastel de {STRINGID}{ENDQUOTES} +STR_1623 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por las Gafas de {STRINGID}{ENDQUOTES} +STR_1624 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por los Fideos de {STRINGID}{ENDQUOTES} +STR_1625 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Arroz Frito de {STRINGID}{ENDQUOTES} +STR_1626 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Sopawonton de {STRINGID}{ENDQUOTES} +STR_1627 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Sopa de Albóndigas de {STRINGID}{ENDQUOTES} +STR_1628 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Zumo de {STRINGID}{ENDQUOTES} +STR_1629 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Leche Soja de {STRINGID}{ENDQUOTES} +STR_1630 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Sujeonggwa de {STRINGID}{ENDQUOTES} +STR_1631 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por el Sándwich de {STRINGID}{ENDQUOTES} +STR_1632 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Galleta de {STRINGID}{ENDQUOTES} STR_1633 : STR_1634 : STR_1635 : -STR_1636 :{SMALLFONT}{OPENQUOTES}I'm not paying that much for a roast sausage from {STRINGID}{ENDQUOTES} +STR_1636 :{SMALLFONT}{OPENQUOTES}No voy a pagar tanto por la Salchicha de {STRINGID}{ENDQUOTES} STR_1637 : STR_1638 : STR_1639 : @@ -1650,37 +1650,37 @@ STR_1644 : STR_1645 : STR_1646 : STR_1647 : -STR_1648 :{SMALLFONT}{OPENQUOTES}Help! Put me down!{ENDQUOTES} -STR_1649 :{SMALLFONT}{OPENQUOTES}I'm running out of cash!{ENDQUOTES} -STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! A new ride being built!{ENDQUOTES} -STR_1651 :{SMALLFONT}{OPENQUOTES}Nice ride! But not as good as the Phoenix...{ENDQUOTES} -STR_1652 :{SMALLFONT}{OPENQUOTES}I'm so excited - It's an Intamin ride!{ENDQUOTES} -STR_1653 :{SMALLFONT}{OPENQUOTES}...and here we are on {STRINGID}!{ENDQUOTES} -STR_1654 :{WINDOW_COLOUR_2}Recent thoughts: -STR_1655 :{SMALLFONT}{BLACK}Construct footpath on land -STR_1656 :{SMALLFONT}{BLACK}Construct bridge or tunnel footpath -STR_1657 :{WINDOW_COLOUR_2}Preferred ride -STR_1658 :{WINDOW_COLOUR_2}intensity: {BLACK}less than {COMMA16} -STR_1659 :{WINDOW_COLOUR_2}intensity: {BLACK}between {COMMA16} and {COMMA16} -STR_1660 :{WINDOW_COLOUR_2}intensity: {BLACK}more than {COMMA16} -STR_1661 :{WINDOW_COLOUR_2}Nausea tolerance: {BLACK}{STRINGID} -STR_1662 :{WINDOW_COLOUR_2}Happiness: -STR_1663 :{WINDOW_COLOUR_2}Nausea: -STR_1664 :{WINDOW_COLOUR_2}Energy: -STR_1665 :{WINDOW_COLOUR_2}Hunger: -STR_1666 :{WINDOW_COLOUR_2}Thirst: -STR_1667 :{WINDOW_COLOUR_2}Bathroom: -STR_1668 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}Unknown -STR_1669 :{WINDOW_COLOUR_2}Satisfaction: {BLACK}{COMMA16}% -STR_1670 :{WINDOW_COLOUR_2}Total customers: {BLACK}{COMMA32} -STR_1671 :{WINDOW_COLOUR_2}Total profit: {BLACK}{CURRENCY2DP} -STR_1672 :Brakes +STR_1648 :{SMALLFONT}{OPENQUOTES}¡Ayuda! ¡Bájame!{ENDQUOTES} +STR_1649 :{SMALLFONT}{OPENQUOTES}¡Me estoy quedando sin dinero!{ENDQUOTES} +STR_1650 :{SMALLFONT}{OPENQUOTES}¡Wow! ¡Están construyendo una nueva atracción!{ENDQUOTES} +STR_1651 :{SMALLFONT}{OPENQUOTES}¡Lindo paseo! Pero no tan bueno como el Fénix...{ENDQUOTES} +STR_1652 :{SMALLFONT}{OPENQUOTES}¡Estoy tan emocionado - Es un paseo Intamin!{ENDQUOTES} +STR_1653 :{SMALLFONT}{OPENQUOTES}... ¡y aquí estamos en {STRINGID}!{ENDQUOTES} +STR_1654 :{WINDOW_COLOUR_2}Pensamientos recientes: +STR_1655 :{SMALLFONT}{BLACK}Construir camino a nivel del suelo. +STR_1656 :{SMALLFONT}{BLACK}Construit puente o túnel. +STR_1657 :{WINDOW_COLOUR_2}Atracción preferida: +STR_1658 :{WINDOW_COLOUR_2}Intensidad: {BLACK}menos de {COMMA16} +STR_1659 :{WINDOW_COLOUR_2}Intensidad: {BLACK}entre {COMMA16} y {COMMA16} +STR_1660 :{WINDOW_COLOUR_2}Intensidad: {BLACK}más de {COMMA16} +STR_1661 :{WINDOW_COLOUR_2}Tolerancia a náusea: {BLACK}{STRINGID} +STR_1662 :{WINDOW_COLOUR_2}Felicidad: +STR_1663 :{WINDOW_COLOUR_2}Náusea: +STR_1664 :{WINDOW_COLOUR_2}Energía: +STR_1665 :{WINDOW_COLOUR_2}Hambre: +STR_1666 :{WINDOW_COLOUR_2}Sed: +STR_1667 :{WINDOW_COLOUR_2}Vejiga: +STR_1668 :{WINDOW_COLOUR_2}Satisfacción {BLACK}Desconocida +STR_1669 :{WINDOW_COLOUR_2}Satisfacción: {BLACK}{COMMA16}% +STR_1670 :{WINDOW_COLOUR_2}Clientes totales: {BLACK}{COMMA32} +STR_1671 :{WINDOW_COLOUR_2}Beneficio total: {BLACK}{CURRENCY2DP} +STR_1672 :Frenos STR_1673 :Spinning Control Toggle Track -STR_1674 :Brake speed +STR_1674 :Velocidad de frenos STR_1675 :{POP16}{VELOCITY} -STR_1676 :{SMALLFONT}{BLACK}Set speed limit for brakes -STR_1677 :{WINDOW_COLOUR_2}Popularity: {BLACK}Unknown -STR_1678 :{WINDOW_COLOUR_2}Popularity: {BLACK}{COMMA16}% +STR_1676 :{SMALLFONT}{BLACK}Establecer límite de velocidad para los frenos +STR_1677 :{WINDOW_COLOUR_2}Popularidad: {BLACK}Desconocida +STR_1678 :{WINDOW_COLOUR_2}Popularidad: {BLACK}{COMMA16}% STR_1679 :Helix up (left) STR_1680 :Helix up (right) STR_1681 :Helix down (left) @@ -1689,846 +1689,846 @@ STR_1683 :Base size 2 x 2 STR_1684 :Base size 4 x 4 STR_1685 :Base size 2 x 4 STR_1686 :Base size 5 x 1 -STR_1687 :Water splash +STR_1687 :Salpicadura de agua STR_1688 :Base size 4 x 1 -STR_1689 :Block brakes +STR_1689 :Bloque de frenado 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_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_1701 :Hire new Mechanic -STR_1702 :Hire new Security Guard -STR_1703 :Hire new Entertainer -STR_1704 :Can't hire new staff... -STR_1705 :{SMALLFONT}{BLACK}Sack this staff member -STR_1706 :{SMALLFONT}{BLACK}Move this person to a new location -STR_1707 :Too many staff in game -STR_1708 :{SMALLFONT}{BLACK}Set patrol area for this staff member -STR_1709 :Sack staff -STR_1710 :Yes -STR_1711 :{WINDOW_COLOUR_1}Are you sure you want to sack {STRINGID}? -STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Sweep footpaths -STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Water gardens -STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Empty litter bins -STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Mow grass -STR_1716 :Invalid name for park -STR_1717 :Can't rename park... -STR_1718 :Park Name -STR_1719 :Enter name for park: -STR_1720 :{SMALLFONT}{BLACK}Name park -STR_1721 :Park closed -STR_1722 :Park open -STR_1723 :Can't open park... -STR_1724 :Can't close park... -STR_1725 :Can't buy land... -STR_1726 :Land not for sale! -STR_1727 :Construction rights not for sale! -STR_1728 :Can't buy construction rights here... -STR_1729 :Land not owned by park! -STR_1730 :{RED}Closed - - +STR_1691 :{WINDOW_COLOUR_2} Precio: {BLACK}{CURRENCY} +STR_1692 :{WINDOW_COLOUR_2} Precio: {BLACK}desde {CURRENCY} +STR_1693 :{SMALLFONT}{BLACK}Visitantes +STR_1694 :{SMALLFONT}{BLACK}Empleados +STR_1695 :{SMALLFONT}{BLACK}Ingresos y costes +STR_1696 :{SMALLFONT}{BLACK}Información de clientes +STR_1697 :No se puede colocar en la fila de espera +STR_1698 :Solo se puede colocar en la fila de espera +STR_1699 :Mucha gente en la partida. +STR_1700 :Contratar nuevo jardinero +STR_1701 :Contratar nuevo mecánico +STR_1702 :Contratar nuevo guarda +STR_1703 :Contratar nuevo animador +STR_1704 :No se pueden contratar nuevos empleados... +STR_1705 :{SMALLFONT}{BLACK}Despedir empleado +STR_1706 :{SMALLFONT}{BLACK}Mover esta persona a otra posición +STR_1707 :Muchos empleados en el parque. +STR_1708 :{SMALLFONT}{BLACK}Establecer zona de patrulla para este empleado +STR_1709 :Despedir empleado +STR_1710 :Sí +STR_1711 :{WINDOW_COLOUR_1}¿Estas seguro de despedir a {STRINGID}? +STR_1712 :{INLINE_SPRITE}{247}{19}{00}{00}{WINDOW_COLOUR_2}Limpiar senderos +STR_1713 :{INLINE_SPRITE}{248}{19}{00}{00}{WINDOW_COLOUR_2}Regar plantas +STR_1714 :{INLINE_SPRITE}{249}{19}{00}{00}{WINDOW_COLOUR_2}Vaciar papeleras +STR_1715 :{INLINE_SPRITE}{250}{19}{00}{00}{WINDOW_COLOUR_2}Cortar césped +STR_1716 :Nombre de parque inválido +STR_1717 :No se puede renombrar el parque... +STR_1718 :Nombrar parque +STR_1719 :Introduce el nuevo nombre del parque: +STR_1720 :{SMALLFONT}{BLACK}Nombrar parque +STR_1721 :Parque cerrado +STR_1722 :Parque abierto +STR_1723 :No puedes abrir el parque... +STR_1724 :No puedes cerrar el parque... +STR_1725 :No puedes comprar terreno... +STR_1726 :¡Terreno no a la venta! +STR_1727 :¡Derechos de construcción no a la venta! +STR_1728 :No puedes comprar derechos de construcción aquí... +STR_1729 :¡El terreno no es propiedad del parque! +STR_1730 :{RED}Cerrado - - STR_1731 :{WHITE}{STRINGID} - - -STR_1732 :Build -STR_1733 :Mode -STR_1734 :{WINDOW_COLOUR_2}Number of laps: -STR_1735 :{SMALLFONT}{BLACK}Number of laps of circuit +STR_1732 :Construir +STR_1733 :Modo +STR_1734 :{WINDOW_COLOUR_2}Numero de vueltas: +STR_1735 :{SMALLFONT}{BLACK}Numero de vueltas de circuito STR_1736 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1737 :{COMMA16} -STR_1738 :Can't change number of laps... -STR_1739 :Race won by guest {INT32} -STR_1740 :Race won by {STRINGID} +STR_1738 :No se puede cambiar el numero de vueltas... +STR_1739 :Carrera ganada por visitante {INT32} +STR_1740 :Carrera ganada por {STRINGID} STR_1741 :Not yet constructed ! -STR_1742 :{WINDOW_COLOUR_2}Max. people on ride: -STR_1743 :{SMALLFONT}{BLACK}Maximum number of people allowed on this ride at one time +STR_1742 :{WINDOW_COLOUR_2}Max. visitantes en juego: +STR_1743 :{SMALLFONT}{BLACK}Numero de visitantes máximo permitido en este juego al mismo tiempo STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1745 :{COMMA16} -STR_1746 :Can't change this... -STR_1747 :{WINDOW_COLOUR_2}Time limit: +STR_1746 :No puedes cambiar esto... +STR_1747 :{WINDOW_COLOUR_2}Límite de tiempo: STR_1748 :{SMALLFONT}{BLACK}Time limit for ride STR_1749 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{DURATION} 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_1756 :{WINDOW_COLOUR_2}Admission price: -STR_1757 :{WINDOW_COLOUR_2}Reliability: {MOVE_X}{255}{BLACK}{COMMA16}% -STR_1758 :{SMALLFONT}{BLACK}Build mode -STR_1759 :{SMALLFONT}{BLACK}Move mode -STR_1760 :{SMALLFONT}{BLACK}Fill-in mode -STR_1761 :{SMALLFONT}{BLACK}Build maze in this direction -STR_1762 :Waterfalls -STR_1763 :Rapids +STR_1751 :No se puede cambiar el límite de tiempo para esta atracción... +STR_1752 :{SMALLFONT}{BLACK}Mostrar lista de visitantes en el parque +STR_1753 :{SMALLFONT}{BLACK}Mostrar lista agrupada de visitantes en el parque +STR_1754 :{BLACK}{COMMA16} visitantes +STR_1755 :{BLACK}{COMMA16} visitante +STR_1756 :{WINDOW_COLOUR_2}Precio de la entrada: +STR_1757 :{WINDOW_COLOUR_2}Fiabilidad: {MOVE_X}{255}{BLACK}{COMMA16}% +STR_1758 :{SMALLFONT}{BLACK}Modo construir +STR_1759 :{SMALLFONT}{BLACK}Modo mover +STR_1760 :{SMALLFONT}{BLACK}Modo rellenar +STR_1761 :{SMALLFONT}{BLACK}Construir laberinto en esta dirección +STR_1762 :Cascadas +STR_1763 :Rápidos STR_1764 :Log Bumps -STR_1765 :On-ride photo section +STR_1765 :Cámara fotográfica STR_1766 :Reverser turntable -STR_1767 :Spinning tunnel -STR_1768 :Can't change number of swings... -STR_1769 :{WINDOW_COLOUR_2}Number of swings: -STR_1770 :{SMALLFONT}{BLACK}Number of complete swings +STR_1767 :Tunel Giratorio +STR_1768 :No puedes cambiar el número de balanceo... +STR_1769 :{WINDOW_COLOUR_2}Número de balanceos: +STR_1770 :{SMALLFONT}{BLACK}Número de balanceos completos STR_1771 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1772 :{COMMA16} -STR_1773 :Only one on-ride photo section allowed per ride -STR_1774 :Only one cable lift hill allowed per ride +STR_1773 :Sólo se permite una sección de fotos por atracción. +STR_1774 :Sólo un cable de elevación por atracción. STR_1775 :Off STR_1776 :On -STR_1777 :{WINDOW_COLOUR_2}Music +STR_1777 :{WINDOW_COLOUR_2}Música de atracción STR_1778 :{STRINGID} - - -STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Panda costume -STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Tiger costume -STR_1781 :{INLINE_SPRITE}{00}{20}{00}{00} Elephant costume -STR_1782 :{INLINE_SPRITE}{01}{20}{00}{00} Roman costume -STR_1783 :{INLINE_SPRITE}{02}{20}{00}{00} Gorilla costume -STR_1784 :{INLINE_SPRITE}{03}{20}{00}{00} Snowman costume -STR_1785 :{INLINE_SPRITE}{04}{20}{00}{00} Knight costume -STR_1786 :{INLINE_SPRITE}{05}{20}{00}{00} Astronaut costume -STR_1787 :{INLINE_SPRITE}{06}{20}{00}{00} Bandit costume -STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Sheriff costume -STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Pirate costume -STR_1790 :{SMALLFONT}{BLACK}Select uniform colour for this type of staff -STR_1791 :{WINDOW_COLOUR_2}Uniform colour: -STR_1792 :Responding to {STRINGID} breakdown call -STR_1793 :Heading to {STRINGID} for an inspection -STR_1794 :Fixing {STRINGID} -STR_1795 :Answering radio call -STR_1796 :Has broken down and requires fixing -STR_1797 :This option cannot be changed for this ride -STR_1798 :Whirlpool +STR_1779 :{INLINE_SPRITE}{254}{19}{00}{00} Disfraz de panda +STR_1780 :{INLINE_SPRITE}{255}{19}{00}{00} Disfraz de tigre +STR_1781 :{INLINE_SPRITE}{00}{20}{00}{00} Disfraz de elefante +STR_1782 :{INLINE_SPRITE}{01}{20}{00}{00} Disfraz de romano +STR_1783 :{INLINE_SPRITE}{02}{20}{00}{00} Disfraz de gorila +STR_1784 :{INLINE_SPRITE}{03}{20}{00}{00} Disfraz de muñeco de nieve +STR_1785 :{INLINE_SPRITE}{04}{20}{00}{00} Disfraz de caballero +STR_1786 :{INLINE_SPRITE}{05}{20}{00}{00} Disfraz de astronauta +STR_1787 :{INLINE_SPRITE}{06}{20}{00}{00} Disfraz de bandido +STR_1788 :{INLINE_SPRITE}{07}{20}{00}{00} Disfraz de sheriff +STR_1789 :{INLINE_SPRITE}{08}{20}{00}{00} Disfraz de pirata +STR_1790 :{SMALLFONT}{BLACK}Selecciona el color del uniforme para este tipo de empleados +STR_1791 :{WINDOW_COLOUR_2}Color del uniforme: +STR_1792 :Dirigiéndose a {STRINGID} +STR_1793 :Yendo a inspeccionar {STRINGID} +STR_1794 :Arreglando {STRINGID} +STR_1795 :Contestando llamada +STR_1796 :Se ha averiado y requiere reparación +STR_1797 :Esta opción no puede ser cambiada para esta atracción +STR_1798 :Remolino STR_1799 :{POP16}{POP16}{POP16}{POP16}{POP16}{CURRENCY2DP} -STR_1800 :Safety cut-out -STR_1801 :Restraints stuck closed -STR_1802 :Restraints stuck open -STR_1803 :Doors stuck closed -STR_1804 :Doors stuck open -STR_1805 :Vehicle malfunction -STR_1806 :Brakes failure -STR_1807 :Control failure -STR_1808 :{WINDOW_COLOUR_2}Last breakdown: {BLACK}{STRINGID} -STR_1809 :{WINDOW_COLOUR_2}Current breakdown: {OUTLINE}{RED}{STRINGID} -STR_1810 :{WINDOW_COLOUR_2}Carrying: -STR_1811 :Can't build this here... +STR_1800 :Paro por seguridad +STR_1801 :Retenciones atascadas cerradas +STR_1802 :Retenciones atascadas abiertas +STR_1803 :Puertas atascadas cerradas +STR_1804 :Puertas atascadas abiertas +STR_1805 :Avería del vehículo +STR_1806 :Fallo de frenos +STR_1807 :Fallo de control +STR_1808 :{WINDOW_COLOUR_2}Última avería: {BLACK}{STRINGID} +STR_1809 :{WINDOW_COLOUR_2}Avería actual: {OUTLINE}{RED}{STRINGID} +STR_1810 :{WINDOW_COLOUR_2}Lleva: +STR_1811 :No puedes construir esto aquí... STR_1812 :{SMALLFONT}{BLACK}{STRINGID} -STR_1813 :Miscellaneous Objects -STR_1814 :Actions -STR_1815 :Thoughts -STR_1816 :{SMALLFONT}{BLACK}Select information type to show in guest list +STR_1813 :Objetos misceláneos +STR_1814 :Acciones +STR_1815 :Pensamientos +STR_1816 :{SMALLFONT}{BLACK}Selecciona el tipo de información a mostrar en la lista de visitantes STR_1817 :({COMMA16}) -STR_1818 :{WINDOW_COLOUR_2}All guests -STR_1819 :{WINDOW_COLOUR_2}All guests (summarised) -STR_1820 :{WINDOW_COLOUR_2}Guests {STRINGID} -STR_1821 :{WINDOW_COLOUR_2}Guests thinking {STRINGID} -STR_1822 :{WINDOW_COLOUR_2}Guests thinking about {POP16}{STRINGID} -STR_1823 :{SMALLFONT}{BLACK}Show guests' thoughts about this ride/attraction -STR_1824 :{SMALLFONT}{BLACK}Show guests on this ride/attraction -STR_1825 :{SMALLFONT}{BLACK}Show guests queuing for this ride/attraction -STR_1826 :Status -STR_1827 :Popularity -STR_1828 :Satisfaction -STR_1829 :Profit -STR_1830 :Queue length -STR_1831 :Queue time -STR_1832 :Reliability -STR_1833 :Down-time -STR_1834 :Visitantes favourite -STR_1835 :Popularity: Unknown -STR_1836 :Popularity: {COMMA16}% -STR_1837 :Satisfaction: Unknown -STR_1838 :Satisfaction: {COMMA16}% -STR_1839 :Reliability: {COMMA16}% -STR_1840 :Down-time: {COMMA16}% -STR_1841 :Profit: {CURRENCY2DP} per hour -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_1818 :{WINDOW_COLOUR_2}Todos los visitantes +STR_1819 :{WINDOW_COLOUR_2}Todos los visitantes (agrupados) +STR_1820 :{WINDOW_COLOUR_2}Visitantes {STRINGID} +STR_1821 :{WINDOW_COLOUR_2}Visitantes Pensando {STRINGID} +STR_1822 :{WINDOW_COLOUR_2}Visitantes Pensando en {POP16}{STRINGID} +STR_1823 :{SMALLFONT}{BLACK}Muestra los pensamientos de los visitantes sobre esta atracción +STR_1824 :{SMALLFONT}{BLACK}Mostrar visitantes en esta atracción +STR_1825 :{SMALLFONT}{BLACK}Mostrar visitantes esperando para subir a esta atracción +STR_1826 :Estado +STR_1827 :Popularidad +STR_1828 :Satisfacción +STR_1829 :Beneficio +STR_1830 :Tamaño de la cola +STR_1831 :Tiempo en cola +STR_1832 :Fiabilidad +STR_1833 :Tiempo averiado +STR_1834 :Favorito de +STR_1835 :Popularidad: Desconocido +STR_1836 :Popularidad: {COMMA16}% +STR_1837 :Satisfacción: Desconocido +STR_1838 :Satisfacción: {COMMA16}% +STR_1839 :Fiabilidad: {COMMA16}% +STR_1840 :Tiempo averiado: {COMMA16}% +STR_1841 :Beneficio: {CURRENCY2DP} per hour +STR_1842 :Favorito de: {COMMA16} visitante +STR_1843 :Favorito de: {COMMA16} visitantes +STR_1844 :{SMALLFONT}{BLACK}Selecciona el tipo de información a mostrar en la lista 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_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 -STR_1852 :{WINDOW_COLOUR_2}Running cost: {BLACK}Unknown -STR_1853 :{WINDOW_COLOUR_2}Built: {BLACK}This Year -STR_1854 :{WINDOW_COLOUR_2}Built: {BLACK}Last Year -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}{CURRENCY} per month -STR_1859 :Handymen -STR_1860 :Mechanics -STR_1861 :Security Guards -STR_1862 :Entertainers -STR_1863 :Handyman -STR_1864 :Mechanic -STR_1865 :Security Guard -STR_1866 :Entertainer +STR_1846 :{COMMA16} visitantes +STR_1847 :{INLINE_SPRITE}{11}{20}{00}{00}{COMMA16} visitantes +STR_1848 :{INLINE_SPRITE}{10}{20}{00}{00}{COMMA16} visitantes +STR_1849 :{WINDOW_COLOUR_2}Reproducir música +STR_1850 :{SMALLFONT}{BLACK}Activar música para esta atracción. +STR_1851 :{WINDOW_COLOUR_2}Coste funcionamiento: {BLACK}{CURRENCY2DP} por hora +STR_1852 :{WINDOW_COLOUR_2}Coste funcionamiento: {BLACK}Desconocido +STR_1853 :{WINDOW_COLOUR_2}Construido: {BLACK}Este año +STR_1854 :{WINDOW_COLOUR_2}Construido: {BLACK}El año pasado +STR_1855 :{WINDOW_COLOUR_2}Construido: {BLACK}Hace {COMMA16} años +STR_1856 :{WINDOW_COLOUR_2}Beneficio por ítem: {BLACK}{CURRENCY2DP} +STR_1857 :{WINDOW_COLOUR_2}Pérdidas por ítem: {BLACK}{CURRENCY2DP} +STR_1858 :{WINDOW_COLOUR_2}Coste: {BLACK}{CURRENCY} al mes +STR_1859 :jardineros +STR_1860 :mecánicos +STR_1861 :guardas de seguridad +STR_1862 :animadores +STR_1863 :jardinero +STR_1864 :mecánico +STR_1865 :guarda de seguridad +STR_1866 :animador STR_1867 :{BLACK}{COMMA16} {STRINGID} -STR_1868 :Can't change number of rotations... -STR_1869 :{WINDOW_COLOUR_2}Number of rotations: -STR_1870 :{SMALLFONT}{BLACK}Number of complete rotations +STR_1868 :No puedes cambiar el número de vueltas... +STR_1869 :{WINDOW_COLOUR_2}Número de vueltas: +STR_1870 :{SMALLFONT}{BLACK}Número de vueltas completas STR_1871 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1872 :{COMMA16} -STR_1873 :{WINDOW_COLOUR_2}Income: {BLACK}{CURRENCY2DP} per hour -STR_1874 :{WINDOW_COLOUR_2}Profit: {BLACK}{CURRENCY2DP} per hour +STR_1873 :{WINDOW_COLOUR_2}Ingresos: {BLACK}{CURRENCY2DP} por hora +STR_1874 :{WINDOW_COLOUR_2}Beneficios: {BLACK}{CURRENCY2DP} por hora 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_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}% -STR_1890 :{SMALLFONT}{BLACK}Select how often a mechanic should check this ride -STR_1891 :No {STRINGID} in park yet! +STR_1876 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{251}{19}{00}{00}Inspeccionar atracciones +STR_1877 :{WINDOW_COLOUR_2}{INLINE_SPRITE}{252}{19}{00}{00}Reparar atracciones +STR_1878 :{WINDOW_COLOUR_2}Inspección: +STR_1879 :Cada 10 minutos +STR_1880 :Cada 20 minutos +STR_1881 :Cada 30 minutos +STR_1882 :Cada 45 minutos +STR_1883 :Cada hora +STR_1884 :Cada 2 horas +STR_1885 :Nunca +STR_1886 :Inspeccionando {STRINGID} +STR_1887 :{WINDOW_COLOUR_2}Tiempo desde la última inspección: {BLACK}{COMMA16} minutos +STR_1888 :{WINDOW_COLOUR_2}Tiempo desde la última inspección: {BLACK}más de 4 horas +STR_1889 :{WINDOW_COLOUR_2}Tiempo averiado: {MOVE_X}{255}{BLACK}{COMMA16}% +STR_1890 :{SMALLFONT}{BLACK}Selecciona con qué frecuencia un mecánico debe inspeccionar esta atracción +STR_1891 :¡Ningún {STRINGID} en el parque todavía! # The following two strings were used to display an error when the disc was missing. # This has been replaced in OpenRCT2. STR_1892 : STR_1893 : -STR_1894 :{WINDOW_COLOUR_2}{STRINGID} sold: {BLACK}{COMMA32} -STR_1895 :{SMALLFONT}{BLACK}Build new ride/attraction -STR_1896 :{WINDOW_COLOUR_2}Expenditure/Income -STR_1897 :{WINDOW_COLOUR_2}Ride construction -STR_1898 :{WINDOW_COLOUR_2}Ride running costs -STR_1899 :{WINDOW_COLOUR_2}Land purchase -STR_1900 :{WINDOW_COLOUR_2}Landscaping -STR_1901 :{WINDOW_COLOUR_2}Park entrance tickets -STR_1902 :{WINDOW_COLOUR_2}Ride tickets -STR_1903 :{WINDOW_COLOUR_2}Shop sales -STR_1904 :{WINDOW_COLOUR_2}Shop stock -STR_1905 :{WINDOW_COLOUR_2}Food/drink sales -STR_1906 :{WINDOW_COLOUR_2}Food/drink stock -STR_1907 :{WINDOW_COLOUR_2}Staff wages -STR_1908 :{WINDOW_COLOUR_2}Marketing -STR_1909 :{WINDOW_COLOUR_2}Research -STR_1910 :{WINDOW_COLOUR_2}Loan interest -STR_1911 :{BLACK} at {COMMA16}% per year +STR_1894 :{WINDOW_COLOUR_2}{STRINGID} vendidos: {BLACK}{COMMA32} +STR_1895 :{SMALLFONT}{BLACK}Construir nueva atracción +STR_1896 :{WINDOW_COLOUR_2}Gastos/Ingresos +STR_1897 :{WINDOW_COLOUR_2}Construcción +STR_1898 :{WINDOW_COLOUR_2}Operación de atracciones +STR_1899 :{WINDOW_COLOUR_2}Compra de terreno +STR_1900 :{WINDOW_COLOUR_2}Decorado +STR_1901 :{WINDOW_COLOUR_2}Entradas al parque +STR_1902 :{WINDOW_COLOUR_2}Entradas a atracciones +STR_1903 :{WINDOW_COLOUR_2}Ventas de tiendas +STR_1904 :{WINDOW_COLOUR_2}Gastos de tiendas +STR_1905 :{WINDOW_COLOUR_2}Ventas de comida y bebida +STR_1906 :{WINDOW_COLOUR_2}Gastos de comida y bebida +STR_1907 :{WINDOW_COLOUR_2}Salarios +STR_1908 :{WINDOW_COLOUR_2}Márketing +STR_1909 :{WINDOW_COLOUR_2}Investigación +STR_1910 :{WINDOW_COLOUR_2}Intereses del crédito +STR_1911 :{BLACK} a {COMMA16}% por año STR_1912 :{MONTH} STR_1913 :{BLACK}+{CURRENCY2DP} STR_1914 :{BLACK}{CURRENCY2DP} STR_1915 :{RED}{CURRENCY2DP} -STR_1916 :{WINDOW_COLOUR_2}Loan: +STR_1916 :{WINDOW_COLOUR_2}Préstamo: STR_1917 :{POP16}{POP16}{POP16}{CURRENCY} -STR_1918 :Can't borrow any more money! -STR_1919 :Not enough cash available! -STR_1920 :Can't pay back loan! -STR_1921 :{SMALLFONT}{BLACK}Start a new game -STR_1922 :{SMALLFONT}{BLACK}Continue playing a saved game -STR_1923 :{SMALLFONT}{BLACK}Show tutorial -STR_1924 :{SMALLFONT}{BLACK}Exit -STR_1925 :Can't place person here... +STR_1918 :¡No puedes pedir más dinero! +STR_1919 :¡No tienes suficiente dinero! +STR_1920 :¡No puedes devolver el préstamo! +STR_1921 :{SMALLFONT}{BLACK}Iniciar nueva partida +STR_1922 :{SMALLFONT}{BLACK}Continuar partida guardada +STR_1923 :{SMALLFONT}{BLACK}Mostrar tutorial +STR_1924 :{SMALLFONT}{BLACK}Salir del juego +STR_1925 :No puedes colocar esta persona aquí... STR_1926 :{SMALLFONT} -STR_1927 :{YELLOW}{STRINGID} has broken down -STR_1928 :{RED}{STRINGID} has crashed! -STR_1929 :{RED}{STRINGID} still hasn't been fixed{NEWLINE}Check where your mechanics are and consider organising them better -STR_1930 :{SMALLFONT}{BLACK}Turn on/off tracking information for this guest - (If tracking is on, guest's movements will be reported in the message area) -STR_1931 :{STRINGID} has joined the queue line for {STRINGID} -STR_1932 :{STRINGID} is on {STRINGID} -STR_1933 :{STRINGID} is in {STRINGID} -STR_1934 :{STRINGID} has left {STRINGID} -STR_1935 :{STRINGID} has left the park -STR_1936 :{STRINGID} has bought {STRINGID} -STR_1937 :{SMALLFONT}{BLACK}Show information about the subject of this message -STR_1938 :{SMALLFONT}{BLACK}Show view of guest -STR_1939 :{SMALLFONT}{BLACK}Show view of staff member -STR_1940 :{SMALLFONT}{BLACK}Show happiness, energy, hunger etc. for this guest -STR_1941 :{SMALLFONT}{BLACK}Show which rides this guest has been on -STR_1942 :{SMALLFONT}{BLACK}Show financial information about this guest -STR_1943 :{SMALLFONT}{BLACK}Show guest's recent thoughts -STR_1944 :{SMALLFONT}{BLACK}Show items guest is carrying -STR_1945 :{SMALLFONT}{BLACK}Show orders and options for this staff member +STR_1927 :{YELLOW}{STRINGID} se ha averiado +STR_1928 :{RED}¡{STRINGID} ha chocado! +STR_1929 :{RED}{STRINGID} no se ha arreglado{NEWLINE}Comprueba dónde están tus mecánicos y considera organizarlos mejor +STR_1930 :{SMALLFONT}{BLACK}Activa/Desactiva el seguimiento de este visitante (Con el seguimiento activado, los movimientos de este visitante aparecerán en el área de mensajes) +STR_1931 :{STRINGID} está haciendo fila en {STRINGID} +STR_1932 :{STRINGID} está en {STRINGID} +STR_1933 :{STRINGID} está en {STRINGID} +STR_1934 :{STRINGID} ha salido de {STRINGID} +STR_1935 :{STRINGID} se ha ido del parque +STR_1936 :{STRINGID} ha comprado {STRINGID} +STR_1937 :{SMALLFONT}{BLACK}Muestra información sobre el tema de este mensaje +STR_1938 :{SMALLFONT}{BLACK}Mostrar vista del visitante +STR_1939 :{SMALLFONT}{BLACK}Mostrar vista de empleado +STR_1940 :{SMALLFONT}{BLACK}Mostrar felicidad, energía, hambre, etc. de este visitante +STR_1941 :{SMALLFONT}{BLACK}Mostrar en qué atracciones se ha subido este visitante +STR_1942 :{SMALLFONT}{BLACK}Mostrar información financiera sobre este visitante +STR_1943 :{SMALLFONT}{BLACK}Mostrar pensamientos recientes de este visitante +STR_1944 :{SMALLFONT}{BLACK}Mostrar los objetos que lleva este visitante +STR_1945 :{SMALLFONT}{BLACK}Mostrar órdenes y opciones para este empleado STR_1946 :{SMALLFONT}{BLACK}Select costume for this entertainer -STR_1947 :{SMALLFONT}{BLACK}Show areas patrolled by selected staff type, and locate the nearest staff member -STR_1948 :{SMALLFONT}{BLACK}Hire a new staff member of the selected type -STR_1949 :Financial Summary -STR_1950 :Financial Graph -STR_1951 :Park Value Graph -STR_1952 :Profit Graph -STR_1953 :Marketing -STR_1954 :Research Funding -STR_1955 :{WINDOW_COLOUR_2}Number of circuits: -STR_1956 :{SMALLFONT}{BLACK}Number of circuits of track per ride +STR_1947 :{SMALLFONT}{BLACK}Mostrar áreas patrulladas por este tipo de empleados, y localiza el empleado más cercano +STR_1948 :{SMALLFONT}{BLACK}Contrata un nuevo empleado del tipo seleccionado +STR_1949 :Resumen financiero +STR_1950 :Gráfica de finanzas +STR_1951 :Gráfica de valor del parque +STR_1952 :Gráfica de beneficios +STR_1953 :Márketing +STR_1954 :Inversión en Innovación y Desarrollo +STR_1955 :{WINDOW_COLOUR_2}Número de circuitos: +STR_1956 :{SMALLFONT}{BLACK}Número de circuitos por juego STR_1957 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1958 :{COMMA16} -STR_1959 :Can't change number of circuits... -STR_1960 :{WINDOW_COLOUR_2}Balloon price: -STR_1961 :{WINDOW_COLOUR_2}Cuddly Toy price: -STR_1962 :{WINDOW_COLOUR_2}Park Map price: -STR_1963 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_1964 :{WINDOW_COLOUR_2}Umbrella price: -STR_1965 :{WINDOW_COLOUR_2}Drink price: -STR_1966 :{WINDOW_COLOUR_2}Burger price: -STR_1967 :{WINDOW_COLOUR_2}Chips price: -STR_1968 :{WINDOW_COLOUR_2}Ice Cream price: -STR_1969 :{WINDOW_COLOUR_2}Candyfloss price: +STR_1959 :No se puede cambiar el número de circuitos... +STR_1960 :{WINDOW_COLOUR_2}Precio de Globo: +STR_1961 :{WINDOW_COLOUR_2}Precio de Juguetito: +STR_1962 :{WINDOW_COLOUR_2}Precio de Mapa: +STR_1963 :{WINDOW_COLOUR_2}Precio de Foto: +STR_1964 :{WINDOW_COLOUR_2}Precio de Paraguas: +STR_1965 :{WINDOW_COLOUR_2}Precio de Bebida: +STR_1966 :{WINDOW_COLOUR_2}Precio de Hamburguesa: +STR_1967 :{WINDOW_COLOUR_2}Precio Papas Fritas: +STR_1968 :{WINDOW_COLOUR_2}Precio de Helado: +STR_1969 :{WINDOW_COLOUR_2}Precio Algodón Azúcar: STR_1970 :{WINDOW_COLOUR_2} STR_1971 :{WINDOW_COLOUR_2} STR_1972 :{WINDOW_COLOUR_2} -STR_1973 :{WINDOW_COLOUR_2}Pizza price: +STR_1973 :{WINDOW_COLOUR_2}Precio de Pizza: STR_1974 :{WINDOW_COLOUR_2} -STR_1975 :{WINDOW_COLOUR_2}Popcorn price: -STR_1976 :{WINDOW_COLOUR_2}Hot Dog price: -STR_1977 :{WINDOW_COLOUR_2}Tentacle price: -STR_1978 :{WINDOW_COLOUR_2}Hat price: -STR_1979 :{WINDOW_COLOUR_2}Toffee Apple price: -STR_1980 :{WINDOW_COLOUR_2}T-Shirt price: -STR_1981 :{WINDOW_COLOUR_2}Doughnut price: -STR_1982 :{WINDOW_COLOUR_2}Coffee price: +STR_1975 :{WINDOW_COLOUR_2}Precio de Palomitas: +STR_1976 :{WINDOW_COLOUR_2}Perrito Caliente: +STR_1977 :{WINDOW_COLOUR_2}Precio de Tentáculo: +STR_1978 :{WINDOW_COLOUR_2}Precio de Sombrero: +STR_1979 :{WINDOW_COLOUR_2}Precio de Manzana: +STR_1980 :{WINDOW_COLOUR_2}Precio de Camiseta: +STR_1981 :{WINDOW_COLOUR_2}Precio de Rosquilla: +STR_1982 :{WINDOW_COLOUR_2}Precio de Café: STR_1983 :{WINDOW_COLOUR_2} -STR_1984 :{WINDOW_COLOUR_2}Fried Chicken price: -STR_1985 :{WINDOW_COLOUR_2}Lemonade price: +STR_1984 :{WINDOW_COLOUR_2}Precio Pollo Frito: +STR_1985 :{WINDOW_COLOUR_2}Precio de Limonada: STR_1986 :{WINDOW_COLOUR_2} STR_1987 :{WINDOW_COLOUR_2} -STR_1988 :Balloon -STR_1989 :Cuddly Toy -STR_1990 :Park Map -STR_1991 :On-Ride Photo -STR_1992 :Umbrella -STR_1993 :Drink -STR_1994 :Burger -STR_1995 :Chips -STR_1996 :Ice Cream -STR_1997 :Candyfloss -STR_1998 :Empty Can -STR_1999 :Rubbish -STR_2000 :Empty Burger Box +STR_1988 :Globo +STR_1989 :Juguetito +STR_1990 :Mapa del Parque +STR_1991 :Foto en Atracción +STR_1992 :Sombrilla +STR_1993 :Bebida +STR_1994 :Hamburguesa +STR_1995 :Patatas Fritas +STR_1996 :Helado +STR_1997 :Algodón de Azúcar +STR_1998 :Lata vacía +STR_1999 :Basura +STR_2000 :Caja de Hamburguesa Vacía STR_2001 :Pizza -STR_2002 :Voucher -STR_2003 :Popcorn -STR_2004 :Hot Dog -STR_2005 :Tentacle -STR_2006 :Hat -STR_2007 :Toffee Apple -STR_2008 :T-Shirt -STR_2009 :Doughnut -STR_2010 :Coffee -STR_2011 :Empty Cup -STR_2012 :Fried Chicken -STR_2013 :Lemonade -STR_2014 :Empty Box -STR_2015 :Empty Bottle -STR_2016 :Balloons -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_2028 :Empty Burger Boxes +STR_2002 :Cupón +STR_2003 :Palomitas de Maíz +STR_2004 :Perrito Caliente +STR_2005 :Tentáculo +STR_2006 :Gorra +STR_2007 :Manzana de Caramelo +STR_2008 :Camiseta +STR_2009 :Rosquilla +STR_2010 :Café +STR_2011 :Taza vacía +STR_2012 :Pollo Frito +STR_2013 :Limonada +STR_2014 :Caja vacía +STR_2015 :Botella vacía +STR_2016 :Globos +STR_2017 :Juguetes Mimosos +STR_2018 :Mapas del parque +STR_2019 :Fotos en atracción +STR_2020 :Paraguas +STR_2021 :Bebidas +STR_2022 :Hamburguesas +STR_2023 :Patatas Fritas +STR_2024 :Helados +STR_2025 :Algodón Azucar +STR_2026 :Latas vacías +STR_2027 :Basuras +STR_2028 :Cajas vacías STR_2029 :Pizzas -STR_2030 :Vouchers -STR_2031 :Popcorn -STR_2032 :Hot Dogs -STR_2033 :Tentacles -STR_2034 :Hats -STR_2035 :Toffee Apples -STR_2036 :T-Shirts -STR_2037 :Doughnuts -STR_2038 :Coffees -STR_2039 :Empty Cups -STR_2040 :Fried Chicken -STR_2041 :Lemonade -STR_2042 :Empty Boxes -STR_2043 :Empty Bottles -STR_2044 :a Balloon -STR_2045 :a Cuddly Toy -STR_2046 :a Park Map -STR_2047 :an On-Ride Photo -STR_2048 :an Umbrella -STR_2049 :a Drink -STR_2050 :a Burger -STR_2051 :some Chips -STR_2052 :an Ice Cream -STR_2053 :some Candyfloss -STR_2054 :an Empty Can -STR_2055 :some Rubbish -STR_2056 :an Empty Burger Box -STR_2057 :a Pizza -STR_2058 :a Voucher -STR_2059 :some Popcorn -STR_2060 :a Hot Dog -STR_2061 :a Tentacle -STR_2062 :a Hat -STR_2063 :a Toffee Apple -STR_2064 :a T-Shirt -STR_2065 :a Doughnut -STR_2066 :a Coffee -STR_2067 :an Empty Cup -STR_2068 :some Fried Chicken -STR_2069 :some Lemonade -STR_2070 :an Empty Box -STR_2071 :an Empty Bottle -STR_2072 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Balloon -STR_2073 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Cuddly Toy -STR_2074 :Map of {STRINGID} -STR_2075 :On-Ride Photo of {STRINGID} -STR_2076 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Umbrella -STR_2077 :Drink -STR_2078 :Burger -STR_2079 :Chips -STR_2080 :Ice Cream -STR_2081 :Candyfloss -STR_2082 :Empty Can -STR_2083 :Rubbish -STR_2084 :Empty Burger Box +STR_2030 :Cupones +STR_2031 :Palomitas de Maíz +STR_2032 :Perritos Calientes +STR_2033 :Tentáculos +STR_2034 :Sombreros +STR_2035 :Manzanas de Caramelo +STR_2036 :Camisetas +STR_2037 :Rosquillas +STR_2038 :Cafés +STR_2039 :Tazas vacías +STR_2040 :Pollos Frito +STR_2041 :Limonadas +STR_2042 :Cajas vacías +STR_2043 :Botellas vacías +STR_2044 :un Globo +STR_2045 :un Juguetito +STR_2046 :un Mapa del Parque +STR_2047 :una Foto +STR_2048 :una Sombrilla +STR_2049 :una Bebida +STR_2050 :una Hamburguesa +STR_2051 :unas Patatas Fritas +STR_2052 :un Helado +STR_2053 :un Algodón de Azúcar +STR_2054 :una Lata vacía +STR_2055 :una Basura +STR_2056 :una Caja vacía +STR_2057 :una Pizza +STR_2058 :un Cupón +STR_2059 :unas Palomitas de Maíz +STR_2060 :un Perrito Caliente +STR_2061 :un Tentáculo +STR_2062 :una Gorra +STR_2063 :una Manzana de Caramelo +STR_2064 :una Camiseta +STR_2065 :una Rosquilla +STR_2066 :un Café +STR_2067 :una taza vacía +STR_2068 :unos Pollos Fritos +STR_2069 :una Limonada +STR_2070 :una Caja vacía +STR_2071 :una Botella vacía +STR_2072 :Globo de {OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2073 :Juguetito de {OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2074 :Mapa de {STRINGID} +STR_2075 :Foto en atracción de {STRINGID} +STR_2076 :Paraguas de {OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2077 :Bebida +STR_2078 :Hamburguesa +STR_2079 :Patatas Fritas +STR_2080 :Helado +STR_2081 :Algodón de Azúcar +STR_2082 :Lata vacía +STR_2083 :Basura +STR_2084 :Caja vacía de hamburguesa STR_2085 :Pizza -STR_2086 :Voucher for {STRINGID} -STR_2087 :Popcorn -STR_2088 :Hot Dog -STR_2089 :Tentacle -STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Hat -STR_2091 :Toffee Apple -STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} T-Shirt -STR_2093 :Doughnut -STR_2094 :Coffee -STR_2095 :Empty Cup -STR_2096 :Fried Chicken -STR_2097 :Lemonade -STR_2098 :Empty Box -STR_2099 :Empty Bottle -STR_2100 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2101 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2102 :{WINDOW_COLOUR_2}On-Ride Photo price: -STR_2103 :{WINDOW_COLOUR_2}Pretzel price: -STR_2104 :{WINDOW_COLOUR_2}Hot Chocolate price: -STR_2105 :{WINDOW_COLOUR_2}Iced Tea price: -STR_2106 :{WINDOW_COLOUR_2}Funnel Cake price: -STR_2107 :{WINDOW_COLOUR_2}Sunglasses price: -STR_2108 :{WINDOW_COLOUR_2}Beef Noodles price: -STR_2109 :{WINDOW_COLOUR_2}Fried Rice Noodles price: -STR_2110 :{WINDOW_COLOUR_2}Wonton Soup price: -STR_2111 :{WINDOW_COLOUR_2}Meatball Soup price: -STR_2112 :{WINDOW_COLOUR_2}Fruit Juice price: -STR_2113 :{WINDOW_COLOUR_2}Soybean Milk price: -STR_2114 :{WINDOW_COLOUR_2}Sujongkwa price: -STR_2115 :{WINDOW_COLOUR_2}Sub Sandwich price: -STR_2116 :{WINDOW_COLOUR_2}Cookie price: +STR_2086 :Cupón para {STRINGID} +STR_2087 :Palomitas de Maíz +STR_2088 :Perrito caliente +STR_2089 :Tentáculo +STR_2090 :Sombrero de {OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2091 :Manzana de Caramelo +STR_2092 :Camiseta de {OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2093 :Rosquilla +STR_2094 :Café +STR_2095 :Taza vacía +STR_2096 :Pollo Frito +STR_2097 :Limonada +STR_2098 :Caja vacía +STR_2099 :Botella vacía +STR_2100 :{WINDOW_COLOUR_2}Precio de Foto: +STR_2101 :{WINDOW_COLOUR_2}Precio de Foto: +STR_2102 :{WINDOW_COLOUR_2}Precio de Foto: +STR_2103 :{WINDOW_COLOUR_2}Precio de Pretzel: +STR_2104 :{WINDOW_COLOUR_2}Precio Chocolate: +STR_2105 :{WINDOW_COLOUR_2}Precio de Té Helado: +STR_2106 :{WINDOW_COLOUR_2}Precio Pastel: +STR_2107 :{WINDOW_COLOUR_2}Precio de Gafas: +STR_2108 :{WINDOW_COLOUR_2}Precio de Fideos: +STR_2109 :{WINDOW_COLOUR_2}Precio Arroz Frito: +STR_2110 :{WINDOW_COLOUR_2}Precio Sopa Wonton: +STR_2111 :{WINDOW_COLOUR_2}Precio Albóndigas: +STR_2112 :{WINDOW_COLOUR_2}Precio Bebida de Fruta: +STR_2113 :{WINDOW_COLOUR_2}Precio Leche Soja: +STR_2114 :{WINDOW_COLOUR_2}Precio Sujongkwa: +STR_2115 :{WINDOW_COLOUR_2}Precio Sándwich: +STR_2116 :{WINDOW_COLOUR_2}Precio de Galleta: STR_2117 :{WINDOW_COLOUR_2} STR_2118 :{WINDOW_COLOUR_2} STR_2119 :{WINDOW_COLOUR_2} -STR_2120 :{WINDOW_COLOUR_2}Roast Sausage price: +STR_2120 :{WINDOW_COLOUR_2}Precio Salchicha: STR_2121 :{WINDOW_COLOUR_2} -STR_2122 :On-Ride Photo -STR_2123 :On-Ride Photo -STR_2124 :On-Ride Photo +STR_2122 :Foto en Atracción +STR_2123 :Foto en Atracción +STR_2124 :Foto en Atracción STR_2125 :Pretzel -STR_2126 :Hot Chocolate -STR_2127 :Iced Tea -STR_2128 :Funnel Cake -STR_2129 :Sunglasses -STR_2130 :Beef Noodles -STR_2131 :Fried Rice Noodles -STR_2132 :Wonton Soup -STR_2133 :Meatball Soup -STR_2134 :Fruit Juice -STR_2135 :Soybean Milk +STR_2126 :Chocolate Caliente +STR_2127 :Té helado +STR_2128 :Pastel +STR_2129 :Gafas de Sol +STR_2130 :Fideo con carne +STR_2131 :Arroz Frito +STR_2132 :Sopa Wonton +STR_2133 :Sopa de Albóndigas +STR_2134 :Jugo de Frutas +STR_2135 :Leche Soja STR_2136 :Sujongkwa -STR_2137 :Sub Sandwich -STR_2138 :Cookie -STR_2139 :Empty Bowl -STR_2140 :Empty Drink Carton -STR_2141 :Empty Juice Cup -STR_2142 :Roast Sausage -STR_2143 :Empty Bowl -STR_2144 :On-Ride Photos -STR_2145 :On-Ride Photos -STR_2146 :On-Ride Photos +STR_2137 :Mini-Sándwich +STR_2138 :Galleta +STR_2139 :Tazón vacío +STR_2140 :Cartón de bebida vacío +STR_2141 :Taza de jugo vacía +STR_2142 :Salchicha Asada +STR_2143 :Tazón vacío +STR_2144 :Foto en Atracción +STR_2145 :Foto en Atracción +STR_2146 :Foto en Atracción STR_2147 :Pretzels -STR_2148 :Hot Chocolates -STR_2149 :Iced Teas -STR_2150 :Funnel Cakes -STR_2151 :Sunglasses -STR_2152 :Beef Noodles -STR_2153 :Fried Rice Noodles -STR_2154 :Wonton Soups -STR_2155 :Meatball Soups -STR_2156 :Fruit Juices -STR_2157 :Soybean Milks +STR_2148 :Chocolates Caliente +STR_2149 :Tés Helados +STR_2150 :Pasteles +STR_2151 :Gafas de Sol +STR_2152 :Fideos con carne +STR_2153 :Arroz frito +STR_2154 :Sopas Wonton +STR_2155 :Sopas de Albóndigas +STR_2156 :Bebidas de Frutas +STR_2157 :Leches Soja STR_2158 :Sujongkwa -STR_2159 :Sub Sandwiches -STR_2160 :Cookies -STR_2161 :Empty Bowls -STR_2162 :Empty Drink Cartons -STR_2163 :Empty Juice cups -STR_2164 :Roast Sausages -STR_2165 :Empty Bowls -STR_2166 :an On-Ride Photo -STR_2167 :an On-Ride Photo -STR_2168 :an On-Ride Photo -STR_2169 :a Pretzel -STR_2170 :a Hot Chocolate -STR_2171 :an Iced Tea -STR_2172 :a Funnel Cake -STR_2173 :a pair of Sunglasses -STR_2174 :some Beef Noodles -STR_2175 :some Fried Rice Noodles -STR_2176 :some Wonton Soup -STR_2177 :some Meatball Soup -STR_2178 :a Fruit Juice -STR_2179 :some Soybean Milk -STR_2180 :some Sujongkwa -STR_2181 :a Sub Sandwich -STR_2182 :a Cookie -STR_2183 :an Empty Bowl -STR_2184 :an Empty Drink Carton -STR_2185 :an Empty Juice Cup -STR_2186 :a Roast Sausage -STR_2187 :an Empty Bowl -STR_2188 :On-Ride Photo of {STRINGID} -STR_2189 :On-Ride Photo of {STRINGID} -STR_2190 :On-Ride Photo of {STRINGID} +STR_2159 :Sándwiches +STR_2160 :Galletas +STR_2161 :Tazones vacíos +STR_2162 :Cartónes de bebida vacío +STR_2163 :Tazas de jugo vacías +STR_2164 :Salchichas asadas +STR_2165 :Tazones vacíos +STR_2166 :una Foto en Atracción +STR_2167 :una Foto en Atracción +STR_2168 :una Foto en Atracción +STR_2169 :un Pretzel +STR_2170 :un Chocolate Caliente +STR_2171 :un Té Helado +STR_2172 :un Pastel +STR_2173 :un par de Gafas +STR_2174 :unos Fideos de carne +STR_2175 :un Arroz Frito +STR_2176 :una Sopa Wonton +STR_2177 :una Sopa de Albóndiga +STR_2178 :una Bebida de Fruta +STR_2179 :una Leche Soja +STR_2180 :un Sujongkwa +STR_2181 :un Mini-Sándwich +STR_2182 :una Galleta +STR_2183 :un Tazón Vacío +STR_2184 :un Cartón de bebida vacío +STR_2185 :una Taza de Bebida vacía +STR_2186 :una Salchicha asada +STR_2187 :un Tazón Vacío +STR_2188 :Foto en Atracción de {STRINGID} +STR_2189 :Foto en Atracción de {STRINGID} +STR_2190 :Foto en Atracción de {STRINGID} STR_2191 :Pretzel -STR_2192 :Hot Chocolate -STR_2193 :Iced Tea -STR_2194 :Funnel Cake -STR_2195 :Sunglasses -STR_2196 :Beef Noodles -STR_2197 :Fried Rice Noodles -STR_2198 :Wonton Soup -STR_2199 :Meatball Soup -STR_2200 :Fruit Juice -STR_2201 :Soybean Milk +STR_2192 :Chocolate Caliente +STR_2193 :Té Helado +STR_2194 :Pastel +STR_2195 :Gafas de Sol +STR_2196 :Fideos con carne +STR_2197 :Arroz Frito +STR_2198 :Sopa Wonton +STR_2199 :Sopa de Albóndigas +STR_2200 :Bebida de Frutas +STR_2201 :Leche de Soja STR_2202 :Sujongkwa -STR_2203 :Sub Sandwich -STR_2204 :Cookie -STR_2205 :Empty Bowl -STR_2206 :Empty Drink Carton -STR_2207 :Empty Juice Cup -STR_2208 :Roast Sausage -STR_2209 :Empty Bowl -STR_2210 :{SMALLFONT}{BLACK}Show list of handymen in park -STR_2211 :{SMALLFONT}{BLACK}Show list of mechanics in park -STR_2212 :{SMALLFONT}{BLACK}Show list of security guards in park -STR_2213 :{SMALLFONT}{BLACK}Show list of entertainers in park -STR_2214 :Construction not possible while game is paused! +STR_2203 :Mini-Sándwich +STR_2204 :Galleta +STR_2205 :Tazón Vacío +STR_2206 :Cartón de bebida vacío +STR_2207 :Taza de Bebida vacía +STR_2208 :Salchicha asada +STR_2209 :Tazón Vacío +STR_2210 :{SMALLFONT}{BLACK}Mostrar lista de jardineros del parque +STR_2211 :{SMALLFONT}{BLACK}Mostrar lista de mecánicos del parque +STR_2212 :{SMALLFONT}{BLACK}Mostrar lista de guardas de seguridad del parque +STR_2213 :{SMALLFONT}{BLACK}Mostrar lista de animadores del parque +STR_2214 :¡No es posible construir mientras el juego está pausado! STR_2215 :{STRINGID}{NEWLINE}({STRINGID}) STR_2216 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}C STR_2217 :{WINDOW_COLOUR_2}{COMMA16}{DEGREE}F -STR_2218 :{RED}{STRINGID} on {STRINGID} hasn't returned to the {STRINGID} yet!{NEWLINE}Check whether it is stuck or has stalled -STR_2219 :{RED}{COMMA16} people have died in an accident on {STRINGID} -STR_2220 :{WINDOW_COLOUR_2}Park Rating: {BLACK}{COMMA16} -STR_2221 :{SMALLFONT}{BLACK}Park Rating: {COMMA16} +STR_2218 :{RED}¡{STRINGID} en {STRINGID} no ha regresado a la {STRINGID}!{NEWLINE}Comprueba si se ha atorado o se ha detenido. +STR_2219 :{RED}{COMMA16} personas han muerto en un accidente en {STRINGID} +STR_2220 :{WINDOW_COLOUR_2}Valoración del parque: {BLACK}{COMMA16} +STR_2221 :{SMALLFONT}{BLACK}Valoración del parque: {COMMA16} STR_2222 :{SMALLFONT}{BLACK}{STRINGID} -STR_2223 :{WINDOW_COLOUR_2}Guests in park: {BLACK}{COMMA16} -STR_2224 :{WINDOW_COLOUR_2}Cash: {BLACK}{CURRENCY2DP} -STR_2225 :{WINDOW_COLOUR_2}Cash: {RED}{CURRENCY2DP} -STR_2226 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} -STR_2227 :{WINDOW_COLOUR_2}Company value: {BLACK}{CURRENCY} -STR_2228 :{WINDOW_COLOUR_2}Last month's profit from food/drink and{NEWLINE}merchandise sales: {BLACK}{CURRENCY} -STR_2229 :Slope up to vertical -STR_2230 :Vertical track -STR_2231 :Holding brake for drop -STR_2232 :Cable lift hill -STR_2233 :{SMALLFONT}{BLACK}Park information -STR_2234 :Recent Messages +STR_2223 :{WINDOW_COLOUR_2}Visitantes en el parque: {BLACK}{COMMA16} +STR_2224 :{WINDOW_COLOUR_2}Efectivo: {BLACK}{CURRENCY2DP} +STR_2225 :{WINDOW_COLOUR_2}Efectivo: {RED}{CURRENCY2DP} +STR_2226 :{WINDOW_COLOUR_2}Valor del parque: {BLACK}{CURRENCY} +STR_2227 :{WINDOW_COLOUR_2}Valor de la compañía: {BLACK}{CURRENCY} +STR_2228 :{WINDOW_COLOUR_2}Ganancias del mes pasado comidas/bebidas y{NEWLINE}venta de mercancías : {BLACK}{CURRENCY} +STR_2229 :Cuesta arriba a vertical +STR_2230 :Tramo Vertical +STR_2231 :Frenos de caída libre +STR_2232 :Cable de elevación +STR_2233 :{SMALLFONT}{BLACK}Información del parque +STR_2234 :Mensajes recientes STR_2235 :{SMALLFONT}{STRINGID} {STRINGID} -STR_2236 :January -STR_2237 :February -STR_2238 :March -STR_2239 :April -STR_2240 :May -STR_2241 :June -STR_2242 :July -STR_2243 :August -STR_2244 :September -STR_2245 :October -STR_2246 :November -STR_2247 :December -STR_2248 :Can't demolish ride/attraction... -STR_2249 :{BABYBLUE}New ride/attraction now available:{NEWLINE}{STRINGID} -STR_2250 :{BABYBLUE}New scenery/themeing now available:{NEWLINE}{STRINGID} +STR_2236 :Enero +STR_2237 :Febrero +STR_2238 :Marzo +STR_2239 :Abril +STR_2240 :Mayo +STR_2241 :Junio +STR_2242 :Julio +STR_2243 :Agosto +STR_2244 :Septiembre +STR_2245 :Octubre +STR_2246 :Noviembre +STR_2247 :Diciembre +STR_2248 :No puedes eliminar la atracción/tienda +STR_2249 :{BABYBLUE}Nueva atracción disponible:{NEWLINE}{STRINGID} +STR_2250 :{BABYBLUE}Nuevo decorado disponible:{NEWLINE}{STRINGID} STR_2251 :Can only be built on paths! STR_2252 :Can only be built across paths! -STR_2253 :Transport Rides -STR_2254 :Gentle Rides -STR_2255 :Roller Coasters -STR_2256 :Thrill Rides -STR_2257 :Water Rides -STR_2258 :Shops & Stalls -STR_2259 :Scenery & Themeing -STR_2260 :No funding -STR_2261 :Minimum funding -STR_2262 :Normal funding -STR_2263 :Maximum funding -STR_2264 :Research funding -STR_2265 :{WINDOW_COLOUR_2}Cost: {BLACK}{CURRENCY} per month -STR_2266 :Research priorities -STR_2267 :Currently in development -STR_2268 :Last development -STR_2269 :{WINDOW_COLOUR_2}Type: {BLACK}{STRINGID} -STR_2270 :{WINDOW_COLOUR_2}Progress: {BLACK}{STRINGID} -STR_2271 :{WINDOW_COLOUR_2}Expected: {BLACK}{STRINGID} -STR_2272 :{WINDOW_COLOUR_2}Ride/attraction:{NEWLINE}{BLACK}{STRINGID} -STR_2273 :{WINDOW_COLOUR_2}Scenery/themeing:{NEWLINE}{BLACK}{STRINGID} -STR_2274 :{SMALLFONT}{BLACK}Show details of this invention or development -STR_2275 :{SMALLFONT}{BLACK}Show funding and options for research & development -STR_2276 :{SMALLFONT}{BLACK}Show research & development status -STR_2277 :Unknown -STR_2278 :Transport Ride -STR_2279 :Gentle Ride -STR_2280 :Roller Coaster -STR_2281 :Thrill Ride -STR_2282 :Water Ride -STR_2283 :Shop/Stall -STR_2284 :Scenery/Themeing -STR_2285 :Initial research -STR_2286 :Designing -STR_2287 :Completing design -STR_2288 :Unknown +STR_2253 :Atracciones de transporte +STR_2254 :Atracciones suaves +STR_2255 :Montañas rusas +STR_2256 :Atracciones intensas +STR_2257 :Atracciones de agua +STR_2258 :Tiendas y puestos +STR_2259 :Decorado +STR_2260 :Sin financiación +STR_2261 :Financiación mínima +STR_2262 :Financiación normal +STR_2263 :Financiación máxima +STR_2264 :Inversión en investigación +STR_2265 :{WINDOW_COLOUR_2}Presupuesto: {BLACK}{CURRENCY} por mes +STR_2266 :Prioridades en investigación +STR_2267 :Actualmente en desarrollo +STR_2268 :Último desarrollo +STR_2269 :{WINDOW_COLOUR_2}Tipo: {BLACK}{STRINGID} +STR_2270 :{WINDOW_COLOUR_2}Progreso: {BLACK}{STRINGID} +STR_2271 :{WINDOW_COLOUR_2}Fecha: {BLACK}{STRINGID} +STR_2272 :{WINDOW_COLOUR_2}Atracción:{NEWLINE}{BLACK}{STRINGID} +STR_2273 :{WINDOW_COLOUR_2}Decorado:{NEWLINE}{BLACK}{STRINGID} +STR_2274 :{SMALLFONT}{BLACK}Mostrar detalles de este desarrollo +STR_2275 :{SMALLFONT}{BLACK}Opciones de financiación y estado de I+D +STR_2276 :{SMALLFONT}{BLACK}Muestra estado de I+D +STR_2277 :Desconocido +STR_2278 :Atracción de Transporte +STR_2279 :Atracción Suave +STR_2280 :Montaña Rusa +STR_2281 :Atracción Intensa +STR_2282 :Atracción de agua +STR_2283 :Tienda/Puesto +STR_2284 :Escenario +STR_2285 :Desarrollo inicial +STR_2286 :Diseñando +STR_2287 :Finalizando diseño +STR_2288 :Desconocido STR_2289 :{STRINGID} {STRINGID} STR_2290 :{SMALLFONT}{BLACK}{STRINGID} {STRINGID} -STR_2291 :Select scenario for new game -STR_2292 :{WINDOW_COLOUR_2}Rides been on: -STR_2293 :{BLACK} Nothing -STR_2294 :{SMALLFONT}{BLACK}Change base land style -STR_2295 :{SMALLFONT}{BLACK}Change vertical edges of land -STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} paid to enter park -STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} ride -STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} rides -STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} item of food -STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} items of food -STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drink -STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} drinks -STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenir -STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} spent on {BLACK}{COMMA16} souvenirs -STR_2305 :Track design files -STR_2306 :Save track design -STR_2307 :Select {STRINGID} design -STR_2308 :{STRINGID} Track Designs -STR_2309 :Install New Track Design -STR_2310 :Build custom design -STR_2311 :{WINDOW_COLOUR_2}Excitement rating: {BLACK}{COMMA2DP32} (approx.) -STR_2312 :{WINDOW_COLOUR_2}Intensity rating: {BLACK}{COMMA2DP32} (approx.) -STR_2313 :{WINDOW_COLOUR_2}Nausea rating: {BLACK}{COMMA2DP32} (approx.) -STR_2314 :{WINDOW_COLOUR_2}Ride length: {BLACK}{STRINGID} -STR_2315 :{WINDOW_COLOUR_2}Cost: {BLACK}around {CURRENCY} -STR_2316 :{WINDOW_COLOUR_2}Space required: {BLACK}{COMMA16} x {COMMA16} blocks +STR_2291 :Selecciona el escenario para una nueva partida +STR_2292 :{WINDOW_COLOUR_2}Atracciones visitadas: +STR_2293 :{BLACK} Nada +STR_2294 :{SMALLFONT}{BLACK}Cambiar estilo de tierra +STR_2295 :{SMALLFONT}{BLACK}Cambiar estilo de acantilado +STR_2296 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gast. en la entrada al parque +STR_2297 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} atracción +STR_2298 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} atracciones +STR_2299 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} comida +STR_2300 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} comidas +STR_2301 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} refresco +STR_2302 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} refrescos +STR_2303 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} souvenir +STR_2304 :{BLACK}{CURRENCY2DP}{WINDOW_COLOUR_2} gastados en {BLACK}{COMMA16} souvenirs +STR_2305 :Archivos Diseño Vía +STR_2306 :Guardar Diseño Vía +STR_2307 :Selecciona diseño de {STRINGID} +STR_2308 :{STRINGID} Diseños de Vía +STR_2309 :Instalar Diseño de Vía +STR_2310 :Construir diseño personalizado +STR_2311 :{WINDOW_COLOUR_2}Nivel de emoción: {BLACK}{COMMA2DP32} (aprox.) +STR_2312 :{WINDOW_COLOUR_2}Nivel de intensidad: {BLACK}{COMMA2DP32} (aprox.) +STR_2313 :{WINDOW_COLOUR_2}Nivel de náuseas: {BLACK}{COMMA2DP32} (aprox.) +STR_2314 :{WINDOW_COLOUR_2}Longitud de vía: {BLACK}{STRINGID} +STR_2315 :{WINDOW_COLOUR_2}Coste: {BLACK}alrededor de {CURRENCY} +STR_2316 :{WINDOW_COLOUR_2}Espacio requerido: {BLACK}{COMMA16} x {COMMA16} bloques STR_2317 : STR_2318 : STR_2319 : STR_2320 : -STR_2321 :{WINDOW_COLOUR_2}Number of rides/attractions: {BLACK}{COMMA16} -STR_2322 :{WINDOW_COLOUR_2}Staff: {BLACK}{COMMA16} -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_2334 :Pounds ({POUND}) -STR_2335 :Dollars ($) -STR_2336 :Franc (F) -STR_2337 :Deutschmark (DM) +STR_2321 :{WINDOW_COLOUR_2}Número de atracciones: {BLACK}{COMMA16} +STR_2322 :{WINDOW_COLOUR_2}Empleados: {BLACK}{COMMA16} +STR_2323 :{WINDOW_COLOUR_2}Extensión del parque: {BLACK}{COMMA32}m{SQUARED} +STR_2324 :{WINDOW_COLOUR_2}Extensión del parque: {BLACK}{COMMA32}sq.ft. +STR_2325 :{SMALLFONT}{BLACK}Comprar terreno para extender el parque. +STR_2326 :{SMALLFONT}{BLACK}Comprar derechos de construcción para construir arriba o debajo del terreno fuera del parque. +STR_2327 :Opciones +STR_2328 :{WINDOW_COLOUR_2}Moneda: +STR_2329 :{WINDOW_COLOUR_2}Distancia y Velocidad: +STR_2330 :{WINDOW_COLOUR_2}Temperatura: +STR_2331 :{WINDOW_COLOUR_2}Marcas de altura: +STR_2332 :Niveles relativos +STR_2333 :Sonido +STR_2334 :Libras ({POUND}) +STR_2335 :Dólares ($) +STR_2336 :Franco (F) +STR_2337 :Marco alemán (DM) STR_2338 :Yen ({YEN}) STR_2339 :Peseta (Pts) STR_2340 :Lira (L) -STR_2341 :Guilders (fl.) -STR_2342 :Krona (kr) +STR_2341 :Florines (fl.) +STR_2342 :Corona sueca (kr) STR_2343 :Euros ({EURO}) STR_2344 :Imperial -STR_2345 :Metric -STR_2346 :Display -STR_2347 :{RED}{STRINGID} has drowned! -STR_2348 :{SMALLFONT}{BLACK}Show statistics for this staff member -STR_2349 :{WINDOW_COLOUR_2}Wages: {BLACK}{CURRENCY} per month -STR_2350 :{WINDOW_COLOUR_2}Employed: {BLACK}{MONTHYEAR} -STR_2351 :{WINDOW_COLOUR_2}Lawns mown: {BLACK}{COMMA16} -STR_2352 :{WINDOW_COLOUR_2}Gardens watered: {BLACK}{COMMA16} -STR_2353 :{WINDOW_COLOUR_2}Litter swept: {BLACK}{COMMA16} -STR_2354 :{WINDOW_COLOUR_2}Bins emptied: {BLACK}{COMMA16} -STR_2355 :{WINDOW_COLOUR_2}Rides fixed: {BLACK}{COMMA16} -STR_2356 :{WINDOW_COLOUR_2}Rides inspected: {BLACK}{COMMA16} -STR_2357 :House -STR_2358 :Units -STR_2359 :Real Values -STR_2360 :{WINDOW_COLOUR_2}Display Resolution: -STR_2361 :Landscape Smoothing -STR_2362 :{SMALLFONT}{BLACK}Toggle landscape tile edge smoothing on/off -STR_2363 :Gridlines on Landscape -STR_2364 :{SMALLFONT}{BLACK}Toggle gridlines on landscape on/off -STR_2365 :The bank refuses to increase your loan! +STR_2345 :Métrico +STR_2346 :Monitor +STR_2347 :{RED}¡{STRINGID} se ha ahogado! +STR_2348 :{SMALLFONT}{BLACK}Mostrar estadísticas de este empleado +STR_2349 :{WINDOW_COLOUR_2}Sueldo: {BLACK}{CURRENCY} al mes +STR_2350 :{WINDOW_COLOUR_2}Contratado: {BLACK}{MONTHYEAR} +STR_2351 :{WINDOW_COLOUR_2}Césped cortado: {BLACK}{COMMA16} +STR_2352 :{WINDOW_COLOUR_2}Jardines regados: {BLACK}{COMMA16} +STR_2353 :{WINDOW_COLOUR_2}Senderos limpiados: {BLACK}{COMMA16} +STR_2354 :{WINDOW_COLOUR_2}Papeleras vaciadas: {BLACK}{COMMA16} +STR_2355 :{WINDOW_COLOUR_2}Atracciones reparadas: {BLACK}{COMMA16} +STR_2356 :{WINDOW_COLOUR_2}Atracc. inspeccionadas: {BLACK}{COMMA16} +STR_2357 :Casa +STR_2358 :Unidas +STR_2359 :Valores reales +STR_2360 :{WINDOW_COLOUR_2}Resolución de la pantalla: +STR_2361 :Suavizado de terreno +STR_2362 :{SMALLFONT}{BLACK}Activa o desactiva el suavizado del terreno +STR_2363 :Mostrar cuadrícula de terreno +STR_2364 :{SMALLFONT}{BLACK}Activa o desactiva la cuadrícula de terreno +STR_2365 :¡El banco se niega a prestarte más dinero! STR_2366 :Celsius ({DEGREE}C) STR_2367 :Fahrenheit ({DEGREE}F) -STR_2368 :None -STR_2369 :Low -STR_2370 :Average -STR_2371 :High -STR_2372 :Low -STR_2373 :Medium -STR_2374 :High -STR_2375 :Very high -STR_2376 :Extreme -STR_2377 :Ultra-Extreme -STR_2378 :{SMALLFONT}{BLACK}Adjust smaller area of land -STR_2379 :{SMALLFONT}{BLACK}Adjust larger area of land -STR_2380 :{SMALLFONT}{BLACK}Adjust smaller area of water -STR_2381 :{SMALLFONT}{BLACK}Adjust larger area of water -STR_2382 :Land -STR_2383 :Water -STR_2384 :{WINDOW_COLOUR_2}Your objective: -STR_2385 :{BLACK}None -STR_2386 :{BLACK}To have at least {COMMA16} guests in your park at the end of {MONTHYEAR}, with a park rating of at least 600 -STR_2387 :{BLACK}To achieve a park value of at least {POP16}{POP16}{CURRENCY} at the end of {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} -STR_2388 :{BLACK}Have Fun! -STR_2389 :{BLACK}Build the best {STRINGID} you can! -STR_2390 :{BLACK}To have 10 different types of roller coasters operating in your park, each with an excitement value of at least 6.00 -STR_2391 :{BLACK}To have at least {COMMA16} guests in your park. You must not let the park rating drop below 700 at any time! -STR_2392 :{BLACK}To achieve a monthly income from ride tickets of at least {POP16}{POP16}{CURRENCY} -STR_2393 :{BLACK}To have 10 different types of roller coasters operating in your park, each with a minimum length of {LENGTH}, and an excitement rating of at least 7.00 -STR_2394 :{BLACK}To finish building all 5 of the partially built roller coasters in this park, designing them to achieve excitement ratings of at least {POP16}{POP16}{COMMA2DP32} each -STR_2395 :{BLACK}To repay your loan and achieve a park value of at least {POP16}{POP16}{CURRENCY} -STR_2396 :{BLACK}To achieve a monthly profit from food, drink and merchandise sales of at least {POP16}{POP16}{CURRENCY} -STR_2397 :None -STR_2398 :Number of guests at a given date -STR_2399 :Park value at a given date -STR_2400 :Have fun -STR_2401 :Build the best ride you can -STR_2402 :Build 10 roller coasters -STR_2403 :Number of guests in park -STR_2404 :Monthly income from ride tickets -STR_2405 :Build 10 roller coasters of a given length -STR_2406 :Finish building 5 roller coasters -STR_2407 :Repay loan and achieve a given park value -STR_2408 :Monthly profit from food/merchandise -STR_2409 :{WINDOW_COLOUR_2}Marketing campaigns in operation -STR_2410 :{BLACK}None -STR_2411 :{WINDOW_COLOUR_2}Marketing campaigns available -STR_2412 :{SMALLFONT}{BLACK}Start this marketing campaign -STR_2413 :{BLACK}({CURRENCY2DP} per week) -STR_2414 :(Not Selected) -STR_2415 :{WINDOW_COLOUR_2}Ride: +STR_2368 :Ninguna +STR_2369 :Bajo +STR_2370 :Media +STR_2371 :Alta +STR_2372 :Baja +STR_2373 :Medio +STR_2374 :Alto +STR_2375 :Muy alto +STR_2376 :Extremo +STR_2377 :Ultra-Extremo +STR_2378 :{SMALLFONT}{BLACK}Seleccionar menos extensión de tierra +STR_2379 :{SMALLFONT}{BLACK}Seleccionar más extensión de tierra +STR_2380 :{SMALLFONT}{BLACK}Seleccionar menos extensión de agua +STR_2381 :{SMALLFONT}{BLACK}Seleccionar más extensión de agua +STR_2382 :Tierra +STR_2383 :Agua +STR_2384 :{WINDOW_COLOUR_2}Tu objetivo: +STR_2385 :{BLACK}Ninguno +STR_2386 :{BLACK}Tener al menos {COMMA16} visitantes en tu parque a finales de {MONTHYEAR}, con una valoración del parque de al menos 600 +STR_2387 :{BLACK}Conseguir un valor del parque {POP16}{POP16}{CURRENCY} a final de {PUSH16}{PUSH16}{PUSH16}{MONTHYEAR} +STR_2388 :{BLACK}¡Diviértete! +STR_2389 :{BLACK}¡Construye el mejor {STRINGID} que puedas! +STR_2390 :{BLACK}Tener al menos 10 tipos de montañas rusas distintas operando en el parque, cada una con un valor de emoción de al menos 6.00 +STR_2391 :{BLACK}Tener al menos {COMMA16} visitantes en tu parque. ¡No dejes que la valoración baje de 700 en ningún momento! +STR_2392 :{BLACK}Conseguir unos ingresos mensuales por venta de entradas a atrcciones de al menos {POP16}{POP16}{CURRENCY} +STR_2393 :{BLACK}Tener al menos 10 tipos de montañas rusas distintas operando en el parque, cada una con una longitud mínima de {LENGTH}, y un valor de emoción de al menos 7.00 +STR_2394 :{BLACK}Terminar de construir 5 de las montañas rusas no terminadas en este parque, diseñándolas de modo que tengan un valor de emoción de al menos {POP16}{POP16}{COMMA2DP32} cada una +STR_2395 :{BLACK}Devolver el crédito y conseguir un valor del parque de al menos {POP16}{POP16}{CURRENCY} +STR_2396 :{BLACK}Conseguir unos ingresos mensuales por comida, bebida y otros artículos de al menos {POP16}{POP16}{CURRENCY} +STR_2397 :Ninguno +STR_2398 :Número de visitantes en una fecha dada +STR_2399 :Valor del parque en una fecha dada +STR_2400 :¡Diviertete! +STR_2401 :Construir la mejor atracción posible +STR_2402 :Construye 10 montañas rusas +STR_2403 :Núnero de visitantes en el parque +STR_2404 :Beneficio mensual de atracciones +STR_2405 :Construye 10 montañas rusas con una longitud +STR_2406 :Terminar la construcción de 5 montañas rusas +STR_2407 :Pagar préstamo y alcanzar un valor de parque +STR_2408 :Beneficio mensual comida/mercadotecnia +STR_2409 :{WINDOW_COLOUR_2}Campañas de márketing en marcha +STR_2410 :{BLACK}Ninguna +STR_2411 :{WINDOW_COLOUR_2}Campañas de márketing disponibles +STR_2412 :{SMALLFONT}{BLACK}Comienza esta campaña de márketing +STR_2413 :{BLACK}({CURRENCY2DP} por semana) +STR_2414 :(Aún no seleccionada) +STR_2415 :{WINDOW_COLOUR_2}Atracción: STR_2416 :{WINDOW_COLOUR_2}Item: -STR_2417 :{WINDOW_COLOUR_2}Length of time: -STR_2418 :Free entry to {STRINGID} -STR_2419 :Free ride on {STRINGID} -STR_2420 :Half-price entry to {STRINGID} -STR_2421 :Free {STRINGID} -STR_2422 :Advertising campaign for {STRINGID} -STR_2423 :Advertising campaign for {STRINGID} -STR_2424 :{WINDOW_COLOUR_2}Vouchers for free entry to the park -STR_2425 :{WINDOW_COLOUR_2}Vouchers for free rides on a particular ride -STR_2426 :{WINDOW_COLOUR_2}Vouchers for half-price entry to the park -STR_2427 :{WINDOW_COLOUR_2}Vouchers for free food or drink -STR_2428 :{WINDOW_COLOUR_2}Advertising campaign for the park -STR_2429 :{WINDOW_COLOUR_2}Advertising campaign for a particular ride -STR_2430 :{BLACK}Vouchers for free entry to {STRINGID} -STR_2431 :{BLACK}Vouchers for free ride on {STRINGID} -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_2417 :{WINDOW_COLOUR_2}Período de tiempo: +STR_2418 :Entrada gratis a {STRINGID} +STR_2419 :Entrada gratis a {STRINGID} +STR_2420 :Descuento 50% en {STRINGID} +STR_2421 :Gratis {STRINGID} +STR_2422 :Campaña de publicidad de {STRINGID} +STR_2423 :Campaña de publicidad de {STRINGID} +STR_2424 :{WINDOW_COLOUR_2}Cupones para entrada gratis al parque +STR_2425 :{WINDOW_COLOUR_2}Cupones para entrada gratis a una de las atracciones +STR_2426 :{WINDOW_COLOUR_2}Cupones para 50% de descuento en entrada al parque +STR_2427 :{WINDOW_COLOUR_2}Cupones para comida o bebida gratis +STR_2428 :{WINDOW_COLOUR_2}Campaña de publicidad del parque +STR_2429 :{WINDOW_COLOUR_2}Campaña de publicidad de una atracción +STR_2430 :{BLACK}Cupones para entrada gratis a {STRINGID} +STR_2431 :{BLACK}Cupones para entrada gratis a {STRINGID} +STR_2432 :{BLACK}Cupones para 50% de descuento en entrada a {STRINGID} +STR_2433 :{BLACK}Cupones para {STRINGID} gratis +STR_2434 :{BLACK}Campaña de publicidad de {STRINGID} +STR_2435 :{BLACK}Campaña de publicidad de {STRINGID} +STR_2436 :1 semana STR_2437 : STR_2438 : STR_2439 : STR_2440 : STR_2441 : STR_2442 : -STR_2443 :{WINDOW_COLOUR_2}Cost per week: {BLACK}{CURRENCY2DP} -STR_2444 :{WINDOW_COLOUR_2}Total cost: {BLACK}{CURRENCY2DP} -STR_2445 :Start this marketing campaign -STR_2446 :{YELLOW}Your marketing campaign for free entry to the park has finished -STR_2447 :{YELLOW}Your marketing campaign for free rides on {STRINGID} has finished -STR_2448 :{YELLOW}Your marketing campaign for half-price entry to the park has finished -STR_2449 :{YELLOW}Your marketing campaign for free {STRINGID} has finished -STR_2450 :{YELLOW}Your advertising campaign for the park has finished -STR_2451 :{YELLOW}Your advertising campaign for {STRINGID} has finished -STR_2452 :{WINDOW_COLOUR_2}Cash (less loan): {BLACK}{CURRENCY2DP} -STR_2453 :{WINDOW_COLOUR_2}Cash (less loan): {RED}{CURRENCY2DP} +STR_2443 :{WINDOW_COLOUR_2}Coste por semana: {BLACK}{CURRENCY2DP} +STR_2444 :{WINDOW_COLOUR_2}Coste total: {BLACK}{CURRENCY2DP} +STR_2445 :Lanzar esta campaña de márketing +STR_2446 :{YELLOW}La campaña de márketing para la entrada gratis al parque ha finalizado +STR_2447 :{YELLOW}La campaña de márketing para entrar gratis a {STRINGID} ha finalizado +STR_2448 :{YELLOW}La campaña de cupones-descuento para entrar al parque ha finalizado +STR_2449 :{YELLOW}La campaña de márketing para {STRINGID} gratis ha finalizado +STR_2450 :{YELLOW}La campaña de publicidad del parque ha finalizado +STR_2451 :{YELLOW}La campaña de publicidad de {STRINGID} ha finalizado +STR_2452 :{WINDOW_COLOUR_2}Efectivo (restando préstamo): {BLACK}{CURRENCY2DP} +STR_2453 :{WINDOW_COLOUR_2}Efectivo (restando préstamo): {RED}{CURRENCY2DP} STR_2454 :{SMALLFONT}{BLACK}{CURRENCY2DP} - STR_2455 :{SMALLFONT}{BLACK}+{CURRENCY2DP} - STR_2456 :{SMALLFONT}{BLACK}{CURRENCY2DP} - -STR_2457 :{SMALLFONT}{BLACK}Show financial accounts -STR_2458 :{SMALLFONT}{BLACK}Show graph of cash (less loan) over time -STR_2459 :{SMALLFONT}{BLACK}Show graph of park value over time -STR_2460 :{SMALLFONT}{BLACK}Show graph of weekly profit -STR_2461 :{SMALLFONT}{BLACK}Show marketing campaigns -STR_2462 :{SMALLFONT}{BLACK}Show view of park entrance -STR_2463 :{SMALLFONT}{BLACK}Show graph of park ratings over time -STR_2464 :{SMALLFONT}{BLACK}Show graph of guest numbers over time -STR_2465 :{SMALLFONT}{BLACK}Show park entrance price and information -STR_2466 :{SMALLFONT}{BLACK}Show park statistics -STR_2467 :{SMALLFONT}{BLACK}Show objectives for this game -STR_2468 :{SMALLFONT}{BLACK}Show recent awards this park has received -STR_2469 :{SMALLFONT}{BLACK}Select level of research & development -STR_2470 :{SMALLFONT}{BLACK}Research new transport rides -STR_2471 :{SMALLFONT}{BLACK}Research new gentle rides -STR_2472 :{SMALLFONT}{BLACK}Research new roller coasters -STR_2473 :{SMALLFONT}{BLACK}Research new thrill rides -STR_2474 :{SMALLFONT}{BLACK}Research new water rides -STR_2475 :{SMALLFONT}{BLACK}Research new shops and stalls -STR_2476 :{SMALLFONT}{BLACK}Research new scenery and themeing -STR_2477 :{SMALLFONT}{BLACK}Select operating mode for this ride/attraction -STR_2478 :{SMALLFONT}{BLACK}Show graph of velocity against time -STR_2479 :{SMALLFONT}{BLACK}Show graph of altitude against time -STR_2480 :{SMALLFONT}{BLACK}Show graph of vertical acceleration against time -STR_2481 :{SMALLFONT}{BLACK}Show graph of lateral acceleration against time -STR_2482 :{SMALLFONT}{BLACK}Profit: {CURRENCY} per week, Park Value: {CURRENCY} -STR_2483 :{WINDOW_COLOUR_2}Weekly profit: {BLACK}+{CURRENCY2DP} -STR_2484 :{WINDOW_COLOUR_2}Weekly profit: {RED}{CURRENCY2DP} -STR_2485 :Controls +STR_2457 :{SMALLFONT}{BLACK}Mostrar finanzas +STR_2458 :{SMALLFONT}{BLACK}Mostrar gráfica de efectivo disponible (restando préstamo) en el tiempo +STR_2459 :{SMALLFONT}{BLACK}Mostrar gráfica de valor del parque en el tiempo +STR_2460 :{SMALLFONT}{BLACK}Mostrar gráfica de beneficios en el tiempo +STR_2461 :{SMALLFONT}{BLACK}Mostrar campañas de márketing +STR_2462 :{SMALLFONT}{BLACK}Mostrar vista de la entrada al parque +STR_2463 :{SMALLFONT}{BLACK}Mostrar gráfica de valoración del parque en el tiempo +STR_2464 :{SMALLFONT}{BLACK}Mostrar gráfica de número de visitantes en el tiempo +STR_2465 :{SMALLFONT}{BLACK}Mostrar precio e información de la entrada +STR_2466 :{SMALLFONT}{BLACK}Mostrar estadísticas del parque +STR_2467 :{SMALLFONT}{BLACK}Mostrar objetivos de este parque +STR_2468 :{SMALLFONT}{BLACK}Mostrar premios recientemente ganados por el parque +STR_2469 :{SMALLFONT}{BLACK}Selecciona el nivel de investigación y desarrollo +STR_2470 :{SMALLFONT}{BLACK}Investigar nuevas atracciones de transporte +STR_2471 :{SMALLFONT}{BLACK}Investigar nuevas atracciones suaves +STR_2472 :{SMALLFONT}{BLACK}Investigar nuevas montañas rusas +STR_2473 :{SMALLFONT}{BLACK}Investigar nuevas atracciones intensas +STR_2474 :{SMALLFONT}{BLACK}Investigar nuevas atracciones de agua +STR_2475 :{SMALLFONT}{BLACK}Investigar nuevas tiendas y puestos +STR_2476 :{SMALLFONT}{BLACK}Investigar nuevo decorado +STR_2477 :{SMALLFONT}{BLACK}Selecciona modo de funcionamiento para esta atracción +STR_2478 :{SMALLFONT}{BLACK}Mostrar gráfico de velocidad con respecto al tiempo +STR_2479 :{SMALLFONT}{BLACK}Mostrar gráfico de velocidad con respecto al tiempo +STR_2480 :{SMALLFONT}{BLACK}Mostrar gráfico de aceleración con respecto al tiempo +STR_2481 :{SMALLFONT}{BLACK}Mostrar gráfico de aceleración lateral con respecto al tiempo +STR_2482 :{SMALLFONT}{BLACK}Beneficios: {CURRENCY} por semana. Valor del parque: {CURRENCY} +STR_2483 :{WINDOW_COLOUR_2}Beneficio semanal: {BLACK}+{CURRENCY2DP} +STR_2484 :{WINDOW_COLOUR_2}Beneficio semanal: {RED}{CURRENCY2DP} +STR_2485 :Controles STR_2486 :General -STR_2487 :Show 'real' names of guests -STR_2488 :{SMALLFONT}{BLACK}Toggle between showing 'real' names of guests and guest numbers -STR_2489 :Shortcut keys... -STR_2490 :Keyboard shortcuts -STR_2491 :Reset keys -STR_2492 :{SMALLFONT}{BLACK}Set all keyboard shortcuts back to default settings -STR_2493 :Close top-most window -STR_2494 :Close all floating windows +STR_2487 :Mostrar nombres 'reales' de los visitantes +STR_2488 :{SMALLFONT}{BLACK}Muestra los nombres 'reales' de los visitantes, o sólo su número de visitante +STR_2489 :Atajos de teclado... +STR_2490 :Atajos de teclado +STR_2491 :Reiniciar teclas +STR_2492 :{SMALLFONT}{BLACK}Cambiar todos los atajos de teclado a los valores por defecto +STR_2493 :Cerrar ventana más-arriba +STR_2494 :Cerrar todas las ventanas STR_2495 :Cancelar construction mode -STR_2496 :Pause game -STR_2497 :Zoom view out -STR_2498 :Zoom view in -STR_2499 :Rotate view clockwise -STR_2500 :Rotate construction object -STR_2501 :Underground view toggle -STR_2502 :Remove base land toggle -STR_2503 :Remove vertical land toggle -STR_2504 :See-through rides toggle -STR_2505 :See-through scenery toggle +STR_2496 :Pausar juego +STR_2497 :Alejar vista +STR_2498 :Acercar vista +STR_2499 :Rotar vista a la derecha +STR_2500 :Rotar objetos en construcción +STR_2501 :Vista subterránea +STR_2502 :Tierra invisible +STR_2503 :Acantilados invisibles +STR_2504 :Mirar a través de atracciones +STR_2505 :Mirar a través del escenario STR_2506 :Invisible supports toggle STR_2507 :Invisible people toggle -STR_2508 :Height marks on land toggle -STR_2509 :Height marks on ride tracks toggle -STR_2510 :Height marks on paths toggle -STR_2511 :Adjust land -STR_2512 :Adjust water -STR_2513 :Build scenery -STR_2514 :Build paths -STR_2515 :Build new ride -STR_2516 :Show financial information -STR_2517 :Show research information -STR_2518 :Show rides list -STR_2519 :Show park information -STR_2520 :Show guest list -STR_2521 :Show staff list -STR_2522 :Show recent messages -STR_2523 :Show map -STR_2524 :Screenshot +STR_2508 :Marcas de altura en el suelo +STR_2509 :Marcas de altura en atracciones +STR_2510 :Marcas de altura en senderos +STR_2511 :Ajustar terreno +STR_2512 :Ajustar agua +STR_2513 :Construir escenario +STR_2514 :Construir sendero +STR_2515 :Construir nueva atracción +STR_2516 :Mostrar info. de finanzas +STR_2517 :Mostrar info. de investigación +STR_2518 :Mostrar lista de atracciones +STR_2519 :Mostrar info. del parque +STR_2520 :Mostrar lista de visitantes +STR_2521 :Mostrar lista de empleados +STR_2522 :Mostrar mensajes recientes +STR_2523 :Mostrar mapa +STR_2524 :Captura Pantalla STR_2525 :??? STR_2526 :??? STR_2527 :??? @@ -2548,7 +2548,7 @@ STR_2540 :??? STR_2541 :??? STR_2542 :??? STR_2543 :Alt/Menu -STR_2544 :Pause +STR_2544 :Pausa STR_2545 :Caps STR_2546 :??? STR_2547 :??? @@ -2575,7 +2575,7 @@ STR_2567 :Print STR_2568 :Execute STR_2569 :Snapshot STR_2570 :Insert -STR_2571 :Borrar +STR_2571 :Delete STR_2572 :Help STR_2573 :0 STR_2574 :1 @@ -2684,37 +2684,37 @@ STR_2676 :??? STR_2677 :??? STR_2678 :??? STR_2679 :??? -STR_2680 :All research complete -STR_2681 :{MEDIUMFONT}{BLACK}Increases your money by {CURRENCY} +STR_2680 :Investigación Completa +STR_2681 :{MEDIUMFONT}{BLACK}Incrementa tu dinero en {CURRENCY} STR_2682 : STR_2683 : -STR_2684 :{SMALLFONT}{BLACK}Large group of peeps arrive +STR_2684 :{SMALLFONT}{BLACK}Llega un gran grupo de visitantes STR_2685 :Simplex Noise Parameters -STR_2686 :{WINDOW_COLOUR_2}Low: -STR_2687 :{WINDOW_COLOUR_2}High: -STR_2688 :{WINDOW_COLOUR_2}Base Frequency: -STR_2689 :{WINDOW_COLOUR_2}Octaves: -STR_2690 :Map Generation -STR_2691 :{WINDOW_COLOUR_2}Base height: -STR_2692 :{WINDOW_COLOUR_2}Water level: -STR_2693 :{WINDOW_COLOUR_2}Terrain: -STR_2694 :Generate -STR_2695 :Random terrain -STR_2696 :Place trees +STR_2686 :{WINDOW_COLOUR_2}Bajo: +STR_2687 :{WINDOW_COLOUR_2}Alto: +STR_2688 :{WINDOW_COLOUR_2}Frecuencia Base: +STR_2689 :{WINDOW_COLOUR_2}Octavas: +STR_2690 :Generación Mapa +STR_2691 :{WINDOW_COLOUR_2}Altura de base: +STR_2692 :{WINDOW_COLOUR_2}Altura de agua: +STR_2693 :{WINDOW_COLOUR_2}Terreno: +STR_2694 :Generar +STR_2695 :Terreno aleatorio +STR_2696 :Colocar arboles STR_2697 :??? STR_2698 :??? STR_2699 :??? -STR_2700 :Autosave frequency: -STR_2701 :Every minute -STR_2702 :Every 5 minutes -STR_2703 :Every 15 minutes -STR_2704 :Every 30 minutes -STR_2705 :Every hour -STR_2706 :Never -STR_2707 :Open new window -STR_2708 :{WINDOW_COLOUR_1}Are you sure you want to overwrite {STRINGID}? -STR_2709 :Overwrite -STR_2710 :Type the name of the file. +STR_2700 :Autoguardado: +STR_2701 :Cada minuto +STR_2702 :Cada 5 minutos +STR_2703 :Cada 15 minutos +STR_2704 :Cada 30 minutos +STR_2705 :Cada hora +STR_2706 :Nunca +STR_2707 :Abrir explorador de archivos +STR_2708 :{WINDOW_COLOUR_1}¿Estas seguro de sobreescribir {STRINGID}? +STR_2709 :Sobreescribir +STR_2710 :Ingresar nombre para este archivo: STR_2711 :; STR_2712 := STR_2713 :, @@ -2722,47 +2722,47 @@ STR_2714 :- STR_2715 :. STR_2716 :/ STR_2717 :' -STR_2718 :(up) -STR_2719 :(new file) -STR_2720 :{UINT16}sec -STR_2721 :{UINT16}secs -STR_2722 :{UINT16}min:{UINT16}sec -STR_2723 :{UINT16}min:{UINT16}secs -STR_2724 :{UINT16}mins:{UINT16}sec -STR_2725 :{UINT16}mins:{UINT16}secs +STR_2718 :(arriba) +STR_2719 :(nuevo archivo) +STR_2720 :{UINT16}seg +STR_2721 :{UINT16}segs +STR_2722 :{UINT16}min:{UINT16}seg +STR_2723 :{UINT16}min:{UINT16}segs +STR_2724 :{UINT16}mins:{UINT16}seg +STR_2725 :{UINT16}mins:{UINT16}segs STR_2726 :{UINT16}min STR_2727 :{UINT16}mins -STR_2728 :{UINT16}hour:{UINT16}min -STR_2729 :{UINT16}hour:{UINT16}mins -STR_2730 :{UINT16}hours:{UINT16}min -STR_2731 :{UINT16}hours:{UINT16}mins +STR_2728 :{UINT16}hora:{UINT16}min +STR_2729 :{UINT16}hora:{UINT16}mins +STR_2730 :{UINT16}horas:{UINT16}min +STR_2731 :{UINT16}horas:{UINT16}mins STR_2732 :{COMMA16}ft STR_2733 :{COMMA16}m STR_2734 :{COMMA16}mph STR_2735 :{COMMA16}km/h STR_2736 :{MONTH}, año {COMMA16} -STR_2737 :{STRINGID} {MONTH}, año {COMMA16} -STR_2738 :Title screen music: -STR_2739 :None +STR_2737 :{STRINGID} {MONTH}, Año {COMMA16} +STR_2738 :Música menú principal: +STR_2739 :Ninguna 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_2742 :css50.dat no encontrado +STR_2743 :Copia data\css17.dat de tu instalación de RCT1 en data\css50.dat de la instalación de RCT2, STR_2744 :[ STR_2745 :\ STR_2746 :] STR_2747 :{ENDQUOTES} -STR_2748 :Bar -STR_2749 :My new scenario -STR_2750 :Move all items to top -STR_2751 :Move all items to bottom -STR_2752 :Clear grass -STR_2753 :Mowed grass -STR_2754 :Water plants -STR_2755 :Fix vandalism -STR_2756 :Remove litter -STR_2757 :Force Sun -STR_2758 :Force Thunder +STR_2748 :Barra +STR_2749 :Mi nuevo escenario +STR_2750 :Mover todo hacia arriba +STR_2751 :Mover todo hacia abajo +STR_2752 :Limpiar césped +STR_2753 :Cortar césped +STR_2754 :Regar plantas +STR_2755 :Arreglar mobiliario +STR_2756 :Vaciar papeleras +STR_2757 :Forzar soleado +STR_2758 :Forzar tormenta STR_2759 :Zero Clearance # New strings used in the cheats window previously these were ??? STR_2760 :+{CURRENCY} @@ -2770,119 +2770,119 @@ STR_2761 : STR_2762 : STR_2763 :??? STR_2764 : -STR_2765 :Large Tram -STR_2766 :Win scenario -STR_2767 :Freeze Climate -STR_2768 :Unfreeze Climate -STR_2769 :Open Park -STR_2770 :Close Park -STR_2771 :Slower Gamespeed -STR_2772 :Faster Gamespeed -STR_2773 :Windowed -STR_2774 :Fullscreen -STR_2775 :Fullscreen (desktop) -STR_2776 :Language: +STR_2765 :Grupo de visitantes +STR_2766 :Ganar escenario +STR_2767 :Mantener clima +STR_2768 :Clima cambiante +STR_2769 :Abrir parque +STR_2770 :Cerrar parque +STR_2771 :Bajar velocidad +STR_2772 :Subir velocidad +STR_2773 :Ventana +STR_2774 :Pantalla completa +STR_2775 :Pantalla completa (Sin bordes) +STR_2776 :Idioma: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} # End of new strings -STR_2779 :Viewport #{COMMA16} -STR_2780 :Extra viewport +STR_2779 :Cámara #{COMMA16} +STR_2780 :Añadir 'cámara de vigilancia' STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} STR_2782 :SHIFT + STR_2783 :CTRL + -STR_2784 :Change keyboard shortcut -STR_2785 :{WINDOW_COLOUR_2}Press new shortcut key for:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} -STR_2786 :{SMALLFONT}{BLACK}Click on shortcut description to select new key -STR_2787 :{WINDOW_COLOUR_2}Park value: {BLACK}{CURRENCY} -STR_2788 :{WINDOW_COLOUR_2}Congratulations !{NEWLINE}{BLACK}You achieved your objective with a company value of {CURRENCY} ! -STR_2789 :{WINDOW_COLOUR_2}You have failed your objective ! -STR_2790 :Enter name into scenario chart -STR_2791 :Enter name -STR_2792 :Please enter your name for the scenario chart: -STR_2793 :{SMALLFONT}(Completed by {STRINGID}) -STR_2794 :{WINDOW_COLOUR_2}Completed by: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} with a company value of: {BLACK}{CURRENCY} -STR_2795 :Sort -STR_2796 :{SMALLFONT}{BLACK}Sort the ride list into order using the information type displayed -STR_2797 :Scroll view when pointer at screen edge -STR_2798 :{SMALLFONT}{BLACK}Select whether to scroll the view when the mouse pointer is at the screen edge -STR_2799 :{SMALLFONT}{BLACK}View or change control key assignments -STR_2800 :{WINDOW_COLOUR_2}Total admissions: {BLACK}{COMMA32} -STR_2801 :{WINDOW_COLOUR_2}Income from admissions: {BLACK}{CURRENCY2DP} -STR_2802 :Map -STR_2803 :{SMALLFONT}{BLACK}Show these guests highlighted on map -STR_2804 :{SMALLFONT}{BLACK}Show these staff members highlighted on map -STR_2805 :{SMALLFONT}{BLACK}Show map of park -STR_2806 :{RED}Guests are complaining about the disgusting state of the paths in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2807 :{RED}Guests are complaining about the amount of litter in your park{NEWLINE}Check where your handymen are and consider organising them better -STR_2808 :{RED}Guests are complaining about the vandalism in your park{NEWLINE}Check where your security guards are and consider organising them better -STR_2809 :{RED}Guests are hungry and can't find anywhere to buy food -STR_2810 :{RED}Guests are thirsty and can't find anywhere to buy drinks -STR_2811 :{RED}Guests are complaining because they can't find the toilets in your park -STR_2812 :{RED}Guests are getting lost or stuck{NEWLINE}Check whether the layout of your footpaths needs improving to help the guests find their way around -STR_2813 :{RED}Your park entrance fee is too high!{NEWLINE}Reduce your entrance fee or improve the value of the park to attract more guests -STR_2814 :{WINDOW_COLOUR_2}Most untidy park award -STR_2815 :{WINDOW_COLOUR_2}Tidiest park award -STR_2816 :{WINDOW_COLOUR_2}Award for the park with the best roller coasters -STR_2817 :{WINDOW_COLOUR_2}Best value park award -STR_2818 :{WINDOW_COLOUR_2}Most beautiful park award -STR_2819 :{WINDOW_COLOUR_2}Worst value park award -STR_2820 :{WINDOW_COLOUR_2}Safest park award -STR_2821 :{WINDOW_COLOUR_2}Best staff award -STR_2822 :{WINDOW_COLOUR_2}Best park food award -STR_2823 :{WINDOW_COLOUR_2}Worst park food award -STR_2824 :{WINDOW_COLOUR_2}Best park toilets award -STR_2825 :{WINDOW_COLOUR_2}Most disappointing park award -STR_2826 :{WINDOW_COLOUR_2}Best water rides award -STR_2827 :{WINDOW_COLOUR_2}Best custom-designed rides award -STR_2828 :{WINDOW_COLOUR_2}Most dazzling ride colour schemes award -STR_2829 :{WINDOW_COLOUR_2}Most confusing park layout award -STR_2830 :{WINDOW_COLOUR_2}Best gentle ride award -STR_2831 :{TOPAZ}Your park has received an award for being 'The most untidy park in the country'! -STR_2832 :{TOPAZ}Your park has received an award for being 'The tidiest park in the country'! -STR_2833 :{TOPAZ}Your park has received an award for being 'The park with the best roller coasters'! -STR_2834 :{TOPAZ}Your park has received an award for being 'The best value park in the country'! -STR_2835 :{TOPAZ}Your park has received an award for being 'The most beautiful park in the country'! -STR_2836 :{TOPAZ}Your park has received an award for being 'The worst value park in the country'! -STR_2837 :{TOPAZ}Your park has received an award for being 'The safest park in the country'! -STR_2838 :{TOPAZ}Your park has received an award for being 'The park with the best staff'! -STR_2839 :{TOPAZ}Your park has received an award for being 'The park with the best food in the country'! -STR_2840 :{TOPAZ}Your park has received an award for being 'The park with the worst food in the country'! -STR_2841 :{TOPAZ}Your park has received an award for being 'The park with the best toilet facilities in the country'! -STR_2842 :{TOPAZ}Your park has received an award for being 'The most disappointing park in the country'! -STR_2843 :{TOPAZ}Your park has received an award for being 'The park with the best water rides in the country'! -STR_2844 :{TOPAZ}Your park has received an award for being 'The park with the best custom-designed rides'! -STR_2845 :{TOPAZ}Your park has received an award for being 'The park with the most dazzling choice of colour schemes'! -STR_2846 :{TOPAZ}Your park has received an award for being 'The park with the most confusing layout'! -STR_2847 :{TOPAZ}Your park has received an award for being 'The park with the best gentle rides'! -STR_2848 :{WINDOW_COLOUR_2}No recent awards -STR_2849 :New scenario installed successfully -STR_2850 :New track design installed successfully -STR_2851 :Scenario already installed -STR_2852 :Track design already installed -STR_2853 :Forbidden by the local authority! -STR_2854 :{RED}Guests can't get to the entrance of {STRINGID} !{NEWLINE}Construct a path to the entrance -STR_2855 :{RED}{STRINGID} has no path leading from its exit !{NEWLINE}Construct a path from the ride exit +STR_2784 :Cambiar atajo de teclado +STR_2785 :{WINDOW_COLOUR_2}Presiona nueva tecla para:{NEWLINE}{OPENQUOTES}{STRINGID}{ENDQUOTES} +STR_2786 :{SMALLFONT}{BLACK}Clic en la descripción del atajo para cambiar +STR_2787 :{WINDOW_COLOUR_2}Valor del parque: {BLACK}{CURRENCY} +STR_2788 :{WINDOW_COLOUR_2}¡Felicidades!{NEWLINE}{BLACK}¡Has conseguido el objetivo con un valor de la compañía de {CURRENCY}! +STR_2789 :{WINDOW_COLOUR_2}¡No has conseguido tu objetivo! +STR_2790 :Introd. nombre en tabla de escenario +STR_2791 :Ingresar nombre +STR_2792 :Introduce nombre en la tabla de escenario: +STR_2793 :{SMALLFONT}(Completado por {STRINGID}) +STR_2794 :{WINDOW_COLOUR_2}Completado por: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} con un valor de la compañía de: {BLACK}{CURRENCY} +STR_2795 :Ordenar +STR_2796 :{SMALLFONT}{BLACK}Ordenar la lista de atracciones según el criterio seleccionedo +STR_2797 :Desplazar mapa con el ratón al borde de la pantalla +STR_2798 :{SMALLFONT}{BLACK}Selecciona si al mover el puntero del ratón al borde de la ventana, el mapa se desplazará +STR_2799 :{SMALLFONT}{BLACK}Mirar o cambiar los atajos de teclado asignados +STR_2800 :{WINDOW_COLOUR_2}Entradas: {BLACK}{COMMA32} +STR_2801 :{WINDOW_COLOUR_2}Beneficios venta entradas: {BLACK}{CURRENCY2DP} +STR_2802 :Mapa +STR_2803 :{SMALLFONT}{BLACK}Mostrar a estos visitantes marcados en el mapa +STR_2804 :{SMALLFONT}{BLACK}Mostrar estos empleados marcados en el mapa +STR_2805 :{SMALLFONT}{BLACK}Mostrar mapa del parque +STR_2806 :{RED}Los visitantes se quejan del mal estado de los senderos{NEWLINE}Comprueba donde están tus jardineros y organizalos mejor. +STR_2807 :{RED}Los visitantes se quejan de la basura en el parque{NEWLINE}Comprueba donde están tus jardineros y organizalos mejor. +STR_2808 :{RED}Los visitantes se quejan del vandalismo en el parque{NEWLINE}Comprueba donde están tus guardias y organizalos mejor. +STR_2809 :{RED}Los visitantes estan hambrientos y no encuentran donde comprar comida. +STR_2810 :{RED}Los visitantes tienen sed y no encuentran donde comprar bebidas. +STR_2811 :{RED}Los visitantes se quejan por que no pueden encontrar los baños en el parque. +STR_2812 :{RED}Los visitantes se pierden o se atascan{NEWLINE}Comprueba el diseño de tus senderos para ayudar a los visitantes. +STR_2813 :{RED}¡La entrada del parque es muy cara!{NEWLINE}Reduce el costo de la entrada o mejora el valor del parque. +STR_2814 :{WINDOW_COLOUR_2}Premio al parque más sucio del país +STR_2815 :{WINDOW_COLOUR_2}Premio al parque más limpio del país +STR_2816 :{WINDOW_COLOUR_2}Premio al parque con las mejores montañas rusas +STR_2817 :{WINDOW_COLOUR_2}Premio al parque con más valor del país +STR_2818 :{WINDOW_COLOUR_2}Premio al parque más bonito del país +STR_2819 :{WINDOW_COLOUR_2}Premio al parque con menos valor del país +STR_2820 :{WINDOW_COLOUR_2}Premio al parque más seguro del país +STR_2821 :{WINDOW_COLOUR_2}Premio al parque con los mejores empleados +STR_2822 :{WINDOW_COLOUR_2}Premio al parque con la mejor comida del país +STR_2823 :{WINDOW_COLOUR_2}Premio al parque con la peor comida del país +STR_2824 :{WINDOW_COLOUR_2}Premio al parque con los mejores aseos del país +STR_2825 :{WINDOW_COLOUR_2}Premio al parque más decepcionante del país +STR_2826 :{WINDOW_COLOUR_2}Premio al parque con las mejores atracciones de agua del país +STR_2827 :{WINDOW_COLOUR_2}Premio al parque con las mejores atracciones de vía personalizada del país +STR_2828 :{WINDOW_COLOUR_2}Premio al parque con los esquemas de colores más deslumbrantes +STR_2829 :{WINDOW_COLOUR_2}Premio al parque con la disposición más confusa +STR_2830 :{WINDOW_COLOUR_2}Premio al parque con las mejores atracciones suaves +STR_2831 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque más sucio del país'! +STR_2832 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque más limpio del país'! +STR_2833 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con las mejores montañas rusas'! +STR_2834 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con más valor del país'! +STR_2835 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque más bonito del país'! +STR_2836 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con menos valor del país'! +STR_2837 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque más seguro del país'! +STR_2838 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con los mejores empleados'! +STR_2839 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con la mejor comida del país'! +STR_2840 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con la peor comida del país'! +STR_2841 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con los mejores aseos del país'! +STR_2842 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque más decepcionante del país'! +STR_2843 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con las mejores atracciones de agua del país'! +STR_2844 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con las mejores atracciones de vía personalizada del país'! +STR_2845 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con los esquemas de colores más deslumbrantes'! +STR_2846 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con la disposición más confusa'! +STR_2847 :{TOPAZ}¡Tu parque ha recibido el premio a 'El parque con las mejores atracciones suaves'! +STR_2848 :{WINDOW_COLOUR_2}Sin premios recientes +STR_2849 :Nuevo escenario instalado exitosamente +STR_2850 :Nueva vía instalada exitosamente +STR_2851 :Escenario ya instalado +STR_2852 :Vía ya instalada +STR_2853 :¡Prohibido por las autoridades locales! +STR_2854 :{RED}¡Los visitantes no encuentran la entrada de {STRINGID}!{NEWLINE}Construye un sendero hacia la entrada +STR_2855 :{RED}¡{STRINGID} no tiene un camino de salida!{NEWLINE}Construye un camino desde la salida de la atracción. STR_2856 :{WINDOW_COLOUR_2}Tutorial -STR_2857 :{WINDOW_COLOUR_2}(Press a key or mouse button to take control) -STR_2858 :Can't start marketing campaign... -STR_2859 :Another instance of OpenRCT is already running -STR_2860 :Infogrames Interactive credits... -STR_2861 :{WINDOW_COLOUR_2}Licensed to Infogrames Interactive Inc. -STR_2862 :Music acknowledgements... -STR_2863 :Music acknowledgements -STR_2864 :{WINDOW_COLOUR_2}March - Children of the Regiment: (Fucik) non copyright +STR_2857 :{WINDOW_COLOUR_2}(Presiona una tecla o da clic para tomar el control) +STR_2858 :No puedes iniciar una campaña publicitaria... +STR_2859 :Otra instancia de OpenRCT ya está en ejecución +STR_2860 :Créditos de Infogrames Interactive... +STR_2861 :{WINDOW_COLOUR_2}Bajo licencia a Infogrames Interactive Inc. +STR_2862 :Agradecimientos musicales... +STR_2863 :Agradecimientos musicales +STR_2864 :{WINDOW_COLOUR_2}Marcha - Children of the Regiment: (Fucik) sin copyright STR_2865 :{WINDOW_COLOUR_2}Heyken's Serenade: (J.Heyken) British Standard Music Coy; GEMA, BRITICO -STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Composer unknown) Copyright Control -STR_2867 :{WINDOW_COLOUR_2}Wedding Journey: (Traditional) -STR_2868 :{WINDOW_COLOUR_2}Tales from the Vienna Woods: (Johann Strauss) non copyright -STR_2869 :{WINDOW_COLOUR_2}Slavonic Dance: (Traditional) -STR_2870 :{WINDOW_COLOUR_2}Das Alpenhorn: (Traditional) -STR_2871 :{WINDOW_COLOUR_2}The Blond Sailor: (Traditional) -STR_2872 :{WINDOW_COLOUR_2}Overture - Poet and Peasant: (Suppe) non copyright -STR_2873 :{WINDOW_COLOUR_2}Waltz Medley: (Johann Strauss) non copyright -STR_2874 :{WINDOW_COLOUR_2}Bella Bella Bimba: (Traditional) -STR_2875 :{WINDOW_COLOUR_2}Original recordings (P) 1976 C.J.Mears Organization, used with consent -STR_2876 :{WINDOW_COLOUR_2}RollerCoaster Tycoon 2 Title Music: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer +STR_2866 :{WINDOW_COLOUR_2}In Continental Mood: (Compositor desconocido) Copyright Control +STR_2867 :{WINDOW_COLOUR_2}Viaje de bodas: (Tradicional) +STR_2868 :{WINDOW_COLOUR_2}Cuentos de los bosques de Viena: (Johann Strauss) sin copyright +STR_2869 :{WINDOW_COLOUR_2}Danza Slava: (Tradicional) +STR_2870 :{WINDOW_COLOUR_2}Das Alpenhorn: (Tradicional) +STR_2871 :{WINDOW_COLOUR_2}The Blond Sailor: (Tradicional) +STR_2872 :{WINDOW_COLOUR_2}Overture - Poet and Peasant: (Suppe) sin copyright +STR_2873 :{WINDOW_COLOUR_2}Waltz Medley: (Johann Strauss) sin copyright +STR_2874 :{WINDOW_COLOUR_2}Bella Bella Bimba: (Tradicional) +STR_2875 :{WINDOW_COLOUR_2}Grabaciones originales (P) 1976 C.J.Mears Organization, usados con permisos +STR_2876 :{WINDOW_COLOUR_2}RollerCoaster Tycoon 2 Música Principal: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2877 :{WINDOW_COLOUR_2}Dodgems Beat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2878 :{WINDOW_COLOUR_2}Mid Summer's Heat: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2879 :{WINDOW_COLOUR_2}Pharaoh's Tomb: (Allister Brimble) copyright {COPYRIGHT} Chris Sawyer @@ -2916,27 +2916,27 @@ STR_2906 :{WINDOW_COLOUR_2}Sweat Dreams: (Allister Brimble) copyright {COPY STR_2907 :{WINDOW_COLOUR_2}What shall we do with the Drunken Sailor: (Anon/Allister Brimble) copyright {COPYRIGHT} Chris Sawyer STR_2908 :{WINDOW_COLOUR_2}Infogrames Interactive STR_2909 :{WINDOW_COLOUR_2}Senior Producer: Thomas J. Zahorik -STR_2910 :{WINDOW_COLOUR_2}Executive Producer: Bill Levay -STR_2911 :{WINDOW_COLOUR_2}Senior Marketing Product Manager: Scott Triola -STR_2912 :{WINDOW_COLOUR_2}V.P. of Product Development: Scott Walker -STR_2913 :{WINDOW_COLOUR_2}General Manager: John Hurlbut -STR_2914 :{WINDOW_COLOUR_2}Director of Quality Assurance: Michael Craighead -STR_2915 :{WINDOW_COLOUR_2}Q.A. Certification Manager: Kurt Boutin -STR_2916 :{WINDOW_COLOUR_2}Q.A. Certification Lead: Mark Huggins -STR_2917 :{WINDOW_COLOUR_2}Testers: Dena Irene Fitzgerald, Scott Rollins, Christopher McPhail +STR_2910 :{WINDOW_COLOUR_2}Productor Ejecutivo: Bill Levay +STR_2911 :{WINDOW_COLOUR_2}Director Jefe de Productos y Marketíng: Scott Triola +STR_2912 :{WINDOW_COLOUR_2}V.P. of Desarrollo de Prodcuto: Scott Walker +STR_2913 :{WINDOW_COLOUR_2}Manager General: John Hurlbut +STR_2914 :{WINDOW_COLOUR_2}Director de Calidad: Michael Craighead +STR_2915 :{WINDOW_COLOUR_2}Q.A. Manager de Certificación: Kurt Boutin +STR_2916 :{WINDOW_COLOUR_2}Q.A. Líder de Certificación: Mark Huggins +STR_2917 :{WINDOW_COLOUR_2}Equipo de Pruebas: Dena Irene Fitzgerald, Scott Rollins, Christopher McPhail STR_2918 :{WINDOW_COLOUR_2}Clif McClure, Erik Maramaldi, Erik Jeffery -STR_2919 :{WINDOW_COLOUR_2}Director of Marketing: Ann Marie Bland -STR_2920 :{WINDOW_COLOUR_2}Manager of Creative Services: Steve Martin -STR_2921 :{WINDOW_COLOUR_2}Manager of Editorial & Documentation Services: Elizabeth Mackney -STR_2922 :{WINDOW_COLOUR_2}Graphic Designer: Paul Anselmi +STR_2919 :{WINDOW_COLOUR_2}Director de Marketíng: Ann Marie Bland +STR_2920 :{WINDOW_COLOUR_2}Manager de Servicios Creativos: Steve Martin +STR_2921 :{WINDOW_COLOUR_2}Manager de Servicios Editoriales y Documentación: Elizabeth Mackney +STR_2922 :{WINDOW_COLOUR_2}Diseño Gráfico: Paul Anselmi STR_2923 :{WINDOW_COLOUR_2}Copywriter: Kurt Carlson -STR_2924 :{WINDOW_COLOUR_2}Special Thanks to: Peter Matiss -STR_2925 :{WINDOW_COLOUR_2}Engineering Specialist: Ken Edwards -STR_2926 :{WINDOW_COLOUR_2}Engineering Services Manager: Luis Rivas -STR_2927 :{WINDOW_COLOUR_2}Lead Compatibility Analyst: Geoffrey Smith -STR_2928 :{WINDOW_COLOUR_2}Compatibility Analysts: Jason Cordero, Burke McQuinn, Kim Jardin -STR_2929 :{WINDOW_COLOUR_2}Lead Tester: Daniel Frisoli -STR_2930 :{WINDOW_COLOUR_2}Senior Tester: Matt Pantaleoni +STR_2924 :{WINDOW_COLOUR_2}Agradecimientos especiales a: Peter Matiss +STR_2925 :{WINDOW_COLOUR_2}Especialista Ingeniería: Ken Edwards +STR_2926 :{WINDOW_COLOUR_2}Manager Servicio Ingeniería: Luis Rivas +STR_2927 :{WINDOW_COLOUR_2}Analista Jefe de Compatibilidad: Geoffrey Smith +STR_2928 :{WINDOW_COLOUR_2}Analistas de Compatibilidad: Jason Cordero, Burke McQuinn, Kim Jardin +STR_2929 :{WINDOW_COLOUR_2}Jefe de Pruebas: Daniel Frisoli +STR_2930 :{WINDOW_COLOUR_2}Director de Pruebas: Matt Pantaleoni STR_2931 :{WINDOW_COLOUR_2} STR_2932 :{WINDOW_COLOUR_2} STR_2933 :{WINDOW_COLOUR_2} @@ -2977,31 +2977,31 @@ STR_2967 : STR_2968 : STR_2969 : STR_2970 : -STR_2971 :Main colour scheme -STR_2972 :Alternative colour scheme 1 -STR_2973 :Alternative colour scheme 2 -STR_2974 :Alternative colour scheme 3 -STR_2975 :{SMALLFONT}{BLACK}Select which colour scheme to change, or paint ride with -STR_2976 :{SMALLFONT}{BLACK}Paint an individual area of this ride using the selected colour scheme -STR_2977 :Staff member name -STR_2978 :Enter new name for this member of staff: -STR_2979 :Can't name staff member... -STR_2980 :Too many banners in game -STR_2981 :{RED}No entry - - -STR_2982 :Banner text -STR_2983 :Enter new text for this banner: -STR_2984 :Can't set new text for banner... -STR_2985 :Banner -STR_2986 :{SMALLFONT}{BLACK}Change text on banner -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_2992 :Sign text -STR_2993 :Enter new text for this sign: -STR_2994 :{SMALLFONT}{BLACK}Change text on sign -STR_2995 :{SMALLFONT}{BLACK}Demolish this sign +STR_2971 :Esquema de color principal +STR_2972 :Esquema de color alternativo 1 +STR_2973 :Esquema de color alternativo 2 +STR_2974 :Esquema de color alternativo 3 +STR_2975 :{SMALLFONT}{BLACK}Selecciona el esquema de color a cambiar, o pinta la atracción con él +STR_2976 :{SMALLFONT}{BLACK}Pintar sólo un área de la atracción utilizando el esquema de color seleccionado +STR_2977 :Nombrar personal +STR_2978 :Escribe un nombre para este miembro +STR_2979 :No se puede nombrar este miembro del personal... +STR_2980 :Demasiadas banderas en juego +STR_2981 :{RED}No pasar - - +STR_2982 :Texto del letrero +STR_2983 :Introduce nuevo texto para este letrero: +STR_2984 :No se puede establecer texto para el letrero... +STR_2985 :Letrero +STR_2986 :{SMALLFONT}{BLACK}Cambiar texto del letrero +STR_2987 :{SMALLFONT}{BLACK}Configura este letrero como 'No pasar' +STR_2988 :{SMALLFONT}{BLACK}Demoler este letrero +STR_2989 :{SMALLFONT}{BLACK}Seleccionar color principal +STR_2990 :{SMALLFONT}{BLACK}Selecciona color del texto +STR_2991 :Letrero +STR_2992 :Texto Letrero +STR_2993 :Escribe un nuevo texto: +STR_2994 :{SMALLFONT}{BLACK}Cambiar texto de la señal +STR_2995 :{SMALLFONT}{BLACK}Demoler señal STR_2996 :{BLACK}ABC STR_2997 :{GREY}ABC STR_2998 :{WHITE}ABC @@ -3016,387 +3016,387 @@ STR_3006 :{PALEGOLD}ABC STR_3007 :{LIGHTPINK}ABC STR_3008 :{PEARLAQUA}ABC STR_3009 :{PALESILVER}ABC -STR_3010 :Unable to load file... -STR_3011 :File contains invalid data -STR_3012 :Dodgems beat style +STR_3010 :No se pudo cargar el archivo... +STR_3011 :El archivo contiene datos no válidos +STR_3012 :Estilo coches de choque STR_3013 :Fairground organ style -STR_3014 :Roman fanfare style -STR_3015 :Oriental style -STR_3016 :Martian style -STR_3017 :Jungle drums style -STR_3018 :Egyptian style -STR_3019 :Toyland style +STR_3014 :Estilo fanfarria romana +STR_3015 :Estilo oriental +STR_3016 :Estilo marciano +STR_3017 :Estilo tambores jungla +STR_3018 :Estilo egipcio +STR_3019 :Estilo juguete STR_3020 : -STR_3021 :Space style -STR_3022 :Horror style -STR_3023 :Techno style -STR_3024 :Gentle style -STR_3025 :Summer style -STR_3026 :Water style -STR_3027 :Wild west style -STR_3028 :Jurassic style -STR_3029 :Rock style -STR_3030 :Ragtime style -STR_3031 :Fantasy style -STR_3032 :Rock style 2 -STR_3033 :Ice style -STR_3034 :Snow style -STR_3035 :Custom music 1 -STR_3036 :Custom music 2 -STR_3037 :Medieval style -STR_3038 :Urban style -STR_3039 :Organ style -STR_3040 :Mechanical style -STR_3041 :Modern style -STR_3042 :Pirates style -STR_3043 :Rock style 3 -STR_3044 :Candy style -STR_3045 :{SMALLFONT}{BLACK}Select style of music to play -STR_3046 :This ride cannot be modified -STR_3047 :Local authority forbids demolition or modifications to this ride -STR_3048 :Marketing campaigns forbidden by local authority -STR_3049 :Golf hole A -STR_3050 :Golf hole B -STR_3051 :Golf hole C -STR_3052 :Golf hole D -STR_3053 :Golf hole E -STR_3054 :Loading... -STR_3055 :White -STR_3056 :Translucent -STR_3057 :{WINDOW_COLOUR_2}Construction Marker: -STR_3058 :Brick walls -STR_3059 :Hedges -STR_3060 :Ice blocks -STR_3061 :Wooden fences -STR_3062 :{SMALLFONT}{BLACK}Standard roller coaster track -STR_3063 :{SMALLFONT}{BLACK}Water channel (track submerged) -STR_3064 :Beginner Parks -STR_3065 :Challenging Parks -STR_3066 :Expert Parks -STR_3067 :{OPENQUOTES}Real{ENDQUOTES} Parks -STR_3068 :Other Parks -STR_3069 :Top Section -STR_3070 :Slope to Level -STR_3071 :{WINDOW_COLOUR_2}Same price throughout park -STR_3072 :{SMALLFONT}{BLACK}Select whether this price is used throughout the entire park -STR_3073 :{RED}WARNING: Your park rating has dropped below 700 !{NEWLINE}If you haven't raised the park rating in 4 weeks, your park will be closed down -STR_3074 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have 3 weeks to raise the park rating -STR_3075 :{RED}WARNING: Your park rating is still below 700 !{NEWLINE}You have only 2 weeks to raise the park rating, or your park will be closed down -STR_3076 :{RED}FINAL WARNING: Your park rating is still below 700 !{NEWLINE}In just 7 days your park will be closed down unless you can raise the rating -STR_3077 :{RED}CLOSURE NOTICE: Your park has been closed down ! -STR_3078 :Plain entrance -STR_3079 :Wooden entrance -STR_3080 :Canvas tent entrance -STR_3081 :Castle entrance (grey) -STR_3082 :Castle entrance (brown) -STR_3083 :Jungle entrance -STR_3084 :Log cabin entrance -STR_3085 :Classical/Roman entrance -STR_3086 :Abstract entrance -STR_3087 :Snow/Ice entrance -STR_3088 :Pagoda entrance -STR_3089 :Space entrance -STR_3090 :{SMALLFONT}{BLACK}Select style of entrance, exit, and station -STR_3091 :You are not allowed to remove this section! -STR_3092 :You are not allowed to move or modify the station for this ride! -STR_3093 :{WINDOW_COLOUR_2}Favourite: {BLACK}{STRINGID} -STR_3094 :N/A -STR_3095 :{WINDOW_COLOUR_2}Lift hill chain speed: +STR_3021 :Estilo espacio +STR_3022 :Estilo horror +STR_3023 :Estilo tecno +STR_3024 :Estilo suave +STR_3025 :Estilo verano +STR_3026 :Estilo acuático +STR_3027 :Estilo salvaje oeste +STR_3028 :Estilo jurásico +STR_3029 :Estilo rock +STR_3030 :Estilo ragtime +STR_3031 :Estilo fantasía +STR_3032 :Estilo rock 2 +STR_3033 :Estilo hielo +STR_3034 :Estilo nieve +STR_3035 :Música personalizada 1 +STR_3036 :Música personalizada 2 +STR_3037 :Estilo medieval +STR_3038 :Estilo urbano +STR_3039 :Estilo órgano +STR_3040 :Estilo mecánico +STR_3041 :Estilo moderno +STR_3042 :Estilo pirata +STR_3043 :Estilo rock 3 +STR_3044 :Estilo caramelo +STR_3045 :{SMALLFONT}{BLACK}Selecciona el estilo de música a reproducir +STR_3046 :Esta atracción no se puede modificar +STR_3047 :La autoridad local no permite demoler o modificar esta atracción +STR_3048 :Campañas de marketing prohibidas por la autoridad local +STR_3049 :Golf agujero A +STR_3050 :Golf agujero B +STR_3051 :Golf agujero C +STR_3052 :Golf agujero D +STR_3053 :Golf agujero E +STR_3054 :Cargando... +STR_3055 :Blanca +STR_3056 :Translúcida +STR_3057 :{WINDOW_COLOUR_2}Marca de construcción: +STR_3058 :Paredes de ladrillo +STR_3059 :Arbusto +STR_3060 :Bloque de hielo +STR_3061 :Cerca de madera +STR_3062 :{SMALLFONT}{BLACK}Tramo de Montaña Rusa Estándar +STR_3063 :{SMALLFONT}{BLACK}Canal de agua (tramo sumergido) +STR_3064 :Parq. para novatos +STR_3065 :Parques Retadores +STR_3066 :Parques Expertos +STR_3067 :Parques {OPENQUOTES}Reales{ENDQUOTES} +STR_3068 :Otros parques +STR_3069 :Sección Superior +STR_3070 :Cuesta a Nivel +STR_3071 :{WINDOW_COLOUR_2}Mismo precio en todo el parque +STR_3072 :{SMALLFONT}{BLACK}Selecciona si este precio es utilizado en todo el parque +STR_3073 :{RED}ADVERTENCIA: ¡La valoración del parque ha caido por debajo de 700!{NEWLINE}Si la valoración no sube en 4 semanas el parque será cerrado. +STR_3074 :{RED}ADVERTENCIA: ¡La valoración del parque ha caido por debajo de 700!{NEWLINE}Tienes 3 semanas para subir la valoración. +STR_3075 :{RED}ADVERTENCIA: ¡La valoración del parque ha caido por debajo de 700!{NEWLINE}Tienes sólo 2 semanas para subir la valoración o el parque cerrará. +STR_3076 :{RED}ADVERTENCIA FINAL: ¡La valoración del parque ha caido por debajo de 700!{NEWLINE}En 7 días tu parque estará cerrado a menos que subas la valoración. +STR_3077 :{RED}CLAUSURA: ¡Tu parque ha sido cerrado! +STR_3078 :Entrada típica +STR_3079 :Entrada de madera +STR_3080 :Entrada estilo carpa de circo +STR_3081 :Entrada estilo castillo (gris) +STR_3082 :Entrada estilo castillo (marrón) +STR_3083 :Entrada estilo jungla +STR_3084 :Entrada estilo troncos de madera +STR_3085 :Entrada estilo clásico/romano +STR_3086 :Entrada estilo abstracto +STR_3087 :Entrada estilo hielo/nieve +STR_3088 :Entrada estilo pagoda +STR_3089 :Entrada estilo espacial +STR_3090 :{SMALLFONT}{BLACK}Seleccionar estilo de la entrada, salida y estación +STR_3091 :¡No estas autorizado para remover esta sección! +STR_3092 :¡No estas autorizado para modificar la estación de esta atracción! +STR_3093 :{WINDOW_COLOUR_2}Favorita: {BLACK}{STRINGID} +STR_3094 :Ninguna +STR_3095 :{WINDOW_COLOUR_2}Veloc. cadenas elevad.: STR_3096 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{VELOCITY} STR_3097 :{SMALLFONT}{BLACK}Select lift hill chain speed -STR_3098 :Can't change lift hill speed... -STR_3099 :{SMALLFONT}{BLACK}Select colour -STR_3100 :{SMALLFONT}{BLACK}Select second colour -STR_3101 :{SMALLFONT}{BLACK}Select third colour -STR_3102 :{SMALLFONT}{BLACK}Re-paint coloured scenery on landscape -STR_3103 :Can't re-paint this... -STR_3104 :{SMALLFONT}{BLACK}List rides -STR_3105 :{SMALLFONT}{BLACK}List shops and stalls -STR_3106 :{SMALLFONT}{BLACK}List information kiosks and other guest facilities -STR_3107 :Close -STR_3108 :Test -STR_3109 :Open -STR_3110 :{WINDOW_COLOUR_2}Block Sections: {BLACK}{COMMA16} -STR_3111 :{SMALLFONT}{BLACK}Click on design to build it -STR_3112 :{SMALLFONT}{BLACK}Click on design to rename or delete it -STR_3113 :Select a different design -STR_3114 :{SMALLFONT}{BLACK}Go back to design selection window -STR_3115 :{SMALLFONT}{BLACK}Save track design -STR_3116 :{SMALLFONT}{BLACK}Save track design (Not possible until ride has been tested and statistics have been generated) -STR_3117 :{BLACK}Calling mechanic... -STR_3118 :{BLACK}{STRINGID} is heading for the ride -STR_3119 :{BLACK}{STRINGID} is fixing the ride -STR_3120 :{SMALLFONT}{BLACK}Locate nearest available mechanic, or mechanic fixing ride -STR_3121 :Unable to locate mechanic, or all nearby mechanics are busy -STR_3122 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guest -STR_3123 :{WINDOW_COLOUR_2}Favourite ride of: {BLACK}{COMMA16} guests -STR_3124 :Broken {STRINGID} -STR_3125 :{WINDOW_COLOUR_2}Excitement Factor: {BLACK}+{COMMA16}% -STR_3126 :{WINDOW_COLOUR_2}Intensity Factor: {BLACK}+{COMMA16}% -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_3098 :No puedes cambiar la velocidad de elevación... +STR_3099 :{SMALLFONT}{BLACK}Seleccionar color +STR_3100 :{SMALLFONT}{BLACK}Seleccionar segundo color +STR_3101 :{SMALLFONT}{BLACK}Seleccionar tercer color +STR_3102 :{SMALLFONT}{BLACK}Repintar decorado coloreado en el parque +STR_3103 :No puedes repintar esto... +STR_3104 :{SMALLFONT}{BLACK}Listar atracciones +STR_3105 :{SMALLFONT}{BLACK}Listar tiendas y puestos +STR_3106 :{SMALLFONT}{BLACK}Listar quioscos de información y otras instalaciones para visitantes +STR_3107 :Cerrar +STR_3108 :Probar +STR_3109 :Abrir +STR_3110 :{WINDOW_COLOUR_2}Secciones de bloque: {BLACK}{COMMA16} +STR_3111 :{SMALLFONT}{BLACK}Clic en este diseño para construirlo +STR_3112 :{SMALLFONT}{BLACK}Clic en el diseño para renombrar o quitar +STR_3113 :Seleccionar otro diseño +STR_3114 :{SMALLFONT}{BLACK}Volver a la ventana selección de diseños +STR_3115 :{SMALLFONT}{BLACK}Guardar diseño de vía +STR_3116 :{SMALLFONT}{BLACK}Guardar diseño de vía (No es posible hasta que la atracción se haya probado y se hayan generado las estadísticas) +STR_3117 :{BLACK}Llamando al mecánico... +STR_3118 :{BLACK}{STRINGID} se está dirigiendo a la atracción +STR_3119 :{BLACK}{STRINGID} está arreglando la atracción +STR_3120 :{SMALLFONT}{BLACK}Localiza el mecánico libre más cercano, o el mecánico que está arreglando la atracción +STR_3121 :No se pudo localizar a un mecánico libre +STR_3122 :{WINDOW_COLOUR_2}Atracción favorita de: {BLACK}{COMMA16} visitante +STR_3123 :{WINDOW_COLOUR_2}Atracción favorita de: {BLACK}{COMMA16} visitantes +STR_3124 :Averiado {STRINGID} +STR_3125 :{WINDOW_COLOUR_2}Factor de emoción: {BLACK}+{COMMA16}% +STR_3126 :{WINDOW_COLOUR_2}Factor de intensidad: {BLACK}+{COMMA16}% +STR_3127 :{WINDOW_COLOUR_2}Factor de náusea: {BLACK}+{COMMA16}% +STR_3128 :Guardar diseño de vía +STR_3129 :Guardar diseño de vía con decorado +STR_3130 :Guardar STR_3131 :Cancelar -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) -STR_3135 :{RED}(Vehicle design unavailable - Ride performance may be affected) -STR_3136 :Warning: This design will be built with an alternative vehicle type and may not perform as expected -STR_3137 :Select Nearby Scenery -STR_3138 :Reset Selection -STR_3139 :Cable lift unable to work in this operating mode -STR_3140 :Cable lift hill must start immediately after station -STR_3141 :Multi-circuit per ride not possible with cable lift hill -STR_3142 :{WINDOW_COLOUR_2}Capacity: {BLACK}{STRINGID} -STR_3143 :{SMALLFONT}{BLACK}Show people on map -STR_3144 :{SMALLFONT}{BLACK}Show rides and stalls on map -STR_3145 :{SMALLFONT}{BLACK}Scroll {STRINGID} left -STR_3146 :{SMALLFONT}{BLACK}Scroll {STRINGID} right -STR_3147 :{SMALLFONT}{BLACK}Scroll {STRINGID} left fast -STR_3148 :{SMALLFONT}{BLACK}Scroll {STRINGID} right fast -STR_3149 :{SMALLFONT}{BLACK}Scroll {STRINGID} left/right -STR_3150 :{SMALLFONT}{BLACK}Scroll {STRINGID} up -STR_3151 :{SMALLFONT}{BLACK}Scroll {STRINGID} down -STR_3152 :{SMALLFONT}{BLACK}Scroll {STRINGID} up fast -STR_3153 :{SMALLFONT}{BLACK}Scroll {STRINGID} down fast -STR_3154 :{SMALLFONT}{BLACK}Scroll {STRINGID} up/down +STR_3132 :{BLACK}Clic en elementos de escenario para guardar junto con el diseño de la vía ... +STR_3133 :No es posible construir esto en una pendiente +STR_3134 :{RED}(Este diseño incluye un decorado que no está disponible) +STR_3135 :{RED}(Vehículo no disponible - El rendimiento puede verse afectado) +STR_3136 :Advertencia: Este diseño se construirá con un tipo de vehículo alternativo y puede no funcionar como se espera. +STR_3137 :Selecc. Escenario Cercano +STR_3138 :Reiniciar Selecc. +STR_3139 :Cable de elevación no puede funcionar en este modo +STR_3140 :Cable de elevación debe comenzar después de la estación +STR_3141 :Multi-circuito por attracc. no es posible con un cable de elevación +STR_3142 :{WINDOW_COLOUR_2}Capacidad: {BLACK}{STRINGID} +STR_3143 :{SMALLFONT}{BLACK}Mostrar visitantes en el mapa +STR_3144 :{SMALLFONT}{BLACK}Mostrar atracciones y puestos en el mapa +STR_3145 :{SMALLFONT}{BLACK}Desplazar {STRINGID} a la izquierda +STR_3146 :{SMALLFONT}{BLACK}Desplazar {STRINGID} a la derecga +STR_3147 :{SMALLFONT}{BLACK}Desplazar {STRINGID} a la izquierda rápido +STR_3148 :{SMALLFONT}{BLACK}Desplazar {STRINGID} a la derecha rápido +STR_3149 :{SMALLFONT}{BLACK}Desplazar {STRINGID} a la izq/der +STR_3150 :{SMALLFONT}{BLACK}Desplazar {STRINGID} arriba +STR_3151 :{SMALLFONT}{BLACK}Desplazar {STRINGID} abajo +STR_3152 :{SMALLFONT}{BLACK}Desplazar {STRINGID} arriba rápido +STR_3153 :{SMALLFONT}{BLACK}Desplazar {STRINGID} abajo rápido +STR_3154 :{SMALLFONT}{BLACK}Desplazar {STRINGID} arriba/abajo STR_3155 : STR_3156 : -STR_3157 :map -STR_3158 :graph -STR_3159 :list +STR_3157 :mapa +STR_3158 :gráfica +STR_3159 :lista STR_3160 : STR_3161 : -STR_3162 :Unable to allocate enough memory -STR_3163 :Installing new data: -STR_3164 :{BLACK}{COMMA16} selected (maximum {COMMA16}) +STR_3162 :No se puede asignar memoria suficiente +STR_3163 :Instalar nuevo dato: +STR_3164 :{BLACK}{COMMA16} seleccionados (máximo {COMMA16}) STR_3165 : STR_3166 :{BLACK}(ID: -STR_3167 :{WINDOW_COLOUR_2}Includes: {BLACK}{COMMA16} objects -STR_3168 :{WINDOW_COLOUR_2}Text: {BLACK}{STRINGID} -STR_3169 :Data for the following object not found: -STR_3170 :Not enough space for graphics -STR_3171 :Too many objects of this type selected -STR_3172 :The following object must be selected first: {STRING} -STR_3173 :This object is currently in use -STR_3174 :This object is required by another object -STR_3175 :This object is always required -STR_3176 :Unable to select this object -STR_3177 :Unable to de-select this object -STR_3178 :At least one path object must be selected -STR_3179 :At least one ride vehicle/attraction object must be selected -STR_3180 :Invalid selection of objects -STR_3181 :Object Selection - {STRINGID} -STR_3182 :Park entrance type must be selected -STR_3183 :Water type must be selected -STR_3184 :Ride Vehicles/Attractions -STR_3185 :Small Scenery -STR_3186 :Large Scenery -STR_3187 :Walls/Fences -STR_3188 :Path Signs -STR_3189 :Footpaths -STR_3190 :Path Extras -STR_3191 :Scenery Groups -STR_3192 :Park Entrance -STR_3193 :Water -STR_3194 :Scenario Description -STR_3195 :Invention List -STR_3196 :{WINDOW_COLOUR_2}Research Group: {BLACK}{STRINGID} -STR_3197 :{WINDOW_COLOUR_2}Items pre-invented at start of game: -STR_3198 :{WINDOW_COLOUR_2}Items to invent during game: -STR_3199 :Random Shuffle -STR_3200 :{SMALLFONT}{BLACK}Randomly shuffle the list of items to invent during the game -STR_3201 :Object Selection -STR_3202 :Landscape Editor -STR_3203 :Invention List Set Up -STR_3204 :Options Selection -STR_3205 :Objective Selection -STR_3206 :Save Scenario -STR_3207 :Roller Coaster Designer -STR_3208 :Track Designs Manager -STR_3209 :Back to Previous Step: -STR_3210 :Forward to Next Step: -STR_3211 :{WINDOW_COLOUR_2}Map size: +STR_3167 :{WINDOW_COLOUR_2}Incluye: {BLACK}{COMMA16} objetos +STR_3168 :{WINDOW_COLOUR_2}Texto: {BLACK}{STRINGID} +STR_3169 :Datos para el sig. objeto no encontrados: +STR_3170 :No se puede asignar más espacio para gráficos +STR_3171 :Se han seleccionado ya muchos objetos de este tipo +STR_3172 :El sig. objeto debe ser selecc. primero: {STRING} +STR_3173 :Este objeto está siendo usado +STR_3174 :Este objeto es requerido por otro objeto +STR_3175 :Este objeto es requerido +STR_3176 :No se puede seleccionar este objeto +STR_3177 :No se puede des-seleccionar este objeto +STR_3178 :Al menos un sendero debe ser seleccionado +STR_3179 :Al menos una atracción debe ser seleccionada +STR_3180 :Selecc. inválida de objetos +STR_3181 :Selección de Objetos - {STRINGID} +STR_3182 :Tipo de entrada del parque debe ser seleccionada +STR_3183 :Tipo de agua debe ser seleccionada +STR_3184 :Atracciones/juegos +STR_3185 :Escenario pequeño +STR_3186 :Escenario grande +STR_3187 :Muros/Vallas +STR_3188 :Señales de Sendero +STR_3189 :Senderos +STR_3190 :Decoración Senderos +STR_3191 :Escenarios +STR_3192 :Entrada del parque +STR_3193 :Agua +STR_3194 :Descripción del escenario +STR_3195 :Lista de inventos +STR_3196 :{WINDOW_COLOUR_2}Grupo Investigación: {BLACK}{STRINGID} +STR_3197 :{WINDOW_COLOUR_2}Elementos preinventados al comienzo de la partida: +STR_3198 :{WINDOW_COLOUR_2}Elementos inventados durante la partida: +STR_3199 :Mezcla aleatoria +STR_3200 :{SMALLFONT}{BLACK}Mezclar la lista de inventos durante la partida aleatoriamente. +STR_3201 :Selección de Objetos +STR_3202 :Editor de paisajes +STR_3203 :Lista de inventos finalizada +STR_3204 :Elección de opciones +STR_3205 :Selección de objetivos +STR_3206 :Guardar Escenario +STR_3207 :Diseñador de Montañas Rusas +STR_3208 :Diseñador de Vías +STR_3209 :Regresar al paso anterior: +STR_3210 :Avanzar al siguiente paso: +STR_3211 :{WINDOW_COLOUR_2}Tamaño de Mapa: STR_3212 :{POP16}{COMMA16} x {PUSH16}{COMMA16} -STR_3213 :Can't decrease map size any further -STR_3214 :Can't increase map size any further -STR_3215 :Too close to edge of map -STR_3216 :{SMALLFONT}{BLACK}Select park-owned land etc. -STR_3217 :Land Owned -STR_3218 :Construction Rights Owned -STR_3219 :Land For Sale -STR_3220 :Construction Rights For Sale -STR_3221 :{SMALLFONT}{BLACK}Set land to be owned by the park -STR_3222 :{SMALLFONT}{BLACK}Set construction rights only to be owned by the park -STR_3223 :{SMALLFONT}{BLACK}Set land to be available to purchase by the park -STR_3224 :{SMALLFONT}{BLACK}Set construction rights to be available to purchase by the park -STR_3225 :{SMALLFONT}{BLACK}Toggle on/off building a random cluster of objects around the selected position -STR_3226 :{SMALLFONT}{BLACK}Build park entrance -STR_3227 :Too many park entrances! -STR_3228 :{SMALLFONT}{BLACK}Set starting positions for people -STR_3229 :Block Brakes cannot be used directly after station -STR_3230 :Block Brakes cannot be used directly after each other -STR_3231 :Block Brakes cannot be used directly after the top of this lift hill -STR_3232 :Options - Financial -STR_3233 :Options - Guests -STR_3234 :Options - Park -STR_3235 :{SMALLFONT}{BLACK}Show financial options -STR_3236 :{SMALLFONT}{BLACK}Show guest options -STR_3237 :{SMALLFONT}{BLACK}Show park options -STR_3238 :No Money -STR_3239 :{SMALLFONT}{BLACK}Make this park a 'no money' park with no financial restrictions -STR_3240 :{WINDOW_COLOUR_2}Initial cash: -STR_3241 :{WINDOW_COLOUR_2}Initial loan: -STR_3242 :{WINDOW_COLOUR_2}Maximum loan size: -STR_3243 :{WINDOW_COLOUR_2}Annual interest rate: -STR_3244 :Forbid marketing campaigns -STR_3245 :{SMALLFONT}{BLACK}Forbid advertising, promotional schemes, and other marketing campaigns +STR_3213 :No puedes disminuir más el tamaño del mapa +STR_3214 :No puedes aumentar más el tamaño del mapa +STR_3215 :Demasiado cerca del borde del mapa +STR_3216 :{SMALLFONT}{BLACK}Selecciona el terreno propiedad del parque, etc. +STR_3217 :Terreno propio +STR_3218 :Derechos constr. propios +STR_3219 :Terreno a la venta +STR_3220 :Derechos constr. en venta +STR_3221 :{SMALLFONT}{BLACK}Establece las tierras propiedad del parque. +STR_3222 :{SMALLFONT}{BLACK}Establece Derechos de Construcción del parque. +STR_3223 :{SMALLFONT}{BLACK}Establece el terreno que esté disponibles para la compra del parque. +STR_3224 :{SMALLFONT}{BLACK}Establecer los derechos de construcción que estén disponibles para la compra del parque +STR_3225 :{SMALLFONT}{BLACK}Activa/Desactiva colocar grupos de objetos en torno a la posición seleccionada +STR_3226 :{SMALLFONT}{BLACK}Construir entrada del parque +STR_3227 :¡Muchas entradas del parque! +STR_3228 :{SMALLFONT}{BLACK}Establecer posición inicial de las personas +STR_3229 :El bloque de frenado no debe ser usado después de la estación. +STR_3230 :El bloque de frenado no debe ser usado después de otro. +STR_3231 :El bloque de frenado no debe ser usado después del final de la cadena de elevación. +STR_3232 :Opciones - Finanzas +STR_3233 :Opciones - Visitantes +STR_3234 :Opciones - Parque +STR_3235 :{SMALLFONT}{BLACK}Opciones de finanzas +STR_3236 :{SMALLFONT}{BLACK}Opciones de visitantes +STR_3237 :{SMALLFONT}{BLACK}Opciones del parque +STR_3238 :Sin dinero +STR_3239 :{SMALLFONT}{BLACK}Elimina las restricciones financieras de este parque +STR_3240 :{WINDOW_COLOUR_2}Efectivo inicial: +STR_3241 :{WINDOW_COLOUR_2}Préstamo inicial: +STR_3242 :{WINDOW_COLOUR_2}Maximo préstamo: +STR_3243 :{WINDOW_COLOUR_2}Interés anual: +STR_3244 :Prohibir campañas de márketing +STR_3245 :{SMALLFONT}{BLACK}Prohibir anuncios, promociones y otras campañas de márketing STR_3246 :{WINDOW_COLOUR_2}{CURRENCY} STR_3247 :{WINDOW_COLOUR_2}{COMMA16}% -STR_3248 :Can't increase initial cash any further! -STR_3249 :Can't reduce initial cash any further! -STR_3250 :Can't increase initial loan any further! -STR_3251 :Can't reduce initial loan any further! -STR_3252 :Can't increase maximum loan size any further! -STR_3253 :Can't reduce maximum loan size any further! -STR_3254 :Can't increase interest rate any further! -STR_3255 :Can't reduce interest rate any further! -STR_3256 :Visitantes prefer less intense rides -STR_3257 :{SMALLFONT}{BLACK}Select whether guests should generally prefer less intense rides only -STR_3258 :Visitantes prefer more intense rides -STR_3259 :{SMALLFONT}{BLACK}Select whether guests should generally prefer more intense rides only -STR_3260 :{WINDOW_COLOUR_2}Cash per guest (average): -STR_3261 :{WINDOW_COLOUR_2}Guests initial happiness: -STR_3262 :{WINDOW_COLOUR_2}Guests initial hunger: -STR_3263 :{WINDOW_COLOUR_2}Guests initial thirst: -STR_3264 :Can't increase this any further! -STR_3265 :Can't reduce this any further! -STR_3266 :{SMALLFONT}{BLACK}Select how this park charges for entrance and rides -STR_3267 :Forbid tree removal -STR_3268 :{SMALLFONT}{BLACK}Forbid tall trees being removed -STR_3269 :Forbid landscape changes -STR_3270 :{SMALLFONT}{BLACK}Forbid any changes to the landscape -STR_3271 :Forbid high construction -STR_3272 :{SMALLFONT}{BLACK}Forbid any tall construction -STR_3273 :Park rating higher difficult level -STR_3274 :{SMALLFONT}{BLACK}Make the park rating value more challenging -STR_3275 :Visitante generation higher difficult level -STR_3276 :{SMALLFONT}{BLACK}Make it more difficult to attract guests to the park -STR_3277 :{WINDOW_COLOUR_2}Cost to buy land: -STR_3278 :{WINDOW_COLOUR_2}Cost to buy construction rights: -STR_3279 :Free park entry / Pay per ride -STR_3280 :Pay to enter park / Free rides -STR_3281 :{WINDOW_COLOUR_2}Entry price: -STR_3282 :{SMALLFONT}{BLACK}Select objective and park name -STR_3283 :{SMALLFONT}{BLACK}Select rides to be preserved -STR_3284 :Objective Selection -STR_3285 :Preserved Rides -STR_3286 :{SMALLFONT}{BLACK}Select objective for this scenario -STR_3287 :{WINDOW_COLOUR_2}Objective: -STR_3288 :{SMALLFONT}{BLACK}Select climate -STR_3289 :{WINDOW_COLOUR_2}Climate: -STR_3290 :Cool and wet -STR_3291 :Warm -STR_3292 :Hot and dry -STR_3293 :Cold -STR_3294 :Change... -STR_3295 :{SMALLFONT}{BLACK}Change name of park -STR_3296 :{SMALLFONT}{BLACK}Change name of scenario -STR_3297 :{SMALLFONT}{BLACK}Change detail notes about park / scenario -STR_3298 :{WINDOW_COLOUR_2}Park Name: {BLACK}{STRINGID} -STR_3299 :{WINDOW_COLOUR_2}Park/Scenario Details: -STR_3300 :{WINDOW_COLOUR_2}Scenario Name: {BLACK}{STRINGID} -STR_3301 :{WINDOW_COLOUR_2}Objective Date: +STR_3248 :¡No se puede incrementar más el dinero inicial! +STR_3249 :¡No se puede reducir más el dinero inicial! +STR_3250 :¡No se puede incrementar más el préstamo inicial! +STR_3251 :¡No se puede reducir más el préstamo inicial! +STR_3252 :¡No se puede incrementar más el préstamo máximo! +STR_3253 :¡No se puede reducir más el préstamo máximo! +STR_3254 :¡No se puede incrementar más la tasa de interés! +STR_3255 :¡No se puede reducir más la tasa de interés! +STR_3256 :Visitantes prefieren atracciones tranquilas +STR_3257 :{SMALLFONT}{BLACK}Los visitantes prefieren atracciones de baja intensidad normalmente +STR_3258 :Visitantes prefieren atracciones intensas +STR_3259 :{SMALLFONT}{BLACK}Los visitantes prefieren atracciones de alta intensidad normalmente +STR_3260 :{WINDOW_COLOUR_2}Efectivo por visitante (media): +STR_3261 :{WINDOW_COLOUR_2}Felicidad inicial de visitantes: +STR_3262 :{WINDOW_COLOUR_2}Hambre inicial de visitantes: +STR_3263 :{WINDOW_COLOUR_2}Sed inicial de visitantes: +STR_3264 :¡No se puede aumentar más! +STR_3265 :¡No se puede reducir más! +STR_3266 :{SMALLFONT}{BLACK}Selecciona cómo se gastan los visitantes el dinero en este parque +STR_3267 :Prohibir talar árboles +STR_3268 :{SMALLFONT}{BLACK}Prohibir la tala de lo árboles altos +STR_3269 :Prohibir cambios en el terreno +STR_3270 :{SMALLFONT}{BLACK}Prohíbe mover tierras +STR_3271 :Prohibir construcciones altas +STR_3272 :{SMALLFONT}{BLACK}Prohíbe que se pueda construir a demasiada altura +STR_3273 :Dificultar la valoración del parque +STR_3274 :{SMALLFONT}{BLACK}Hacer que la valoración del parque crezca más lentamente +STR_3275 :Dificultar la generación de visitantes +STR_3276 :{SMALLFONT}{BLACK}Disminuye la frecuencia con la que aparecen visitantes +STR_3277 :{WINDOW_COLOUR_2}Coste de terreno: +STR_3278 :{WINDOW_COLOUR_2}Coste derechos de construcción: +STR_3279 :Entrada libre / Atracciones de pago +STR_3280 :Pagar por entrar / Atracciones gratis +STR_3281 :{WINDOW_COLOUR_2}Precio de entrada: +STR_3282 :{SMALLFONT}{BLACK}Seleccionar objetivo y nombre del parque +STR_3283 :{SMALLFONT}{BLACK}Seleccionar atracciones a preservar +STR_3284 :Elección de objetivos +STR_3285 :Atracciones preservadas +STR_3286 :{SMALLFONT}{BLACK}Seleccionar objetivos para este escenario +STR_3287 :{WINDOW_COLOUR_2}Objetivo: +STR_3288 :{SMALLFONT}{BLACK}Seleccionar clima +STR_3289 :{WINDOW_COLOUR_2}Clima: +STR_3290 :Frío y húmedo +STR_3291 :Cálido +STR_3292 :Caliente y seco +STR_3293 :Frío +STR_3294 :Cambiar... +STR_3295 :{SMALLFONT}{BLACK}Cambiar nombre del parque +STR_3296 :{SMALLFONT}{BLACK}Cambiar nombre del escenario +STR_3297 :{SMALLFONT}{BLACK}Cambiar detalles del parque/escenario +STR_3298 :{WINDOW_COLOUR_2}Nombre del Parque: {BLACK}{STRINGID} +STR_3299 :{WINDOW_COLOUR_2}Detalles del parque/escenario: +STR_3300 :{WINDOW_COLOUR_2}Nombre de escenario: {BLACK}{STRINGID} +STR_3301 :{WINDOW_COLOUR_2}Fecha de Objetivo: STR_3302 :{WINDOW_COLOUR_2}{MONTHYEAR} -STR_3303 :{WINDOW_COLOUR_2}Number of guests: -STR_3304 :{WINDOW_COLOUR_2}Park value: -STR_3305 :{WINDOW_COLOUR_2}Monthly income: -STR_3306 :{WINDOW_COLOUR_2}Monthly profit: -STR_3307 :{WINDOW_COLOUR_2}Minimum length: -STR_3308 :{WINDOW_COLOUR_2}Excitement rating: +STR_3303 :{WINDOW_COLOUR_2}Número de visitantes: +STR_3304 :{WINDOW_COLOUR_2}Valor del parque: +STR_3305 :{WINDOW_COLOUR_2}Ingreso mensual: +STR_3306 :{WINDOW_COLOUR_2}Ganancia mensual: +STR_3307 :{WINDOW_COLOUR_2}Longitud mínima: +STR_3308 :{WINDOW_COLOUR_2}Rango Satisfacción: STR_3309 :{WINDOW_COLOUR_2}{COMMA16} STR_3310 :{WINDOW_COLOUR_2}{LENGTH} STR_3311 :{WINDOW_COLOUR_2}{COMMA2DP32} -STR_3312 :{WINDOW_COLOUR_2}Rides/attractions under a preservation order: -STR_3313 :Scenario Name -STR_3314 :Enter name for scenario: -STR_3315 :Park/Scenario Details -STR_3316 :Enter description of this scenario: -STR_3317 :No details yet -STR_3318 :{SMALLFONT}{BLACK}Select which group this scenario appears in -STR_3319 :{WINDOW_COLOUR_2}Scenario Group: -STR_3320 :Unable to save scenario file... +STR_3312 :{WINDOW_COLOUR_2}Atracciones/Juegos con orden de preservación: +STR_3313 :Nombrar de escenario +STR_3314 :Escribe el nombre del escenario: +STR_3315 :Detalles Parque/Escenario +STR_3316 :Escribe la descripción de este escenario: +STR_3317 :Sin detalles todavía +STR_3318 :{SMALLFONT}{BLACK}Selecciona el grupo al que pertenece tu escenario +STR_3319 :{WINDOW_COLOUR_2}Grupo Escenario: +STR_3320 :No se pudo guardar el archivo de escenario... STR_3321 :New objects installed successfully -STR_3322 :{WINDOW_COLOUR_2}Objective: {BLACK}{STRINGID} -STR_3323 :Missing object data, ID: -STR_3324 :Requires Add-On Pack: -STR_3325 :Requires an Add-On Pack -STR_3326 :{WINDOW_COLOUR_2}(no image) -STR_3327 :Starting positions for people not set -STR_3328 :Can't advance to next editor stage... -STR_3329 :Park entrance not yet built -STR_3330 :Park must own some land -STR_3331 :Path from park entrance to map edge either not complete or too complex - Path must be single-width with as few junctions and corners as possible -STR_3332 :Park entrance is the wrong way round or has no path leading to the map edge -STR_3333 :Export plug-in objects with saved games -STR_3334 :{SMALLFONT}{BLACK}Select whether to save any additional plug-in object data required (add-in data not supplied with the main product) in saved game or scenario files, allowing them to be loaded by someone who doesn't have the additional object data -STR_3335 :Roller Coaster Designer - Select Ride Types & Vehicles -STR_3336 :Track Designs Manager - Select Ride Type +STR_3322 :{WINDOW_COLOUR_2}Objetivo: {BLACK}{STRINGID} +STR_3323 :Dat. de objeto no encontrado, ID: +STR_3324 :Requiere complemento: +STR_3325 :Requiere un complemento +STR_3326 :{WINDOW_COLOUR_2}(sin imágen) +STR_3327 :No se ha establecido la posición inicial de los visitantes +STR_3328 :No se puede avanzar a la siguiente etapa del editor... +STR_3329 :No se ha construido una entrada del parque +STR_3330 :El parque debe poseer un terreno +STR_3331 :El sendero de la entrada del parque al borde del mapa no está completo o es demasiado complejo. Ha de tener un sólo carril con el menor número posible de cruces y curvas. +STR_3332 :La entrada del parque está al revés o no tiene un camino que lleve al borde del mapa +STR_3333 :Exportar complementos al guardar el juego +STR_3334 :{SMALLFONT}{BLACK}Selecciona si los complementos adicionales (datos no distribuídos con el juego principal) utilizados en un escenario deben exportarse al guardar el juego, lo que permite que otros jugadores que no tengan esos complementos puedan abrirlo. +STR_3335 :Diseñador de Montañas Rusas - Selecciona el tipo de Atracción y Vehículo +STR_3336 :Gestor de Diseños de vías - Elige tipo de atracción STR_3337 : -STR_3338 :{BLACK}Custom-designed layout -STR_3339 :{BLACK}{COMMA16} design available, or custom-designed layout -STR_3340 :{BLACK}{COMMA16} designs available, or custom-designed layout -STR_3341 :{SMALLFONT}{BLACK}Game tools -STR_3342 :Scenario Editor -STR_3343 :Convert Saved Game to Scenario -STR_3344 :Roller Coaster Designer -STR_3345 :Track Designs Manager -STR_3346 :Can't save track design... -STR_3347 :Ride is too large, contains too many elements, or scenery is too spread out -STR_3348 :Rename +STR_3338 :{BLACK}Recorrido personalizado +STR_3339 :{BLACK}{COMMA16} diseño disponible, o recorrido personalizado +STR_3340 :{BLACK}{COMMA16} diseños disponibles, o recorrido personalizado +STR_3341 :{SMALLFONT}{BLACK}Herramientas de juego +STR_3342 :Editor de escenarios +STR_3343 :Convertir partida guardada en escenario +STR_3344 :Diseñador de Montañas Rusas +STR_3345 :Diseñador de Vías +STR_3346 :No se puede guardar el diseño de vía... +STR_3347 :Atracc. demasiada larga, contiene demasiados elementos, o el paisaje está demasiado lejos. +STR_3348 :Renombrar STR_3349 :Borrar -STR_3350 :Track design name -STR_3351 :Enter new name for this track design: -STR_3352 :Can't rename track design... -STR_3353 :New name contains invalid characters -STR_3354 :Another file exists with this name, or file is write-protected -STR_3355 :File is write-protected or locked +STR_3350 :Nombrar Diseño Vía +STR_3351 :Nuevo nombre de diseño de vía: +STR_3352 :No se puede renombrar el diseño de vía... +STR_3353 :El nuevo nombre contiene caracteres inválidos +STR_3354 :Otro archivo ya tiene este nombre o se encuentra protegido contra escritura +STR_3355 :El archivo esta bloqueado o protegido contra escritura STR_3356 :Borrar Archivo -STR_3357 :{WINDOW_COLOUR_2}Are you sure you want to permanently delete {STRINGID} ? -STR_3358 :Can't delete track design... -STR_3359 :{BLACK}No track designs of this type -STR_3360 :Warning! -STR_3361 :Too many track designs of this type - Some will not be listed. +STR_3357 :{WINDOW_COLOUR_2}¿Estás seguro de borrar permanentemente {STRINGID} ? +STR_3358 :No se puede eliminar el diseño da vía... +STR_3359 :{BLACK}Sin diseños de vías para esta atracción +STR_3360 :¡Advertencia! +STR_3361 :Demasiados diseños de vía - Algunos no se listarán. STR_3362 : STR_3363 : -STR_3364 :Advanced -STR_3365 :{SMALLFONT}{BLACK}Allow selection of individual items of scenery in addition to scenery groups -STR_3366 :{BLACK}= Ride -STR_3367 :{BLACK}= Food Stall -STR_3368 :{BLACK}= Drink Stall -STR_3369 :{BLACK}= Souvenir Stall -STR_3370 :{BLACK}= Info. Kiosk -STR_3371 :{BLACK}= First Aid -STR_3372 :{BLACK}= Cash Machine -STR_3373 :{BLACK}= Toilet -STR_3374 :Warning: Too many objects selected! -STR_3375 :Not all objects in this scenery group could be selected -STR_3376 :Install new track design... -STR_3377 :{SMALLFONT}{BLACK}Install a new track design file -STR_3378 :Install +STR_3364 :Avanzado +STR_3365 :{SMALLFONT}{BLACK}Permitir la selección de escenario además de grupos de escenarios. +STR_3366 :{BLACK}= Atracción +STR_3367 :{BLACK}= Puesto comida +STR_3368 :{BLACK}= Puesto bebida +STR_3369 :{BLACK}= Puesto souvenirs +STR_3370 :{BLACK}= Quiosco informac. +STR_3371 :{BLACK}= Primeros auxilios +STR_3372 :{BLACK}= Cajero automático +STR_3373 :{BLACK}= Servicios +STR_3374 :Advertencia: Demasiados objetos seleccionados +STR_3375 :No se seleccionaron todos los objetos de este grupo +STR_3376 :Instalar nuevo diseño de vía... +STR_3377 :{SMALLFONT}{BLACK}Instalar nuevo archivo de diseño de vía +STR_3378 :Instalar STR_3379 :Cancelar -STR_3380 :Unable to install this track design... -STR_3381 :File is not compatible or contains invalid data -STR_3382 :File copy failed -STR_3383 :Select new name for track design -STR_3384 :An existing track design already has this name - Please select a new name for this design: -STR_3385 :Beginners Tutorial -STR_3386 :Custom Rides Tutorial -STR_3387 :Roller Coaster Building Tutorial -STR_3388 :Unable to switch to selected mode -STR_3389 :Unable to select additional item of scenery... -STR_3390 :Too many items selected +STR_3380 :No se pudo instalar este diseño de vía... +STR_3381 :Archivo no compatible o contiene datos inválidos +STR_3382 :Copia de archivo fallada +STR_3383 :Selecc. nuevo nombre diseño de vía +STR_3384 :Un diseño de vía ya tiene este nombre - escoge otro nombre: +STR_3385 :Tutorial Principiantes +STR_3386 :Tutorial Atracc. Personalizada +STR_3387 :Tutorial Construcc. Roller Coaster +STR_3388 :No se puede cambiar al modo seleccionado +STR_3389 :No es posible seleccionar el elemento adicional de escenario... +STR_3390 :Demasiados elementos seleccionados # Start of tutorial strings. Not used at the moment, so not necessary to translate. STR_3391 :{SMALLFONT}{BLACK}Here is our park - Let's have a quick look around... STR_3392 :{SMALLFONT}{BLACK}Holding down the RIGHT mouse button and moving the mouse is the quickest way to move the view... @@ -3445,20 +3445,1122 @@ STR_3434 :{SMALLFONT}{BLACK}Let's test the ride and see if it works! STR_3435 :{SMALLFONT}{BLACK}Great - It worked! Let's add the footpaths and let guests onto our new roller coaster... STR_3436 :{SMALLFONT}{BLACK}While waiting for our first riders, we could customise the ride a bit... # End of tutorial strings -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_3445 :Set Patrol Area -STR_3446 :Cancelar Patrol Area +STR_3437 :{SMALLFONT}{BLACK}Demoler grandes áreas de decorado +STR_3438 :No se puede quitar este decorado... +STR_3439 :Quitar decorado +STR_3440 :Página 1 +STR_3441 :Página 2 +STR_3442 :Página 3 +STR_3443 :Página 4 +STR_3444 :Página 5 +STR_3445 :Establecer Área de Patrullaje +STR_3446 :Cancelar Área de Patrullaje -#Thousands separator +# New strings, cleaner +STR_5120 :Finanzas +STR_5121 :Investigación +STR_5122 :Selecciona atracciones por tipo (como en RCT1) +STR_5123 :Renueva atracciones +STR_5124 : +STR_5125 :Todo editable +STR_5126 :Música aleatoria +STR_5127 :{SMALLFONT}{BLACK}Pintar el terreno en lugar de cambiar la elevación mientras se arrastra. +STR_5128 :Tamaño de Selección +STR_5129 :Escribe un tamaño de selección entre {COMMA16} y {COMMA16} +STR_5130 :Tamaño de Mapa +STR_5131 :Escribe un tamaño de mapa entre {COMMA16} y {COMMA16} +STR_5132 :Arregla atracciones +STR_5133 :{SMALLFONT}{BLACK}Ajustar un area menor para los derechos de construcción. +STR_5134 :{SMALLFONT}{BLACK}Ajustar un area mayor para los derechos de construcción. +STR_5135 :{SMALLFONT}{BLACK}Comprar terreno o derechos de construcción +STR_5136 :Der. Construcc. +STR_5137 :Desbloquea límites de funcionamiento +STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} +STR_5139 :{WHITE}{STRINGID} +STR_5140 :Desactiva fallos de frenos +STR_5141 :Desactiva todas las averías +STR_5142 :Velocidad normal +STR_5143 :Velocidad ligera +STR_5144 :Velocidad rápida +STR_5145 :Velocidad turbo +STR_5146 :Hiper velocidad +STR_5147 :Trucos +STR_5148 :{SMALLFONT}{BLACK}Cambiar velocidad de juego +STR_5149 :{SMALLFONT}{BLACK}Opciones de trucos +STR_5150 :Activar herramientas de depuración STR_5151 :. -#Decimal separator STR_5152 :, +STR_5153 :Editar temas... +STR_5154 :Renderizado por hardware +STR_5155 :Permitir tests de atracciones sin finalizar +STR_5156 :{SMALLFONT}{BLACK}Permite probar la mayoría de atracciones incluso cuando aún no se han terminado de construir. No aplica a los modos de funcionamiento de secciones de bloques +STR_5157 :Desbloquear precios +STR_5158 :Salir al menú principal +STR_5159 :Salir de OpenRCT2 +STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, Año {POP16}{COMMA16} +STR_5161 :Formato de fecha: +STR_5162 :Día/Mes/Año +STR_5163 :Mes/Día/Año +STR_5164 :Nombre del Canal Twitch +STR_5165 :Nombrar visitantes como tus seguidores +STR_5166 :{SMALLFONT}{BLACK}Nombrará a los visitantes de tu parque como tus seguidores en Twitch +STR_5167 :Seguimiento de 'visitantes seguidores' +STR_5168 :{SMALLFONT}{BLACK}Activará información de seguimiento de los visitantes que sean tus seguidores en Twitch +STR_5169 :Nombrar visitantes como gente del chat de Twitch +STR_5170 :{SMALLFONT}{BLACK}Nombrará a los visitantes de tu parque como la gente que hay conectada en el chat de Twitch +STR_5171 :Seguimiento de 'visitantes del chat' +STR_5172 :{SMALLFONT}{BLACK}Activará información de seguimiento de los visitantes que sean las personadas conectadas al chat de Twitch +STR_5173 :Mostrar noticias del chat Twitch +STR_5174 :{SMALLFONT}{BLACK}Los mensajes del chat de Twitch que comiencen por "!news" se mostrarán como notificaciones en el juego +STR_5175 :Escribe el nombre de tu canal Twitch +STR_5176 :Hab. integración Twitch +STR_5177 :Modo de pantalla: +STR_5178 :{SMALLFONT}{BLACK}Mostrar trucos de dinero +STR_5179 :{SMALLFONT}{BLACK}Mostrar trucos de visitante +STR_5180 :{SMALLFONT}{BLACK}Mostrar trucos del parque +STR_5181 :{SMALLFONT}{BLACK}Mostrar trucos de atracciones +STR_5182 :{INT32} +STR_5183 :Altura de base +STR_5184 :Ingresa una altura entre {COMMA16} y {COMMA16} +STR_5185 :Nivel de agua +STR_5186 :Ingresa un nivel entre {COMMA16} y {COMMA16} +STR_5187 :Finanzas +STR_5188 :Nueva Campaña +STR_5189 :Investigación +STR_5190 :Mapa +STR_5191 :Ventana +STR_5192 :Mensajes recientes +STR_5193 :Terreno +STR_5194 :Agua +STR_5195 :Limpiar escenario +STR_5196 :Derechos de construcción +STR_5197 :Escenario +STR_5198 :Sendero +STR_5199 :Construcción de Atracción +STR_5200 :Editor de Vías +STR_5201 :Nueva atracción +STR_5202 :Selección Editor de Vías +STR_5203 :Atracciones +STR_5204 :Lista de Atraciones +STR_5205 :Visitante +STR_5206 :Lista de visitantes +STR_5207 :Empleado +STR_5208 :Lista de empleados +STR_5209 :Bandera +STR_5210 :Selección de Objetos +STR_5211 :Lista de Inventos +STR_5212 :Opciones de Escenario +STR_5213 :Opciones de Objetivos +STR_5214 :Generación de Mapa +STR_5215 :Gestor de Diseño de Vías +STR_5216 :Gestor de Listado de Diseños de Vías +STR_5217 :Trucos +STR_5218 :Temas +STR_5219 :Opciones +STR_5220 :Atajos de teclado +STR_5221 :Cambiar Atajos de teclado +STR_5222 :Cargar/Guardar +STR_5223 :Aviso Guardar +STR_5224 :Aviso Demoler Attrac. +STR_5225 :Aviso Despedir Empleado +STR_5226 :Aviso Demoler Vía +STR_5227 :Aviso sobreescribir partida +STR_5228 :{SMALLFONT}{BLACK}Interfaz Principal +STR_5229 :{SMALLFONT}{BLACK}Parque +STR_5230 :{SMALLFONT}{BLACK}Herramientas +STR_5231 :{SMALLFONT}{BLACK}Atracciones y visitantes +STR_5232 :{SMALLFONT}{BLACK}Editores +STR_5233 :{SMALLFONT}{BLACK}Misceláneos +STR_5234 :{SMALLFONT}{BLACK}Avisos +STR_5235 :{SMALLFONT}{BLACK}Configuraciones +STR_5236 :Ventana: +STR_5237 :Paleta: +STR_5238 :Tema actual: +STR_5239 :Duplicar +STR_5240 :Escribir nombre del tema +STR_5241 :No puedes cambiar este tema +STR_5242 :Nombre del tema ya existe +STR_5243 :Texto no válido +STR_5244 :Temas +STR_5245 :Barra de herramientas superior +STR_5246 :Barra de herramientas inferior +STR_5247 :Editor de Vías (barra inferior) +STR_5248 :Editor de Escenarios (barra inferior) +STR_5249 :Color de botones del menú +STR_5250 :Color del botón salir +STR_5251 :Color de botones de opciones +STR_5252 :Color selección de escenarios +STR_5253 :Información del parque +STR_5254 :Crear +STR_5255 :{SMALLFONT}{BLACK}Create a new title sequence from scratch +STR_5256 :Crea un nuevo tema para hacer cambios +STR_5257 :{SMALLFONT}{BLACK}Crear tema basado en el actual +STR_5258 :{SMALLFONT}{BLACK}Borrar tema actual +STR_5259 :{SMALLFONT}{BLACK}Renombrar tema actual +STR_5260 :Tomar captura de pantalla de escenario completo +STR_5261 :Filtro +STR_5262 :Wacky Worlds +STR_5263 :Time Twister +STR_5264 :Personalizado +STR_5265 :{SMALLFONT}{BLACK}Selecciona que contenidos son visibles +STR_5266 :{SMALLFONT}{BLACK}Gráficos +STR_5267 :{SMALLFONT}{BLACK}Idioma y unidades +STR_5268 :{SMALLFONT}{BLACK}Audio +STR_5269 :{SMALLFONT}{BLACK}Interfaz y controles +STR_5270 :{SMALLFONT}{BLACK}Otras opciones +STR_5271 :{SMALLFONT}{BLACK}Twitch +STR_5272 :{SMALLFONT}{BLACK}Decorado pequeño +STR_5273 :{SMALLFONT}{BLACK}Decorado grande +STR_5274 :{SMALLFONT}{BLACK}Senderos +STR_5275 :Buscar por objetos +STR_5276 :Escribe el nombre del objeto a buscar +STR_5277 :Borrar +STR_5278 :Modo sandbox +STR_5279 :Quitar modo sandbox +STR_5280 :{SMALLFONT}{BLACK}Permite editar el terreno en propiedad y otras opciones restringidas al Editor de Escenario +STR_5281 :{SMALLFONT}{BLACK}Características +STR_5282 :Luces abrir/cerrar de Atracc. iguales a RCT1 +STR_5283 :Luces abrir/cerrar de Parque iguales a RCT1 +STR_5284 :Selección de Fuente Escenario igual a RCT1 +STR_5285 :¡¡EXPLOTAN!!! +STR_5286 :{SMALLFONT}{BLACK}Algunos visitantes explotan +STR_5287 :La atracción ya está averiada +STR_5288 :La atracción está cerrada +STR_5289 :No hay averías disponibles para esta atracción +STR_5290 :Arreglar atracción +STR_5291 :No puedes forzar una avería +STR_5292 :{SMALLFONT}{BLACK}Forzar una avería +STR_5293 :{SMALLFONT}{BLACK}Cerrar atracción/juego +STR_5294 :{SMALLFONT}{BLACK}Probar atracción/juego +STR_5295 :{SMALLFONT}{BLACK}Abrir atracción/juego +STR_5296 :{SMALLFONT}{BLACK}Cerrar parque +STR_5297 :{SMALLFONT}{BLACK}Abrir parque +STR_5298 :{RED}{STRINGID} +STR_5299 :{LIGHTPINK}{STRINGID} +STR_5300 :{SMALLFONT}{BLACK}Despedir empleados rápidamente +STR_5301 :{MEDIUMFONT}{BLACK}Eliminar deuda con el banco +STR_5302 :Reiniciar préstamo +STR_5303 :Permite construir en pausa +STR_5304 :Sec. Menú Principal: +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 :Aleatorio +STR_5311 :{SMALLFONT}{BLACK}Herramientas de depuración +STR_5312 :Mostrar consola +STR_5313 :Mostrar inspc. Baldosa +STR_5314 :Inspector de Baldosa +STR_5315 :Césped +STR_5316 :Arena +STR_5317 :Tierra +STR_5318 :Roca +STR_5319 :Marte +STR_5320 :Ajedrez +STR_5321 :Hierba +STR_5322 :Hielo +STR_5323 :Reja (rojo) +STR_5324 :Reja (amarillo) +STR_5325 :Reja (azul) +STR_5326 :Reja (verde) +STR_5327 :Arena (oscura) +STR_5328 :Arena (clara) +STR_5329 :Ajedrez (invertido) +STR_5330 :Vista subterránea +STR_5331 :Roca +STR_5332 :Madera (roja) +STR_5333 :Madera (negra) +STR_5334 :Hielo +STR_5335 :Entrada +STR_5336 :Salida +STR_5337 :Entrada del Parque +STR_5338 :Tipo de elemento: +STR_5339 :{SMALLFONT}{BLACK}Altura de la base +STR_5340 :{SMALLFONT}{BLACK}Altura de franqueamiento +STR_5341 :Banderas +STR_5342 :Elige una baldosa del mapa +STR_5343 :Posicionar trabajadores automáticamente +STR_5344 :Cambios +STR_5345 :Trucos de dinero +STR_5346 :Trucos de visitante +STR_5347 :Trucos del parque +STR_5348 :Trucos de atracciones +STR_5349 :{SMALLFONT}{BLACK}Todas las atracciones +STR_5350 :Máx +STR_5351 :Min +STR_5352 :{BLACK}Felicidad: +STR_5353 :{BLACK}Energía: +STR_5354 :{BLACK}Hambre: +STR_5355 :{BLACK}Sed: +STR_5356 :{BLACK}Náusea: +STR_5357 :{BLACK}Tolerancia a náusea: +STR_5358 :{BLACK}Vejiga: +STR_5359 :Eliminar visitantes +STR_5360 :{SMALLFONT}{BLACK}Elimina todos los visitantes del mapa +STR_5361 :Dar a todos los visitantes: +STR_5362 :{BLACK}Todos los visitantes prefieren intensidades: +STR_5363 :Más de 1 +STR_5364 :Menos de 15 +STR_5365 :{BLACK}Velocidad empleados: +STR_5366 :Normal +STR_5367 :Rápida +STR_5368 :Reiniciar Accidentes +STR_5369 :Parámetros parque... +STR_5370 :{SMALLFONT}{BLACK}Modificar parámetros como restricciones, afluencia de visitantes y dinero. +STR_5371 :Selección de Objetos +STR_5372 :Invertir desplazamiento del clic derecho +STR_5373 :Nombre {STRINGID} +STR_5374 :Fecha {STRINGID} +STR_5375 :{UP} +STR_5376 :{DOWN} +STR_5377 :{SMALLFONT}{BLACK}Partidas a cargar +STR_5378 :{SMALLFONT}{BLACK}Instrucciones +STR_5379 :{SMALLFONT}{BLACK}Ir al siguiente comando de espera +STR_5380 :{SMALLFONT}{BLACK}Iniciar la secuencia de la pantalla del Titulo +STR_5381 :{SMALLFONT}{BLACK}Detener la secuencia de la pantalla del Titulo +STR_5382 :{SMALLFONT}{BLACK}Reiniciar secuencia del Titulo +STR_5383 :{SMALLFONT}{BLACK}Crear una secuencia del Titulo basada en la actual +STR_5384 :{SMALLFONT}{BLACK}Borrar la secuencia del Titulo actual +STR_5385 :{SMALLFONT}{BLACK}Renombrar la secuencia del Titulo actual +STR_5386 :{SMALLFONT}{BLACK}Insertar un nuevo comando +STR_5387 :{SMALLFONT}{BLACK}Editar comando seleccionado +STR_5388 :{SMALLFONT}{BLACK}Eliminar comando seleccionado +STR_5389 :{SMALLFONT}{BLACK}Ir al comando seleccionado en la ventana de Secuencias de Titulos +STR_5390 :{SMALLFONT}{BLACK}Mover comando seleccionado arriba +STR_5391 :{SMALLFONT}{BLACK}Mover comando seleccionado abajo +STR_5392 :{SMALLFONT}{BLACK}Añadir partida al secuenciador +STR_5393 :{SMALLFONT}{BLACK}Quitar la partida seleccionada del secuenciador +STR_5394 :{SMALLFONT}{BLACK}Renombrar partida seleccionada +STR_5395 :{SMALLFONT}{BLACK}Cargar partida en juego +STR_5396 :{SMALLFONT}{BLACK}Reinicia la secuencia de Titulo si se han realizado cambios fuera del juego +STR_5397 :Sólo se puede usar en la ventana principal +STR_5398 :No puedes editar la secuencia del titulo mientras se usa +STR_5399 :Presiona el botón de Parar para continuar con la edición +STR_5400 :No se puede editar esta secuencia de Titulo +STR_5401 :Crear una nueva secuencia de título para hacer cambios a +STR_5402 :Falló la carga de la secuencia de Titulo +STR_5403 :Es posible que no haya ningun comando Cargar o Esperar, o el guardado puede no ser válido +STR_5404 :El nombre ya existe +STR_5405 :Escribe un nombre para la partida +STR_5406 :Escribe un nombre para la secuencia +STR_5407 :Añadir +STR_5408 :Quitar +STR_5409 :Insertar +STR_5410 :Editar +STR_5411 :Recargar +STR_5412 :Cambiar a +STR_5413 :Cargar +STR_5414 :Cargar{MOVE_X}{87}Six Flags Magic Mountain.SC6 +STR_5415 :Cargar{MOVE_X}{87}{STRING} +STR_5416 :Cargar{MOVE_X}{87}No seleccionado +STR_5417 :Localización +STR_5418 :Localización{MOVE_X}{87}{COMMA16} {COMMA16} +STR_5419 :Rotar +STR_5420 :Rotar{MOVE_X}{87}{COMMA16} +STR_5421 :Enfocar +STR_5422 :Enfocar{MOVE_X}{87}{COMMA16} +STR_5423 :Esperar +STR_5424 :Esperar{MOVE_X}{87}{COMMA16} +STR_5425 :Reiniciar +STR_5426 :Fin +STR_5427 :Coordenadas: +STR_5428 :Rotaciones en contra del reloj: +STR_5429 :Nivel de enfoque +STR_5430 :Segundos a esperar: +STR_5431 :Partida a cargar: +STR_5432 :Comando: +STR_5433 :Secuencias del Menú Principal +STR_5434 :Añadir comando +STR_5435 :Renombrar +STR_5436 :Editar secuencias +STR_5437 :Partida no seleccionada +STR_5438 :No se pueden hacer cambios mientras el editor de comandos está abierto +STR_5439 :Un comando de espera con al menos 4 segundos es necesario con un comando de reinicio +STR_5440 :Minimizar desde pantalla completa al perder el foco +STR_5441 :{SMALLFONT}{BLACK}Identifica atracciones por el tipo de pista,{NEWLINE}para que los vehículos puedan modificarse{NEWLINE}posteriormente, como en RCT1. +STR_5442 :Forzar valoración: +STR_5443 :Velocidad{MOVE_X}{87}{STRINGID} +STR_5444 :Velocidad: +STR_5445 :Velocidad +STR_5446 :Obtener +STR_5447 :Tipo {STRINGID} +STR_5448 :Juego / Vehículo {STRINGID} +STR_5449 :Reducir velocidad del juego +STR_5450 :Aumentar velocidad del juego +STR_5451 :Abrir ventana de trucos +STR_5452 :Alternar visibilidad de herramientas +STR_5453 :Selecciona otra atracción +STR_5454 :No limitar FPS +STR_5455 :Activar modo sandbox +STR_5456 :Desactivar comprobación de gálibo +STR_5457 :Desactivar límites de altura +STR_5458 :Rotar en el sentido de las agujas del reloj +STR_5459 :Rotar en sentido contrario a las agujas del reloj +STR_5460 :Rotar vista a la izquierda +STR_5461 :Ajustar parámetros de los visitantes +STR_5462 :{CURRENCY} +STR_5463 :Meta: ¡Diviértete! +STR_5464 :General +STR_5465 :Clima +STR_5466 :Empleados +STR_5467 :ALT + +STR_5468 :Mensajes recientes +STR_5469 :Desplazar mapa arriba +STR_5470 :Desplazar mapa izq. +STR_5471 :Desplazar mapa abajo +STR_5472 :Desplazar mapa derecha +STR_5473 :Alternar día y noche +STR_5474 :Mostrar texto de letreros en mayúscula +STR_5475 :{COMMA16} semanas +STR_5476 :Hardware +STR_5477 :Renderizado de mapa +STR_5478 :Controles +STR_5479 :Barra de herramientas +STR_5480 :Muestra los siguientes botones: +STR_5481 :Apariencia +STR_5482 :{WINDOW_COLOUR_2}Tiempo desde la última inspección: {BLACK}1 minuto +STR_5483 :{BLACK}({COMMA16} semanas restantes) +STR_5484 :{BLACK}({COMMA16} semana restante) +STR_5485 :{SMALLFONT}{STRING} +STR_5486 :{BLACK}{COMMA16} +STR_5487 :{SMALLFONT}{BLACK}Mensajes recientes +STR_5488 :Entrada invisible (¡sólo OpenRCT2!) +STR_5489 :{SMALLFONT}{BLACK}Mostrar sólo los visitantes con seguimiento activado +STR_5490 :Silenciar al perder el foco +STR_5491 :Lista de inventos +STR_5492 :Opciones de escenario +STR_5493 :Enviar mensaje +STR_5494 : +STR_5495 :Lista de jugadores +STR_5496 :Jugador: +STR_5497 :Ping: +STR_5498 :Lista de servidores +STR_5499 :Nombre Jugador: +STR_5500 :Añadir servidor +STR_5501 :Iniciar servidor +STR_5502 :Multijugador +STR_5503 :Escribe el nombre del host o la IP: +STR_5504 :{SMALLFONT}{BLACK}Mostrar estado multijugador +STR_5505 :No se pudo conectar al servidor. +STR_5506 :Visitantes ignoran intensidad de atracc. +STR_5507 :Los Jardineros cortan el césped por defecto +STR_5508 :Permitir cargar ficheros dañados +STR_5509 :{SMALLFONT}{BLACK}Permite cargar ficheros cuya suma de verificación no es correcta, como partidas guardadas de versiones de demostración y ficheros dañados +STR_5510 :Dispositivo de sonido predeterminado +STR_5511 :(DESCONOCIDO) +STR_5512 :Guardar Partida como... +STR_5513 :Guardar juego de forma rápida +STR_5514 :Desactivar vandalismo +STR_5515 :{SMALLFONT}{BLACK}Impide que los visitantes enfadados cometan actos de vandalismo +STR_5516 :{SMALLFONT}{BLACK}Negro +STR_5517 :{SMALLFONT}{BLACK}Gris +STR_5518 :{SMALLFONT}{BLACK}Blanco +STR_5519 :{SMALLFONT}{BLACK}Púrpura oscuro +STR_5520 :{SMALLFONT}{BLACK}Púrpura claro +STR_5521 :{SMALLFONT}{BLACK}Púrpura brillante +STR_5522 :{SMALLFONT}{BLACK}Azul oscuro +STR_5523 :{SMALLFONT}{BLACK}Azul claro +STR_5524 :{SMALLFONT}{BLACK}Azul helado +STR_5525 :{SMALLFONT}{BLACK}Agua oscuro +STR_5526 :{SMALLFONT}{BLACK}Agua claro +STR_5527 :{SMALLFONT}{BLACK}Verde saturado +STR_5528 :{SMALLFONT}{BLACK}Verde oscuro +STR_5529 :{SMALLFONT}{BLACK}Verde musgo +STR_5530 :{SMALLFONT}{BLACK}Verde brillante +STR_5531 :{SMALLFONT}{BLACK}Verde oliva +STR_5532 :{SMALLFONT}{BLACK}Verde oliva oscuro +STR_5533 :{SMALLFONT}{BLACK}Amarillo brillante +STR_5534 :{SMALLFONT}{BLACK}Amarillo +STR_5535 :{SMALLFONT}{BLACK}Amarillo oscuro +STR_5536 :{SMALLFONT}{BLACK}Naranja claro +STR_5537 :{SMALLFONT}{BLACK}Naranja oscuro +STR_5538 :{SMALLFONT}{BLACK}Café claro +STR_5539 :{SMALLFONT}{BLACK}Café saturado +STR_5540 :{SMALLFONT}{BLACK}Café oscuro +STR_5541 :{SMALLFONT}{BLACK}Rosa salmón +STR_5542 :{SMALLFONT}{BLACK}Rojo burdeo +STR_5543 :{SMALLFONT}{BLACK}Rojo saturado +STR_5544 :{SMALLFONT}{BLACK}Rojo brillante +STR_5545 :{SMALLFONT}{BLACK}Rosa oscuro +STR_5546 :{SMALLFONT}{BLACK}Rosa brillante +STR_5547 :{SMALLFONT}{BLACK}Rosa claro +STR_5548 :Muestra los modos de funcionamiento +STR_5549 :Año/Mes/Día +STR_5550 :{POP16}{POP16}Año {COMMA16}, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} +STR_5551 :Año/Día/Mes +STR_5552 :{POP16}{POP16}Año {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} +STR_5553 :Pausar juego cuando Steam se abra +STR_5554 :{SMALLFONT}{BLACK}Activar herramienta de montaña +STR_5555 :Muestra vehículos de otros tipos de vía +STR_5556 :{SMALLFONT}{BLACK}Expulsar jugador +STR_5557 :Mantener conex. tras desincronización (Multijugador) +STR_5558 :Se debe reiniciar para aplicar los cambios +STR_5559 :Inspecciones 10m +STR_5560 :{SMALLFONT}{BLACK}Establece el tiempo de inspección a 'Cada 10 minutos' en todas las atracciones +STR_5561 :No se pudo cargar el idioma. +STR_5562 :ADVERTENCIA! +STR_5563 :Esta configuración es inestable, toma precauciones. +STR_5564 :Insertar Elemento Corrupto +STR_5565 :{SMALLFONT}{BLACK}Insertar un elemento corrupto en la parte superior de la baldosa del mapa. Esto ocultará cualquier elemento sobre este elemento corrupto. +STR_5566 :Contraseña: +STR_5567 :Mostrar en la lista de servidores +STR_5568 :Contraseña requerida +STR_5569 :Este servidor requiere contraseña +STR_5570 :Actualizar lista +STR_5571 :Unirse al juego +STR_5572 :Añadir a favoritos +STR_5573 :Quitar de favoritos +STR_5574 :Nombre del servidor: +STR_5575 :Jugadores máximos: +STR_5576 :Puerto: +STR_5577 :Won surcoreano (W) +STR_5578 :Rublo ruso (R) +STR_5579 :Factor escala ventana: +STR_5580 :Corona checa (Kc) +STR_5581 :Mostrar FPS +STR_5582 :Mantener puntero del ratón en ventana +STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} +STR_5584 :SI +STR_5585 :{SMALLFONT}{BLACK}Desbloquea los límites operativos de funcionamiento, permitiendo cosas como cadenas elevadoras a {VELOCITY} +STR_5586 :Abrir automáticamente tiendas y puestos +STR_5587 :{SMALLFONT}{BLACK}Si se activa las tiendas y puestos abrirán automáticamente al colocarse. +STR_5588 :{SMALLFONT}{BLACK}Jugar con otros jugadores +STR_5589 :Configuración de notificaciones +STR_5590 :Premios al parque +STR_5591 :Campañas de márketing finalizadas +STR_5592 :Advertencias sobre el parque +STR_5593 :Advertencias sobre la valoración del parque +STR_5594 :Atracción se ha averiado +STR_5595 :Atracción se ha destruído +STR_5596 :Advertencias sobre las atracciones +STR_5597 :Atracción y decorado desarrollado +STR_5598 :Advertencias sobre los visitantes +STR_5599 :Visitante se ha perdido +STR_5600 :Visitante ha abandonado el parque +STR_5601 :Visitante se ha puesto en la cola de una atracción +STR_5602 :Visitante se ha subido a una atracción +STR_5603 :Visitante se ha bajado de la atracción +STR_5604 :Visitante ha comprado algo +STR_5605 :Visitante ha usado una instalación +STR_5606 :Visitante ha muerto +STR_5607 :{SMALLFONT}{BLACK}Eliminar forzadamente el elemento del mapa seleccionado. +STR_5608 :BH +STR_5609 :CH +STR_5610 :{SMALLFONT}{BLACK}Quitar el elemento del mapa seleccionado. Esto forza la eliminación, por lo que no se devolverá el costo de este elemento. Utiliza esto con precaución. +STR_5611 :G +STR_5612 :{SMALLFONT}{BLACK}Bandera Fantasma +STR_5613 :B +STR_5614 :{SMALLFONT}{BLACK}Bandera Roto +STR_5615 :L +STR_5616 :{SMALLFONT}{BLACK}Último elemento para bandera de baldosa. +STR_5617 :{SMALLFONT}{BLACK}Mover elementos selec. arriba. +STR_5618 :{SMALLFONT}{BLACK}Mover elementos selec. abajo. +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 :Parques {OPENQUOTES}Reales{ENDQUOTES} +STR_5626 :Otros parques +STR_5627 :Agrupar lista de escenarios: +STR_5628 :Juego original +STR_5629 :Nivel de dificultad +STR_5630 :Activa el desbloqueo de escenarios +STR_5631 :DLC de parques originales +STR_5632 :Construye tu propio... +STR_5633 :CMD + +STR_5634 :OPCIÓN + +STR_5635 :{WINDOW_COLOUR_2}Dinero gastado: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Acciones en total: {BLACK}{COMMA16} +STR_5637 :No puedes hacer esto... +STR_5638 :Permiso denegado +STR_5639 :{SMALLFONT}{BLACK}Mostrar lista de jugadores +STR_5640 :{SMALLFONT}{BLACK}Administrar grupos +STR_5641 :Grupo por defecto: +STR_5642 :Grupo: +STR_5643 :Añadir Grupo +STR_5644 :Remover Grupo +STR_5645 :Chat +STR_5646 :Ajustar terreno +STR_5647 :Alternar pausa +STR_5648 :Ajustar agua +STR_5649 :Crear atracción +STR_5650 :Demoler atracción +STR_5651 :Construir atracción +STR_5652 :Editar atracción +STR_5653 :Escenarios +STR_5654 :Senderos +STR_5655 :Gestionar invitados +STR_5656 :Gestionar empleados +STR_5657 :Prop. del parque +STR_5658 :Finanzas +STR_5659 :Expulsar jugador +STR_5660 :Editar grupos +STR_5661 :Cambiar grupos +STR_5662 :Ninguna +STR_5663 :Limpiar paisaje +STR_5664 :Usar trucos +STR_5665 :Colocación de Multiples Escenarios +STR_5701 :{WINDOW_COLOUR_2}Ultima acción: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Ir a la última acción del jugador. +STR_5703 :No puedes expulsar al anfitrión. +STR_5704 :Ultima acción: +STR_5705 :No se puede cambiar a este grupo. +STR_5706 :No se puede eliminar el grupo, hay jugadores en él. +STR_5707 :Este grupo no puede ser modificado. +STR_5708 :No se puede cambiar el grupo del anfitrión +STR_5709 :Renombrar grupo +STR_5710 :Nombrar grupo +STR_5711 :Escribe el nuevo nombre para este grupo: +STR_5712 :No puedes modificar el permiso que no tienes +STR_5713 :Expulsar jugador +STR_5714 :Opciones de ventana +STR_5715 :Nueva Partida +STR_5716 :No permitido en el modo multijugador +# For identifying client network version in server list window +STR_5717 :Versión de software: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Versión de software: {STRING} +STR_5719 :Soleado +STR_5720 :Parc. Nublado +STR_5721 :Nublado +STR_5722 :Lluvia ligera +STR_5723 :Lluvia +STR_5724 :Tormenta +STR_5725 :{BLACK}Forzar clima: +STR_5726 :{SMALLFONT}{BLACK}Establecer el clima actual en el parque +STR_5727 :Calidad de escalado +STR_5728 :Requiere Renderizado por Hardware +STR_5729 :{SMALLFONT}{BLACK}Requiere Renderizado por Hardware +STR_5730 :Próximo +STR_5731 :Lineal +STR_5732 :Anisotrópico +STR_5733 :Usar escala NN en escalas numéricas +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Renderizado +STR_5735 :Estado de la red +STR_5736 :Jugador +STR_5737 :Cerrado, {COMMA16} persona en la atracción +STR_5738 :Cerrado, {COMMA16} personas en la atracción +STR_5739 :{WINDOW_COLOUR_2}Visitantes en atracción: {BLACK}{COMMA16} +STR_5740 :Campañas Márketing nunca terminan +STR_5741 :{SMALLFONT}{BLACK}Las Campañas de Márketing nunca terminan. +STR_5742 :Autenticando ... +STR_5743 :Conectando ... +STR_5744 :Resolviendo ... +STR_5745 :Desincronización detectada +STR_5746 :Desconectado +STR_5747 :Desconectado: {STRING} +STR_5748 :Expulsado +STR_5749 :¡Sal del servidor! +STR_5750 :Conexión Cerrada +STR_5751 :Sin Datos +STR_5752 :{OUTLINE}{RED}{STRING} se ha desconectado +STR_5753 :{OUTLINE}{RED}{STRING} se ha desconectado ({STRING}) +STR_5754 :Nombre Jugador Incorrecto +STR_5755 :Ver. de Software incorrecto +STR_5756 :Contraseña Incorrecta +STR_5757 :Servidor Lleno +STR_5758 :{OUTLINE}{GREEN}{STRING} se ha unido al juego +STR_5759 :Descargando mapa ... ({INT32} / {INT32}) +STR_5760 :Dólar de Hong Kong (HK$) +STR_5761 :Nuevo dólar de Taiwán (NT$) +STR_5762 :Yuan Chino (CN{YEN}) +STR_5763 :Todos los archivos +STR_5764 :Tipo de Atracción inválido +STR_5765 :No se puede editar una atracción de un tipo no válido +STR_5766 : +STR_5767 :Ingresos +STR_5768 :Clientes totales +STR_5769 :Beneficio total +STR_5770 :Clientes por hora +STR_5771 :Coste de funcionamiento +STR_5772 :Edad +STR_5773 :Clientes totales: {COMMA32} +STR_5774 :Beneficio total: {CURRENCY2DP} +STR_5775 :Clientes: {COMMA32} per hour +STR_5776 :Construido: Este año +STR_5777 :Construido: El año pasado +STR_5778 :Construido: Hace {COMMA16} años +STR_5779 :Ingresos: {CURRENCY2DP} por hora +STR_5780 :Coste de funcionamiento: {CURRENCY2DP} por hora +STR_5781 :Coste de funcionamiento: Desconocido +STR_5782 :Ahora estas conectado. Presiona '{STRING}' para chatear. +STR_5783 :{WINDOW_COLOUR_2}Escenario bloqueado +STR_5784 :{BLACK}Completa escenarios anteriores para desbloquear este escenario. +STR_5785 :No puedes renombrar el grupo... +STR_5786 :Nombre de grupo no válido +STR_5787 :{COMMA32} jugadores en línea. +STR_5788 :Inter. Inspecc. por defecto: +STR_5789 :Desactivar relámpagos +STR_5790 :{SMALLFONT}{BLACK}Cambiar al estilo de precio como en RCT1{NEWLINE}(Con este truco tanto el precio de entrada al parque como el precio de una atracción pueden ser editados). +STR_5791 :{SMALLFONT}{BLACK}Establece la fiabilidad de las atracciones en 100% y reestablece la fecha de construcción a "este año". +STR_5792 :{SMALLFONT}{BLACK}Arregla todas las atracciones averiadas. +STR_5793 :{SMALLFONT}{BLACK}Reestablece el historial de accidentes de una atracción, por lo que los visitantes no se quejarán si no es seguro. +STR_5794 :{SMALLFONT}{BLACK}Algunos escenarios deshabilitan la edición de las atracciones que ya están en el parque. Este truco quita esta restricción. +STR_5795 :{SMALLFONT}{BLACK}Los visitantes se suben a cualquier atraccion sin importar si la intensidad es extremadamente alta. +STR_5796 :{SMALLFONT}{BLACK}Fuerza a abrir o cerrar las entradas al parque. +STR_5797 :{SMALLFONT}{BLACK}Deshabilita el cambio climático y mantiene el clima seleccionado. +STR_5798 :{SMALLFONT}{BLACK}Permite hacer acciones de construcción en el modo de pausa. +STR_5799 :{SMALLFONT}{BLACK}Deshabilita las averías y accidentes a causa de la falla de frenos. +STR_5800 :{SMALLFONT}{BLACK}Evita que las atracciones se averíen. -# Note: as this is an unmaintained language, don't add new strings unless you intend to become the mainainer. +############# +# Scenarios # +############# + +## RCT Original + +STR_SCNR :Fronteras Forestales +STR_PARK :Fronteras Forestales +STR_DTLS :Construye un próspero parque temático en una amplia zona deforestada de un espeso bosque. + + +STR_SCNR :Dunas Dinamita +STR_PARK :Dunas Dinamita +STR_DTLS :Construido en pleno desierto, este parque temático contiene únicamente una montaña rusa, pero tiene espacio para crecer. + + +STR_SCNR :Lago Frondoso +STR_PARK :Lago Frondoso +STR_DTLS :Empezando desde cero, construye un parque temático alrededor de un gran lago. + + +STR_SCNR :Cumbres Diamantinas +STR_PARK :Cumbres Diamantinas +STR_DTLS :Cumbres Diamantinas es ya un parque temático de éxito con magníficas atracciones. Desarróllalo hasta duplicar su valor. + + +STR_SCNR :Jardines Perennes +STR_PARK :Jardines Perennes +STR_DTLS :Convierte los hermosos Jardines Perennes en un próspero parque temático. + + +STR_SCNR :Playa Coqueta +STR_PARK :Playa Coqueta +STR_DTLS :Convierte el pequeño parque de atracciones de Playa Coqueta en un próspero parque temático. + + +STR_SCNR :Islas de la Trinidad +STR_PARK :Islas de la Trinidad +STR_DTLS :Varias islas forman la base de este nuevo parque. + + +STR_SCNR :Mundo de Katie +STR_PARK :Mundo de Katie +STR_DTLS :Un pequeño parque temático con unas cuantas atracciones y posibilidades de expansión. Tu objetivo será duplicar el valor del parque. + + +STR_SCNR :Parque Pequeno +STR_PARK :Parque Pequeno +STR_DTLS :Un pequeño y abarrotado parque de atracciones que necesita una gran expansión. + + +STR_SCNR :Parque Acuatico +STR_PARK :Parque Acuatico +STR_DTLS :Un parque con unas cuantas atracciones acuáticas, y que necesita expansión. + + +STR_SCNR :Minas del Milenio +STR_PARK :Minas del Milenio +STR_DTLS :Convierte una gran mina abandonada que es en la actualidad una atracción turística, en un parque temático. + + +STR_SCNR :Go-Karts & Montañas Rusas +STR_PARK :Karts & Coasters +STR_DTLS :Un gran parque oculto en el bosque, que sólo contiene pistas de Go-karts y montañas rusas de madera. + + +STR_SCNR :Mundo de Mel +STR_PARK :Mundo de Mel +STR_DTLS :Este parque temático tiene algunas atracciones modernas y bien diseñadas, pero aún hay mucho espacio libre para ampliarlo. + + +STR_SCNR :Montana Mistica +STR_PARK :Montana Mistica +STR_DTLS :Construye un parque temático a partir de cero en las boscosas colinas de la Montaña Mística. + + +STR_SCNR :Piramides Pacificas +STR_PARK :Piramides Pacificas +STR_DTLS :Convierte la atracción turística de las ruinas egipcias en un próspero parque temático. + + +STR_SCNR :Maderas Viejas +STR_PARK :Maderas Viejas +STR_DTLS :Un gran parque con atracciones bien diseñadas, pero más bien anticuadas. Sustituye las viejas atracciones o añade atracciones nuevas para hacer el parque más popular. + + +STR_SCNR :Gran Muelle +STR_PARK :Gran Muelle +STR_DTLS :Convierte el muelle de esta mortecina ciudad en una próspera atracción. + + +STR_SCNR :Picos del Rayo +STR_PARK :Picos del Rayo +STR_DTLS :Las hermosas montañas de los Picos del Rayo son muy populares entre excursionistas y turistas. Utiliza el terreno disponible para atraer a una nueva clientela en busca de atracciones de riesgo. + + +STR_SCNR :Torres de marfil +STR_PARK :Torres de marfil +STR_DTLS :Un parque bien establecido, con algunos problemas. + + +STR_SCNR :Valle del Arco Iris +STR_PARK :Valle del Arco Iris +STR_DTLS :Las autoridades del Valle del Arco Iris no te dejarán introducir cambios paisajísticos ni eliminar árboles grandes; aún así, debes convertir el área en un gran parque temático. + + +STR_SCNR :La Roca del Trueno +STR_PARK :La Roca del Trueno +STR_DTLS :La Roca del Trueno se encuentra en pleno desierto y atrae muchos turistas. Utiliza el espacio disponible para construir atracciones y captar más clientes. + + +STR_SCNR :Mega Parque +STR_PARK :Mega Parque +STR_DTLS :¡Por pasarlo bien! + +## Corkscrew Follies + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Develop the seaside cliffs into a thriving amusement 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 + + +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 + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :An old redundant bridge is yours to develop into an amusement park + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Covering land both sides of a highway, this park has several rides already operating + + +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 + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :This castle is all yours to turn into a theme park + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :This futuristic park has plenty of space for new rides on its alien landscape + + +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 + + +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 + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :A series of stepped lakes form the basis for this new park + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :This elderly park has many historical rides but is badly in debt + + +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 + + +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 + + +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 + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :A vast canyon is yours to turn into a theme 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 + + +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 + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Develop this Roman-themed park by adding rides and roller coasters + + +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 + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Build a park to appeal to the high-intensity thrill-seeking local people + + +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 + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Overgrown and dilapidated, can you resurrect this once-great amusement park? + + +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 + + +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 + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :A four lane steeplechase ride is the centerpiece of this expanding park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Turn this abandoned stone quarry into a place to attract thrill-seeking tourists + + +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 + + +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 + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :A large garden park needs turning into a thriving theme park + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :A collection of icebergs make a cold setting for this ambitious theme park + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :A dormant volcano is the setting of this coaster-building challenge + + +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 + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Your task is to build a massive coaster-filled park in amongst Razor Rocks + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :A large lake in an ancient crater is the setting for this park + + +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 + + +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 + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :This sea-side cove is the setting for this coaster-building challenge + + +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 + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :A park which has much of its footpaths and coasters underground + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :A glacier-filled valley is yours to develop into a theme park + + +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 + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Five coasters require completion in this desert park + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :This historical park is only allowed to build older-styled rides + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Develop this alien park to maximize its profit + + +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 + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :A scary park with a giant centrepiece coaster + + +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 + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :In this large park you must design and build ten large coasters + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :A long thin island makes a challenging setting to build a selection of coasters + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :An icy landscape needs turning into a thriving theme park + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :A desert park with some cleverly designed coasters is yours to expand + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :In this tiny park you must finish building the five existing coasters + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :A large park with a novel transporation system around its edge + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :This large island is all yours to develop as an amusement park + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :A giant abandoned skyscraper is a unique opportunity for a theme park developer + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :This urban area is all yours to develop into as an amusement park + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :A giant park already packed full of rides needs improving + + +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 + + +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 + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : + +###################### +# Juegos/Atracciones # +###################### + +#WW +[CONDORRD] +STR_NAME :Atracción Condor +STR_DESC :Los pasajeros viajan boca abajo y acostados, suspendidos del arnés debajo de la pista en un vagón con forma de Cóndor que se balancea libremente de un lado a otro al pasar por las curvas. +STR_CPTY :4 pasajeros por vagón + +################### +# Tiendas/Puestos # +################### + +[INFOK] +STR_NAME :Quiosco de información +STR_DESC :Puesto en el que los visitantes obtienen mapas del parque y compran paraguas. diff --git a/data/language/swedish.txt b/data/language/swedish.txt index a5ef9b4bb9..691cc9fbdb 100644 --- a/data/language/swedish.txt +++ b/data/language/swedish.txt @@ -15,20 +15,20 @@ STR_0010 :Båttur STR_0011 :Vildmus i trä STR_0012 :Hinderbana STR_0013 :Bilåktur -STR_0014 :Launched Freefall -STR_0015 :Bobsleigh Coaster +STR_0014 :Fritt Fall +STR_0015 :Bobslädesbana STR_0016 :Observationstorn STR_0017 :Loopande berg- och dalbana -STR_0018 :Dinghy Slide +STR_0018 :Jollebana STR_0019 :Gruvtåg STR_0020 :Stolslift STR_0021 :Korkskruvs berg- och dalbana STR_0022 :Labyrint -STR_0023 :Spiral Slide +STR_0023 :Spiral Rutschkana STR_0024 :Go Karts -STR_0025 :Log Flume -STR_0026 :River Rapids -STR_0027 :Dodgems +STR_0025 :Stock Forsen +STR_0026 :Forsränning +STR_0027 :Radiobilar STR_0028 :Piratskepp STR_0029 :Svängande omvänt Piratskepp STR_0030 :Matstånd @@ -47,9 +47,9 @@ STR_0042 :Top Spin STR_0043 :Rymdringar STR_0044 :Bakvänd fritt fall-bana STR_0045 :Lift -STR_0046 :Vertical Drop Roller Coaster +STR_0046 :Vertikalt Stup STR_0047 :Bankomat -STR_0048 :Twist +STR_0048 :Twister STR_0049 :Spökhuset STR_0050 :Första Hjälpen STR_0051 :Cirkusföreställning @@ -62,38 +62,38 @@ STR_0057 :Flerdimensionell berg- och dalbana STR_0058 :Okänd Åktur (38) STR_0059 :Inverterad berg- och dalbana STR_0060 :Okänd Åktur (3A) -STR_0061 :Virginia Reel -STR_0062 :Splash Boats -STR_0063 :Mini Helicopters +STR_0061 :Virginiavirveln +STR_0062 :Plaskbåtar +STR_0063 :Mini Helikoptrar STR_0064 :Liggande berg- och dalbana STR_0065 :Hängande balkbana STR_0066 :Okänd Åktur (40) -STR_0067 :Reverser Roller Coaster +STR_0067 :Vändberg- och dalbana STR_0068 :Skruvbana STR_0069 :Mini Golf -STR_0070 :Giga Coaster +STR_0070 :Giga-banan STR_0071 :Roto-Fall -STR_0072 :Flying Saucers -STR_0073 :Crooked House -STR_0074 :Monorail Cycles -STR_0075 :Compact Inverted Coaster +STR_0072 :Flygande Tefat +STR_0073 :Lustiga Huset +STR_0074 :Enspårs-cyklar +STR_0075 :Kompakt Omvänd Bana STR_0076 :Vattenbana -STR_0077 :Air Powered Vertical Coaster -STR_0078 :Inverted Hairpin Coaster -STR_0079 :Magisk matta -STR_0080 :Submarine Ride -STR_0081 :River Rafts +STR_0077 :Luftdriven Vertikal Bana +STR_0078 :Inverterad Hårnålsbana +STR_0079 :Flygande Mattan +STR_0080 :Ubåts Bana +STR_0081 :Flodflottar STR_0082 :Okänd Åktur (50) STR_0083 :Enterprise STR_0084 :Okänd Åktur (52) STR_0085 :Okänd Åktur (53) STR_0086 :Okänd Åktur (54) STR_0087 :Okänd Åktur (55) -STR_0088 :Inverted Impulse Coaster +STR_0088 :Inverterad Impulsbana STR_0089 :Mini berg- och dalbana -STR_0090 :Mine Ride +STR_0090 :Gruvattraktion STR_0091 :Okänd Åktur (59) -STR_0092 :LIM Launched Roller Coaster +STR_0092 :Induktionsberg- och dalbana STR_0093 : STR_0094 : STR_0095 : @@ -513,31 +513,31 @@ STR_0508 : STR_0509 : STR_0510 : STR_0511 : -STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops. -STR_0513 :A looping roller coaster where the riders ride in a standing position +STR_0512 :En kompakt berg- och dalbana med en spiral lyftkedja och mjuka, vridna stup. +STR_0513 :En ringlande berg- och dalbana där passagerarna åker ståendes STR_0514 :Hängande tåg under banan svingar ut åt sidan i svängar -STR_0515 :A steel roller coaster with trains that are held beneath the track, with many complex and twisting track elements +STR_0515 :En stål berg- och dalbana med tåg som hålls under spåren, med många vridna och spännande delar STR_0516 :En snäll berg- och dalbana för de som inte har mod nog att utmana större åkturer STR_0517 :Passagerare åker i miniatyrtåg på en smal tågräls STR_0518 :Passagerare åker i elektriska tåg på en balkbana STR_0519 :Passagerare åker i små vagnar som hänger under en enkelspårig bana, fritt svingande från sida till sida i svängar -STR_0520 :A dock platform where guests can drive/row personal watercraft on a body of water -STR_0521 :A fast and twisting roller coaster with tight turns and steep drops. Intensity is bound to be high. -STR_0522 :A smaller roller coaster where the riders sit above the track with no car around them +STR_0520 :En plattform där gästerna kan köra/ro vattenfartyg på vatten +STR_0521 :En snabb och tvistande berg- och dalbana med skarpa kurvor. Intensiteten kommer vara hög. +STR_0522 :En mindre berg- och dalbana där passagerarna sitter på spåret utan ett fordon runt dem STR_0523 :Passagerare åker sakta i motoriserade fordon på en spår-baserad väg -STR_0524 :Freefall car is pneumatically launched up a tall steel tower and then allowed to freefall down -STR_0525 :Riders career down a twisting track guided only by the curvature and banking of the semi-circular track -STR_0526 :Passengers travel in a rotating observation cabin which travels up a tall tower +STR_0524 :Frittfall konstruerade fordon är uppskjutna med lufttryck upp för ett högt stål torn innan den rusar ner igen i frittfallande stil +STR_0525 :Passagerarna dundrar nerför ett slingrande spår som styrs enbart av det halvcirkelformade spårets kurvatur och lutning +STR_0526 :Roterande utsiktskabin som åker upp för ett högt torn STR_0527 :En mjuk berg- och dalbana byggd av stål som kan göra vertikala loopar -STR_0528 :Riders travel in inflatable dinghies down a twisting semi-circular or completely enclosed tube track -STR_0529 :Mine train themed roller coaster trains career along steel roller coaster track made to look like old railway track +STR_0528 :Passagerarna åker i uppblåsbara jollar ner för ett skruvat halvrunt eller helt slutet rörspår +STR_0529 :Gruvtågsberg- och dalbana - tågen rusar fram längst stålskenor som ser ut som riktiga gamla järnvägsspår STR_0530 :Vagnar hänger från en stålkabel som kör kontinuerligt från ena sidan åkturen till den andra, och sedan tillbaka igen -STR_0531 :A compact steel-tracked roller coaster where the train travels through corkscrews and loops +STR_0531 :En kompakt stålberg- och dalbana där tågen åker längs korkskruvar och loopar STR_0532 : STR_0533 : -STR_0534 :Self-drive petrol-engined go karts -STR_0535 :Log-shaped boats travel along a water channel, splashing down steep slopes to soak the riders -STR_0536 :Circular boats meander along a wide water channel, splashing through waterfalls and thrilling riders through foaming rapids +STR_0534 :Kör själv- gokarts som är bensindrivna +STR_0535 :Stockformade båtar som åker längs en lång vattenkanal, plaskar ner längs branta lutningar för att blöta ner passagerarna +STR_0536 :Runda båtar snirklar sig längst en lång bred vattenkanal, plaskar genom vattenfall och för de nervösa passagerarna genom skummande forsar STR_0537 : STR_0538 : STR_0539 : @@ -556,14 +556,14 @@ STR_0551 : STR_0552 : STR_0553 : STR_0554 :Vagnen accelereras ut ur stationen på en platt bana med hjälp av linjärmotorer, sen åker den vertikalt uppåt tills gravitationen tar över och vagnen åker tillbaka till stationen -STR_0555 :Guests ride in an elevator up or down a vertical tower to get from one level to another -STR_0556 :Extra-wide cars descend completely vertical sloped track for the ultimate freefall roller coaster experience +STR_0555 :Gästerna åker en hiss vertikalt upp eller ner till olika våningar +STR_0556 :Extrabreda vagnar går ner för fullständigt lodräta spår för den ultimata frittfall-upplevelsen i berg- och dalbanan STR_0557 : STR_0558 : STR_0559 : STR_0560 : STR_0561 : -STR_0562 :Powered cars travel along a multi-level track past spooky scenery and special effects +STR_0562 :Motordrivna monsterformade vagnar som åker längst ett flernivåspår förbi spöklika scener och specialeffekter STR_0563 :Sittandes i bekväma vagnar njuter passagerare av enorma nedförsbackar och spännande svängar, samt mycket tid flygandes över topparna STR_0564 :Den här berg- och dalbanan i trä är snabb, tuff, högljudd, och ger en känsla av att tappa kontrollen. Dessutom spenderar man mycket tid flygandes över topparna STR_0565 :En enkel berg- och dalbana i trä som bara har snälla backar och svängar. Vagnarna hålls på banan med sidofriktion på hjulen och gravitation @@ -572,38 +572,38 @@ STR_0567 :Passagerare sitter i säten på varsin sida av banan och vänds upp STR_0568 : STR_0569 :Hängandes i speciella selar får passagerare känna på känslan av att flyga runt i luften STR_0570 : -STR_0571 :Circular cars spin around as they travel along the zig-zagging wooden track -STR_0572 :Large capacity boats travel along a wide water channel, propelled up slopes by a conveyer belt, accelerating down steep slopes to soak the riders with a gaint splash -STR_0573 :Powered helicoper shaped cars running on a steel track, controlled by the pedalling of the riders -STR_0574 :Riders are held in special harnesses in a lying-down position, travlling through twisted track and inversions either on their backs or facing the ground +STR_0571 :Runda vagnar snurrar runt medan de åker längst ett zick-zack-spår av trä +STR_0572 :Högkapacitetsbåtar färdas längst en bred vattenkanal, drivs upp för lutningar av transportband, accelererar ner för branter för att blöta ner passagerarna med ett jätteplast +STR_0573 :Motordrivna helikopterformade vagnar kör på ett stålspår och styrs med pedaler av passagerarna +STR_0574 :Passagerarna hålls fast i speciella seldon i liggande läge, åker genom ett tvinnat spår och håller dem antingen på rygg eller med ansiktet mot marken STR_0575 :Motoriserade tåg som hänger från en enkelspårig bana transporterar folk runt om i parken STR_0576 : -STR_0577 :Bogied cars run on wooden tracks, turning around on special reversing sections +STR_0577 :Boggivagnar kör på ett träspår, vänder runt på speciella vändsektioner STR_0578 :Vagnar åker runt en bana omgiven av ringar utför branta nedförsbackar och skruvar STR_0579 : -STR_0580 :A giant steel roller coaster capable of smooth drops and hills of over 300ft -STR_0581 :A ring of seats is pulled to the top of a tall tower while gently rotating, then allowed to free-fall down, stopping gently at the bottom using magnetic brakes +STR_0580 :En gigantisk stålberg- och dalbana som klara mjuka fall och höjder på över 1000 m +STR_0581 :En ring med säten dras upp till toppen av ett högt torn medan det roterar sakta, därefter faller det fritt varefter det stoppas mjukt vid botten med hjälp av magnetbromsar STR_0582 : STR_0583 : -STR_0584 :Special bicycles run on a steel monorail track, propelled by the pedalling of the riders -STR_0585 :Riders sit in pairs of seats suspended beneath the track as they loop and twist through tight inversions +STR_0584 :Speciella cyklar åker på en stål enskensbana, glidande fram av passagerarens cyklande +STR_0585 :Passagerarna sitter i par med ansiktena antingen bakåt eller framåt då de åker genom loopar och skruvar med snabba omkastningar STR_0586 :Båtformade vagnar åker på berg- och dalbanespår med snurriga svängar och branta nedförsbackar, men plumsar då och då ner i lugna vattensektioner -STR_0587 :After an exhilarating air-powered launch, the train speeds up a vertical track, over the top, and vertically down the other side to return to the station -STR_0588 :Individual cars run beneath a zig-zagging track with hairpin turns and sharp drops +STR_0587 :Efter en luftdriven snabbstart susar vagnarna uppför och nedför en vertikal bana innan de återvänder till stationen +STR_0588 :Vagnarna kör på ett träspår som lutar farligt över då de korsar hårnålssvängar och skarpa nedgångar STR_0589 : -STR_0590 :Riders ride in a submerged submarine through an underwater course -STR_0591 :Raft-shaped boats gently meander around a river track +STR_0590 :Passagerarna åker i en nedsänkt ubåt genom en undervattensbana +STR_0591 :Flottformade båtar som lugnt snirklar sig runt ett flodspår STR_0592 : STR_0593 : STR_0594 : STR_0595 : STR_0596 : STR_0597 : -STR_0598 :Inverted roller coaster trains are accelerated out of the station to travel up a vertical spike of track, then reverse back through the station to travel backwards up another vertical spike of track +STR_0598 :Omvända berg- och dalbanevagnar som accelereras ut från stationen kör upp för ett lodrät brant torn, vänder sedan och åker baklänges genom stationen upp för ett annan lodrät brant torn STR_0599 :En kompakt berg- och dalbana med individuella vagnar och mjuka snurrade nedförsbackar -STR_0600 :Powered mine trains career along a smooth and twisted track layout +STR_0600 :Motordrivna gruvtåg rusar längst en mjuk tvinnad spårlayout STR_0601 : -STR_0602 :Roller coaster trains are accelerated out of the station by linear induction motors to speed through twisting inversions +STR_0602 :Berg- och dalbanetågen accelereras ut från stationen med induktionsmotorer för att fara genom tvinnande inversioner STR_0603 :Gäst {INT32} STR_0604 :Gäst {INT32} STR_0605 :Gäst {INT32} @@ -1060,14 +1060,14 @@ STR_1054 :{SMALLFONT}{BLACK}Namnge åktur/attraktion STR_1055 :{SMALLFONT}{BLACK}Namnge person STR_1056 :{SMALLFONT}{BLACK}Namnge anställd STR_1057 :Åkturens/attraktionens namn -STR_1058 :Skriv in ett nytt namn för den här åkturen/attraktionen: +STR_1058 :Skriv in ett nytt namn för den här åkturen: STR_1059 :Kan inte namnge åktur/attraktion... STR_1060 :Ogiltigt åktur/attraktionsnamn STR_1061 :Normalt läge STR_1062 :Kontinuerligt banläge #TODO -STR_1063 :Reverse-Incline launched shuttle mode -STR_1064 :Accelererad start (passing station) +STR_1063 :Backande kjedjelyfts start i pendlat läge +STR_1064 :Accelererad start (passerar station) STR_1065 :Pendlarläge STR_1066 :Uthyrning STR_1067 :Uppskjut @@ -1096,7 +1096,7 @@ STR_1089 :Berserkläge STR_1090 :Spökhuset STR_1091 :Cirkusvisning STR_1092 :Nedåtriktad start -STR_1093 :Snea huset +STR_1093 :Lustiga huset STR_1094 :Fritt fall STR_1095 :Blockavdelat kontinuerligt banläge STR_1096 :Motoriserad start (utan att passera station) @@ -1117,7 +1117,7 @@ STR_1110 :Roterar STR_1111 :Roterar STR_1112 :Pågår STR_1113 :Visar film -STR_1114 :Rotating +STR_1114 :Roterar STR_1115 :Pågår STR_1116 :Pågår STR_1117 :Cirkusshow pågår @@ -1166,15 +1166,15 @@ STR_1159 :{SMALLFONT}{BLACK}Placera dekorationer, trädgårdar, och andra til STR_1160 :{SMALLFONT}{BLACK}Skapa/justera sjöar och vatten STR_1161 :Kan inte placera detta här... STR_1162 :{OUTLINE}{TOPAZ}{STRINGID} -STR_1163 :{STRINGID}{NEWLINE}(Höger-Click to Modify) -STR_1164 :{STRINGID}{NEWLINE}(Höger-Click to Remove) +STR_1163 :{STRINGID}{NEWLINE}(Höger-klicka för att modifiera) +STR_1164 :{STRINGID}{NEWLINE}(Höger-klicka för att ta bort) STR_1165 :{STRINGID} - {STRINGID} {COMMA16} STR_1166 :Kan inte sänka vattennivån... STR_1167 :Kan inte höja vattennivån... STR_1168 :Inställningar STR_1169 :(Inga) STR_1170 :{STRING} -STR_1171 :{RED}Closed - - +STR_1171 :{RED}Stängd - - STR_1172 :{YELLOW}{STRINGID} - - STR_1173 :{SMALLFONT}{BLACK}Bygg gångvägar och köer STR_1174 :En skylt är i vägen @@ -1192,8 +1192,8 @@ STR_1185 :{SMALLFONT}{BLACK}Riktning STR_1186 :{SMALLFONT}{BLACK}Sluttning nedåt STR_1187 :{SMALLFONT}{BLACK}Platt STR_1188 :{SMALLFONT}{BLACK}Sluttning uppåt -STR_1189 :{SMALLFONT}{BLACK}Bygg den valda gångvägssektionen -STR_1190 :{SMALLFONT}{BLACK}Ta bort gångvägssektion +STR_1189 :{SMALLFONT}{BLACK}Bygg den valda gångvägs sektionen +STR_1190 :{SMALLFONT}{BLACK}Ta bort gångvägs sektion STR_1191 :{BLACK}{STRINGID} STR_1192 :{OUTLINE}{RED}{STRINGID} STR_1193 :{WINDOW_COLOUR_2}{STRINGID} @@ -1362,7 +1362,7 @@ STR_1355 :{WINDOW_COLOUR_2}Fall: {BLACK}{COMMA16} STR_1356 :{WINDOW_COLOUR_2}Inversioner: {BLACK}{COMMA16} STR_1357 :{WINDOW_COLOUR_2}Hål: {BLACK}{COMMA16} STR_1358 :{WINDOW_COLOUR_2}Total 'flyg'-tid: {BLACK}{COMMA2DP32}secs -STR_1359 :{WINDOW_COLOUR_2}Kötod: {BLACK}{COMMA16} minute +STR_1359 :{WINDOW_COLOUR_2}Kötid: {BLACK}{COMMA16} minute STR_1360 :{WINDOW_COLOUR_2}Kötid: {BLACK}{COMMA16} minutes STR_1361 :Kan inte ändra hastighet... STR_1362 :Kan inte ändra starthastighet... @@ -1397,7 +1397,7 @@ STR_1390 :{CURRENCY2DP} STR_1391 :{RED}{CURRENCY2DP} STR_1392 :{SMALLFONT}{BLACK}Åkturs/attraktions-vy STR_1393 :{SMALLFONT}{BLACK}Fordondetaljer och inställningar -STR_1394 :{SMALLFONT}{BLACK}Operating options +STR_1394 :{SMALLFONT}{BLACK}Manövrerings inställningar STR_1395 :{SMALLFONT}{BLACK}Underhållsinställningar STR_1396 :{SMALLFONT}{BLACK}Färginställningar STR_1397 :{SMALLFONT}{BLACK}Ljud- och musikinställningar @@ -1412,7 +1412,7 @@ STR_1405 :{SMALLFONT}{BLACK}Spegla STR_1406 :{SMALLFONT}{BLACK}Dölj/visa dekorationer (om de finns på designen) STR_1407 :{WINDOW_COLOUR_2}Bygg detta... STR_1408 :{WINDOW_COLOUR_2}Kostnad: {BLACK}{CURRENCY} -STR_1409 :Ingång/utgång-Platform +STR_1409 :Ingång/utgång Platform STR_1410 :Vertikalt Torn STR_1411 :{STRINGID} är i vägen STR_1412 :{WINDOW_COLOUR_3}Den här sortens åktur kan inte spara data @@ -1516,7 +1516,7 @@ STR_1509 :{SMALLFONT}{OPENQUOTES}Jag vill ut ur {STRINGID}{ENDQUOTES} STR_1510 :{SMALLFONT}{OPENQUOTES}Jag tänker inte åka {STRINGID} - Det är inte säkert nog{ENDQUOTES} STR_1511 :{SMALLFONT}{OPENQUOTES}Den här gångvägen är vidrig{ENDQUOTES} STR_1512 :{SMALLFONT}{OPENQUOTES}Det är för mycket folk här{ENDQUOTES} -STR_1513 :{SMALLFONT}{OPENQUOTES}The vandalism here is really bad{ENDQUOTES} +STR_1513 :{SMALLFONT}{OPENQUOTES}Skadegörelsen här är verkligen illa{ENDQUOTES} STR_1514 :{SMALLFONT}{OPENQUOTES}Snygga dekorationer!{ENDQUOTES} STR_1515 :{SMALLFONT}{OPENQUOTES}Den här parken är verkligen ren och fin{ENDQUOTES} STR_1516 :{SMALLFONT}{OPENQUOTES}Fontänerna är fantastiska{ENDQUOTES} @@ -1525,7 +1525,7 @@ STR_1518 :{SMALLFONT}{OPENQUOTES}Ballongen från {STRINGID} var verkligen vä STR_1519 :{SMALLFONT}{OPENQUOTES}Kramdjuret från {STRINGID} var verkligen värt pengarna{ENDQUOTES} STR_1520 :{SMALLFONT}{OPENQUOTES}Kartan från {STRINGID} var verkligen värd pengarna{ENDQUOTES} STR_1521 :{SMALLFONT}{OPENQUOTES}Fotot från åkturen {STRINGID} var verkligen värt pengarna{ENDQUOTES} -STR_1522 :{SMALLFONT}{OPENQUOTES}Paraplyt från {STRINGID} var verkligen värt pengarna{ENDQUOTES} +STR_1522 :{SMALLFONT}{OPENQUOTES}Paraplyet från {STRINGID} var verkligen värt pengarna{ENDQUOTES} STR_1523 :{SMALLFONT}{OPENQUOTES}Drickan från {STRINGID} var verkligen värd pengarna{ENDQUOTES} STR_1524 :{SMALLFONT}{OPENQUOTES}Hamburgaren från {STRINGID} var verkligen värd pengarna{ENDQUOTES} STR_1525 :{SMALLFONT}{OPENQUOTES}Pommes fritesen från {STRINGID} var verkligen värda pengarna{ENDQUOTES} @@ -1542,7 +1542,7 @@ STR_1535 :{SMALLFONT}{OPENQUOTES}Tentakeln från {STRINGID} var verkligen vä STR_1536 :{SMALLFONT}{OPENQUOTES}Hatten från {STRINGID} var verkligen värd pengarna{ENDQUOTES} STR_1537 :{SMALLFONT}{OPENQUOTES}Kanderat äpplet från {STRINGID} var verkligen värt pengarna{ENDQUOTES} STR_1538 :{SMALLFONT}{OPENQUOTES}T-shirten från {STRINGID} var verkligen värd pengarna{ENDQUOTES} -STR_1539 :{SMALLFONT}{OPENQUOTES}Donuten från {STRINGID} var verkligen värd pengarna{ENDQUOTES} +STR_1539 :{SMALLFONT}{OPENQUOTES}Munken från {STRINGID} var verkligen värd pengarna{ENDQUOTES} STR_1540 :{SMALLFONT}{OPENQUOTES}Kaffet från {STRINGID} var verkligen värt pengarna{ENDQUOTES} STR_1541 : STR_1542 :{SMALLFONT}{OPENQUOTES}Friterade kycklingen från {STRINGID} var verkligen värd pengarna{ENDQUOTES} @@ -1555,7 +1555,7 @@ STR_1548 : STR_1549 : STR_1550 :{SMALLFONT}{OPENQUOTES}Wow!{ENDQUOTES} STR_1551 :{SMALLFONT}{OPENQUOTES}Det känns som att någon iakttar mig{ENDQUOTES} -STR_1552 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för Jag tänker inte betala så mycket för a balloon from {STRINGID}{ENDQUOTES} +STR_1552 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för Jag tänker inte betala så mycket för en ballong från {STRINGID}{ENDQUOTES} STR_1553 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för ett mjukisdjur från {STRINGID}{ENDQUOTES} STR_1554 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en karta från {STRINGID}{ENDQUOTES} STR_1555 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för ett foto från åkturen {STRINGID}{ENDQUOTES} @@ -1576,7 +1576,7 @@ STR_1569 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för tent STR_1570 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en hatt från {STRINGID}{ENDQUOTES} STR_1571 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för ett kanderat äpple från {STRINGID}{ENDQUOTES} STR_1572 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en T-shirt från {STRINGID}{ENDQUOTES} -STR_1573 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en donut från {STRINGID}{ENDQUOTES} +STR_1573 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en munk från {STRINGID}{ENDQUOTES} STR_1574 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en kaffe från {STRINGID}{ENDQUOTES} STR_1575 : STR_1576 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för friterad kyckling från {STRINGID}{ENDQUOTES} @@ -1590,7 +1590,7 @@ STR_1583 : STR_1584 :{SMALLFONT}{OPENQUOTES}Fotot från åkturen {STRINGID} var verkligen värt pengarna{ENDQUOTES} STR_1585 :{SMALLFONT}{OPENQUOTES}Fotot från åkturen {STRINGID} var verkligen värt pengarna{ENDQUOTES} STR_1586 :{SMALLFONT}{OPENQUOTES}Fotot från åkturen {STRINGID} var verkligen värt pengarna{ENDQUOTES} -STR_1587 :{SMALLFONT}{OPENQUOTES}Pretzeln från {STRINGID} var verkligen värd pengarna{ENDQUOTES} +STR_1587 :{SMALLFONT}{OPENQUOTES}Kringlan från {STRINGID} var verkligen värd pengarna{ENDQUOTES} STR_1588 :{SMALLFONT}{OPENQUOTES}Varma chokladen från {STRINGID} var verkligen värd pengarna{ENDQUOTES} STR_1589 :{SMALLFONT}{OPENQUOTES}Istéet från {STRINGID} var verkligen värt pengarna{ENDQUOTES} STR_1590 :{SMALLFONT}{OPENQUOTES}Struvan från {STRINGID} var verkligen värd pengarna{ENDQUOTES} @@ -1622,7 +1622,7 @@ STR_1615 : STR_1616 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för ett foto från åkturen {STRINGID}{ENDQUOTES} STR_1617 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för ett foto från åkturen {STRINGID}{ENDQUOTES} STR_1618 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för ett foto från åkturen {STRINGID}{ENDQUOTES} -STR_1619 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en pretzel från {STRINGID}{ENDQUOTES} +STR_1619 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en kringla från {STRINGID}{ENDQUOTES} STR_1620 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för varm choklad från {STRINGID}{ENDQUOTES} STR_1621 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för isté från {STRINGID}{ENDQUOTES} STR_1622 :{SMALLFONT}{OPENQUOTES}Jag tänker inte betala så mycket för en struva från {STRINGID}{ENDQUOTES} @@ -1655,7 +1655,7 @@ STR_1648 :{SMALLFONT}{OPENQUOTES}Hjälp! Släpp ner mig!{ENDQUOTES} STR_1649 :{SMALLFONT}{OPENQUOTES}Jag börjar få slut på pengar!{ENDQUOTES} STR_1650 :{SMALLFONT}{OPENQUOTES}Wow! Dom bygger en ny åktur!{ENDQUOTES} STR_1651 :{SMALLFONT}{OPENQUOTES}Najs åktur! Men inte lika bra som Fenixen...{ENDQUOTES} -STR_1652 :{SMALLFONT}{OPENQUOTES}Jag är så taggad - Det är en Intamin-åktur!{ENDQUOTES} +STR_1652 :{SMALLFONT}{OPENQUOTES}Jag är så taggad - Det är en intensiv åktur!{ENDQUOTES} STR_1653 :{SMALLFONT}{OPENQUOTES}...och nu är vi på {STRINGID}!{ENDQUOTES} STR_1654 :{WINDOW_COLOUR_2}Nyliga tankar: STR_1655 :{SMALLFONT}{BLACK}Bygg gångväg på land @@ -1671,13 +1671,13 @@ STR_1664 :{WINDOW_COLOUR_2}Energi: STR_1665 :{WINDOW_COLOUR_2}Hunger: STR_1666 :{WINDOW_COLOUR_2}Törst: STR_1667 :{WINDOW_COLOUR_2}Blåsa: -STR_1668 :{WINDOW_COLOUR_2}Tillfredställdhet: {BLACK}Okänd -STR_1669 :{WINDOW_COLOUR_2}Tillfredställdhet: {BLACK}{COMMA16}% +STR_1668 :{WINDOW_COLOUR_2}Tillfredställd: {BLACK}Okänd +STR_1669 :{WINDOW_COLOUR_2}Tillfredställd: {BLACK}{COMMA16}% STR_1670 :{WINDOW_COLOUR_2}Totalt antal kunder: {BLACK}{COMMA32} STR_1671 :{WINDOW_COLOUR_2}Total vinst: {BLACK}{CURRENCY2DP} STR_1672 :Bromsar #TODO -STR_1673 :Spinning Control Toggle Track +STR_1673 :Snurr kontroll växlare STR_1674 :Bromshastighet STR_1675 :{POP16}{VELOCITY} STR_1676 :{SMALLFONT}{BLACK}Sätt hastighetsgräns för bromsar @@ -1701,8 +1701,8 @@ STR_1693 :{SMALLFONT}{BLACK}Gäster STR_1694 :{SMALLFONT}{BLACK}Personal STR_1695 :{SMALLFONT}{BLACK}Inkomst och utgifter STR_1696 :{SMALLFONT}{BLACK}Kundinformation -STR_1697 :Kan inte placera dessa i ett köområde -STR_1698 :Kan endast placera dessa i ett köområde +STR_1697 :Kan inte placera dessa i ett kö område +STR_1698 :Kan endast placera dessa i ett kö område STR_1699 :För mycket folk i spelet STR_1700 :Anställ ny Vaktmästare STR_1701 :Anställ ny Mekaniker @@ -1746,8 +1746,8 @@ STR_1738 :Kan inte ändra antal varv... STR_1739 :Gäst {INT32} vann rallyt STR_1740 :{STRINGID} vann rallyt STR_1741 :Inte byggt än ! -STR_1742 :{WINDOW_COLOUR_2}Max. people on Åktur: -STR_1743 :{SMALLFONT}{BLACK}Maximum number of people allowed on this Åktur at one time +STR_1742 :{WINDOW_COLOUR_2}Max. personer på Åktur: +STR_1743 :{SMALLFONT}{BLACK}Maximala antal personer på denna Åktur samtidigt STR_1744 :{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{POP16}{COMMA16} STR_1745 :{COMMA16} STR_1746 :Kan inte ändra detta... @@ -1826,13 +1826,13 @@ STR_1818 :{WINDOW_COLOUR_2}Alla gäster STR_1819 :{WINDOW_COLOUR_2}Alla gäster (sammanfattat) STR_1820 :{WINDOW_COLOUR_2}Gäster {STRINGID} STR_1821 :{WINDOW_COLOUR_2}Gäster som tänker {STRINGID} -STR_1822 :{WINDOW_COLOUR_2}Guests som tänker på {POP16}{STRINGID} +STR_1822 :{WINDOW_COLOUR_2}Gäster som tänker på {POP16}{STRINGID} STR_1823 :{SMALLFONT}{BLACK}Visa gästers tankar om den här åkturen/attraktionen STR_1824 :{SMALLFONT}{BLACK}Visa gäster på den här åkturen/attraktionen STR_1825 :{SMALLFONT}{BLACK}Visa gäster som köar till den här åkturen/attraktionen STR_1826 :Status STR_1827 :Popularitet -STR_1828 :Tillfredsställdhet +STR_1828 :Tillfredsställd STR_1829 :Vinst STR_1830 :Kölängd STR_1831 :Kötid @@ -1987,7 +1987,7 @@ STR_1977 :{WINDOW_COLOUR_2}Pris på Tentakel: STR_1978 :{WINDOW_COLOUR_2}Pris på Hatt: STR_1979 :{WINDOW_COLOUR_2}Pris på Kanderat Äpple: STR_1980 :{WINDOW_COLOUR_2}Pris på T-Shirt: -STR_1981 :{WINDOW_COLOUR_2}Pris på Donut: +STR_1981 :{WINDOW_COLOUR_2}Pris på Munk: STR_1982 :{WINDOW_COLOUR_2}Pris på Kaffe: STR_1983 :{WINDOW_COLOUR_2} STR_1984 :{WINDOW_COLOUR_2}Pris på Friterad Kyckling: @@ -2015,7 +2015,7 @@ STR_2005 :Tentakel STR_2006 :Hatt STR_2007 :Kanderat Äpple STR_2008 :T-Shirt -STR_2009 :Donut +STR_2009 :Munk STR_2010 :Kaffe STR_2011 :Tom Mugg STR_2012 :Friterad Kyckling @@ -2043,7 +2043,7 @@ STR_2033 :Tentakler STR_2034 :Hattar STR_2035 :Kanderade Äpplen STR_2036 :T-Shirts -STR_2037 :Donuts +STR_2037 :Munkar STR_2038 :Kaffekoppar STR_2039 :Tomma Muggar STR_2040 :Friterad Kyckling @@ -2071,7 +2071,7 @@ STR_2061 :en Tentakel STR_2062 :en Hatt STR_2063 :ett Kanderat Äpple STR_2064 :en T-Shirt -STR_2065 :en Donut +STR_2065 :en Munk STR_2066 :en Kaffe STR_2067 :en Tom Mugg STR_2068 :Friterad Kyckling @@ -2099,7 +2099,7 @@ STR_2089 :Tentakel STR_2090 :{OPENQUOTES}{STRINGID}{ENDQUOTES} Hatt STR_2091 :Kanderat Äpple STR_2092 :{OPENQUOTES}{STRINGID}{ENDQUOTES} T-Shirt -STR_2093 :Donut +STR_2093 :Munk STR_2094 :Kaffe STR_2095 :Tom Mugg STR_2096 :Friterad Kyckling @@ -2146,14 +2146,14 @@ STR_2136 :Sujeonggwa STR_2137 :Macka STR_2138 :Kaka STR_2139 :Tom Skål -STR_2140 :Tomma Tetrapak +STR_2140 :Tom Pappmugg STR_2141 :Tom Juiceförpackning STR_2142 :Ugnskorv STR_2143 :Tom Skål STR_2144 :Åktursfoton STR_2145 :Åktursfoton STR_2146 :Åktursfoton -STR_2147 :Pretzels +STR_2147 :Kringla STR_2148 :Muggar Varm Choklad STR_2149 :Istéer STR_2150 :Struvor @@ -2168,7 +2168,7 @@ STR_2158 :Sujeonggwas STR_2159 :Mackor STR_2160 :Kakor STR_2161 :Tomma Skålar -STR_2162 :Tomma Tetrapak +STR_2162 :Tomma Pappmuggar STR_2163 :Tomma Juiceförpackningar STR_2164 :Ugnskorvar STR_2165 :Tomma Skålar @@ -2190,7 +2190,7 @@ STR_2180 :Sujeonggwa STR_2181 :en Macka STR_2182 :en Kaka STR_2183 :en Tom Skål -STR_2184 :en Tom Tetrapak +STR_2184 :en Tom Pappmugg STR_2185 :en Tom Juiceförpackning STR_2186 :en Ugnskorv STR_2187 :en Tom Skål @@ -2212,7 +2212,7 @@ STR_2202 :Sujeonggwa STR_2203 :Macka STR_2204 :Kaka STR_2205 :Tom Skål -STR_2206 :Tom Tetrapak +STR_2206 :Tom Pappmugg STR_2207 :Tom Juiceförpackning STR_2208 :Ugnskorv STR_2209 :Tom Skål @@ -2382,7 +2382,7 @@ STR_2372 :Låg STR_2373 :Mellan STR_2374 :Hög STR_2375 :Väldigt hög -STR_2376 :Exttrem +STR_2376 :Extrem STR_2377 :Ultra-Extrem STR_2378 :{SMALLFONT}{BLACK}Justera ett mindre landområde STR_2379 :{SMALLFONT}{BLACK}Justera ett större landområde @@ -2455,7 +2455,7 @@ STR_2445 :Starta kampanjen STR_2446 :{YELLOW}Din kampanj för gratis entré till parken har slutförts STR_2447 :{YELLOW}Din kampanj för gratis åkturer på {STRINGID} har slutförts STR_2448 :{YELLOW}Din kampanj för halva priset på entré till parken har slutförts -STR_2449 :{YELLOW}Din kampank för gratis {STRINGID} har slutförts +STR_2449 :{YELLOW}Din kampanj för gratis {STRINGID} har slutförts STR_2450 :{YELLOW}Din kampanj för parken har slutförts STR_2451 :{YELLOW}Din kampanj för {STRINGID} har slutförts STR_2452 :{WINDOW_COLOUR_2}Pengar (utan lån): {BLACK}{CURRENCY2DP} @@ -2691,22 +2691,22 @@ STR_2681 :{MEDIUMFONT}{BLACK}Ökar pengarna med {CURRENCY} STR_2682 : STR_2683 : STR_2684 :{SMALLFONT}{BLACK}En stor grupp anländer -STR_2685 :Simplex Noise Parameters -STR_2686 :{WINDOW_COLOUR_2}Low: -STR_2687 :{WINDOW_COLOUR_2}High: -STR_2688 :{WINDOW_COLOUR_2}Base Frequency: -STR_2689 :{WINDOW_COLOUR_2}Octaves: -STR_2690 :Map Generation -STR_2691 :{WINDOW_COLOUR_2}Base height: -STR_2692 :{WINDOW_COLOUR_2}Water level: -STR_2693 :{WINDOW_COLOUR_2}Terrain: +STR_2685 :Simpla Brus Inställningar +STR_2686 :{WINDOW_COLOUR_2}Låg: +STR_2687 :{WINDOW_COLOUR_2}Hög: +STR_2688 :{WINDOW_COLOUR_2}Bas Frekvens: +STR_2689 :{WINDOW_COLOUR_2}Oktav: +STR_2690 :Mark generator +STR_2691 :{WINDOW_COLOUR_2}Bas höjd: +STR_2692 :{WINDOW_COLOUR_2}Vatten: +STR_2693 :{WINDOW_COLOUR_2}Terräng: STR_2694 :Generera STR_2695 :Slumpvis terräng STR_2696 :Placera trä STR_2697 :??? STR_2698 :??? STR_2699 :??? -STR_2700 :Autospar frekvens: +STR_2700 :Spara automatiskt: STR_2701 :Varje minut STR_2702 :Var 5:e minut STR_2703 :Var 15:e minut @@ -2724,8 +2724,8 @@ STR_2714 :- STR_2715 :. STR_2716 :/ STR_2717 :' -STR_2718 :(up) -STR_2719 :(new file) +STR_2718 :(upp) +STR_2719 :(Ny fil) STR_2720 :{UINT16}sek STR_2721 :{UINT16}sek STR_2722 :{UINT16}min:{UINT16}sek @@ -2744,28 +2744,28 @@ STR_2734 :{COMMA16}mph STR_2735 :{COMMA16}km/h STR_2736 :{MONTH}, År {COMMA16} STR_2737 :{STRINGID} {MONTH}, År {COMMA16} -STR_2738 :Title screen music: -STR_2739 :None +STR_2738 :Startskärmens musik: +STR_2739 :Ingen 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_2742 :css50.dat hittades inte +STR_2743 :Kopiera data\css17.dat från din RCT1 installation till data\css50.dat i din RCT2 installation. STR_2744 :[ STR_2745 :\ STR_2746 :] STR_2747 :{ENDQUOTES} STR_2748 :Bar -STR_2749 :My new scenario +STR_2749 :Mitt nya scenario # New strings used in the cheats window previously these were ??? -STR_2750 :Move all items to top -STR_2751 :Move all items to bottom -STR_2752 :Clear grass -STR_2753 :Mowed grass -STR_2754 :Water plants -STR_2755 :Fix vandalism -STR_2756 :Remove litter -STR_2757 :Force Sun -STR_2758 :Force Thunder +STR_2750 :Flytta alla föremål till toppen +STR_2751 :Flytta alla föremål till botten +STR_2752 :Plocka ogräs +STR_2753 :Klipp gräsmattan +STR_2754 :Vattna blommorna +STR_2755 :Fixa skadegörelsen +STR_2756 :Städa nedskräpningen +STR_2757 :Tvinga sol +STR_2758 :Tvinga åska STR_2759 :Zero Clearance # New strings used in the cheats window previously these were ??? STR_2760 :+{CURRENCY} @@ -2774,7 +2774,7 @@ STR_2762 : STR_2763 :??? STR_2764 : STR_2765 :Stort Tåg -STR_2766 :Win scenario +STR_2766 :Vinn scenario STR_2767 :Frys Klimat STR_2768 :Avfrys klimat STR_2769 :Öppna Park @@ -2788,8 +2788,8 @@ STR_2776 :Språk: STR_2777 :{MOVE_X}{SMALLFONT}{STRING} STR_2778 :{RIGHTGUILLEMET}{MOVE_X}{SMALLFONT}{STRING} # End of new strings -STR_2779 :Viewport #{COMMA16} -STR_2780 :Extra viewport +STR_2779 :Bildskärm #{COMMA16} +STR_2780 :Extra bildskärm STR_2781 :{STRINGID}:{MOVE_X}{195}{STRINGID} STR_2782 :SHIFT + STR_2783 :CTRL + @@ -2799,18 +2799,16 @@ STR_2786 :{SMALLFONT}{BLACK}Klicka på en beskrivning för att välja en ny s STR_2787 :{WINDOW_COLOUR_2}Parkvärde: {BLACK}{CURRENCY} STR_2788 :{WINDOW_COLOUR_2}Grattis !{NEWLINE}{BLACK}Du uppnådde ditt mål med ett företagsvärde på {CURRENCY} ! STR_2789 :{WINDOW_COLOUR_2}Du har misslyckats med ditt mål ! -#TODO, scenario chart? -STR_2790 :Skriv in namn i scenario chart +STR_2790 :Skriv in namn i scenario listan STR_2791 :Skriv in namn -#TODO -STR_2792 :Var god skriv in ditt namn i scenario chart: +STR_2792 :Var god skriv in ditt namn i scenario listan: STR_2793 :{SMALLFONT}(Avklarad av {STRINGID}) STR_2794 :{WINDOW_COLOUR_2}Avklarad av: {BLACK}{STRINGID}{NEWLINE}{WINDOW_COLOUR_2} med ett företagsvärde på: {BLACK}{CURRENCY} STR_2795 :Sortera STR_2796 :{SMALLFONT}{BLACK}Sortera åkturslistan i ordning enligt den valda informationstypen STR_2797 :Flytta vyn när muspekaren är vid skärmens kant STR_2798 :{SMALLFONT}{BLACK}Välj om vyn ska förflyttas när muspekaren är vid skärmens kant -STR_2799 :{SMALLFONT}{BLACK}Visa eller ändra kontrolltangentstilldelningar +STR_2799 :{SMALLFONT}{BLACK}Visa eller ändra kontrollerna STR_2800 :{WINDOW_COLOUR_2}Totalt antal inträden: {BLACK}{COMMA32} STR_2801 :{WINDOW_COLOUR_2}Inkomst från inträden: {BLACK}{CURRENCY2DP} STR_2802 :Karta @@ -2819,7 +2817,7 @@ STR_2804 :{SMALLFONT}{BLACK}Markera denna personal på kartan STR_2805 :{SMALLFONT}{BLACK}Visa karta över parken STR_2806 :{RED}Gäster klagar på gångvägarnas snuskiga tillstånd{NEWLINE}Kolla var dina vaktmästare är och överväg att organisera dom bättre STR_2807 :{RED}Gäster klagar på mängden skräp i din park{NEWLINE}Kolla var dina vaktmästare är och överväg att organisera dom bättre -STR_2808 :{RED}Gäster klagar på vandalismen i din park{NEWLINE}Kolla var dina säkerhetsvakter är och överväg att organisera dom bättre +STR_2808 :{RED}Gäster klagar på skadegörelsen i din park{NEWLINE}Kolla var dina säkerhetsvakter är och överväg att organisera dom bättre STR_2809 :{RED}Gäster är hungriga och kan inte hitta någonstans att köpa mat STR_2810 :{RED}Gäster är törstiga och kan inte hitta någonstans att köpa dricka STR_2811 :{RED}Gäster klagar för att dom inte kan hitta toaletterna i din park @@ -3178,7 +3176,7 @@ STR_3163 :Installerar ny data: STR_3164 :{BLACK}{COMMA16} valda (av max {COMMA16}) STR_3165 : STR_3166 :{BLACK}(ID: -STR_3167 :{WINDOW_COLOUR_2}Inkluderar: {BLACK}{COMMA16} objects +STR_3167 :{WINDOW_COLOUR_2}Inkluderar: {BLACK}{COMMA16} objekt STR_3168 :{WINDOW_COLOUR_2}Text: {BLACK}{STRINGID} STR_3169 :Data för detta objekt hittades ej: STR_3170 :Inte nog plats för grafik @@ -3236,7 +3234,7 @@ STR_3221 :{SMALLFONT}{BLACK}Välj att marken ska ägas av parken STR_3222 :{SMALLFONT}{BLACK}Välj att bara bygglov ska ägas av parken STR_3223 :{SMALLFONT}{BLACK}Välj att mark ska vara tillgängligt för köp STR_3224 :{SMALLFONT}{BLACK}Välj att bygglov ska vara tillgängligt för köp -STR_3225 :{SMALLFONT}{BLACK}Aktivera/inaktivera generering av en slumpmässig samling object runt den valda positionen +STR_3225 :{SMALLFONT}{BLACK}Aktivera/inaktivera generering av en slumpmässig samling objekt runt den valda positionen STR_3226 :{SMALLFONT}{BLACK}Bygg parkentré STR_3227 :För många parkentréer! STR_3228 :{SMALLFONT}{BLACK}Sätt startpositioner för besökare @@ -3327,7 +3325,7 @@ STR_3312 :{WINDOW_COLOUR_2}Åkturer/attraktioner som måste bevaras: STR_3313 :Scenarionamn STR_3314 :Skriv in namn för scenario: STR_3315 :Park- och Scenariodetails -STR_3316 :Skriv in en beskriving för detta scenario: +STR_3316 :Skriv in en beskrivning för detta scenario: STR_3317 :Inga detaljer än STR_3318 :{SMALLFONT}{BLACK}Välj vilken grupp detta scenario hör till STR_3319 :{WINDOW_COLOUR_2}Scenariogrupp: @@ -3461,9 +3459,1108 @@ STR_3444 :Sida 5 STR_3445 :Sätt Patrullområde STR_3446 :Avbryt Patrullområde -#Thousands separator -STR_5151 : -#Decimal separator -STR_5152 :, +# New strings, cleaner +STR_5120 :Finans +STR_5121 :Forskning +STR_5122 :Välj vagnar efter spår typ (som i RCT1) +STR_5123 :Förnya karuseller +STR_5124 : +STR_5125 :All destructable +#This needs to be changed, really confusing string + add a description (See issue #489 in Localisation on github) +STR_5126 :Slumpvald titel musik +STR_5127 :{SMALLFONT}{BLACK}Måla landskap +STR_5128 :Välj storlek +STR_5129 :Skriv in vald storlek mellan {COMMA16} och {COMMA16} +STR_5130 :Kart storlek +STR_5131 :Skriv in en kart storlek mellan {COMMA16} och {COMMA16} +STR_5132 :Laga alla åkturer +STR_5133 :{SMALLFONT}{BLACK}Justera mindre storlek av landrättigheter +STR_5134 :{SMALLFONT}{BLACK}Justera större storlek av landrättigheter +STR_5135 :{SMALLFONT}{BLACK}Köp land- och konstruktions-rättigheter +STR_5136 :Landrättigheter +STR_5137 :Lås upp körläges gränser +STR_5138 :{SMALLFONT}{WINDOW_COLOUR_2}{STRINGID} +STR_5139 :{WHITE}{STRINGID} +STR_5140 :Avaktivera bromsfel +STR_5141 :Avaktivera alla haverin +STR_5142 :Normal Hastighet +STR_5143 :Kvick Hastighet +STR_5144 :Snabb Hastighet +STR_5145 :Turbo Hastighet +STR_5146 :Hyper Hastighet +STR_5147 :Fusk +STR_5148 :{SMALLFONT}{BLACK}Ändra spelets hastighet +STR_5149 :{SMALLFONT}{BLACK}Visa fusk +STR_5150 :Aktivera felsöknings verktygen +STR_5151 :, +STR_5152 :. +STR_5153 :Redigera Teman... +STR_5154 :Hårdvare hanteraren +STR_5155 :Tillåt testning av spår som inte är färdiga +STR_5156 :{SMALLFONT}{BLACK}Tillåter testning av de mesta åkturerna även när spåret är oklart, gäller inte Blockavdelade kontinuerliga banlägen +STR_5157 :Lås upp alla priser +STR_5158 :Avsluta till menyn +STR_5159 :Avsluta OpenRCT2 +STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, År {POP16}{COMMA16} +STR_5161 :Datum format: +STR_5162 :Dag/Månad/År +STR_5163 :Månad/Dag/År +STR_5164 :Twitch Kanal namn +STR_5165 :Namnge gäster efter följare +STR_5166 :{SMALLFONT}{BLACK}Kommer namnge gäster efter Twitch kanalens följare +STR_5167 :Spåra Twitch följande gäster +STR_5168 :{SMALLFONT}{BLACK}Kommer aktivera spårnings information för gäster döpta efter kanalens Twitch följare +STR_5169 :Döp gäster efter namn i Twitch chatten +STR_5170 :{SMALLFONT}{BLACK}Kommer döpa gästerna till namnen i Twitch kanalens chatt +STR_5171 :Spåra chatt gästerna +STR_5172 :{SMALLFONT}{BLACK}Kommer aktivera spårnings information för gäster döpta efter Twitch kanalens chattare +STR_5173 :Använd Twitch chatten som nyheter +STR_5174 :{SMALLFONT}{BLACK}Kommer använda Twitch chattens meddelanden följt med !nyheter som nofitikationer i spelet +STR_5175 :Skriv in namnet på Twitch kanalen +STR_5176 :Aktivera Twitch fuktionen +STR_5177 :Skärmlägen: +STR_5178 :{SMALLFONT}{BLACK}Visa ekonomiska fusk +STR_5179 :{SMALLFONT}{BLACK}Visa gäst fusk +STR_5180 :{SMALLFONT}{BLACK}Visa park fusk +STR_5181 :{SMALLFONT}{BLACK}Visa karusell fusk +STR_5182 :{INT32} +STR_5183 :Bas höjd +STR_5184 :Skriv in bas höjden mellan {COMMA16} och {COMMA16} +STR_5185 :Vatten nivå +STR_5186 :Skriv in vatten nivån mellan {COMMA16} och {COMMA16} +STR_5187 :Finansiering +STR_5188 :Ny Kampanj +STR_5189 :Forskning +STR_5190 :Karta +STR_5191 :Bildskärm +STR_5192 :Nyliga Nyheter +STR_5193 :Land +STR_5194 :Vatten +STR_5195 :Rensa Dekorationer +STR_5196 :Landsrättigheter +STR_5197 :Dekorationer +STR_5198 :Gångväg +STR_5199 :Karusell Konstruktion +STR_5200 :Spår Design Placering +STR_5201 :Ny åktur +STR_5202 :Spår Design val +STR_5203 :Åkturer +STR_5204 :Åkturs Lista +STR_5205 :Gäst +STR_5206 :Gäst Lista +STR_5207 :Personal +STR_5208 :Personal Lista +STR_5209 :Banderoll +STR_5210 :Objekt Väljare +STR_5211 :Forsknings Lista +STR_5212 :Dekorations Inställningar +STR_5213 :Mål Inställningar +STR_5214 :Kart-Generator +STR_5215 :Spår Design Hanterare +STR_5216 :Spår Design Hanterarings Lista +STR_5217 :Fusk +STR_5218 :Teman +STR_5219 :Inställningar +STR_5220 :Snabbtangenter +STR_5221 :Ändra Snabbtangenter +STR_5222 :Ladda/Spara +STR_5223 :Spara Inmatning +STR_5224 :Riva Åkturs Hanteraren +STR_5225 :Avskeda Personal Hanteraren +STR_5226 :Radera Spår Hanteraren +STR_5227 :Spar Överskrivar Hanteraren +STR_5228 :{SMALLFONT}{BLACK}Huvudgränsnitt +STR_5229 :{SMALLFONT}{BLACK}Park +STR_5230 :{SMALLFONT}{BLACK}Verktyg +STR_5231 :{SMALLFONT}{BLACK}Åkturer och Gäster +STR_5232 :{SMALLFONT}{BLACK}Redigerare +STR_5233 :{SMALLFONT}{BLACK}Övrigt +STR_5234 :{SMALLFONT}{BLACK}Hanterare +STR_5235 :{SMALLFONT}{BLACK}Inställningar +STR_5236 :Fönster: +STR_5237 :Palett: +STR_5238 :Nuvarande Tema: +STR_5239 :Kopiera +STR_5240 :Döp ditt tema +STR_5241 :Kan inte ändra detta teama +STR_5242 :Temats namn finns redan +STR_5243 :Ogiltig karaktär använd +STR_5244 :Teman +STR_5245 :Topp Verktygsfält +STR_5246 :Bott Verktygsfält +STR_5247 :Spår Redigerarens Bott Verktygsfält +STR_5248 :Dekorations Redigerarens Bott Verktygsfält +STR_5249 :Titelns Meny Knappar +STR_5250 :Titelns Avsluta Knapp +STR_5251 :Titelns Inställnings Knapp +STR_5252 :Titelns Scenario Väljare +STR_5253 :Park Information +STR_5254 :Skapa +STR_5255 :{SMALLFONT}{BLACK}Skapa ny titelsekvens från början +STR_5256 :Skapa ett nytt tema att göra ändringar på +STR_5257 :{SMALLFONT}{BLACK}Skapa ett nytt tema baserat på denna +STR_5258 :{SMALLFONT}{BLACK}Ta bort det använda temat +STR_5259 :{SMALLFONT}{BLACK}Döp om det använda temat +STR_5260 :Gigantisk skärmdump +STR_5261 :Filter +STR_5262 :Wacky Worlds +STR_5263 :Time Twister +STR_5264 :Egna +STR_5265 :{SMALLFONT}{BLACK}Välj vilket innehåll som ska vara synliga +STR_5266 :{SMALLFONT}{BLACK}Skärm +STR_5267 :{SMALLFONT}{BLACK}Kultur och Enhet +STR_5268 :{SMALLFONT}{BLACK}Ljud +STR_5269 :{SMALLFONT}{BLACK}Kontroller och Gränssnitt +STR_5270 :{SMALLFONT}{BLACK}Diverse +STR_5271 :{SMALLFONT}{BLACK}Twitch +STR_5272 :{SMALLFONT}{BLACK}Liten Dekoration +STR_5273 :{SMALLFONT}{BLACK}Stor Dekoration +STR_5274 :{SMALLFONT}{BLACK}Gångväg +STR_5275 :Sök efter Objekt +STR_5276 :Skriv in namnet på objektet du letar efter +STR_5277 :Återbetala +STR_5278 :Sandlådesläge +STR_5279 :Sandlådesläge av +STR_5280 :{SMALLFONT}{BLACK}Tillåter landsrättigheter inställningar genom "Karta" fönstret och andra inställningar som normalt är begränsat till Scenario Redigeraren +STR_5281 :{SMALLFONT}{BLACK}Tillägg +STR_5282 :RCT1 Öppen/Stängd Åkturs Ljus +STR_5283 :RCT1 Öppen/Stängd Parks Ljus +STR_5284 :RCT1 Scenario Väljar Font +STR_5285 :EXPLODERA!!! +STR_5286 :{SMALLFONT}{BLACK}Får gäster att explodera +STR_5287 :Åkturen är redan trasig +STR_5288 :Åkturen är stängd +STR_5289 :Inga haverier tillgängliga för denna åktur +STR_5290 :Laga åktur +STR_5291 :Kan inte tvinga haveri +STR_5292 :{SMALLFONT}{BLACK}Tvinga haveri +STR_5293 :{SMALLFONT}{BLACK}Ständ åktur/attraktion +STR_5294 :{SMALLFONT}{BLACK}Testa åktur/attraktion +STR_5295 :{SMALLFONT}{BLACK}Öppna åktur/attraktion +STR_5296 :{SMALLFONT}{BLACK}Stäng parken +STR_5297 :{SMALLFONT}{BLACK}Öppna parken +STR_5298 :{RED}{STRINGID} +STR_5299 :{LIGHTPINK}{STRINGID} +STR_5300 :{SMALLFONT}{BLACK}Snabb avskeda personal +STR_5301 :{MEDIUMFONT}{BLACK}Återbetala ditt lån +STR_5302 :Återbetala lån +STR_5303 :Tillåt byggande i pausat läge +STR_5304 :Titelsekvens: +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 :Slumpvald +STR_5311 :{SMALLFONT}{BLACK}Felsöknings verktyg +STR_5312 :Visa konsol +STR_5313 :Visa rut inspekteraren +STR_5314 :Rut inspekteraren +STR_5315 :Gräs +STR_5316 :Sand +STR_5317 :Jord +STR_5318 :Sten +STR_5319 :Utomjordisk +STR_5320 :Schackbräde +STR_5321 :Gräs klumpar +STR_5322 :Is +STR_5323 :Nät (röd) +STR_5324 :Nät (gul) +STR_5325 :Nät (blå) +STR_5326 :Nät (grön) +STR_5327 :Sand (mörk) +STR_5328 :Sand (ljus) +STR_5329 :Schackbräde (omvänt) +STR_5330 :Underjordisk vy +STR_5331 :Sten +STR_5332 :Trä (röd) +STR_5333 :Trä (svart) +STR_5334 :Is +STR_5335 :Åkturs Ingång +STR_5336 :Åkturs Utgång +STR_5337 :Park Entré +STR_5338 :Ämnes Typ +STR_5339 :{SMALLFONT}{BLACK}Bas höjd +STR_5340 :{SMALLFONT}{BLACK}Frihöjd +STR_5341 :Flaggor +STR_5342 :Välj en ruta +STR_5343 :Automatiskt placera personal +STR_5344 :Logg över Förändringar +STR_5345 :Finans fusk +STR_5346 :Gäst fusk +STR_5347 :Park fusk +STR_5348 :Åkturs fusk +STR_5349 :{SMALLFONT}{BLACK}Alla åkturer +STR_5350 :Max +STR_5351 :Min +STR_5352 :{BLACK}Glädje: +STR_5353 :{BLACK}Energi: +STR_5354 :{BLACK}Hunger: +STR_5355 :{BLACK}Törst: +STR_5356 :{BLACK}Illamående: +STR_5357 :{BLACK}Illamående tolerans: +STR_5358 :{BLACK}Blåsa: +STR_5359 :Ta bort gäster +STR_5360 :{SMALLFONT}{BLACK}Tar bort alla gäster från parken +STR_5361 :Ge alla gäster: +STR_5362 :{BLACK}Gästernas föredragna åkturs intensitet: +STR_5363 :Mer än 1 (Lågt) +STR_5364 :Mindre än 15 (Högt) +STR_5365 :{BLACK}Personal hastighet: +STR_5366 :Normal +STR_5367 :Snabb +STR_5368 :Återställ krash status +STR_5369 :Park inställningar... +STR_5370 :{SMALLFONT}{BLACK}Klicka på denna knapp för att modifiera{NEWLINE}park inställningar som begränsningar,{NEWLINE}gäst generering och pengar. +STR_5371 :Objekt väljare +STR_5372 :Invertera höger mus dragning +STR_5373 :Namn {STRINGID} +STR_5374 :Datum {STRINGID} +STR_5375 :{UP} +STR_5376 :{DOWN} +STR_5377 :{SMALLFONT}{BLACK}Sparfiler +STR_5378 :{SMALLFONT}{BLACK}Skript +STR_5379 :{SMALLFONT}{BLACK}Skippa til nästa wait kommando +STR_5380 :{SMALLFONT}{BLACK}Börja spela titelsekvensen +STR_5381 :{SMALLFONT}{BLACK}Sluta spela titelsekvensen +STR_5382 :{SMALLFONT}{BLACK}Börja om titelsekvensen +STR_5383 :{SMALLFONT}{BLACK}Skapa en ny titelsekvensen baserat på den valda +STR_5384 :{SMALLFONT}{BLACK}Ta bort den valda titelsekvensen +STR_5385 :{SMALLFONT}{BLACK}Döp om den valda titelsekvensen +STR_5386 :{SMALLFONT}{BLACK}Skriv in nytt kommando +STR_5387 :{SMALLFONT}{BLACK}Redigera det valda kommandot +STR_5388 :{SMALLFONT}{BLACK}Ta bort det valda kommandot +STR_5389 :{SMALLFONT}{BLACK}Hoppa till det valda kommandot i titelsekvensen +STR_5390 :{SMALLFONT}{BLACK}Flytta valda kommandot neråt +STR_5391 :{SMALLFONT}{BLACK}Flytta valda kommandot uppåt +STR_5392 :{SMALLFONT}{BLACK}Lägg till en sparfil till titelsekvensen +STR_5393 :{SMALLFONT}{BLACK}Ta bort den valda sparfilen från titelsekvensen +STR_5394 :{SMALLFONT}{BLACK}Döp om den valda sparfilen +STR_5395 :{SMALLFONT}{BLACK}Ladda den valda sparfilen i spelet +STR_5396 :{SMALLFONT}{BLACK}Ladda om titelsekvensen om ändringar har gjorts utanför spelet +STR_5397 :Kan endast användas i titelsekvensen +STR_5398 :Kan inte redigera titelsekvensen medan den körs +STR_5399 :Klicka på stopp knappen innan du försöker ändra något +STR_5400 :Kan inte byta denna titelsekvens +STR_5401 :Skapa en ny titelsekvens att göra ändringar på +STR_5402 :Misslyckades att ladda titelsekvens +STR_5403 :De kanske inte finns något Load eller Wait kommando eller sparfilen är kanske inte giltig +STR_5404 :Namnet finns redan +STR_5405 :Skriv in ett namn för sparfilen +STR_5406 :Skriv in ett namn för titelsekvensen +STR_5407 :Lägg till +STR_5408 :Ta bort +STR_5409 :Lägg till +STR_5410 :Redigera +STR_5411 :Börja om +STR_5412 :Skippa till +STR_5413 :Ladda +STR_5414 :Load{MOVE_X}{87}Six Flags Magic Mountain.SC6 +STR_5415 :Load{MOVE_X}{87}{STRING} +STR_5416 :Load{MOVE_X}{87}Ingen sparfil vald +STR_5417 :Location +STR_5418 :Location{MOVE_X}{87}{COMMA16} {COMMA16} +STR_5419 :Rotate +STR_5420 :Rotate{MOVE_X}{87}{COMMA16} +STR_5421 :Zoom +STR_5422 :Zoom{MOVE_X}{87}{COMMA16} +STR_5423 :Wait +STR_5424 :Wait{MOVE_X}{87}{COMMA16} +STR_5425 :Restart +STR_5426 :End +STR_5427 :Kordinater: +STR_5428 :Moturs rotation: +STR_5429 :Zoom nivå: +STR_5430 :Sekunder att vänta: +STR_5431 :Sparfil att ladda: +STR_5432 :Kommando: +STR_5433 :Titelsekvens +STR_5434 :Kommando Redigerare +STR_5435 :Döp om sparat spel +STR_5436 :Redigera titelsekvens... +STR_5437 :Ingen sparfil vald +STR_5438 :Kan inte göra ändringar medan kommando redigeraren är öppen +STR_5439 :Ett wait kommando med åtminstone 4 sekunder krävs för ett restart kommando +STR_5440 :Minimera fullskärm vid tappad fokus +STR_5441 :{SMALLFONT}{BLACK}Identifera åkturer via spår typ,{NEWLINE}så vagnar kan bli ändrade{NEWLINE}efteråt, som i RCT1. +STR_5442 :Tvinga park betyg: +STR_5443 :Hastighet{MOVE_X}{87}{STRINGID} +STR_5444 :Hastighet: +STR_5445 :Hastighet +STR_5446 :Få +STR_5447 :Typ {STRINGID} +STR_5448 :Åktur / Fordon {STRINGID} +STR_5449 :Minska spel hastigheten +STR_5450 :Öka spel hastigheten +STR_5451 :Öppna fusk fönstret +STR_5452 :Växla visning av verktysrader +STR_5453 :Välj en annan åktur +STR_5454 :Lås upp FPS +STR_5455 :Aktivera sandlåds läge +STR_5456 :Placera föremål på varandra +STR_5457 :Avaktivera Stödplar Gränserna +STR_5458 :Rotatera medurs +STR_5459 :Rotatera moturs +STR_5460 :Rotera vyn moturs +STR_5461 :Gästernas inställningar +STR_5462 :{CURRENCY} +STR_5463 :Mål: Ha kul! +STR_5464 :Allmänt +STR_5465 :Klimat +STR_5466 :Personal +STR_5467 :ALT + +STR_5468 :Nyliga meddelanden +STR_5469 :Skrolla kartan upp +STR_5470 :Skrolla kartan vänster +STR_5471 :Skrolla kartan ner +STR_5472 :Skrolla kartan höger +STR_5473 :Växla mellan dag / natt +STR_5474 :Visa text i banderoller med stora bokstäver +STR_5475 :{COMMA16} veckor +STR_5476 :Hårdvara +STR_5477 :Rendering +STR_5478 :Kontroller +STR_5479 :Verktygsrad +STR_5480 :Visa knappar för: +STR_5481 :Teman +STR_5482 :{WINDOW_COLOUR_2}Tid sen senaste inspektionen: {BLACK}1 minut +STR_5483 :{BLACK}({COMMA16} veckor återstår) +STR_5484 :{BLACK}({COMMA16} vecka återstår) +STR_5485 :{SMALLFONT}{STRING} +STR_5486 :{BLACK}{COMMA16} +STR_5487 :{SMALLFONT}{BLACK}Visa nyliga meddelanden +STR_5488 :Ingen ingång (OpenRCT2 endast!) +STR_5489 :{SMALLFONT}{BLACK}Visa endast gäster du följer +STR_5490 :Stäng av ljudet vid minimerat spel +STR_5491 :Uppfinning list +STR_5492 :Scenario inställningar +STR_5493 :Skicka Meddelande +STR_5494 : +STR_5495 :Spelar Lista +STR_5496 :Spelare: +STR_5497 :Ping: +STR_5498 :Server Lista +STR_5499 :Spelarens Namn: +STR_5500 :Lägg till server +STR_5501 :Starta en server +STR_5502 :Flerspelare +STR_5503 :Skriv in ägarens namn eller IP adressen: +STR_5504 :{SMALLFONT}{BLACK}Visa alla spelare +STR_5505 :Kunde inte ansluta till servern. +STR_5506 :Gästerna igronerar intensivitetnivån +STR_5507 :Vaktmästare klipper alltid gräs +STR_5508 :Tillåt filer med inkorrekta 'checksums' att laddas +STR_5509 :{SMALLFONT}{BLACK}Tillåter spelet att ladda scenarion och sparfiler som har inkorrekta checksum, som scenariorna från demon och skadade sparfiler. +STR_5510 :Standard ljuduppspelningen +STR_5511 :(UNKNOWN) +STR_5512 :Spara spelet som +STR_5513 :(Snabb) spara spelet +STR_5514 :Stäng av skadegörelse +STR_5515 :{SMALLFONT}{BLACK}Stoppar gäster från att vandalisera parken när de är arga +STR_5516 :{SMALLFONT}{BLACK}Svart +STR_5517 :{SMALLFONT}{BLACK}Grå +STR_5518 :{SMALLFONT}{BLACK}Vit +STR_5519 :{SMALLFONT}{BLACK}Mörk lila +STR_5520 :{SMALLFONT}{BLACK}Mjuk lila +STR_5521 :{SMALLFONT}{BLACK}Ljus lila +STR_5522 :{SMALLFONT}{BLACK}Mörk blå +STR_5523 :{SMALLFONT}{BLACK}Ljus blå +STR_5524 :{SMALLFONT}{BLACK}Isig blå +STR_5525 :{SMALLFONT}{BLACK}Mörkt vatten +STR_5526 :{SMALLFONT}{BLACK}Ljust vatten +STR_5527 :{SMALLFONT}{BLACK}Mättad grön +STR_5528 :{SMALLFONT}{BLACK}Mörk grön +STR_5529 :{SMALLFONT}{BLACK}Moss grön +STR_5530 :{SMALLFONT}{BLACK}Ljud grön +STR_5531 :{SMALLFONT}{BLACK}Oliv grön +STR_5532 :{SMALLFONT}{BLACK}Mörk oliv grön +STR_5533 :{SMALLFONT}{BLACK}Ljus gul +STR_5534 :{SMALLFONT}{BLACK}Gul +STR_5535 :{SMALLFONT}{BLACK}Mörk gul +STR_5536 :{SMALLFONT}{BLACK}Ljus orange +STR_5537 :{SMALLFONT}{BLACK}Mörk orange +STR_5538 :{SMALLFONT}{BLACK}Ljus brun +STR_5539 :{SMALLFONT}{BLACK}Mättad brun +STR_5540 :{SMALLFONT}{BLACK}Mörk brun +STR_5541 :{SMALLFONT}{BLACK}Lax rosa +STR_5542 :{SMALLFONT}{BLACK}Lyx röd +STR_5543 :{SMALLFONT}{BLACK}Mättad röd +STR_5544 :{SMALLFONT}{BLACK}Ljus röd +STR_5545 :{SMALLFONT}{BLACK}Mörk rosa +STR_5546 :{SMALLFONT}{BLACK}Ljus rosa +STR_5547 :{SMALLFONT}{BLACK}Lätt rosa +STR_5548 :Visa alla körlägen +STR_5549 :År/Månad/Dag +STR_5550 :{POP16}{POP16}År {COMMA16}, {PUSH16}{PUSH16}{MONTH} {PUSH16}{PUSH16}{STRINGID} +STR_5551 :År/Dag/Månad +STR_5552 :{POP16}{POP16}År {COMMA16}, {PUSH16}{PUSH16}{PUSH16}{STRINGID} {MONTH} +STR_5553 :Pausa spelet när Steam overlayen är uppe +STR_5554 :{SMALLFONT}{BLACK}Tillåt berg verktyget +STR_5555 :Visa fordon från andra karuseller +STR_5556 :{SMALLFONT}{BLACK}Sparka ut spelare +STR_5557 :Fortsätt vara ansluten efter synk-problem (Online) +STR_5558 :En omstart krävs för denna inställning ska gälla +STR_5559 :10 min. inspektion +STR_5560 :{SMALLFONT}{BLACK}Sätter inspektions tiden till 'Var 10 minut' på alla åkturer +STR_5561 :Misslyckades att ladda språk +STR_5562 :VARNING! +STR_5563 :Denna funktion är i nuläget ostabil, använd med försiktighet. +STR_5564 :Insert Corrupt Element +STR_5565 :{SMALLFONT}{BLACK}Inserts a corrupt map element at top of tile. This will hide any element above the corrupt element. ** +STR_5566 :Lösenord: +STR_5567 :Visa för alla spelare +STR_5568 :Lösenord krävs +STR_5569 :Denna server kräver lösenord +STR_5570 :Hämta Servrar +STR_5571 :Gå med i Spel +STR_5572 :Lägg Till I Favoriter +STR_5573 :Ta Bort Från Favoriter +STR_5574 :Server Namn: +STR_5575 :Max Spelare: +STR_5576 :Port: +STR_5577 :Syd Koreansk Won (W) +STR_5578 :Rysk Rouble (R) +STR_5579 :Fönster skalning: +STR_5580 :Czech koruna (Kc) +STR_5581 :Visa FPS +STR_5582 :Behåll muspekaren i spelet +STR_5583 :{COMMA1DP16}ms{POWERNEGATIVEONE} +STR_5584 :SI +STR_5585 :{SMALLFONT}{BLACK}Avaktivera åkturernas hastighetsgränser, vilket tillåter till exepmepl {VELOCITY} upplyftskedjeshastighet +STR_5586 :Öppna butiker och stånd automatiskt +STR_5587 :{SMALLFONT}{BLACK}Om aktiverad, butiker och stånd öppnas automatiskt efter du har byggt dem +STR_5588 :{SMALLFONT}{BLACK}Spela med andra spelare +STR_5589 :Notifikations Inställningar +STR_5590 :Park priser +STR_5591 :Marknadskampanj är avslutad +STR_5592 :Park varningar +STR_5593 :Park rating warnings +STR_5594 :Åktur har gått sönder +STR_5595 :Åktur har kraschat +STR_5596 :Åktur varning +STR_5597 :Ride / scenery researched +STR_5598 :Gäst varning +STR_5599 :Gäst är vilse +STR_5600 :Gäst har lämnat parken +STR_5601 :Gäst köar för åktur +STR_5602 :Gäst är på åktur +STR_5603 :Gäst har lämnat åktur +STR_5604 :Gäst har köpt föremål +STR_5605 :Guest has used facility +STR_5606 :Gäst har dött +STR_5607 :{SMALLFONT}{BLACK}Tvinga borttagning av vald ruta/element. +STR_5608 :BH +STR_5609 :CH +STR_5610 :{SMALLFONT}{BLACK}Ta bort den valda rutan/elementet. Detta kommer tvinga en borttagning, så inga pengar kommer ges/användas. Använd med försiktighet. +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}Sista elementet för tile flag +STR_5617 :{SMALLFONT}{BLACK}Flytta valda elementet upp. +STR_5618 :{SMALLFONT}{BLACK}Flytta valda elementet ner. +STR_5619 :RollerCoaster Tycoon +STR_5620 :Tillagda Attraktioner +STR_5621 :Loopy Landscapes +STR_5622 :RollerCoaster Tycoon 2 +STR_5623 :Wacky Worlds +STR_5624 :Time Twister +STR_5625 :{OPENQUOTES}Riktiga{ENDQUOTES} Parker +STR_5626 :Andra parker +STR_5627 :Sortera scenarion via: +STR_5628 :Spel paket +STR_5629 :Svårighetsgrad +STR_5630 :Tillåt upplåsning av scenarion +STR_5631 :Orginal DLC parker +STR_5632 :Bygg din egna... +STR_5633 :CMD + +STR_5634 :OPTION + +STR_5635 :{WINDOW_COLOUR_2}Pengar spenderat: {BLACK}{CURRENCY2DP} +STR_5636 :{WINDOW_COLOUR_2}Utförda kommandon: {BLACK}{COMMA16} +STR_5637 :Kan inte göra detta... +STR_5638 :Åtkomst nekad +STR_5639 :{SMALLFONT}{BLACK}Visa lista med spelarna på servern +STR_5640 :{SMALLFONT}{BLACK}Ändra grupper +STR_5641 :Standard grupp: +STR_5642 :Grupp: +STR_5643 :Lägg till Grupp +STR_5644 :Ta bort Grupp +STR_5645 :Chatta +STR_5646 :Terräng +STR_5647 :Pausa +STR_5648 :Ändra vattennivå +STR_5649 :Skapar åktur +STR_5650 :Ta bort åktur +STR_5651 :Bygger åktur +STR_5652 :Åkturs inställningar +STR_5653 :Dekorationer +STR_5654 :Gångväg +STR_5655 :Gäster +STR_5656 :Personal +STR_5657 :Park inställningar +STR_5658 :Park fonder +STR_5659 :Sparka ut spelare +STR_5660 :Modifiera grupper +STR_5661 :Sätt spelares grupp +STR_5662 :N/A +STR_5663 :Rensa landskap +STR_5664 :Fusk +STR_5665 :Dekoration Utspridning +STR_5701 :{WINDOW_COLOUR_2}Senaste handling: {BLACK}{STRINGID} +STR_5702 :{SMALLFONT}{BLACK}Visa spelarens senaste handling +STR_5703 :Kan inte sparka ut ägaren +STR_5704 :Senaste Handling: +STR_5705 :Kan inte välja denna grupp +STR_5706 :Kan inte ta bort grupper spelare finns i +STR_5707 :Denna grupp kan inte modifieras +STR_5708 :Kan inte ändra gruppen ägaren är i +STR_5709 :Döp om Grupp +STR_5710 :Grupp namn +STR_5711 :Skriv in ett nytt namn för gruppen: +STR_5712 :Kan inte modifiera tillstånd du inte själv har +STR_5713 :Sparka ut Spelaren +STR_5714 :Visa inställningsfönstret +STR_5715 :Nytt Spel +STR_5716 :Inte tillåtet i flerspelsläge +# For identifying client network version in server list window +STR_5717 :Nätverkets version: {STRING} +STR_5718 :{SMALLFONT}{BLACK}Nätverkets version: {STRING} +STR_5719 :Soligt +STR_5720 :Delvis Molning +STR_5721 :Molningt +STR_5722 :Regn +STR_5723 :Spö Regn +STR_5724 :Åska +STR_5725 :{BLACK}Tvinga Väder: +STR_5726 :{SMALLFONT}{BLACK}Sätter vädret i parken +STR_5727 :Skalnings kvalité +STR_5728 :Kräver att Hårdvare hanteraren är ikryssad +STR_5729 :{SMALLFONT}{BLACK}Kräver att Hårdvare hanteraren är ibockad +STR_5730 :Närmsta granne +STR_5731 :Linjär +STR_5732 :Anisotropisk +STR_5733 :Använd NN skalning som enhetskalor +# tooltip for tab in options window +STR_5734 :{SMALLFONT}{BLACK}Rendering +STR_5735 :Nätverksstatus +STR_5736 :Spelare +STR_5737 :Stängd, {COMMA16} person fortfarande på åkturen +STR_5738 :Stängd, {COMMA16} personer fortfarande på åkturen +STR_5739 :{WINDOW_COLOUR_2}Kunder på åktur: {BLACK}{COMMA16} +STR_5740 :Oändliga kampanjer +STR_5741 :{SMALLFONT}{BLACK}Marknadskampanjer slutar aldrig +STR_5742 :Verifierar ... +STR_5743 :Ansluter ... +STR_5744 :Laddar ... +STR_5745 :Du är inte i synk med servern +STR_5746 :Frånkopplad +STR_5747 :Frånkopplad: {STRING} +STR_5748 :Utslängd +STR_5749 :Ut från servern! +STR_5750 :Anslutningen är avslutad +STR_5751 :Ingen Data +STR_5752 :{OUTLINE}{RED}{STRING} har lämnat +STR_5753 :{OUTLINE}{RED}{STRING} har lämnat ({STRING}) +STR_5754 :Ogiltigt Spelar Namn +STR_5755 :Fel Version av OpenRCT +STR_5756 :Fel Lösenord +STR_5757 :Servern är Full +STR_5758 :{OUTLINE}{GREEN}{STRING} har anslutit till spelet +STR_5759 :Laddar ner barnan ... ({INT32} / {INT32}) +STR_5760 :Hong Kong Dollar (HK$) +STR_5761 :New Taiwan Dollar (NT$) +STR_5762 :Kinesiska Yuan (CN{YEN}) +STR_5763 :Alla filer +STR_5764 :Ogilltig åkturs typ +STR_5765 :Kan inte redigera åkturer av okända typer +STR_5766 : +STR_5767 :Inkomst +STR_5768 :Totala kunder +STR_5769 :Totala vinst +STR_5770 :Kunder per timme +STR_5771 :Driftskostnad +STR_5772 :Ålder +STR_5773 :Totala kunder: {COMMA32} +STR_5774 :Totala vinst: {CURRENCY2DP} +STR_5775 :Kunder: {COMMA32} per hour +STR_5776 :Byggd: Detta år +STR_5777 :Byggd: Förra året +STR_5778 :Byggd: {COMMA16} År sen +STR_5779 :Inkomst: {CURRENCY2DP} per timme +STR_5780 :Kör kostnad: {CURRENCY2DP} per timme +STR_5781 :Kör kostnad: Okänd +STR_5782 :Du är nu ansluten. Tryck på '{STRING}' för att skriva. +STR_5783 :{WINDOW_COLOUR_2}Scenario Låst +STR_5784 :{BLACK}Klara tidigare senarion för att låsa upp denna +STR_5785 :Kan inte byta gruppnamn... +STR_5786 :Ogiltigt gruppnamn +STR_5787 :{COMMA32} spelare anslutna +STR_5788 :Inspektions mellanrum: +STR_5789 :Avaktivera åsk effekter +STR_5790 :{SMALLFONT}{BLACK}Växlar mellan RCT1-stilens prissättning{NEWLINE}(både karusell- och entré biljettpris) +STR_5791 :{SMALLFONT}{BLACK}Sätter tillförlitligheten på alla karuseller till 100%{NEWLINE}och sätter deras byggda datum till 'Detta år' +STR_5792 :{SMALLFONT}{BLACK}Fixar alla trasiga karuseller +STR_5793 :{SMALLFONT}{BLACK}Tar bort krash historiken för alla åkturer,{NEWLINE}så gäster inte klagar på farliga attraktioner +STR_5794 :{SMALLFONT}{BLACK}Vissa scenarion tillåter inte redigering{NEWLINE}av vissa åkturer som redan exsisterar i parken.{NEWLINE}Detta fusk lyfter den begränsningen +STR_5795 :{SMALLFONT}{BLACK}Gäster åker alla attraktioner i parken{NEWLINE}även om intensiteten är extremt hög på karusellen +STR_5796 :{SMALLFONT}{BLACK}Tvingar parken att stänga eller öppnas +STR_5797 :{SMALLFONT}{BLACK}Avaktiverar väderändringar och{NEWLINE}behåller det valda vädret +STR_5798 :{SMALLFONT}{BLACK}Tillåter byggnationer när spelet är pausat +STR_5799 :{SMALLFONT}{BLACK}Avaktiverar haveriet bromsfel så åkturernas vagnar inte krockar med varandra +STR_5800 :{SMALLFONT}{BLACK}Hindrar karuseller från att gå sönder -# Note: as this is an unmaintained language, don't add new strings unless you intend to become the mainainer. +############# +# Scenarion # +################ +# RCT Original # +################ + +STR_SCNR :Forest Frontiers +STR_PARK :Forest Frontiers +STR_DTLS :Djupt in i skogen, ska du bygga en utgrenande nöjespark på en stor öppen glänta + + +STR_SCNR :Dynamite Dunes +STR_PARK :Dynamite Dunes +STR_DTLS :Bygg i den varma ökenhettan, detta nöjesfält har bara en berg-o-dalbana men har plats för utveckling + + +STR_SCNR :Leafy Lake +STR_PARK :Leafy Lake +STR_DTLS :Börja från början till att bygga ett nöjesfält runt en stor sjö + + +STR_SCNR :Diamond Heights +STR_PARK :Diamond Heights +STR_DTLS :Diamond Heights är redan en framgångsrik nöjespark - utveckla den för att dubbla värdet + + +STR_SCNR :Evergreen Gardens +STR_PARK :Evergreen Gardens +STR_DTLS :Gör om den vackra trädgården till en spännande nöjespark + + +STR_SCNR :Bumbly Beach +STR_PARK :Bumbly Beach +STR_DTLS :Utveckla Bumbly Beach's lilla nöjespark nära stranden i ett samhälle till en spännande turistattraktion till stranden + + +STR_SCNR :Trinity Islands +STR_PARK :Trinity Islands +STR_DTLS :Flera små öar som är till för att bygga en mega park + + +STR_SCNR :Katie's Dreamland +STR_PARK :Katie's Dreamland +STR_DTLS :Ett litet nöjesfält som behöver uppfräschas och utökas - Ditt mål är att dubbla parkvärdet + + +STR_SCNR :Pokey Park +STR_PARK :Pokey Park +STR_DTLS :En liten, trång nöjespark som behöver en stor uppfräschning och utvigning + + +STR_SCNR :White Water Park +STR_PARK :White Water Park +STR_DTLS :En park med fantastiska vattenattraktioner som behöver utökas + + +STR_SCNR :Millennium Mines +STR_PARK :Millennium Mines +STR_DTLS :Bygg om en stor övergiven gruva till ett stort nöjesfält + + +STR_SCNR :Karts & Coasters +STR_PARK :Karts & Coasters +STR_DTLS :En stor park gömd i skogen, med endast go-karts och trä berg-o-dalbanor + + +STR_SCNR :Mel's World +STR_PARK :Mel's World +STR_DTLS :Detta nöjesfält har några moderna karuseller, men med massor av plats för utökning + + +STR_SCNR :Mystic Mountain +STR_PARK :Mystic Mountain +STR_DTLS :I den beriga skogen Mystic Mountain, bygg ett nöjesfält från början + + +STR_SCNR :Pacific Pyramids +STR_PARK :Pacific Pyramids +STR_DTLS :Fövandla de Egyptiska Ruinerna till en spännande nöjespark + + +STR_SCNR :Crumbly Woods +STR_PARK :Crumbly Woods +STR_DTLS :En stor park med väldesignade, men äldre attraktioner - Byt ut dem gamla eller skaffa nya för att få parken mer populär + + +STR_SCNR :Paradise Pier +STR_PARK :Paradise Pier +STR_DTLS :Fövandla denna trötta Pir till en välkänd attraktion + + +STR_SCNR :Lightning Peaks +STR_PARK :Lightning Peaks +STR_DTLS :Dem vackra bergen vid Lightning Peaks är populär för fotgängare och ävertyrare - Använd marken för att attrahera nya spänningssökande gäster + + +STR_SCNR :Ivory Towers +STR_PARK :Ivory Towers +STR_DTLS :En välgrundad park, som har några problem + + +STR_SCNR :Rainbow Valley +STR_PARK :Rainbow Valley +STR_DTLS :Rainbow Valley's lokala myndigheten tillåter inga land ändringar eller stora trädfällningar, men du måste göra en stor park av marken ändå + + +STR_SCNR :Thunder Rock +STR_PARK :Thunder Rock +STR_DTLS :Thunder Rock är i mitten av öknen och attraherar många turister - Använd den tillgängliga marken för att locka mer turister + + +STR_SCNR :Mega Park +STR_PARK :Mega Park +STR_DTLS :För skoj skull! + +## Added Attractions + +STR_SCNR :Whispering Cliffs +STR_PARK :Whispering Cliffs +STR_DTLS :Utveckla havskustens klippor till en spännande nöjespark + + +STR_SCNR :Three Monkeys Park +STR_PARK :Three Monkeys Park +STR_DTLS :I centrum av denna stora utvecklande parken finns ett trippel-spår racing/duellering stål berg-o-dalbana + + +STR_SCNR :Canary Mines +STR_PARK :Canary Mines +STR_DTLS :Denna övergivna gruva har redan några få turistattraktioner som en miniatyr tågbarna och ett par berg-o-dalbanor + + +STR_SCNR :Barony Bridge +STR_PARK :Barony Bridge +STR_DTLS :En gammal övergiven bro som du får förvandla till ett nöjesfält + + +STR_SCNR :Funtopia +STR_PARK :Funtopia +STR_DTLS :Utsträckande mark på båda sidor av en motorväg, denna park har ett flertal åkturer igång + + +STR_SCNR :Haunted Harbor +STR_PARK :Haunted Harbor +STR_DTLS :Den lokala myndigheten har godkänt tillåtelse att sälja land i närheten billigt till denna lilla sjösatta parken, på vilkoret att vissa åkturer är bevarade + + +STR_SCNR :Fun Fortress +STR_PARK :Fun Fortress +STR_DTLS :Detta slott är ditt att förvandla till ett nöjesfält + + +STR_SCNR :Future World +STR_PARK :Future World +STR_DTLS :Denna framtidsdrivna parken har massor med plats för nya åkturer på dess rymd landskap + + +STR_SCNR :Gentle Glen +STR_PARK :Gentle Glen +STR_DTLS :Den lokala befolkningen föredrar lugna attraktioner, så det är ditt jobb att bygga på denna park med deras behov + + +STR_SCNR :Jolly Jungle +STR_PARK :Jolly Jungle +STR_DTLS :Djupt in i djungeln ligger en öppen mark väntandes på att bli förvandlat till ett nöjesfält + + +STR_SCNR :Hydro Hills +STR_PARK :Hydro Hills +STR_DTLS :En serie av sjöar och berg formar basen till detta nöjesfält + + +STR_SCNR :Sprightly Park +STR_PARK :Sprightly Park +STR_DTLS :Denna historiska park har mycket historia, men är också mycket skuldsatt + + +STR_SCNR :Magic Quarters +STR_PARK :Magic Quarters +STR_DTLS :Ett stort område av land har blivit rensat och teman nedsatta för att göra en park med teman + + +STR_SCNR :Fruit Farm +STR_PARK :Fruit Farm +STR_DTLS :En populär fruktfarm har byggt en järnväg för att öka sin inkomst, ditt jobb är att förvandla det till en spektakulär nöjespark + + +STR_SCNR :Butterfly Dam +STR_PARK :Butterfly Dam +STR_DTLS :Området runt dammen är ditt för att skapa ett nöjesfält + + +STR_SCNR :Coaster Canyon +STR_PARK :Coaster Canyon +STR_DTLS :En stor ravin som är din för att byggas till ett nöjesfält + + +STR_SCNR :Thunderstorm Park +STR_PARK :Thunderstorm Park +STR_DTLS :Vädret är så vått så den stora pyramiden är byggd för att låta attraktioner ha skydd från regnet + + +STR_SCNR :Harmonic Hills +STR_PARK :Harmonic Hills +STR_DTLS :Den lokala myndigheten tillåter dig inte att bygga över trädhöjderna i dennna park + + +STR_SCNR :Roman Village +STR_PARK :Roman Village +STR_DTLS :Utveckla denna romerska park genom att utöka den + + +STR_SCNR :Swamp Cove +STR_PARK :Swamp Cove +STR_DTLS :Byggd på små öar, denna park har redan några berg-o-dalbanor på sig + + +STR_SCNR :Adrenaline Heights +STR_PARK :Adrenaline Heights +STR_DTLS :Bygg en park för den hög intensitets-spänningssökande lokala befolkningen + + +STR_SCNR :Utopia Park +STR_PARK :Utopia Park +STR_DTLS :En oas i mitten av öknen skapar en ovanlig chans till att bygga en nöjespark + + +STR_SCNR :Rotting Heights +STR_PARK :Rotting Heights +STR_DTLS :Igenvuxet och förfallet, kan du återuppliva detta övergivna nöjesfält? + + +STR_SCNR :Fiasco Forest +STR_PARK :Fiasco Forest +STR_DTLS :Full av dåliga- och farliga berg-o-dalbanor, du har en väldigt tajt budget att fixa problemen och vändra perken tillbaka till det positiva + + +STR_SCNR :Pickle Park +STR_PARK :Pickle Park +STR_DTLS :Den lokala myndigheten tillåter ingen reklam eller marknadsföring, så denna park måste klara sig med sitt rykte + + +STR_SCNR :Giggle Downs +STR_PARK :Giggle Downs +STR_DTLS :En hästbana för hinderlöpning är i centrum för denna växande park + + +STR_SCNR :Mineral Park +STR_PARK :Mineral Park +STR_DTLS :Förvandla detta övergivna stenbrott till en plats för att locka spänningsökande turister + + +STR_SCNR :Coaster Crazy +STR_PARK :Coaster Crazy +STR_DTLS :Du har begränsade fonder men oändligt med tid att förvandla denna klippsida till en stor berg-o-dalbane park + + +STR_SCNR :Urban Park +STR_PARK :Urban Park +STR_DTLS :En liten park som har gjort en uppgörelse med staden som tillåter byggnationer genom staden + + +STR_SCNR :Geoffrey Gardens +STR_PARK :Geoffrey Gardens +STR_DTLS :En stor trädgård måste förvandlas till ett spännande nöjesfält + + +## Loopy Landscapes + +STR_SCNR :Iceberg Islands +STR_PARK :Iceberg Islands +STR_DTLS :En samling av isberg i det kalla klimatet som ska förvandlas till ett nöjesfält + + +STR_SCNR :Volcania +STR_PARK :Volcania +STR_DTLS :En passiv vulkan är grunden till denna berg-o-dalbane byggar utmaningen + + +STR_SCNR :Arid Heights +STR_PARK :Arid Heights +STR_DTLS :Fri från någon finansiell gräns, din utmaning är att utöka denna ökenpark medan du håller gästerna glada + + +STR_SCNR :Razor Rocks +STR_PARK :Razor Rocks +STR_DTLS :Ditt mål är att bygga en stor berg-o-dalbane park mellan sylvassa stenar + + +STR_SCNR :Crater Lake +STR_PARK :Crater Lake +STR_DTLS :En stor sjö i en uråldrig krater är grunden för parken + + +STR_SCNR :Vertigo Views +STR_PARK :Vertigo Views +STR_DTLS :Denna stora park har redan en imponerande berg-o-dalbana, men ditt mål är att öka vinsten + + +STR_SCNR :Paradise Pier 2 +STR_PARK :Paradise Pier 2 +STR_DTLS :Paradise Pier har utökat sitt nätverk med gångvägar över haven, ditt mål är att utöka parken för att använda den tillgängliga marken + + +STR_SCNR :Dragon's Cove +STR_PARK :Dragon's Cove +STR_DTLS :Denna sjösatta vik är grunden för denna berg-o-dalbane utmaningen + + +STR_SCNR :Good Knight Park +STR_PARK :Good Knight Park +STR_DTLS :Ett slott med ett par karuseller måste utrustas med nya karuseller + + +STR_SCNR :Wacky Warren +STR_PARK :Wacky Warren +STR_DTLS :En park som har sina gångar och karuseller underjorden + + +STR_SCNR :Grand Glacier +STR_PARK :Grand Glacier +STR_DTLS :En glaciärdal är din för att skapa ett nöjesfält + + +STR_SCNR :Crazy Craters +STR_PARK :Crazy Craters +STR_DTLS :I en värld långt bort där pengar inte är nödvändigt, måste du bygga ett nöjesfält för att få befolkningen glada + + +STR_SCNR :Dusty Desert +STR_PARK :Dusty Desert +STR_DTLS :Fem berg-o-dalbanor måste slutföras i detta ökenområde + + +STR_SCNR :Woodworm Park +STR_PARK :Woodworm Park +STR_DTLS :Denna historiska park är endast tillåten att bygga äldre, historiska attraktioner + + +STR_SCNR :Icarus Park +STR_PARK :Icarus Park +STR_DTLS :Utvekcla denna alien park för att maximera deras vinst + + +STR_SCNR :Sunny Swamps +STR_PARK :Sunny Swamps +STR_DTLS :Denna temapark har redan ett antal med åkturer, med gott om utrymme för utökning + + +STR_SCNR :Frightmare Hills +STR_PARK :Frightmare Hills +STR_DTLS :En läskig park med en stor mittplaserad karusell + + +STR_SCNR :Thunder Rocks +STR_PARK :Thunder Rocks +STR_DTLS :Två stora stenar sticker upp från sanden, vilket är början till konstruktionen av en nöjespark + + +STR_SCNR :Octagon Park +STR_PARK :Octagon Park +STR_DTLS :I denna stora park måste du designa och bygga tio berg-o-dalbanor + + +STR_SCNR :Pleasure Island +STR_PARK :Pleasure Island +STR_DTLS :En lång tunn ö gör det utmanande att bygga berg-o-dalbanor med ett fåtal att välja på + + +STR_SCNR :Icicle Worlds +STR_PARK :Icicle Worlds +STR_DTLS :Ett isigt landskap måste byggas om till en varm nöjespark + + +STR_SCNR :Southern Sands +STR_PARK :Southern Sands +STR_DTLS :En öken park med några läckra attraktioner är din till att bygga på + + +STR_SCNR :Tiny Towers +STR_PARK :Tiny Towers +STR_DTLS :I denna lilla park måste du slutföra de fem ofärdiga berg-o-dalbanorna + + +STR_SCNR :Nevermore Park +STR_PARK :Nevermore Park +STR_DTLS :En stor park med ett ovanligt transportsystem runt kanterna + + +STR_SCNR :Pacifica +STR_PARK :Pacifica +STR_DTLS :Denna stora ö är din för att bygga ett nöjesfält + + +STR_SCNR :Urban Jungle +STR_PARK :Urban Jungle +STR_DTLS :En gigantisk övergiven skyskrapa är ett unik chans till att bygga en park + + +STR_SCNR :Terror Town +STR_PARK :Terror Town +STR_DTLS :Detta stadsområde är ditt för att göras till en nöjespark + + +STR_SCNR :Megaworld Park +STR_PARK :Megaworld Park +STR_DTLS :En gigantiskt park packad av attraktioner behöver upprustas + + +STR_SCNR :Venus Ponds +STR_PARK :Venus Ponds +STR_DTLS :På en planet långt bort behövs denna mark förvandlas till en nöjespark + + +STR_SCNR :Micro Park +STR_PARK :Micro Park +STR_DTLS :Försök att skapa världens minsta vinstgivande park + +## Real Parks from RCT1 +# None of them had details + +STR_SCNR :Alton Towers +STR_PARK :Alton Towers +STR_DTLS : + + +STR_SCNR :Heide-Park +STR_PARK :Heide-Park +STR_DTLS : + + +STR_SCNR :Blackpool Pleasure Beach +STR_PARK :Blackpool Pleasure Beach +STR_DTLS : + +## Misc parks from RCT1 +# Had no details + +STR_SCNR :Fort Anachronism +STR_PARK :Fort Anachronism +STR_DTLS : + +##################### +# Rides/attractions # +##################### + +#WW +[CONDORRD] +STR_NAME :Kondorhjulet +STR_DESC :Åkandes i speciella byglar under spåret, passagerarna känner av känslan av flygning när dem sveper genom luften i through kondor-formade vagnar +STR_CPTY :4 passagerare per vagn + + +#Maintainer: Nubbie (Nubbiy on Github) diff --git a/data/title/openrct2/Cypress Grove Title.sv6 b/data/title/openrct2/Cypress Grove Title.sv6 new file mode 100644 index 0000000000..0becfb65cb Binary files /dev/null and b/data/title/openrct2/Cypress Grove Title.sv6 differ diff --git a/data/title/openrct2/Ill Paradise.sv6 b/data/title/openrct2/Ill Paradise.sv6 new file mode 100644 index 0000000000..62ac421cf8 Binary files /dev/null and b/data/title/openrct2/Ill Paradise.sv6 differ diff --git a/data/title/openrct2/TaCW.sv6 b/data/title/openrct2/TaCW.sv6 new file mode 100644 index 0000000000..fefd623dcd Binary files /dev/null and b/data/title/openrct2/TaCW.sv6 differ diff --git a/data/title/openrct2/Title Sequence Park 1.sv6 b/data/title/openrct2/Title Sequence Park 1.sv6 new file mode 100644 index 0000000000..873ebb9b80 Binary files /dev/null and b/data/title/openrct2/Title Sequence Park 1.sv6 differ diff --git a/data/title/openrct2/achilleshiel.sv6 b/data/title/openrct2/achilleshiel.sv6 deleted file mode 100644 index 24ce7be588..0000000000 Binary files a/data/title/openrct2/achilleshiel.sv6 and /dev/null differ diff --git a/data/title/openrct2/alexfablelake.SV6 b/data/title/openrct2/alexfablelake.SV6 deleted file mode 100644 index b48dbf132e..0000000000 Binary files a/data/title/openrct2/alexfablelake.SV6 and /dev/null differ diff --git a/data/title/openrct2/bigfoot.sv6 b/data/title/openrct2/bigfoot.sv6 deleted file mode 100644 index 662a7b28ac..0000000000 Binary files a/data/title/openrct2/bigfoot.sv6 and /dev/null differ diff --git a/data/title/openrct2/gymnasiast1.sv6 b/data/title/openrct2/gymnasiast1.sv6 deleted file mode 100644 index 916823ef7a..0000000000 Binary files a/data/title/openrct2/gymnasiast1.sv6 and /dev/null differ diff --git a/data/title/openrct2/gymnasiast2.sv6 b/data/title/openrct2/gymnasiast2.sv6 deleted file mode 100644 index a678752eb4..0000000000 Binary files a/data/title/openrct2/gymnasiast2.sv6 and /dev/null differ diff --git a/data/title/openrct2/mci.sv6 b/data/title/openrct2/mci.sv6 deleted file mode 100644 index 95008afc08..0000000000 Binary files a/data/title/openrct2/mci.sv6 and /dev/null differ diff --git a/data/title/openrct2/netgrouppark.sv6 b/data/title/openrct2/netgrouppark.sv6 deleted file mode 100644 index 4d8554ce80..0000000000 Binary files a/data/title/openrct2/netgrouppark.sv6 and /dev/null differ diff --git a/data/title/openrct2/pfckrutonium1.sv6 b/data/title/openrct2/pfckrutonium1.sv6 deleted file mode 100644 index 907da0bde0..0000000000 Binary files a/data/title/openrct2/pfckrutonium1.sv6 and /dev/null differ diff --git a/data/title/openrct2/phann.sv6 b/data/title/openrct2/phann.sv6 deleted file mode 100644 index ca3846acb5..0000000000 Binary files a/data/title/openrct2/phann.sv6 and /dev/null differ diff --git a/data/title/openrct2/poke.sv6 b/data/title/openrct2/poke.sv6 deleted file mode 100644 index f9702ff6dc..0000000000 Binary files a/data/title/openrct2/poke.sv6 and /dev/null differ diff --git a/data/title/openrct2/rid6.sv6 b/data/title/openrct2/rid6.sv6 deleted file mode 100644 index c83a3af928..0000000000 Binary files a/data/title/openrct2/rid6.sv6 and /dev/null differ diff --git a/data/title/openrct2/script.txt b/data/title/openrct2/script.txt index 0943a1bd72..a20b7ecab8 100644 --- a/data/title/openrct2/script.txt +++ b/data/title/openrct2/script.txt @@ -1,81 +1,84 @@ -# OpenRCT2 0.0.3 Title Sequence Script -# Arranged by Gymnasiast (Michael Steenbeek). -# Based on the 0.0.2 script, which was arranged by IntelOrca. +# OpenRCT2 0.0.4 Title Sequence Script +# Arranged by NWSpacek (Kelson Blakewood). +# If you have parks you think would work well in a title sequence (must be NCSO), contact me on reddit at u/spacek_toast -LOAD pfckrutonium1.sv6 -LOCATION 7 41 -WAIT 10 +LOAD Ill Paradise.sv6 +LOCATION 113 105 +WAIT 15 -LOAD netgrouppark.sv6 -LOCATION 91 10 -WAIT 9 - -LOCATION 25 15 -WAIT 9 - -LOAD bigfoot.sv6 -LOCATION 58 29 -WAIT 10 - -ROTATE 1 -LOCATION 29 63 -WAIT 10 - -LOAD gymnasiast2.sv6 -LOCATION 39 79 -WAIT 11 - -LOAD achilleshiel.sv6 -LOCATION 25 77 -WAIT 10 - -LOCATION 36 58 +LOCATION 120 102 ROTATE 3 -WAIT 8 +WAIT 10 -LOAD mci.sv6 -LOCATION 46 60 -WAIT 6 - -LOCATION 76 32 +LOCATION 73 136 ROTATE 1 -WAIT 11 +WAIT 15 -LOAD phann.sv6 -LOCATION 96 73 -WAIT 8 +LOAD Title Sequence Park 1.sv6 +ROTATE 2 +LOCATION 120 43 +WAIT 15 -LOAD rid6.sv6 -LOCATION 56 34 -WAIT 8 - -LOCATION 10 29 -ROTATE 1 -WAIT 8 - -LOAD gymnasiast1.sv6 -LOCATION 51 46 -WAIT 11 - -LOAD alexfablelake.SV6 -LOCATION 50 25 -WAIT 9 +LOCATION 124 74 +WAIT 15 ROTATE 1 -LOCATION 35 74 -WAIT 9 +LOCATION 120 90 +WAIT 10 -LOAD poke.sv6 -LOCATION 43 83 -WAIT 9 +LOCATION 123 130 +WAIT 20 -LOCATION 63 35 +LOCATION 70 85 +ROTATE 1 +WAIT 15 + +LOAD Cypress Grove Title.sv6 +LOCATION 106 43 ROTATE 3 -WAIT 9 +WAIT 15 -LOCATION 12 47 +LOCATION 60 103 +ROTATE 1 +WAIT 10 + +LOCATION 91 83 +WAIT 10 + +ROTATE 1 +LOCATION 117 61 +WAIT 10 + +LOCATION 82 95 +ROTATE 1 +WAIT 20 + +LOCATION 110 94 ROTATE 3 -WAIT 6 +WAIT 15 + +LOCATION 79 94 +WAIT 10 + +LOCATION 63 97 +ROTATE 1 +WAIT 10 + +LOAD TaCW.sv6 +WAIT 15 + +ROTATE 1 +LOCATION 110 95 +WAIT 15 + +LOCATION 57 101 +ROTATE 3 +WAIT 15 + +LOCATION 100 63 +ROTATE 2 +WAIT 15 RESTART +END diff --git a/data/title/rct1/script.txt b/data/title/rct1/script.txt new file mode 100644 index 0000000000..6d9ea69198 --- /dev/null +++ b/data/title/rct1/script.txt @@ -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 diff --git a/data/title/rct1aa/script.txt b/data/title/rct1aa/script.txt new file mode 100644 index 0000000000..a3dd850a27 --- /dev/null +++ b/data/title/rct1aa/script.txt @@ -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 diff --git a/data/title/rct1aall/script.txt b/data/title/rct1aall/script.txt new file mode 100644 index 0000000000..63a64545c7 --- /dev/null +++ b/data/title/rct1aall/script.txt @@ -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 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000000..10b59261f3 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +openrct2 (0.0.4-develop-1) unstable; urgency=medium + + * Initial release. (Closes: #XXXXXX) + + -- Michał Janiszewski Sun, 10 Jan 2016 23:41:16 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000000..ec635144f6 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +9 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000000..ee42fe1764 --- /dev/null +++ b/debian/control @@ -0,0 +1,18 @@ +Source: openrct2 +Maintainer: Michał Janiszewski +Section: misc +Priority: optional +Standards-Version: 3.9.2 +Multi-Arch: same +Build-Depends: debhelper (>= 9), cmake, libsdl2-dev, libsdl2-ttf-dev, gcc, pkg-config, g++-multilib, gcc-multilib, libjansson4 (>= 2.7), libjansson-dev (>= 2.7), libspeex-dev, libspeexdsp-dev, libcurl4-openssl-dev, libcrypto++-dev, libfontconfig1-dev, libfreetype6-dev, libpng-dev + +Package: openrct2 +Architecture: i386 +Homepage: https://openrct2.website/ +Vcs-Browser: https://github.com/OpenRCT2/OpenRCT2 +Vcs-Git: https://github.com/OpenRCT2/OpenRCT2 +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: An open source re-implementation of Roller Coaster Tycoon 2. + An open source clone of RollerCoaster Tycoon 2 built by decompiling the + original game one bit at a time. + Requires original game assets. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000000..e69de29bb2 diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000000..a3bada8c8f --- /dev/null +++ b/debian/rules @@ -0,0 +1,13 @@ +#!/usr/bin/make -f + +BUILDDIR=build_dir + +build: + scripts/linux/install.sh + mkdir $(BUILDDIR) + cd $(BUILDDIR); cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .. + make -C $(BUILDDIR) + touch build + +%: + dh $@ diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000000..163aaf8d82 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 7b2d736895..c91a367ed7 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,3 +1,74 @@ +0.0.4-rc1 +------------------------------------------------------------------------ +- Feature: Full native OSX .app support. +- Feature: Add displaying of frames per second (FPS). +- Feature: Changing the number of trains no longer requires retesting. +- 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: Add more columns and information to tile inspector. +- Feature: Add ability to remove and reorder elements in tile inspector. +- Feature: Integrate RCT1 style scenario select with optional unlock progression. +- Feature: Add graphics scaling and filtering. +- Feature: Add cheat: permanent marketing. +- Feature: Closed rides show number of guests currently on the ride in tooltip and on the ride window customer page. +- Feature: Scrolling the mouse wheel over any land tool preview box will increment or decrement the tool size. +- Feature: Additional property views added to the ride list window. +- Feature: Improved overall view centring for rides and shops. +- Feature: Add permission and group management in multiplayer. +- Feature: Add player windows with viewport and trace in multiplayer. +- Feature: Add ability to start a new scenario when starting a new server. +- Feature: Compress game data that is downloaded when connecting to a server. +- Feature: Support for using system load/save dialogs on Linux and OS X. +- Feature: OpenRCT2 now detects if the server is running a compatible version when attempting to connect to a multiplayer game. +- Feature: Ride information list can show more properties, like age and running cost. +- Feature: Added translations for Czech and Japanese. +- Feature: Added Hong Kong dollar, New Taiwan dollar and Chinese yuan as currencies. +- Feature: Weather cheat now allows for more types of weather. +- Feature: Use fontconfig on Linux and Objective-C APIs on OS X to detect fonts and provide a fallback if necessary. +- Feature: Ability to automatically open shops after placing them. +- Feature: Ability to change the default inspection interval for rides. +- Feature: Ability to disable lightning effect during a thunderstorm. +- Feature: Display a chat hotkey when joining a server. +- Change: Server IP addresses are no longer shown in the server list. +- Change: Theme format changed from INI to JSON (INI format no longer supported). +- Change: Sound controls re-worked to control sound effects and ride music separately. +- Change: Use native line endings in config.ini. +- Change: Remove default audio device from audio device dropdown in Linux. +- Technical: lodepng dropped in return for libpng. +- Technical: SDL2 upgraded from 2.0.3 to 2.0.4. +- Technical: argparse dropped in return for bespoke command line parsing implementation. +- Technical: Integrated breakpad for (manual) crash reporting +- Improve: performance of rendering, particularly for highly populated parks. +- Improve: performance of loading parks. +- Improve: support for hacked parks. +- Removed: Anti-cheat code that detected money hack attempts. +- Fix: Dated autosave files are not created on OSX and Linux. +- Fix: Title sequence directories are not deleted when title sequence is deleted on OSX and Linux. +- Fix: Tile not highlighted when placing staff members. +- Fix: Various de-synchronisation issues in multiplayer. +- Fix: Cheats not supported in multiplayer. +- Fix: [#1333] Rides never become safe again after a crash. +- Fix: [#1742] Non-ascii characters in scenario details not showing correctly. +- 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. +- Fix: [#2477] When opening the built-in load/save dialog, the list is not properly sorted. +- Fix: [#2650] Server did not validate actions send from clients (caused error box and desynchronisation). +- Fix: [#2651] Ride was not removed when multiplayer client aborted ride construction. +- Fix: [#2654] Free transport rides can prevent guests from properly leaving the park. +- Fix: [#2657] Don't create copies of official objects due to bugged saves (original bug). +- Fix: [#2681] When lowering/raising land/water with clearance checks off, walls still get removed. +- Fix: [#2693] Multiplayer chat caret does not show true position. +- Fix: [#2704] OSX Command Key not read for keyboard shortcuts. +- Fix: [#2728] Closing a boat ride with passengers causes empty boats to leave the platform (original bug). +- Fix: [#2925] Screenshots don't show night filters. +- Fix: [#2941] Enter does not work on input box when on the title screen. +- Fix: [#2948] New Ride window incorrectly said there were track designs available when in multiplayer mode. +- Fix: [#2958] Unable to import RCT1 parks in the scenario editor using the load landscape dialog. +- Fix: [#3015] Walls in SC4/SV4 files are not imported correctly. +- Fix: [#3063] Search exe directory for SSL bundle as well as CWD. +- Fix: [#3120] Negative cash in finance window is not red. + 0.0.3.1-beta (2015-12-04) ------------------------------------------------------------------------ - Fix: [#2407] save game prompt delay is not reset on start scenario diff --git a/distribution/known_issues.txt b/distribution/known_issues.txt index de62cc621d..592c7bac61 100644 --- a/distribution/known_issues.txt +++ b/distribution/known_issues.txt @@ -1,6 +1,7 @@ -Release version: 0.0.3-1-beta +Release version: 0.0.4-rc1 ------------------------------------------------------------------------ * Some sounds play at their maximum volume irrespective of the sound volume control. * Scenario editor object selection window will show object names in the selected language at the time of building the object cache. (Deleting plugin.dat in Documents/OpenRCT2 will fix this) +* Guest AI is slightly worse than the original game. -Some bugs or limitations present in the original game have not yet been fixed or lifted. \ No newline at end of file +Some bugs or limitations present in the original game have not yet been fixed or lifted. diff --git a/distribution/linux/ld_script.xc b/distribution/linux/ld_script.xc new file mode 100644 index 0000000000..5e3b3be7be --- /dev/null +++ b/distribution/linux/ld_script.xc @@ -0,0 +1,214 @@ +/* This script is based on elf_i386.xc with modifications for OpenRCT2 */ +/* Script for -z combreloc: combine and sort reloc sections */ +/* Copyright (C) 2014 Free Software Foundation, Inc. + Copying and distribution of this script, with or without modification, + are permitted in any medium without royalty provided the copyright + notice and this notice are preserved. */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", + "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SEARCH_DIR("/usr/i386-unknown-linux-gnu/lib32"); SEARCH_DIR("/usr/x86_64-unknown-linux-gnu/lib32"); SEARCH_DIR("/usr/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/usr/i386-unknown-linux-gnu/lib"); +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x010000)); . = SEGMENT_START("text-segment", 0x010000) + SIZEOF_HEADERS; + + .interp : { *(.interp) } + .note.gnu.build-id : { *(.note.gnu.build-id) } + .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + *(.rel.ifunc) + } + .rel.plt : + { + *(.rel.plt) + PROVIDE_HIDDEN (__rel_iplt_start = .); + *(.rel.iplt) + PROVIDE_HIDDEN (__rel_iplt_end = .); + } + .init : + { + KEEP (*(SORT_NONE(.init))) + } + .plt : { *(.plt) *(.iplt) } + .rct2_text 0x401000 : { *(.rct2_text) } + .rct2_data : { *(.rct2_data) } + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } + .fini : + { + KEEP (*(SORT_NONE(.fini))) + } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .eh_frame_hdr : { *(.eh_frame_hdr) } + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table + .gcc_except_table.*) } + /* These sections are generated by the Sun/Oracle C++ compiler. */ + .exception_ranges : ONLY_IF_RO { *(.exception_ranges + .exception_ranges*) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); + /* Exception handling */ + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) *(.igot) } + . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 12 ? 12 : 0, .); + .got.plt : { *(.got.plt) *(.igot.plt) } + .data : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + _edata = .; PROVIDE (edata = .); + . = .; + __bss_start = .; + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. + FIXME: Why do we need it? When there is no .bss section, we don't + pad the .data section. */ + . = ALIGN(. != 0 ? 32 / 8 : 1); + } + . = ALIGN(32 / 8); + . = SEGMENT_START("ldata-segment", .); + . = ALIGN(32 / 8); + _end = .; PROVIDE (end = .); + . = DATA_SEGMENT_END (.); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } + +} diff --git a/distribution/osx/Assets.xcassets/AppIcon.appiconset/Contents.json b/distribution/osx/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000000..8828718d66 --- /dev/null +++ b/distribution/osx/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16x16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "icon_16x16@2x.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32x32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "icon_32x32@2x.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128x128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "icon_128x128@2x.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256x256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "icon_256x256@2x.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512x512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "icon_512x512@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/distribution/osx/Info.plist b/distribution/osx/Info.plist new file mode 100644 index 0000000000..eb13bb75db --- /dev/null +++ b/distribution/osx/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ORCT + CFBundleVersion + 1 + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + OpenRCT2 is licensed under the GNU General Public License version 3 + CFBundleAllowMixedLocalizations + + + diff --git a/distribution/readme.txt b/distribution/readme.txt index 52c8c86a18..cc2d6299c2 100644 --- a/distribution/readme.txt +++ b/distribution/readme.txt @@ -1,5 +1,5 @@ -Last updated: 2015-12-04 -Release version: 0.0.3-1-beta +Last updated: 2016-12-04 +Release version: 0.0.4-rc1 ------------------------------------------------------------------------ @@ -68,11 +68,10 @@ following information in your bug report: 3.0) Supported platforms ---- ------------------- -OpenRCT2 currently requires the original RollerCoaster Tycoon 2 binary. While -this is still the case, the only supported platform is Windows. OpenRCT2 can -still be played on other operating systems either via a virtual machine or a -compatibility layer application such as Wine. Further instructions can be found -on GitHub. +OpenRCT2 is currently supported on Windows Vista and above, many distributions of +Linux and OSX 10.7. OpenRCT2 will only work on x86 architectures as the +original RollerCoaster Tycoon 2 binary is still required to run the game. +Further instructions can be found on GitHub. 4.0) Installing and running OpenRCT2 ---- ------------------------------ @@ -82,7 +81,7 @@ be installed, or you have downloaded an installer, which will automatically extract OpenRCT2 in the given directory. OpenRCT2 requires an installation of RollerCoaster Tycoon 2 (RCT2) to run. You -must have either installed the original RCT2 disc, the GOG version or the steam +must have either installed the original RCT2 disc, the GOG version or the Steam version. Alternatively you can manually specify the location of where your RCT2 data files are. These may be directly copied of the original disc and placed in a directory of your choice. @@ -105,7 +104,7 @@ the RCT2 install path. If you are running Windows and have set a DPI scale, OpenRCT2 might look blury. This is because OpenRCT2 currently uses the original RollerCoaster Tycoon 2 -binary as a application host. However you can manually configure this binary to +binary as an application host. However you can manually configure this binary to not be scaled. This will make the game more crisp, but may result in the interface being too small to see clearly and less ergonomic to use. To stop DPI scaling, right click the binary itself (openrct2.exe) in the install directory @@ -116,8 +115,9 @@ select properties. Select the compatibility tab, check If you wish to use Steam Overlay or capture game for video recording or streaming, you might have to enable hardware display in the options window. This will still render the graphics on the CPU but the pixel data will be -displayed using either DirectX or OpenGL. This might slow down the game but can -also make the game look smoother. +displayed using either DirectX or OpenGL. This may also enable vertical +synchronisation if supported by your graphics card and you have enabled +"Uncap FPS". 5.0) Development ---- ----------- @@ -147,16 +147,16 @@ OpenRCT2 is licensed under the GNU General Public Licence version 3.0. For the complete licence text, see the file 'licence.txt'. This licence applies to all files in this distribution, except as noted below. -argparse | MIT licence. -CuTest | zlib licence. Jansson | MIT licence. libcURL | MIT (or Modified BSD-style) licence. libspeex | BSD-style license. -LodePNG | zlib licence. +libpng | libpng licence. SDL2 | zlib licence. +SDL2 TTF | zlib licence. +zlib | zlib licence. Licences for sub-libraries used by the above may vary. For more information, visit the libraries' respective official websites. 9.0) Credits ---- ------- -For the full list of contributors to OpenRCT2, see the file 'contributors.md'. \ No newline at end of file +For the full list of contributors to OpenRCT2, see the file 'contributors.md'. diff --git a/distribution/windows/build.ps1 b/distribution/windows/build.ps1 index e53b36e516..11cecea326 100644 --- a/distribution/windows/build.ps1 +++ b/distribution/windows/build.ps1 @@ -1,3 +1,11 @@ +param ( + [Parameter(Position = 1)] + [string]$VersionExtra = "" +) + $path = Split-Path $Script:MyInvocation.MyCommand.Path -Write-Output "Building Windows Installer (NSIS script)"; -makensis /DVERSION_INCLUDE=$path\win32.txt $path\install.nsi > $path\win32.log; \ No newline at end of file +Write-Host "Building Windows Installer (NSIS script)"; +Write-Host " $VersionExtra"; +makensis /DAPPV_EXTRA=$VersionExtra ` + /DVERSION_INCLUDE=$path\win32.txt ` + $path\install.nsi > $path\win32.log; diff --git a/distribution/windows/code-sign-key-openrct2.org.pfx.enc b/distribution/windows/code-sign-key-openrct2.org.pfx.enc new file mode 100644 index 0000000000..99f16381c5 Binary files /dev/null and b/distribution/windows/code-sign-key-openrct2.org.pfx.enc differ diff --git a/distribution/windows/install.nsi b/distribution/windows/install.nsi index ab98ba78d1..77c5e36a44 100644 --- a/distribution/windows/install.nsi +++ b/distribution/windows/install.nsi @@ -1,8 +1,8 @@ # Version numbers to update !define /ifndef APPV_MAJOR 0 !define /ifndef APPV_MINOR 0 -!define /ifndef APPV_MAINT 3 -!define /ifndef APPV_BUILD 1 +!define /ifndef APPV_MAINT 4 +!define /ifndef APPV_BUILD 0 !define /ifndef APPV_EXTRA "-beta" !define APPNAME "OpenRCT2" ; Define application name @@ -111,13 +111,9 @@ Section "!OpenRCT2" Section1 SetShellVarContext all - ; Copy language files - SetOutPath "$INSTDIR\data\language\" - File ${PATH_ROOT}data\language\*.txt - ; Copy data files SetOutPath "$INSTDIR\data\" - File /r ${PATH_ROOT}data\* + File /r ${PATH_ROOT}bin\data\* ; Copy the rest of the stuff SetOutPath "$INSTDIR\" @@ -125,13 +121,13 @@ Section "!OpenRCT2" Section1 ; Copy curl ca file File ..\..\curl-ca-bundle.crt - ; Copy curl ca file - File ..\..\curl-ca-bundle.crt - ; Copy text files File ..\changelog.txt Push "$INSTDIR\changelog.txt" Call unix2dos + File ..\known_issues.txt + Push "$INSTDIR\known_issues.txt" + Call unix2dos File ..\..\licence.txt Push "$INSTDIR\licence.txt" Call unix2dos @@ -145,7 +141,6 @@ Section "!OpenRCT2" Section1 ; Copy executable File /oname=openrct2.exe ${BINARY_DIR}\openrct2.exe File /oname=openrct2.dll ${BINARY_DIR}\openrct2.dll - File /oname=SDL2.dll ${BINARY_DIR}\SDL2.dll ; Create the Registry Entries WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenRCT2" "Comments" "Visit ${APPURLLINK}" @@ -211,7 +206,6 @@ Section "Uninstall" Delete "$INSTDIR\contributors.md" Delete "$INSTDIR\openrct2.exe" Delete "$INSTDIR\openrct2.dll" - Delete "$INSTDIR\SDL2.dll" Delete "$INSTDIR\licence.txt" Delete "$INSTDIR\INSTALL.LOG" Delete "$INSTDIR\crash.log" @@ -464,17 +458,10 @@ Function .onInit SectionSetFlags 0 17 - ; Starts Setup - let's look for an older version of OpenRCT2 - ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenRCT2" "Version" - - IfErrors ShowWelcomeMessage ShowUpgradeMessage ShowWelcomeMessage: ReadRegStr $R8 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenRCT2" "Version" IfErrors FinishCallback -ShowUpgradeMessage: - ${VersionCompare} "${APPVERSIONINTERNAL}" "$R8" $R0 - IntCmp $R0 1 WelcomeToSetup VersionsAreEqual InstallerIsOlder WelcomeToSetup: ; An older version was found. Let's let the user know there's an upgrade that will take place. ReadRegStr $OLDVERSION HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenRCT2" "DisplayVersion" @@ -483,26 +470,6 @@ WelcomeToSetup: "Welcome to ${APPNAMEANDVERSION} Setup.$\nThis will allow you to upgrade from version $OLDVERSION." Goto FinishCallback -VersionsAreEqual: - ReadRegStr $UninstallString HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\OpenRCT2" "UninstallString" - IfFileExists "$UninstallString" "" FinishCallback - MessageBox MB_YESNO|MB_ICONQUESTION \ - "Setup detected ${APPNAMEANDVERSION} on your system. This is the same version that this program will install.$\nAre you trying to uninstall it?" \ - IDYES DoUninstall IDNO FinishCallback -DoUninstall: ; You have the same version as this installer. This allows you to uninstall. - Exec "$UninstallString" - Quit - -InstallerIsOlder: - ;MessageBox MB_OK|MB_ICONSTOP \ - ; "You have a newer version of ${APPNAME}.$\nSetup will now exit." - ;Quit - MessageBox MB_OK|MB_ICONSTOP \ - "You have a newer version of ${APPNAME}.$\nPlease note downgrading is currently untested." - MessageBox MB_OK|MB_ICONQUESTION \ - "Welcome to ${APPNAMEANDVERSION} Setup.$\nThis will allow you to downgrade from version $OLDVERSION." - Goto FinishCallback - FinishCallback: ClearErrors ; Call CheckProcessorArchitecture diff --git a/distribution/windows/readme.md b/distribution/windows/readme.md index edd0c28c17..573a74915b 100644 --- a/distribution/windows/readme.md +++ b/distribution/windows/readme.md @@ -3,4 +3,4 @@ This directory contains the script and resources for the Windows installer. The As there is currently only a 32 bit version of OpenRCT2 available, the architecture and windows version checks have been disabled. These will be re-enabled once OpenRCT2 is a stand alone executable. -Code based on [OpenTTD](http://openttd.org) installer. \ No newline at end of file +Code based on [OpenTTD](http://openttd.org) installer. diff --git a/distribution/windows/win32.txt b/distribution/windows/win32.txt index 55988ec058..a33ea783b6 100644 --- a/distribution/windows/win32.txt +++ b/distribution/windows/win32.txt @@ -1,5 +1,5 @@ !define APPBITS 32 ; Define number of bits for the architecture !define EXTRA_VERSION "Vista, 7, 8.1 and 10" !define APPARCH "win32" ; Define the application architecture -!define BINARY_DIR "${PATH_ROOT}build\Release" -InstallDir "$PROGRAMFILES32\OpenRCT2\" \ No newline at end of file +!define BINARY_DIR "${PATH_ROOT}bin" +InstallDir "$PROGRAMFILES32\OpenRCT2\" diff --git a/dockerfiles/32bit/Dockerfile b/dockerfiles/32bit/Dockerfile index 30ce06b4c4..8a6590cc99 100644 --- a/dockerfiles/32bit/Dockerfile +++ b/dockerfiles/32bit/Dockerfile @@ -26,4 +26,4 @@ RUN pacman -R --noconfirm gcc RUN yes | pacman -S gcc-libs-multilib RUN pacman -S --noconfirm gcc-multilib USER travis -RUN yaourt -S --noconfirm lib32-jansson lib32-curl lib32-sdl2 lib32-sdl2_ttf lib32-speex +RUN yaourt -S --noconfirm lib32-jansson lib32-curl lib32-sdl2 lib32-sdl2_ttf lib32-speex lib32-fontconfig diff --git a/openrct2.sln b/openrct2.sln new file mode 100644 index 0000000000..e92027ef3a --- /dev/null +++ b/openrct2.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.24720.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openrct2", "openrct2.vcxproj", "{D24D94F6-2A74-480C-B512-629C306CE92F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D24D94F6-2A74-480C-B512-629C306CE92F}.Debug|Win32.ActiveCfg = Debug|Win32 + {D24D94F6-2A74-480C-B512-629C306CE92F}.Debug|Win32.Build.0 = Debug|Win32 + {D24D94F6-2A74-480C-B512-629C306CE92F}.Release|Win32.ActiveCfg = Release|Win32 + {D24D94F6-2A74-480C-B512-629C306CE92F}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/openrct2.vcxproj b/openrct2.vcxproj new file mode 100644 index 0000000000..b616449867 --- /dev/null +++ b/openrct2.vcxproj @@ -0,0 +1,400 @@ + + + + + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {D24D94F6-2A74-480C-B512-629C306CE92F} + openrct2 + openrct2 + + + + DynamicLibrary + true + v140 + MultiByte + + + DynamicLibrary + false + v140 + true + MultiByte + + + + + + + + + + + + $(SolutionDir)lib\include;$(SolutionDir)lib\include\breakpad;$(SolutionDir)lib\include\libspeex;$(SolutionDir)lib\include\sdl;$(SolutionDir)lib\include\jansson;$(SolutionDir)lib\include\sdl_ttf;$(SolutionDir)lib\include\libpng;$(SolutionDir)lib\include\zlib;$(IncludePath) + $(SolutionDir)lib;$(LibraryPath) + $(SolutionDir)bin\ + $(SolutionDir)obj\$(ProjectName)\$(Configuration)\ + + + + $(SolutionDir)lib\include;$(SolutionDir)lib\include\breakpad;$(SolutionDir)lib\include\libspeex;$(SolutionDir)lib\include\sdl;$(SolutionDir)lib\include\jansson;$(SolutionDir)lib\include\sdl_ttf;$(SolutionDir)lib\include\libpng;$(SolutionDir)lib\include\zlib;$(IncludePath) + $(SolutionDir)lib;$(LibraryPath) + $(SolutionDir)bin\ + $(SolutionDir)obj\$(ProjectName)\$(Configuration)\ + + + + USE_BREAKPAD;%(PreprocessorDefinitions) + + + + + 4091;%(DisableSpecificWarnings) + Level3 + Disabled + true + 1Byte + $(OpenRCT2_DEFINES);DEBUG;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + MultiThreaded + true + $(IntDir)\%(RelativeDir) + 4013 + false + + + true + openrct2-libs-vs2015.lib;imm32.lib;version.lib;winmm.lib;%(AdditionalDependencies) + UseFastLinkTimeCodeGeneration + /OPT:NOLBR /ignore:4099 %(AdditionalOptions) + + + + + 4091;%(DisableSpecificWarnings) + Level3 + Full + true + true + + MultiThreaded + 1Byte + 4013 + + false + $(OpenRCT2_DEFINES);_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;%(PreprocessorDefinitions) + $(IntDir)\%(RelativeDir) + true + Speed + + + true + true + true + openrct2-libs-vs2015.lib;imm32.lib;version.lib;winmm.lib;%(AdditionalDependencies) + /ignore:4099 %(AdditionalOptions) + + + + + diff --git a/projects/openrct2.vcxproj.filters b/openrct2.vcxproj.filters similarity index 52% rename from projects/openrct2.vcxproj.filters rename to openrct2.vcxproj.filters index d32f0f5439..07a3682284 100644 --- a/projects/openrct2.vcxproj.filters +++ b/openrct2.vcxproj.filters @@ -56,773 +56,847 @@ {28a808eb-9017-44cc-939b-f828fd1e2e7d} + + {4bf369d2-3df8-40c9-a878-f484b0a0afd3} + - + Resource Files - + Resource Files - + Source\Management - + Source\Management - + Source\Management - + Source\Management - + Source\Audio - + Source\Audio - + Source\Interface - + Source\Interface - + Source\Interface - + Source\Interface - + Source\Interface - + Source\World - + Source\World - + Source\World - + Source\World - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Localisation - + Source\Ride - + Source\Ride - + Source\Ride - + Source\Ride - + Source\Ride - + Source\Util - + Source\Util - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - - Source - - + Source\Localisation - + Source\Drawing - + Source\Drawing - + Source\Drawing - + Source\Drawing - + Source\Drawing - + Source\Localisation - + Source\Platform - + Source\Platform - + Source\Platform - - Source\Platform - - + Source\Localisation - + Source\Peep - + Source\Peep - + Source\Management - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Drawing - + Source - - Source - - + Source\World - + Source\World - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Ride - + Source\Windows - + Source\Interface - + Source\Interface - + Source\World - + Source - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Localisation - + Source\Windows - + Source\Windows - + Source\Windows - + Source\World - + Source\World - + Source\Windows - + Source\Windows - + Source\Ride - + Source - + Source\Windows - + Source - + Source\Windows - + Source\World - + Source\World - + Source - + Source\Windows - + Source - + Source\Windows - + Source\Interface - + Source\Network - + Source\Network - + + Source\Windows + + + Source\Windows + + + Source\Windows + + Source\Interface - + Source\Windows - - Test - - - Test\Management - - - Test\Ride - - + Source\Windows - - Source\Windows - - - Source\Windows - - - Source\Interface - - - Source\Windows - - - Source\Windows - - + Source - + Source\Localisation - + Source\Drawing - + Source\Drawing - + Source\Localisation - + Source\Network - + Source\Windows - - Source\Windows - - + Source\Interface - + Source\Windows - + Source\World - + Source\World - + Source\World - + Source\World - + Source\Localisation - + Source\Localisation - + Source\Ride - + Source\Platform - + Source\Windows - + Source\Interface + + Source + + + Source\Ride + + + Source\Drawing + + + Source\Windows + + + Source + + + Source + + + Source\Core + + + Source\CommandLine + + + Source\CommandLine + + + Source\CommandLine + + + Source\CommandLine + + + Source\Core + + + Source\Core + + + Source\Core + + + Source\Windows + + + Source\Windows + + + Source\Interface + + + + + Source\Drawing + + + Source\Core + + - + Source\Management - + Source\Management - + Source\Management - + Source\Management - + Source\Audio - + Source\Audio - + Source\Interface - + Source\Interface - + Source\Interface - + Source\Interface - + Source\Interface - + Source\World - + Source\World - + Source\World - + Source\World - + Source\World - + Source\Windows - + Source\Windows - + Source\Windows - + Source\Localisation - + Source\Localisation - + Source\Localisation - + Source\Ride - + Source\Ride - + Source\Ride - + Source\Ride - + Source\Ride - + Source\Util - + Source\Util - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - + Source - - Source - - + Source\Localisation - + Source\Drawing - + Source - + Source\Localisation - + Source\Platform - + Source\Localisation - + Source\Peep - + Source\Peep - + Source\Management - + Source - - Source - - + Source\World - + Source\Ride - + Source\Interface - + Source\World - + Source - + Source - + Source\World - + Source\World - + Source\Ride - + Source\World - + Source\World - + Source\World - + Source\World - + Source\Interface - + Source\Network - + Source\Network - + Source\Interface - + Test - + Test\Management - + Test\Ride - + Source\Interface - + Source - + Source\Drawing - + Source\Network - + Source\Interface - + Source\Core - + Source\Core - + Source\Core - + Source\Core - + Source\Localisation - + Source\Core - + Source\Core - + Source\Core - + Source\Core - + Source\Ride - + Source\Interface + + Source\Ride + + + Source\Core + + + Source\Drawing + + + Source + + + Source\Core + + + Source + + + Source\Core + + + Source\Core + + + Source\CommandLine + + + Source\Core + + + Source\Core + + + Source\Core + + + + + + + Source\Core + + diff --git a/projects/openrct2.vcxproj.user b/openrct2.vcxproj.user similarity index 84% rename from projects/openrct2.vcxproj.user rename to openrct2.vcxproj.user index e977faccec..fd6680fbf4 100644 --- a/projects/openrct2.vcxproj.user +++ b/openrct2.vcxproj.user @@ -1,24 +1,28 @@  - false + true $(TargetDir)\openrct2.exe WindowsLocalDebugger $(TargetDir) + + $(TargetDir) WindowsLocalDebugger $(TargetDir)\openrct2.exe - + + $(TargetDir) WindowsLocalDebugger $(TargetDir)\openrct2.exe - + + $(TargetDir) diff --git a/pre-build.ps1 b/pre-build.ps1 deleted file mode 100644 index 3e350d0c26..0000000000 --- a/pre-build.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -#init -$libversion = 4 -$path = Split-Path $Script:MyInvocation.MyCommand.Path -$zip = $path+'\orctlibs.zip' -$libs = $path+'\lib' -$libsVFile = $path+'\libversion' -$liburl = 'https://openrct2.website/files/orctlibs-vs.zip' -$libsTest = Test-Path $libs - -#libs version test -$libsVersionTest = Test-Path $libsVFile -$currentVersion = 0 -$needsdownload = $true -if ($libsVersionTest) { - $currentVersion = [IO.File]::ReadAllText($libsVFile) -} -if ($currentVersion -ge $libversion) { - $needsdownload = $false -} - -#download -if (!$libsTest -or $needsdownload) { - if ($libsTest) { - rm $libs -Recurse -Force - } - mkdir $libs - Invoke-WebRequest $liburl -OutFile $path\orctlibs.zip - [System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') > $null - [System.IO.Compression.ZipFile]::ExtractToDirectory($zip, $libs) - rm $path\orctlibs.zip -Force -ErrorAction SilentlyContinue - $libversion | Set-Content $libsVFile -} else { - echo 'All libs up to date' -} diff --git a/projects/language/language.vcxproj b/projects/language/language.vcxproj deleted file mode 100644 index 071a041562..0000000000 --- a/projects/language/language.vcxproj +++ /dev/null @@ -1,164 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Release XP - Win32 - - - Release with Tests - Win32 - - - - {0468FC1E-5881-4DB9-9DDE-1892290B31D9} - language - - - - Utility - true - v140 - MultiByte - - - Utility - false - v140 - true - MultiByte - - - Utility - false - v140_xp - true - MultiByte - - - Utility - false - v140 - true - MultiByte - - - - - - - - - - - - - - - - - - - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)..\build\Release\ - $(SolutionDir)..\obj\$(ProjectName)\Release\ - - - - Level3 - Disabled - true - - - true - - - xcopy /Y "$(SolutionDir)\..\Data\Language\*.*" "$(TargetDir)\Data\Language\" - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - true - - - xcopy /Y "$(SolutionDir)\..\Data\Language\*.*" "$(TargetDir)\Data\Language\" - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - true - - - xcopy /Y "$(SolutionDir)\..\Data\Language\*.*" "$(TargetDir)\Data\Language\" - - - - - Level3 - MaxSpeed - true - true - true - - - true - true - true - - - xcopy /Y "$(SolutionDir)\..\Data\Language\*.*" "$(TargetDir)\Data\Language\" - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/projects/language/language.vcxproj.filters b/projects/language/language.vcxproj.filters deleted file mode 100644 index 6810d604ae..0000000000 --- a/projects/language/language.vcxproj.filters +++ /dev/null @@ -1,44 +0,0 @@ - - - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {96ec0470-f3e0-443e-8715-171ad8676bb6} - - - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - Resource Files\Language - - - \ No newline at end of file diff --git a/projects/libs/libs.vcxproj b/projects/libs/libs.vcxproj deleted file mode 100644 index aa57182937..0000000000 --- a/projects/libs/libs.vcxproj +++ /dev/null @@ -1,231 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Release XP - Win32 - - - Release with Tests - Win32 - - - - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB} - libs - - - - StaticLibrary - true - v140 - MultiByte - - - StaticLibrary - false - v140 - true - MultiByte - - - StaticLibrary - false - v140_xp - true - MultiByte - - - StaticLibrary - false - v140 - true - MultiByte - - - - - - - - - - - - - - - - - - - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - ..\..\lib\libcurl\include;..\..\lib\jansson;..\..\lib\cutest\CuTest.h;..\..\lib\SDL2_ttf\include;$(IncludePath) - ..\..\lib\libcurl\lib;..\..\lib\SDL2_ttf\lib\x86;$(LibraryPath) - - - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - ..\..\lib\libcurl\include;..\..\lib\jansson;..\..\lib\cutest\CuTest.h;..\..\lib\SDL2_ttf\include;$(IncludePath) - ..\..\lib\libcurl\lib;..\..\lib\SDL2_ttf\lib\x86;$(LibraryPath) - - - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - ..\..\lib\libcurl\include;..\..\lib\jansson;..\..\lib\cutest\CuTest.h;..\..\lib\SDL2_ttf\include;$(IncludePath) - ..\..\lib\libcurl\lib;..\..\lib\SDL2_ttf\lib\x86;$(LibraryPath) - - - $(SolutionDir)..\build\Release\ - $(SolutionDir)..\obj\$(ProjectName)\Release\ - ..\..\lib\libcurl\include;..\..\lib\jansson;..\..\lib\cutest\CuTest.h;..\..\lib\SDL2_ttf\include;$(IncludePath) - ..\..\lib\libcurl\lib;..\..\lib\SDL2_ttf\lib\x86;$(LibraryPath) - - - - Level3 - Disabled - true - MultiThreaded - 1Byte - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;NS_ENABLE_THREADS;NS_ENABLE_SSL;DISABLE_MD5;%(PreprocessorDefinitions) - - - true - - - libcurl.lib;Ws2_32.lib;SDL2_ttf.lib;%(AdditionalDependencies) - true - - - Powershell -NonInteractive -ExecutionPolicy "ByPass" -File "$(ProjectDir)../../pre-build.ps1" - - - - - Level3 - MaxSpeed - true - true - true - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;NS_ENABLE_THREADS;NS_ENABLE_SSL;DISABLE_MD5;%(PreprocessorDefinitions) - MultiThreaded - 1Byte - - - - - true - true - true - - - libcurl.lib;Ws2_32.lib;SDL2_ttf.lib;%(AdditionalDependencies) - - - Powershell -NonInteractive -ExecutionPolicy "ByPass" -File "$(ProjectDir)../../pre-build.ps1" - - - - - Level3 - MaxSpeed - true - true - true - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;NS_ENABLE_THREADS;NS_ENABLE_SSL;DISABLE_MD5;%(PreprocessorDefinitions) - MultiThreaded - 1Byte - - - - - true - true - true - - - libcurl.lib;Ws2_32.lib;SDL2_ttf.lib;%(AdditionalDependencies) - - - Powershell -NonInteractive -ExecutionPolicy "ByPass" -File "$(ProjectDir)../../pre-build.ps1" - - - - - Level3 - MaxSpeed - true - true - true - _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;NS_ENABLE_THREADS;NS_ENABLE_SSL;DISABLE_MD5;%(PreprocessorDefinitions) - MultiThreaded - 1Byte - - - - - true - true - true - - - libcurl.lib;Ws2_32.lib;SDL2_ttf.lib;%(AdditionalDependencies) - - - Powershell -NonInteractive -ExecutionPolicy "ByPass" -File "$(ProjectDir)../../pre-build.ps1" - - - - - TurnOffAllWarnings - - - - - - - - - - - - - - - TurnOffAllWarnings - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/projects/libs/libs.vcxproj.filters b/projects/libs/libs.vcxproj.filters deleted file mode 100644 index feaf95a9ee..0000000000 --- a/projects/libs/libs.vcxproj.filters +++ /dev/null @@ -1,124 +0,0 @@ - - - - - {f28d7721-061f-44b8-bbd5-42dc9483b387} - - - {69f22202-b887-4e7c-bf7c-eb581571398d} - - - {45966214-8043-431c-8eb3-920c00bf749d} - - - {7f953e55-d294-4158-b309-67f41fa82760} - - - {7b46a2d6-1095-4e7a-b98b-006b832ef7a1} - - - {16ee6cb9-307a-4e8a-8261-a69d91b17739} - - - {92e56bd7-37be-465c-9212-3b6cfb8cf7c9} - - - - - argparse - - - libspeex - - - lodepng - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - cutest - - - - - argparse - - - libspeex - - - libspeex - - - libspeex - - - libspeex - - - libspeex\speex - - - libspeex\speex - - - lodepng - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - jansson - - - - \ No newline at end of file diff --git a/projects/openrct2.sln b/projects/openrct2.sln deleted file mode 100644 index 5667f3043f..0000000000 --- a/projects/openrct2.sln +++ /dev/null @@ -1,51 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openrct2", "openrct2.vcxproj", "{D24D94F6-2A74-480C-B512-629C306CE92F}" - ProjectSection(ProjectDependencies) = postProject - {0468FC1E-5881-4DB9-9DDE-1892290B31D9} = {0468FC1E-5881-4DB9-9DDE-1892290B31D9} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "language", "language\language.vcxproj", "{0468FC1E-5881-4DB9-9DDE-1892290B31D9}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libs", "libs\libs.vcxproj", "{074DC930-05C6-4B7F-B5DD-DD237E6E44DB}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release with Tests|Win32 = Release with Tests|Win32 - Release XP|Win32 = Release XP|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D24D94F6-2A74-480C-B512-629C306CE92F}.Debug|Win32.ActiveCfg = Debug|Win32 - {D24D94F6-2A74-480C-B512-629C306CE92F}.Debug|Win32.Build.0 = Debug|Win32 - {D24D94F6-2A74-480C-B512-629C306CE92F}.Release with Tests|Win32.ActiveCfg = Release with Tests|Win32 - {D24D94F6-2A74-480C-B512-629C306CE92F}.Release with Tests|Win32.Build.0 = Release with Tests|Win32 - {D24D94F6-2A74-480C-B512-629C306CE92F}.Release XP|Win32.ActiveCfg = Release XP|Win32 - {D24D94F6-2A74-480C-B512-629C306CE92F}.Release XP|Win32.Build.0 = Release XP|Win32 - {D24D94F6-2A74-480C-B512-629C306CE92F}.Release|Win32.ActiveCfg = Release|Win32 - {D24D94F6-2A74-480C-B512-629C306CE92F}.Release|Win32.Build.0 = Release|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Debug|Win32.ActiveCfg = Debug|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Debug|Win32.Build.0 = Debug|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Release with Tests|Win32.ActiveCfg = Release with Tests|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Release with Tests|Win32.Build.0 = Release with Tests|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Release XP|Win32.ActiveCfg = Release XP|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Release XP|Win32.Build.0 = Release XP|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Release|Win32.ActiveCfg = Release|Win32 - {0468FC1E-5881-4DB9-9DDE-1892290B31D9}.Release|Win32.Build.0 = Release|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Debug|Win32.ActiveCfg = Debug|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Debug|Win32.Build.0 = Debug|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Release with Tests|Win32.ActiveCfg = Release with Tests|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Release with Tests|Win32.Build.0 = Release with Tests|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Release XP|Win32.ActiveCfg = Release XP|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Release XP|Win32.Build.0 = Release XP|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Release|Win32.ActiveCfg = Release|Win32 - {074DC930-05C6-4B7F-B5DD-DD237E6E44DB}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/projects/openrct2.vcxproj b/projects/openrct2.vcxproj deleted file mode 100644 index 13d1c0ff54..0000000000 --- a/projects/openrct2.vcxproj +++ /dev/null @@ -1,512 +0,0 @@ - - - - - - - - - - Debug - Win32 - - - Release - Win32 - - - Release XP - Win32 - - - Release with Tests - Win32 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {074dc930-05c6-4b7f-b5dd-dd237e6e44db} - - - - {D24D94F6-2A74-480C-B512-629C306CE92F} - openrct2 - openrct2 - 10.0.10240.0 - - - - DynamicLibrary - true - v140 - MultiByte - - - DynamicLibrary - false - v140 - true - MultiByte - - - DynamicLibrary - false - v140_xp - true - MultiByte - - - DynamicLibrary - false - v140 - true - MultiByte - - - - - - - - - - - - - - - - - - - $(SolutionDir)..\lib;$(SolutionDir)..\lib\libspeex;$(SolutionDir)..\lib\sdl\include;$(SolutionDir)..\lib\libcurl\include;$(SolutionDir)..\lib\jansson;$(SolutionDir)..\lib\cutest;$(SolutionDir)..\lib\SDL2_ttf\include;$(IncludePath) - $(SolutionDir)..\lib\sdl\lib\x86;$(SolutionDir)..\lib\libcurl\lib;$(LibraryPath) - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)..\lib;$(SolutionDir)..\lib\libspeex;$(SolutionDir)..\lib\sdl\include;$(SolutionDir)..\lib\libcurl\include;$(SolutionDir)..\lib\jansson;$(SolutionDir)..\lib\cutest;$(SolutionDir)..\lib\SDL2_ttf\include;$(IncludePath) - $(SolutionDir)..\lib\sdl\lib\x86;$(SolutionDir)..\lib\libcurl\lib;$(LibraryPath) - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)..\lib;$(SolutionDir)..\lib\libspeex;$(SolutionDir)..\lib\sdl\include;$(SolutionDir)..\lib\libcurl\include;$(SolutionDir)..\lib\jansson;$(SolutionDir)..\lib\cutest;$(SolutionDir)..\lib\SDL2_ttf\include;$(IncludePath) - $(SolutionDir)..\lib\sdl\lib\x86;$(SolutionDir)..\lib\libcurl\lib;$(LibraryPath) - $(SolutionDir)..\build\$(Configuration)\ - $(SolutionDir)..\obj\$(ProjectName)\$(Configuration)\ - - - $(SolutionDir)..\lib;$(SolutionDir)..\lib\libspeex;$(SolutionDir)..\lib\sdl\include;$(SolutionDir)..\lib\libcurl\include;$(SolutionDir)..\lib\jansson;$(SolutionDir)..\lib\cutest;$(SolutionDir)..\lib\SDL2_ttf\include;$(IncludePath) - $(SolutionDir)..\lib\sdl\lib\x86;$(SolutionDir)..\lib\libcurl\lib;$(LibraryPath) - $(SolutionDir)..\build\Release\ - $(SolutionDir)..\obj\$(ProjectName)\Release\ - - - - Level3 - Disabled - true - 1Byte - DEBUG;_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) - MultiThreaded - true - $(IntDir)fake\%(RelativeDir) - 4013 - false - - - true - winmm.lib;sdl2.lib;%(AdditionalDependencies) - - - "$(TargetDir)openrct2.exe" sprite build "$(SolutionDir)..\Data\g2.dat" "$(SolutionDir)..\Resources\g2" -xcopy /YS "$(SolutionDir)..\Data" "$(TargetDir)Data" - Build g2.dat and copy the Data directory. - - - - - Level3 - Full - true - true - - - MultiThreaded - 1Byte - 4013 - - - false - _CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;%(PreprocessorDefinitions) - $(IntDir)fake\%(RelativeDir) - true - Speed - - - true - true - true - winmm.lib;sdl2.lib;%(AdditionalDependencies) - /ignore:4099 %(AdditionalOptions) - - - "$(TargetDir)openrct2.exe" sprite build "$(SolutionDir)..\Data\g2.dat" "$(SolutionDir)..\Resources\g2" -xcopy /YS "$(SolutionDir)..\Data" "$(TargetDir)Data" - Build g2.dat and copy the Data directory. - - - - - - - - - - - - - Level3 - Full - true - true - - - MultiThreaded - 1Byte - 4013 - - - false - DISABLE_NETWORK;DISABLE_HTTP;DISABLE_TWITCH;_CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;%(PreprocessorDefinitions) - $(IntDir)fake\%(RelativeDir) - true - Speed - - - true - true - true - winmm.lib;sdl2.lib;%(AdditionalDependencies) - /ignore:4099 %(AdditionalOptions) - Windows - - - "$(TargetDir)openrct2.exe" sprite build "$(SolutionDir)..\Data\g2.dat" "$(SolutionDir)..\Resources\g2" -xcopy /YS "$(SolutionDir)..\Data" "$(TargetDir)Data" - Build g2.dat and copy the Data directory. - - - - - - - - - - - - - Level3 - Disabled - true - true - - - MultiThreaded - 1Byte - 4013 - - - false - _CRT_SECURE_NO_WARNINGS;HAVE_CONFIG_H;_USE_MATH_DEFINES;CURL_STATICLIB;SDL_MAIN_HANDLED;ENABLE_TESTS;%(PreprocessorDefinitions) - $(IntDir)fake\%(RelativeDir) - true - - - true - true - true - winmm.lib;sdl2.lib;%(AdditionalDependencies) - /ignore:4099 %(AdditionalOptions) - - - "$(TargetDir)openrct2.exe" sprite build "$(SolutionDir)..\Data\g2.dat" "$(SolutionDir)..\Resources\g2" -xcopy /YS "$(SolutionDir)..\Data" "$(TargetDir)Data" - Build g2.dat and copy the Data directory. - - - - - - - - - - - - - - diff --git a/projects/resource.h b/projects/resource.h deleted file mode 100644 index 545b58f6b5..0000000000 --- a/projects/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by openrct2.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/readme.md b/readme.md index 6b395f4abc..260e149c28 100644 --- a/readme.md +++ b/readme.md @@ -1,17 +1,16 @@ # OpenRCT2 -An open source clone of RollerCoaster Tycoon 2 built by decompiling the original game one bit at a time. -- [Screenshot 1, cheat windows](http://imgur.com/a/zJTYd) -- [Screenshot 2, large land tool area](http://i.imgur.com/kTkK5Gw.png) (up to 64 squares at once) -- [Screenshot 3, high resolution](http://i.imgur.com/yFzNyVu.jpg) -- [Screenshot 4, resizable window](http://imgur.com/a/3GDuT) +An open source re-implementation of Roller Coaster Tycoon 2. A construction and management simulation video game that simulates amusement park management. -Linux Build: -[![Travis CI](https://travis-ci.org/OpenRCT2/OpenRCT2.svg)](https://travis-ci.org/OpenRCT2/OpenRCT2) -Windows Build: -[![AppVeyor](https://ci.appveyor.com/api/projects/status/fib6re830brysuo2?svg=true)](https://ci.appveyor.com/project/IntelOrca/openrct2) +### Build Status +| | Windows | Linux / OSX | Download | +|-------------|---------|-------------|----------| +| **master** | [![AppVeyor](https://ci.appveyor.com/api/projects/status/7efnemxhon6i5n34/branch/develop?svg=true)](https://ci.appveyor.com/project/IntelOrca/openrct2-ject9) | [![Travis CI](https://travis-ci.org/OpenRCT2/OpenRCT2.svg?branch=master)](https://travis-ci.org/OpenRCT2/OpenRCT2) | [OpenRCT2.org](https://openrct2.org/downloads/master/latest) | +| **develop** | [![AppVeyor](https://ci.appveyor.com/api/projects/status/7efnemxhon6i5n34/branch/develop?svg=true)](https://ci.appveyor.com/project/IntelOrca/openrct2-ject9) | [![Travis CI](https://travis-ci.org/OpenRCT2/OpenRCT2.svg?branch=develop)](https://travis-ci.org/OpenRCT2/OpenRCT2) | [OpenRCT2.org](https://openrct2.org/downloads/develop/latest) | -Come talk with us if you have any questions: -[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/OpenRCT2/OpenRCT2?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +### Chat +| Developers | Players / Off-topic | +|------------|---------------------| +|[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/OpenRCT2/OpenRCT2)|[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/OpenRCT2/OpenRCT2/non-dev)| # Contents - 1 - [Introduction](#1-introduction) @@ -62,51 +61,58 @@ The aim is to completely decompile RollerCoaster Tycoon 2 into C so that cross-p # 2 Downloading the game / Building the source code -Several third party build servers offer precompiled builds and installers of the latest stable and the develop branch. -[OpenRCT2.com](https://openrct2.com/download) -[OpenRCT.net](https://openrct.net/builds.php) -[UrsaLabs](https://openrct.ursalabs.co) - -There is also a Launcher available from [OpenRCT.net](https://openrct.net/download) that will automatically update your build so that you always have the current version as they are released. +[OpenRCT2.org](https://openrct2.org/downloads) offers precompiled builds and installers of the latest stable and the develop branch. There is also a Launcher available that will automatically update your build so that you always have the current version as they are released. ## 2.1 Building prerequisites OpenRCT2 requires original files of Rollercoaster Tycoon 2 to play. It can be bought at either [Steam](http://store.steampowered.com/app/285330/) or [GOG.com](http://www.gog.com/game/rollercoaster_tycoon_2). ### Windows: -- Windows XP / Vista / 7 / 8 / 10 +- Vista / 7 / 8 / 10 - Visual Studio 2015 (Enterprise / Professional / [Community (Free)](https://www.visualstudio.com/products/visual-studio-community-vs)) - [Powershell 4.0](http://social.technet.microsoft.com/wiki/contents/articles/21016.how-to-install-windows-powershell-4-0.aspx). ### Mac OS X: -- [Homebrew](http://brew.sh) or [MacPorts](https://www.macports.org/) +- [Homebrew](http://brew.sh) ### Mac OS X / Linux: -- [MinGW-w64](http://mingw-w64.sourceforge.net/) -- [Wine](http://www.winehq.org) -- libsdl2 compiled with MinGW-w64 +- sdl2 +- sdl2-ttf +- speexdsp +- curl (only if building with network support) +- jansson (only if building with network support) +- iconv (part of glibc on Linux) +- cmake +All libs listed here (bar cmake) required in 32 bit variants. ## 2.2 Compiling and running ### Windows: 1. Check out the repository. This can be done using [GitHub Windows](https://windows.github.com/) or [other tools](https://help.github.com/articles/which-remote-url-should-i-use). -2. Open the solution in the projects directory (**openrct2.sln**) with Visual Studio. -3. [Select the 'Release' configuration](http://msdn.microsoft.com/en-us/library/wx0123s5.aspx) and click Build -> Rebuild Solution. The dropdown menu to enable the 'release' configuration is towards the top of the VS Express window, near the "TEST" menu. -4. Start debugging. Press the "Local Windows Debugger" button with a green "play" icon next to it. If Visual Studio shows a warning about *openrct2.exe* not having debug information, press Continue. -5. When OpenRCT2 is run for the first time, it creates a settings file in `My Documents/OpenRCT2`. If it can't find the original installation of RCT2, you will need to edit `config.ini` in that folder and change the value of `game_path` to where RCT2 is installed. -6. If the game crashes, you may need to press the red, square Stop button along the top of VS Express to stop the program. +2. Open a new PowerShell window and navigate to the repository. +3. Run the setenv.ps1 script in the repository to setup your PowerShell environment for OpenRCT2 development. This will warn you of any missing applications required to build OpenRCT2. +4. Run ```install``` to download the required dependencies to build OpenRCT2. +5. Run ```build all``` to build all the required components for OpenRCT2. +6. Run ```run``` to run OpenRCT2. -Alternatively, to simply build the project you can just execute ``build.bat`` within VS2015 Native Tools Command prompt or Github Windows prompt. +These PowerShell scripts are stored in ```.\scripts\ps``` and have parameters. Once you have use the build script once, further development can be done within Visual Studio by opening ```openrct2.sln```. The build scripts have several commands allowing you to rebuild certain components such g2.dat or language files. ### Mac OS X: -Providing Homebrew or MacPorts are installed (but not both!), OpenRCT2's dependencies and Wine can be installed automatically through `install.sh`. +We support native builds OS X (limited to i386 only for now). +Make sure that you have [Homebrew](http://brew.sh/) installed and than run the following commands to install all the needed libraries and build openrct2. ``` -bash install.sh -bash build.sh -wine openrct2.exe +# Install libraries +./install.sh + +# Build OpenRCT2 +./build.sh + +# Run the game +./openrct2 ``` ### Linux: -As the easiest approach depends on your distribution, please take a look at the [wiki](https://github.com/OpenRCT2/OpenRCT2/wiki). +We support native builds for Linux (limited to i386 only for now). +As the easiest approach depends on your distribution, please take a look at the [wiki](https://github.com/OpenRCT2/OpenRCT2/wiki/Building-OpenRCT2-on-Linux). # 3 Contributing @@ -143,9 +149,8 @@ Translations are in progress for German, Dutch, French, Hungarian, Polish, Spani # 5 More information - [GitHub](https://github.com/OpenRCT2/OpenRCT2) +- [OpenRCT2.org](https://openrct2.org) - [Forums](https://openrct2.org/forums/) - [Facebook](https://www.facebook.com/OpenRCT2) -- [OpenRCT2.com](https://openrct2.com) -- [OpenRCT.net](https://openrct.net) - [rct subreddit](http://www.reddit.com/r/rct/) - [openrct2 subreddit](http://www.reddit.com/r/openrct2/) diff --git a/resources/g2/60.png b/resources/g2/60.png new file mode 100644 index 0000000000..2b4369ea8a Binary files /dev/null and b/resources/g2/60.png differ diff --git a/resources/logo/makeico.linq b/resources/logo/makeico.linq index 247c87eb0b..0371075d12 100644 --- a/resources/logo/makeico.linq +++ b/resources/logo/makeico.linq @@ -41,4 +41,4 @@ using (FileStream fs = new FileStream(outputPath, FileMode.Create)) { } bw.Write(dataStream.ToArray()); } -} \ No newline at end of file +} diff --git a/run.bat b/run.bat deleted file mode 100644 index 6f18175b9f..0000000000 --- a/run.bat +++ /dev/null @@ -1 +0,0 @@ -.\build\Release\openrct2.exe %* \ No newline at end of file diff --git a/scripts/linux/build.sh b/scripts/linux/build.sh new file mode 100755 index 0000000000..3de68319ce --- /dev/null +++ b/scripts/linux/build.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +set -e + +cachedir=.cache +mkdir -p $cachedir + +# Sets default target to "linux", if none specified +TARGET=${TARGET-linux} +SYSTEM=$(uname -s) + +if [[ ! -d build ]]; then + mkdir -p build +fi + +if [[ $TARGET != "linux" && $TARGET != "docker32" && $SYSTEM != "Darwin" ]]; then + # keep in sync with version in install.sh + if [[ $SYSTEM == "Darwin" ]]; then + # keep in sync with version in Xcode project + sha256sum=6562ce9e1f37f125e3345bfd8b961777800436bf607b30dc7c964e0e6991ad2c + else + sha256sum=f124c954bbd0b58c93e5fba46902806bd3637d3a1c5fb8e4b67441052f182df2 + fi + libVFile="./libversion" + libdir="./lib" + currentversion=0 + needsdownload="true" + + if [ -f $libVFile ]; then + while read line; do + currentversion=$line + continue + done < $libVFile + fi + + if [ "z$currentversion" == "z$sha256sum" ]; then + needsdownload="false" + fi + + if [ ! -d $libdir ]; then + needsdownload="true" + fi + + if [[ "$needsdownload" = "true" ]]; then + echo "Found library had sha256sum $currentversion, expected $sha256sum" + echo "New libraries need to be downloaded. Clearing cache and calling ./install.sh" + rm -rf ./lib + if [[ -f $cachedir/orctlibs.zip ]]; then + rm -rf $cachedir/orctlibs.zip + fi + if [[ -d /usr/local/cross-tools/orctlibs ]]; then + sudo rm -rf /usr/local/cross-tools/orctlibs + fi + if [[ -d $cachedir/orctlibs ]]; then + rm -rf $cachedir/orctlibs + fi + scripts/linux/install.sh + fi +# if [[ $TARGET != "linux" && $TARGET != "docker32" && $SYSTEM != "Darwin" ]]; then +fi + +pushd build + echo OPENRCT2_CMAKE_OPTS = $OPENRCT2_CMAKE_OPTS + if [[ $TARGET == "docker32" ]] + then + PARENT=$(readlink -f ../) + chmod a+rwx $(pwd) + chmod g+s $(pwd) + # CMAKE and MAKE opts from environment + docker run -u travis -v $PARENT:/work/openrct2 -w /work/openrct2/build -i -t openrct2/openrct2:32bit-only bash -c "cmake ../ $OPENRCT2_CMAKE_OPTS && make $OPENRCT_MAKE_OPTS" + else + cmake $OPENRCT2_CMAKE_OPTS .. + # NOT the same variable as above + make $OPENRCT2_MAKE_OPTS + fi +popd + +if [[ $TARGET == "windows" ]]; then + if [[ ! -h openrct2.dll ]]; then + ln -s build/openrct2.dll openrct2.dll + fi +fi + +if [[ ! -h build/data ]]; then + ln -s ../data build/data +fi + +if [[ $TARGET == "linux" ]] || [[ $TARGET == "docker32" ]]; then + if [[ ! -h openrct2 ]]; then + ln -s build/openrct2 openrct2 + fi +fi + +if [[ -z "$DISABLE_G2_BUILD" ]]; then + echo Building: g2.dat + pushd build + make g2 + popd +fi + +if [[ $TARGET == "windows" ]]; then + if [[ -t 1 ]]; then + echo -e "\nDone! Run OpenRCT2 by typing:\n\n\033[95mwine openrct2.exe\n\033[0m" + else + echo -e "\nDone! Run OpenRCT2 by typing:\n\nwine openrct2.exe\n" + fi +else + if [[ -t 1 ]]; then + echo -e "\nDone! Run OpenRCT2 by typing:\n\n\033[95m./openrct2\n\033[0m" + else + echo -e "\nDone! Run OpenRCT2 by typing:\n\n./openrct2\n" + fi +fi diff --git a/clean.sh b/scripts/linux/clean.sh similarity index 100% rename from clean.sh rename to scripts/linux/clean.sh diff --git a/install.sh b/scripts/linux/install.sh similarity index 63% rename from install.sh rename to scripts/linux/install.sh index eb04f41dd3..998f26ecf2 100755 --- a/install.sh +++ b/scripts/linux/install.sh @@ -4,10 +4,12 @@ SDL2_PV=2.0.3 SDL2_TTF_PV=2.0.12 cachedir=.cache -liburl=https://openrct2.website/files/orctlibs.zip -mkdir -p $cachedir - -echo $(uname) +if [[ $(uname -s) == "Darwin" ]]; then + liburl=https://openrct2.website/files/orctlibs-osx.zip +else + liburl=https://openrct2.website/files/orctlibs.zip +fi +mkdir -p "$cachedir" # Sets default target to "linux", if none specified TARGET=${TARGET-linux} @@ -15,10 +17,25 @@ TARGET=${TARGET-linux} libversion=3 libVFile="./libversion" +function has_cmd { + command -v "$1" >/dev/null 2>&1 +} + +function calculate_sha256 { + if has_cmd "shasum"; then + command shasum -a 256 "$1" | cut -f1 -d" " + elif has_cmd "sha256sum"; then + command sha256sum "$1" | cut -f1 -d" " + else + echo "Please install either sha256sum or shasum to continue" + exit 1 + fi +} + function download { - if command -v curl > /dev/null 2>&1; then + if has_cmd "curl"; then curl -L -o "$2" "$1" - elif command -v wget > /dev/null 2>&1; then + elif has_cmd "wget"; then wget -O "$2" "$1" else echo "Please install either wget or curl to continue" @@ -97,71 +114,46 @@ function install_pkg_config { cat /usr/local/bin/i686-w64-mingw32-pkg-config } -function install_local_libs { - mkdir -p lib - cp -rf $cachedir/orctlibs/local/* ./lib/. +function os_x_install_mingw_32 { + local mingw_name="mingw-w32-bin_i686-darwin" + local mingw_tar="${mingw_name}_20130531.tar.bz2" + local mingw_path="/usr/local/$mingw_name" + + if [[ ! -f "$cachedir/$mingw_tar" ]]; then + download "https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win32/Automated Builds/$mingw_tar" "$cachedir/$mingw_tar" + fi + + if [[ ! -d "$mingw_path" ]]; then + echo "Extracting contents of $mingw_tar to $mingw_path" + echo "Don't forget to add $mingw_path/bin to your PATH variable!" + + mkdir "$mingw_path" + tar -xyf "$cachedir/$mingw_tar" -C "$mingw_path" + + pushd "$mingw_path" + find . -type d -exec chmod 755 {} \; + popd + fi } -echo TARGET = $TARGET +echo "HOST = $(uname)" +echo "TARGET = $TARGET" -if [[ $(uname) == "Darwin" ]]; then - echo "Installation of OpenRCT2 assumes you have homebrew and use it to install packages." +if [[ "$(uname)" == "Darwin" ]]; then + if ! has_cmd "brew"; then + echo "Homebrew is not installed, or brew is not in your \$PATH" + echo "install instructions: http://brew.sh/" + exit 1 + fi - echo "Check if brew is installed" - package_command="brew" - which -s brew - if [ $? -eq 1 ]; then - echo "brew is not installed, or is not in your \$PATH" - echo "Check if MacPorts is installed" - which -s port - if [ $? -eq 1 ]; then - echo "MacPorts not found either, abort" - exit - else - echo "MacPorts found" - package_command="sudo port" - fi - else - echo "brew was found" - fi + brew install cmake - # Install packages with whatever command was found. - # Very possible I'm missing some dependencies here. - eval "$package_command install cmake wine" - - if [[ ! -d /usr/include/wine ]]; then - # This will almost certainly break as brew changes. Better ideas - # welcome. - wine_path="/usr/local/Cellar/wine/1.6.2/include/wine" - if [ $package_command == "sudo port" ]; then - wine_path="/opt/local/include/wine" - fi - sudo ln -s $wine_path /usr/include - fi - - mingw_name=mingw-w32-bin_i686-darwin - mingw_tar=$mingw_name"_20130531".tar.bz2 - mingw_path=/usr/local/$mingw_name - if [[ ! -f $cachedir/$mingw_tar ]]; then - download "https://downloads.sourceforge.net/project/mingw-w64/Toolchains targetting Win32/Automated Builds/$mingw_tar" $cachedir/$mingw_tar - fi - if [[ ! -d "$mingw_path" ]]; then - - pushd /usr/local/ - sudo mkdir $mingw_name - popd - - echo "Extracting contents of $mingw_tar to $mingw_path" - echo "Don't forget to add $mingw_path/bin to your PATH variable!" - sudo tar -xyf $cachedir/$mingw_tar -C $mingw_path - - pushd /usr/local - sudo chmod 755 $mingw_name - pushd $mingw_name - sudo find . -type d -exec chmod 755 {} \; - popd - popd - fi + if [[ $TARGET == "windows" ]]; then + brew install wine + os_x_install_mingw_32 + else + brew install jansson sdl2 sdl2_ttf speex --universal + fi elif [[ $(uname) == "Linux" ]]; then if [[ -z "$TRAVIS" ]]; then sudo apt-get install -y binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686 cmake @@ -174,7 +166,7 @@ elif [[ $(uname) == "Linux" ]]; then "linux") sudo dpkg --add-architecture i386 sudo apt-get update - sudo apt-get install --no-install-recommends -y --force-yes cmake libsdl2-dev:i386 libsdl2-ttf-dev:i386 gcc-4.8 pkg-config:i386 g++-4.8-multilib gcc-4.8-multilib libjansson-dev:i386 libspeex-dev:i386 libspeexdsp-dev:i386 libcurl4-openssl-dev:i386 libcrypto++-dev:i386 clang + sudo apt-get install --no-install-recommends -y --force-yes cmake libsdl2-dev:i386 libsdl2-ttf-dev:i386 gcc-4.8 pkg-config:i386 g++-4.8-multilib gcc-4.8-multilib libjansson-dev:i386 libspeex-dev:i386 libspeexdsp-dev:i386 libcurl4-openssl-dev:i386 libcrypto++-dev:i386 clang libfontconfig1-dev:i386 libfreetype6-dev:i386 libpng-dev:i386 download https://launchpad.net/ubuntu/+archive/primary/+files/libjansson4_2.7-1ubuntu1_i386.deb libjansson4_2.7-1ubuntu1_i386.deb download https://launchpad.net/ubuntu/+archive/primary/+files/libjansson-dev_2.7-1ubuntu1_i386.deb libjansson-dev_2.7-1ubuntu1_i386.deb sudo dpkg -i libjansson4_2.7-1ubuntu1_i386.deb @@ -195,16 +187,13 @@ elif [[ $(uname) == "Linux" ]]; then fi fi -download_libs -# mind the gap (trailing space) -if [[ $(uname) == "Darwin" ]]; then - shasum -a 256 $cachedir/orctlibs.zip | cut -f1 -d\ > $libVFile -else - sha256sum $cachedir/orctlibs.zip | cut -f1 -d\ > $libVFile +if [[ $TARGET == "windows" || $(uname -s) == "Darwin" ]]; then + download_libs + calculate_sha256 "$cachedir/orctlibs.zip" > "$libVFile" + echo "Downloaded library with sha256sum: $(cat "$libVFile")" + # Local libs are required for all targets +# $TARGET == "windows" || $(uname -s) == "Darwin" fi -echo "Downloaded library with sha256sum: $(cat $libVFile)" -# Local libs are required for all targets -install_local_libs if [[ $TARGET == "windows" ]]; then download_sdl diff --git a/scripts/ps/appveyor_run.ps1 b/scripts/ps/appveyor_run.ps1 new file mode 100644 index 0000000000..665ffab9e0 --- /dev/null +++ b/scripts/ps/appveyor_run.ps1 @@ -0,0 +1,162 @@ +######################################################### +# Script to build OpenRCT2 on AppVeyor +######################################################### + +function Push-Build($file, $name, $version, $flavourId) +{ + curl.exe -s -o - ` + --form "key=${env:OPENRCT2.ORG_TOKEN}" ` + --form "fileName=$name" ` + --form "version=$version" ` + --form "gitHash=${env:APPVEYOR_REPO_COMMIT}" ` + --form "gitBranch=${env:APPVEYOR_REPO_BRANCH}" ` + --form "flavourId=$flavourId" ` + --form "file=@$file" ` + "https://openrct2.org/altapi/?command=push-build" +} + +$server = "AppVeyor" + +# Provide a short commit SHA1 too +${env:APPVEYOR_REPO_COMMIT_SHORT} = (${env:APPVEYOR_REPO_COMMIT}).Substring(0, 7) + +# Current version +$version = "0.0.4.0" + +# Tagged builds will hide branch and commit SHA1 +$tag = $null +if (${env:APPVEYOR_REPO_TAG} -ne $null) +{ + $tag = ${env:APPVEYOR_REPO_TAG_NAME} +} + +# Enable code signing if password environment variable is set +$codeSign = $false +if (${env:CODE-SIGN-KEY-OPENRCT2.ORG.PFX.PASSWORD} -ne $null) +{ + $codeSign = $true +} + +# Enable pushing builds to OpenRCT2.org if token environment variable is set +$pushBuilds = $false +$installer = $false +$symbols = $false +if (${env:OPENRCT2.ORG_TOKEN} -ne $null) +{ + $installer = $true + $symbols = $true + + if ($tag -ne $null -or $env:APPVEYOR_REPO_BRANCH -match "^develop$|^push/") + { + $pushBuilds = $true + } +} + +# Write out summary of the build +Write-Host "AppVeyor CI Build" -ForegroundColor Green +if ($tag -ne $null) +{ + Write-Host " $version ($tag)" -ForegroundColor Green +} +else +{ + Write-Host " $version-$env:APPVEYOR_REPO_BRANCH-$env:APPVEYOR_REPO_COMMIT_SHORT" -ForegroundColor Green +} +Write-Host " Signed: $codeSign" -ForegroundColor Green +Write-Host " Push : $pushBuilds" -ForegroundColor Green + +# Install dependencies +install -Quiet + +# Build OpenRCT2 +publish build ` + -Server $server ` + -GitTag $tag ` + -GitBranch $env:APPVEYOR_REPO_BRANCH ` + -GitSha1 $env:APPVEYOR_REPO_COMMIT ` + -GitSha1Short $env:APPVEYOR_REPO_COMMIT_SHORT ` + -CodeSign $codeSign + +if ($LASTEXITCODE -ne 0) +{ + exit 1 +} + +# Create a Portable ZIP +publish package ` + -Server $server ` + -GitTag $tag ` + -GitBranch $env:APPVEYOR_REPO_BRANCH ` + -GitSha1 $env:APPVEYOR_REPO_COMMIT ` + -GitSha1Short $env:APPVEYOR_REPO_COMMIT_SHORT ` + -CodeSign $codeSign + +# Create an Installer +if ($installer) +{ + publish package ` + -Installer ` + -Server $server ` + -GitTag $tag ` + -GitBranch $env:APPVEYOR_REPO_BRANCH ` + -GitSha1 $env:APPVEYOR_REPO_COMMIT ` + -GitSha1Short $env:APPVEYOR_REPO_COMMIT_SHORT ` + -CodeSign $codeSign +} + +if ($symbols) +{ + publish package ` + -Symbols ` + -Server $server ` + -GitTag $tag ` + -GitBranch $env:APPVEYOR_REPO_BRANCH ` + -GitSha1 $env:APPVEYOR_REPO_COMMIT ` + -GitSha1Short $env:APPVEYOR_REPO_COMMIT_SHORT ` + -CodeSign $codeSign +} + +if ($pushBuilds) +{ + $versionExtension = "" + if ($tag -ne $null) + { + # Hide tag if it is a version + if ($GitTag -notmatch "^v[0-9]") + { + $versionExtension = "-$tag" + } + } + else + { + $versionExtension = "-${env:APPVEYOR_REPO_BRANCH}-${env:APPVEYOR_REPO_COMMIT_SHORT}" + } + $pushFileName = "OpenRCT2-${version}${versionExtension}-windows" + + # Push portable zip + Write-Host "Sending portable zip to OpenRCT2.org" -ForegroundColor Cyan + Push-Build -file ".\artifacts\openrct2.zip" ` + -name "$pushFileName.zip" ` + -version $version ` + -flavourId 1 + + # Push installer + if ($installer) + { + Write-Host "Sending installer to OpenRCT2.org" -ForegroundColor Cyan + Push-Build -file ".\artifacts\openrct2-install.exe" ` + -name "$pushFileName.exe" ` + -version $version ` + -flavourId 2 + } + + # Push symbols + if ($symbols) + { + Write-Host "Sending symbols to OpenRCT2.org" -ForegroundColor Cyan + Push-Build -file ".\artifacts\openrct2-symbols-${env:APPVEYOR_REPO_COMMIT_SHORT}.zip" ` + -name "$pushFileName-symbols.zip" ` + -version $version ` + -flavourId 5 + } +} diff --git a/scripts/ps/build.ps1 b/scripts/ps/build.ps1 new file mode 100644 index 0000000000..99a188f97a --- /dev/null +++ b/scripts/ps/build.ps1 @@ -0,0 +1,81 @@ +######################################################### +# Script to build different parts of OpenRCT2 +######################################################### +[CmdletBinding()] +param ( + [Parameter(Mandatory = $false, Position = 1)] + [string]$Task = "openrct2", + + [Parameter(Mandatory = $false)] + [string]$Configuration = "Release", + + [Parameter(Mandatory = $false)] + [switch]$Rebuild = $false, + + [Parameter(Mandatory = $false)] + [switch]$Breakpad = $false +) + +# Setup +$ErrorActionPreference = "Stop" +$scriptsPath = Split-Path $Script:MyInvocation.MyCommand.Path +Import-Module "$scriptsPath\common.psm1" -DisableNameChecking + +# Get paths +$rootPath = Get-RootPath +$binPath = Join-Path $rootPath "bin" +$openrct2Path = Join-Path $binPath "openrct2.exe" + +function Build-Data() +{ + Write-Host "Copying data to bin..." -ForegroundColor Cyan + New-Item -Force -ItemType Directory $binPath > $null + Copy-Item -Force -Recurse "$rootPath\data" $binPath + return 0 +} + +function Build-OpenRCT2() +{ + Write-Host "Building OpenRCT2 ($Configuration)..." -ForegroundColor Cyan + + $target = "" + if ($Rebuild) + { + $target = "/t:rebuild" + } + msbuild $rootPath\openrct2.sln /p:Breakpad=$Breakpad /p:Configuration=$Configuration /p:Platform=Win32 $target /v:minimal | Write-Host + return $LASTEXITCODE +} + +function Build-G2() +{ + # Check if OpenRCT2 binary exists + if (-not (Test-Path $openrct2Path)) + { + Write-Host "You must build OpenRCT2 first before g2.dat can be built." -ForegroundColor Red + return 1 + } + + Write-Host "Building g2.dat..." -ForegroundColor Cyan + & $openrct2Path sprite build "$binPath\data\g2.dat" "$rootPath\resources\g2" + return $LASTEXITCODE +} + +function Build-All() +{ + if (($result = (Build-Data )) -ne 0) { return $result } + if (($result = (Build-OpenRCT2)) -ne 0) { return $result } + if (($result = (Build-G2 )) -ne 0) { return $result } +} + +# Script entry point +switch ($Task) +{ + "data" { $result = Build-Data } + "openrct2" { $result = Build-OpenRCT2 } + "g2" { $result = Build-G2 } + "all" { $result = Build-All } + default { Write-Host "Unknown build task." -ForegroundColor Red + $result = 1 } +} +exit $result diff --git a/scripts/ps/common.psm1 b/scripts/ps/common.psm1 new file mode 100644 index 0000000000..f643f6da8a --- /dev/null +++ b/scripts/ps/common.psm1 @@ -0,0 +1,29 @@ +######################################################### +# Common functions for OpenRCT2 PowerShell scripts +######################################################### +$scriptsPath = Split-Path $Script:MyInvocation.MyCommand.Path + +function AppExists($app) +{ + $result = (Get-Command $app -CommandType Application -ErrorAction SilentlyContinue) + return ($result -ne $null -and $result.Count -gt 0) +} + +function AddPath($path) +{ + $env:path = "$path;$env:path" +} + +function Get-RootPath() +{ + return Split-Path (Split-Path $scriptsPath) +} + +function Prompt-User($message) +{ + $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Yes" + $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "No" + $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) + $choice = $host.UI.PromptForChoice("", $message, $options, 1) + return ($choice -eq 0) +} diff --git a/scripts/ps/install.ps1 b/scripts/ps/install.ps1 new file mode 100644 index 0000000000..016e181e65 --- /dev/null +++ b/scripts/ps/install.ps1 @@ -0,0 +1,63 @@ +######################################################### +# Script to install the latest dependencies for OpenRCT2 +######################################################### +param ( + [switch]$Force, + [switch]$Quiet +) +Write-Host "Installing OpenRCT2 development environment for Windows" -ForegroundColor Cyan + +# Setup +$ErrorActionPreference = "Stop" +$scriptsPath = Split-Path $Script:MyInvocation.MyCommand.Path +Import-Module "$scriptsPath\common.psm1" -DisableNameChecking + +# Constants +$libsUrl = "https://openrct2.website/files/openrct2-libs-vs2015.zip" +$libsVersion = 7 + +# Get paths +$rootPath = Get-RootPath +$libsPath = Join-Path $rootPath "lib" +$zipPath = Join-Path $libsPath "openrct2-libs-vs2015.zip" +$libsVersionPath = Join-Path $libsPath "libversion" + +# Check if we need to update the dependencies +$currentLibsVersion = 0 +$updateLibs = $true +if (Test-Path $libsVersionPath) +{ + $currentLibsVersion = [IO.File]::ReadAllText($libsVersionPath) +} +if ($currentLibsVersion -ge $libsVersion) +{ + $updateLibs = $false +} + +# Check if user needs to download dependencies +$libsPathExists = Test-Path $libsPath +if ($libsPathExists -and -not $updateLibs -and -not $Force) +{ + if (-not $Quiet -and (Prompt-User "Dependencies already exists, reinstall?")) + { + $updateLibs = $true + } +} +else +{ + $updateLibs = $true +} + +# Download latest version of the dependencies +if ($updateLibs) { + Write-Host "Updating dependencies..." -ForegroundColor Cyan + + Remove-Item -Force -Recurse $libsPath -ErrorAction SilentlyContinue + New-Item -Force -ItemType Directory $libsPath > $null + + Invoke-WebRequest $libsUrl -OutFile $zipPath + [System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') > $null + [System.IO.Compression.ZipFile]::ExtractToDirectory($zipPath, $libsPath) + Remove-Item $zipPath -Force -ErrorAction SilentlyContinue + $libsVersion | Set-Content $libsVersionPath +} diff --git a/scripts/ps/publish.ps1 b/scripts/ps/publish.ps1 new file mode 100644 index 0000000000..ed2d4288da --- /dev/null +++ b/scripts/ps/publish.ps1 @@ -0,0 +1,326 @@ +######################################################### +# Script to build and package OpenRCT2 +# - Sets the source code preprocessor defines +# - Builds a clean release of OpenRCT2 +# - Creates a ZIP for distribution +######################################################### +param ( + [Parameter(Position = 1)] + [string]$Task = "all", + + [string]$Server = "", + [string]$GitTag = "", + [string]$GitBranch = "", + [string]$GitSha1 = "", + [string]$GitSha1Short = "", + [bool] $CodeSign = $false, + [switch]$Installer = $false, + [switch]$Symbols = $false +) + +if ($GitTag -eq "") +{ + if ($GitBranch -eq $null) + { + $GitBranch = (git rev-parse --abbrev-ref HEAD) + } + if ($GitCommitSha1 -eq $null) + { + $GitCommitSha1 = (git rev-parse HEAD) + } + if ($GitCommitSha1Short -eq $null) + { + $GitCommitSha1Short = (git rev-parse --short HEAD) + } +} + +# Setup +$ErrorActionPreference = "Stop" +$scriptsPath = Split-Path $Script:MyInvocation.MyCommand.Path +Import-Module "$scriptsPath\common.psm1" -DisableNameChecking + +# Get paths +$rootPath = Get-RootPath + +# Set build attributes +function Do-PrepareSource() +{ + Write-Host "Setting build #defines..." -ForegroundColor Cyan + $defines = @{ } + $defines["OPENRCT2_BUILD_SERVER"] = $Server; + if ($GitTag -ne "") + { + # Hide tag if it is a version + if ($GitTag -match "^v[0-9]") + { + $defines["OPENRCT2_BRANCH"] = ""; + } + else + { + $defines["OPENRCT2_BRANCH"] = $GitTag; + } + } + else + { + $defines["OPENRCT2_BRANCH"] = $GitBranch; + $defines["OPENRCT2_COMMIT_SHA1"] = $GitCommitSha1; + $defines["OPENRCT2_COMMIT_SHA1_SHORT"] = $GitCommitSha1Short; + } + + $defineString = "" + foreach ($key in $defines.Keys) { + $value = $defines[$key] + if ($value -is [System.String]) { + $value = $value.Replace('"', '\"') + } + $defineString += "$key=""$value"";"; + } + + # Set the environment variable which the msbuild project will use + $env:OPENRCT2_DEFINES = $defineString; + + return 0 +} + +# Building OpenRCT2 +function Do-Build() +{ + Write-Host "Building OpenRCT2..." -ForegroundColor Cyan + & "$scriptsPath\build.ps1" all -Rebuild -Breakpad + if ($LASTEXITCODE -ne 0) + { + Write-Host "Failed to build OpenRCT2" -ForegroundColor Red + return 1 + } + + if ($CodeSign) + { + $releaseDir = "$rootPath\bin" + $exePath = "$releaseDir\openrct2.exe" + $dllPath = "$releaseDir\openrct2.dll" + + if (-not (Sign-Binary($exePath))) { return 1 } + if (-not (Sign-Binary($dllPath))) { return 1 } + } + + return 0 +} + +# Symbols +function Do-Symbols() +{ + Write-Host "Publishing OpenRCT2 debug symbols as zip..." -ForegroundColor Cyan + $artifactsDir = "$rootPath\artifacts" + $releaseDir = "$rootPath\bin" + $outZip = "$rootPath\artifacts\openrct2-symbols-$GitSha1Short.zip" + + Copy-Item -Force "$releaseDir\openrct2.pdb" $artifactsDir -ErrorAction Stop + Copy-Item -Force "$releaseDir\openrct2.dll" $artifactsDir -ErrorAction Stop + + # Create archive using 7z (renowned for speed and compression) + $7zcmd = "7za" + if (-not (AppExists($7zcmd))) + { + # AppVeyor in particular uses '7z' instead + $7zcmd = "7z" + if (-not (AppExists($7zcmd))) + { + Write-Host "Publish script requires 7z to be in PATH" -ForegroundColor Red + return 1 + } + } + & $7zcmd a -tzip -mx9 $outZip "$artifactsDir\openrct2.pdb" "$artifactsDir\openrct2.dll" > $null + if ($LASTEXITCODE -ne 0) + { + Write-Host "Failed to create zip." -ForegroundColor Red + return 1 + } + Remove-Item -Force -Recurse "$artifactsDir\openrct2.pdb" -ErrorAction SilentlyContinue + return 0 +} + +# Package +function Do-Package() +{ + Write-Host "Publishing OpenRCT2 as zip..." -ForegroundColor Cyan + $releaseDir = "$rootPath\bin" + $distDir = "$rootPath\distribution" + $tempDir = "$rootPath\artifacts\temp" + $outZip = "$rootPath\artifacts\openrct2.zip" + + # Create new temp directory + Remove-Item -Force -Recurse $tempDir -ErrorAction SilentlyContinue + New-Item -Force -ItemType Directory $tempDir > $null + + # Copy files to be archived + Copy-Item -Force -Recurse "$releaseDir\data" $tempDir -ErrorAction Stop + Copy-Item -Force "$releaseDir\openrct2.exe" $tempDir -ErrorAction Stop + Copy-Item -Force "$releaseDir\openrct2.dll" $tempDir -ErrorAction Stop + Copy-Item -Force "$releaseDir\curl-ca-bundle.crt" $tempDir -ErrorAction Stop + Copy-Item -Force "$distDir\changelog.txt" $tempDir -ErrorAction Stop + Copy-Item -Force "$distDir\known_issues.txt" $tempDir -ErrorAction Stop + Copy-Item -Force "$distDir\readme.txt" $tempDir -ErrorAction Stop + Copy-Item -Force "$rootPath\contributors.md" $tempDir -ErrorAction Stop + Copy-Item -Force "$rootPath\licence.txt" $tempDir -ErrorAction Stop + + # Create archive using 7z (renowned for speed and compression) + $7zcmd = "7za" + if (-not (AppExists($7zcmd))) + { + # AppVeyor in particular uses '7z' instead + $7zcmd = "7z" + if (-not (AppExists($7zcmd))) + { + Write-Host "Publish script requires 7z to be in PATH" -ForegroundColor Red + return 1 + } + } + & $7zcmd a -tzip -mx9 $outZip "$tempDir\*" > $null + if ($LASTEXITCODE -ne 0) + { + Write-Host "Failed to create zip." -ForegroundColor Red + return 1 + } + + # Remove temp directory + Remove-Item -Force -Recurse $tempDir -ErrorAction SilentlyContinue + return 0 +} + +# Installer +function Do-Installer() +{ + Write-Host "Publishing OpenRCT2 as installer..." -ForegroundColor Cyan + $artifactsDir = "$rootPath\artifacts" + $installerDir = "$rootPath\distribution\windows" + + # Create artifacts directory + New-Item -Force -ItemType Directory $artifactsDir > $null + + # Resolve version extension + $VersionExtra = "" + if ($GitTag -ne "") + { + # Hide tag if it is a version + if ($GitTag -notmatch "^v[0-9]") + { + $VersionExtra = "-$GitTag"; + } + } + else + { + $VersionExtra = "-$GitBranch-$GitCommitSha1Short" + } + + # Create installer + & "$installerDir\build.ps1" -VersionExtra $VersionExtra + if ($LASTEXITCODE -ne 0) + { + Write-Host "Failed to create installer." -ForegroundColor Red + if (Test-Path -PathType Leaf "$installerDir\win32.log") + { + Get-Content "$installerDir\win32.log" | Write-Host + } + return 1 + } + + $binaries = (Get-ChildItem "$installerDir\*.exe" | Sort-Object -Property LastWriteTime -Descending) + if ($binaries -eq 0) + { + Write-Host "Unable to find created installer." -ForegroundColor Red + return 1 + } + + $installerPath = $binaries[0].FullName + + if ($CodeSign) + { + if (-not (Sign-Binary($installerPath))) { return 1 } + } + + Move-Item -Force $installerPath "$artifactsDir\openrct2-install.exe" + return 0 +} + +function Do-Task-Build() +{ + if (($result = (Do-PrepareSource)) -ne 0) { return $result } + if (($result = (Do-Build )) -ne 0) { return $result } + return 0 +} + +function Do-Task-Package() +{ + if ($Installer) + { + if (($result = (Do-Installer)) -ne 0) { return $result } + } + elseif ($Symbols) + { + if (($result = (Do-Symbols)) -ne 0) { return $result } + } + else + { + if (($result = (Do-Package)) -ne 0) { return $result } + } + return 0 +} + +function Do-Task-All() +{ + if (($result = (Do-Task-Build )) -ne 0) { return $result } + if (($result = (Do-Task-Package)) -ne 0) { return $result } + return 0 +} + +function Sign-Binary($binaryPath) +{ + $pfxPath = "$rootPath\distribution\windows\code-sign-key-openrct2.org.pfx" + $pfxPassword = ${env:CODE-SIGN-KEY-OPENRCT2.ORG.PFX.PASSWORD} + $timestampUrl = "http://timestamp.comodoca.com/authenticode" + + if (-not (Test-Path -PathType Leaf $pfxPath)) + { + Write-Host "Unable to sign, code signature key was not found." -ForegroundColor Red + return 1 + } + + if ($pfxPassword -eq $null) + { + Write-Host "Unable to sign, %CODE-SIGN-KEY-OPENRCT2.ORG.PFX.PASSWORD% was not set." -ForegroundColor Red + return 1 + } + + # Resolve signtool path + $signtoolcmd = "signtool" + if (-not (AppExists($signtoolcmd))) + { + $signtoolcmd = "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\SignTool.exe" + if (-not (AppExists($signtoolcmd))) + { + Write-Host "Publish script requires signtool to be in PATH" -ForegroundColor Red + return 1 + } + } + + # Sign the binary + & $signtoolcmd sign /f $pfxPath /p $pfxPassword /t $timestampUrl $binaryPath + if ($LASTEXITCODE -ne 0) + { + Write-Host "Failed to sign binary." -ForegroundColor Red + return 1 + } + + return 0 +} + +# Script entry point +switch ($Task) +{ + "build" { $result = Do-Task-Build } + "package" { $result = Do-Task-Package } + "all" { $result = Do-Task-All } + default { Write-Host "Unknown publish task." -ForegroundColor Red + $result = 1 } +} +exit $result diff --git a/scripts/ps/run.ps1 b/scripts/ps/run.ps1 new file mode 100644 index 0000000000..e1e1737b05 --- /dev/null +++ b/scripts/ps/run.ps1 @@ -0,0 +1,3 @@ +$scriptsPath = Split-Path $Script:MyInvocation.MyCommand.Path +$rootPath = Split-Path (Split-Path $scriptsPath) +&("$rootPath\bin\openrct2.exe") $args diff --git a/setenv.ps1 b/setenv.ps1 new file mode 100644 index 0000000000..15aadc5ef4 --- /dev/null +++ b/setenv.ps1 @@ -0,0 +1,38 @@ +########################################################### +# Setups a PowerShell environment for OpenRCT2 development +########################################################### + +# Setup +$ErrorActionPreference = "Stop" +$rootPath = Split-Path $Script:MyInvocation.MyCommand.Path +$scriptsPath = "$rootPath\scripts\ps" +Import-Module "$scriptsPath\common.psm1" -DisableNameChecking + +Write-Host "Setting up OpenRCT2 development environment for Windows" -ForegroundColor Cyan + +$appExists = @{} +$appExists["msbuild"] = AppExists("msbuild"); +$appExists["7za"] = AppExists("7za"); +$appExists["7z"] = AppExists("7z"); + +if (-not $appExists["msbuild"]) +{ + if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") + { + $lookPath = Join-Path ${env:ProgramFiles(x86)} "MSBuild\14.0\Bin\amd64\MSBuild.exe" + } + else + { + $lookPath = Join-Path $env:ProgramFiles "MSBuild\14.0\Bin\MSBuild.exe" + } + if (Test-Path $lookPath) + { + AddPath(Split-Path $lookPath) + } + else + { + Write-Host "Warning: msbuild not found, please include it in your PATH" -ForegroundColor Yellow + } +} + +AddPath($scriptsPath) diff --git a/src/addresses.c b/src/addresses.c index 0e9f4d3a89..335d905b72 100644 --- a/src/addresses.c +++ b/src/addresses.c @@ -1,7 +1,11 @@ #include "addresses.h" #if defined(__GNUC__) -#define DISABLE_OPT __attribute__((noinline,optimize("O0"))) + #ifdef __clang__ + #define DISABLE_OPT __attribute__((noinline,optnone)) + #else + #define DISABLE_OPT __attribute__((noinline,optimize("O0"))) + #endif // __clang__ #else #define DISABLE_OPT #endif // defined(__GNUC__) diff --git a/src/addresses.h b/src/addresses.h index 7f2622284e..bc235a15f4 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -21,38 +21,14 @@ #ifndef _ADDRESSES_H_ #define _ADDRESSES_H_ +#include "common.h" + #ifdef _MSC_VER #pragma warning(disable : 4731) #endif #define RCT2_ADDRESS(address, type) ((type*)(address)) #define RCT2_GLOBAL(address, type) (*((type*)(address))) -#ifdef _WIN32 -#define RCT2_CALLPROC(address) (((void(*)())(address))()) -#define RCT2_CALLFUNC(address, returnType) (((returnType(*)())(address))()) - -#define RCT2_CALLFUNC_1(address, returnType, a1, v1) (((returnType(*)(a1))(address))(v1)) -#define RCT2_CALLFUNC_2(address, returnType, a1, a2, v1, v2) (((returnType(*)(a1, a2))(address))(v1, v2)) -#define RCT2_CALLFUNC_3(address, returnType, a1, a2, a3, v1, v2, v3) (((returnType(*)(a1, a2, a3))(address))(v1, v2, v3)) -#define RCT2_CALLFUNC_4(address, returnType, a1, a2, a3, a4, v1, v2, v3, v4) (((returnType(*)(a1, a2, a3, a4))(address))(v1, v2, v3, v4)) -#define RCT2_CALLFUNC_5(address, returnType, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) (((returnType(*)(a1, a2, a3, a4, a5))(address))(v1, v2, v3, v4, v5)) -#define RCT2_CALLFUNC_6(address, returnType, a1, a2, a3, a4, a5, a6, v1, v2, v3, v4, v5, v6) (((returnType(*)(a1, a2, a3, a4, a5, a6))(address))(v1, v2, v3, v4, v5, v6)) -#else -#define RCT2_CALLPROC(address) -#define RCT2_CALLFUNC(address, returnType) -#define RCT2_CALLFUNC_1(address, returnType, a1, v1) -#define RCT2_CALLFUNC_2(address, returnType, a1, a2, v1, v2) -#define RCT2_CALLFUNC_3(address, returnType, a1, a2, a3, v1, v2, v3) -#define RCT2_CALLFUNC_4(address, returnType, a1, a2, a3, a4, v1, v2, v3, v4) -#define RCT2_CALLFUNC_5(address, returnType, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) -#define RCT2_CALLFUNC_6(address, returnType, a1, a2, a3, a4, a5, a6, v1, v2, v3, v4, v5, v6) -#endif // _WIN32 - -#define RCT2_CALLPROC_1(address, a1, v1) RCT2_CALLFUNC_1(address, void, a1, v1) -#define RCT2_CALLPROC_2(address, a1, a2, v1, v2) RCT2_CALLFUNC_2(address, void, a1, a2, v1, v2) -#define RCT2_CALLPROC_3(address, a1, a2, a3, v1, v2, v3) RCT2_CALLFUNC_3(address, void, a1, a2, a3, v1, v2, v3) -#define RCT2_CALLPROC_4(address, a1, a2, a3, a4, v1, v2, v3, v4) RCT2_CALLFUNC_4(address, void, a1, a2, a3, a4, v1, v2, v3, v4) -#define RCT2_CALLPROC_5(address, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) RCT2_CALLFUNC_5(address, void, a1, a2, a3, a4, a5, v1, v2, v3, v4, v5) #pragma region Memory locations @@ -63,6 +39,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 @@ -146,6 +123,9 @@ #define RCT2_ADDRESS_PATH_TYPES 0x009ADA14 #define RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES 0x009ADA54 #define RCT2_ADDRESS_SCENERY_SET_ENTRIES 0x009ADA90 +#define RCT2_ADDRESS_PARK_ENTRANCE_ENTRIES 0x009ADADC +#define RCT2_ADDRESS_WATER_ENTRIES 0x009ADAE0 +#define RCT2_ADDRESS_SCENARIO_TEXT_ENTRIES 0x009ADAE4 #define RCT2_ADDRESS_INSTALLED_OBJECT_LIST 0x009ADAE8 #define RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST 0x009ADAEC @@ -191,7 +171,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 @@ -291,6 +271,10 @@ #define RCT2_ADDRESS_PEEP_UPDATE_FALLING_MAP 0x00F1AEC4 #define RCT2_ADDRESS_PEEP_UPDATE_FALLING_HEIGHT 0x00F1AEC8 +#define RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X 0x00F1AECE +#define RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y 0x00F1AED0 +#define RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z 0x00F1AED2 + #define RCT2_ADDRESS_PROVISIONAL_PATH_FLAGS 0x00F3EF92 #define RCT2_ADDRESS_PROVISIONAL_PATH_X 0x00F3EF94 #define RCT2_ADDRESS_PROVISIONAL_PATH_Y 0x00F3EF96 @@ -479,6 +463,7 @@ #define RCT2_ADDRESS_SAVED_VIEW_X 0x0138869A #define RCT2_ADDRESS_SAVED_VIEW_Y 0x0138869C #define RCT2_ADDRESS_SAVED_VIEW_ZOOM_AND_ROTATION 0x0138869E +#define RCT2_ADDRESS_SCENARIO_COMPLETED_BY 0x013587D8 #define RCT2_ADDRESS_RIDE_MEASUREMENTS 0x0138B60C #define RCT2_ADDRESS_GRASS_SCENERY_TILEPOS 0x013B0E70 @@ -513,6 +498,8 @@ #define RCT2_ADDRESS_FONT_CHAR_WIDTH 0x0141E9E8 +#define RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT 0x0141E9D8 + #define RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER 0x0141ED68 // This value is always 4 times the actual type @@ -639,16 +626,17 @@ #pragma endregion -/* Returns the flags register +/** + * Returns the flags register * - *Flags register is as follows: - *0bSZ0A_0P0C_0000_0000 - *S = Signed flag - *Z = Zero flag - *C = Carry flag - *A = Adjust flag - *P = Parity flag - *All other bits are undefined. + * Flags register is as follows: + * 0bSZ0A_0P0C_0000_0000 + * S = Signed flag + * Z = Zero flag + * C = Carry flag + * A = Adjust flag + * P = Parity flag + * All other bits are undefined. */ int RCT2_CALLPROC_X(int address, int _eax, int _ebx, int _ecx, int _edx, int _esi, int _edi, int _ebp); @@ -657,16 +645,17 @@ static int RCT2_CALLPROC_EBPSAFE(int address) return RCT2_CALLPROC_X(address, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB, 0xBBBBBBBB); } -/* Returns the flags register +/** + * Returns the flags register * - *Flags register is as follows: - *0bSZ0A_0P0C_0000_00000 - *S = Signed flag - *Z = Zero flag - *C = Carry flag - *A = Adjust flag - *P = Parity flag - *All other bits are undefined. + * Flags register is as follows: + * 0bSZ0A_0P0C_0000_00000 + * S = Signed flag + * Z = Zero flag + * C = Carry flag + * A = Adjust flag + * P = Parity flag + * All other bits are undefined. */ int RCT2_CALLFUNC_X(int address, int *_eax, int *_ebx, int *_ecx, int *_edx, int *_esi, int *_edi, int *_ebp); diff --git a/src/audio/audio.c b/src/audio/audio.c index cc91211127..ff91b26ed5 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -44,7 +44,6 @@ void *gCrowdSoundChannel = 0; bool gGameSoundsOff = false; void *gRainSoundChannel = 0; rct_ride_music gRideMusicList[AUDIO_MAX_RIDE_MUSIC]; -rct_ride_music_info *gRideMusicInfoList[NUM_DEFAULT_MUSIC_TRACKS]; rct_ride_music_params gRideMusicParamsList[AUDIO_MAX_RIDE_MUSIC]; rct_ride_music_params *gRideMusicParamsListEnd; void *gTitleMusicChannel = 0; @@ -61,9 +60,9 @@ void audio_init() if (result >= 0) return; - log_fatal("SDL_Init %s", SDL_GetError()); - exit(-1); - } + log_fatal("SDL_Init %s", SDL_GetError()); + exit(-1); +} void audio_quit() { @@ -79,18 +78,26 @@ void audio_populate_devices() if (gAudioDeviceCount <= 0) return; - gAudioDeviceCount++; - gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); - safe_strncpy(gAudioDevices[0].name, language_get_string(5510), AUDIO_DEVICE_NAME_SIZE); - - for (int i = 1; i < gAudioDeviceCount; i++) { - const char *utf8Name = SDL_GetAudioDeviceName(i - 1, SDL_FALSE); + audio_device *systemAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); + for (int i = 0; i < gAudioDeviceCount; i++) { + const char *utf8Name = SDL_GetAudioDeviceName(i, SDL_FALSE); if (utf8Name == NULL) utf8Name = language_get_string(5511); - safe_strncpy(gAudioDevices[i].name, utf8Name, AUDIO_DEVICE_NAME_SIZE); - } + safe_strcpy(systemAudioDevices[i].name, utf8Name, AUDIO_DEVICE_NAME_SIZE); } +#ifndef __LINUX__ + gAudioDeviceCount++; + gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); + safe_strcpy(gAudioDevices[0].name, language_get_string(5510), AUDIO_DEVICE_NAME_SIZE); + memcpy(&gAudioDevices[1], systemAudioDevices, (gAudioDeviceCount - 1) * sizeof(audio_device)); +#else + gAudioDevices = malloc(gAudioDeviceCount * sizeof(audio_device)); + memcpy(gAudioDevices, systemAudioDevices, gAudioDeviceCount * sizeof(audio_device)); +#endif // __LINUX__ + + free(systemAudioDevices); +} int audio_play_sound_panned(int soundId, int pan, sint16 x, sint16 y, sint16 z) { @@ -128,6 +135,8 @@ rct_audio_params audio_get_params_from_location(int soundId, const rct_xyz16 *lo int volumeDown = 0; rct_audio_params params; params.in_range = true; + params.volume = 0; + params.pan = 0; rct_map_element *element = map_get_surface_element_at(location->x / 32, location->y / 32); if (element && (element->base_height * 8) - 5 > location->z) @@ -137,9 +146,9 @@ rct_audio_params audio_get_params_from_location(int soundId, const rct_xyz16 *lo rct_xy16 pos2 = coordinate_3d_to_2d(location, rotation); rct_window *window = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); while (true) { - window--; + window--; if (window < RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_LIST, rct_window)) - break; + break; rct_viewport *viewport = window->viewport; if (!viewport || !(viewport->flags & VIEWPORT_FLAG_SOUND_ON)) @@ -153,11 +162,11 @@ rct_audio_params audio_get_params_from_location(int soundId, const rct_xyz16 *lo if (vy < 0 || vy >= viewport->view_height || vx < 0 || vx >= viewport->view_width || params.volume < -10000) { params.in_range = false; return params; - } - } + } + } return params; - } +} int audio_play_sound(int soundId, int volume, int pan) { @@ -204,6 +213,7 @@ void audio_start_title_music() } gTitleMusicChannel = Mixer_Play_Music(pathId, MIXER_LOOP_INFINITE, true); + Mixer_Channel_SetGroup(gTitleMusicChannel, MIXER_GROUP_TITLE_MUSIC); } void audio_stop_ride_music() @@ -260,10 +270,9 @@ void audio_init_ride_sounds_and_info() if (file == NULL) continue; - uint32 head; - SDL_RWread(file, &head, sizeof(head), 1); - SDL_RWclose(file); - RCT2_GLOBAL(0x014241BC, uint32) = 0; + uint32 head; + SDL_RWread(file, &head, sizeof(head), 1); + SDL_RWclose(file); if (head == 0x78787878) rideMusicInfo->length = 0; } @@ -295,8 +304,8 @@ void audio_close() } void audio_toggle_all_sounds(){ - gConfigSound.sound = !gConfigSound.sound; - if (gConfigSound.sound) + gConfigSound.sound_enabled = !gConfigSound.sound_enabled; + if (gConfigSound.sound_enabled) audio_unpause_sounds(); else { audio_stop_title_music(); @@ -323,7 +332,7 @@ void audio_stop_vehicle_sounds() if (gOpenRCT2Headless || RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, sint32) == -1) return; - for (int i = 0; i < countof(gVehicleSoundList); i++) { + for (int i = 0; i < countof(gVehicleSoundList); i++) { rct_vehicle_sound *vehicleSound = &gVehicleSoundList[i]; if (vehicleSound->id == 0xFFFF) continue; diff --git a/src/audio/audio.h b/src/audio/audio.h index 3bfde4a2f5..fcbbc4d5e9 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -170,7 +170,7 @@ extern rct_vehicle_sound_params *gVehicleSoundParamsListEnd; * rct2: 0x006BAB21 */ void audio_close(); -/* +/** * Initialises the audio subsystem. */ void audio_init(); diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp index 1edda91bc7..c9fcf20bd5 100644 --- a/src/audio/mixer.cpp +++ b/src/audio/mixer.cpp @@ -19,6 +19,7 @@ *****************************************************************************/ extern "C" { + #include "../addresses.h" #include "../config.h" #include "../platform/platform.h" #include "../localisation/localisation.h" @@ -27,6 +28,8 @@ extern "C" { } #include "mixer.h" #include +#include "../core/Math.hpp" +#include "../core/Util.hpp" Mixer gMixer; @@ -434,10 +437,10 @@ Mixer::Mixer() { effectbuffer = 0; volume = 1; - for (int i = 0; i < countof(css1sources); i++) { + for (size_t i = 0; i < Util::CountOf(css1sources); i++) { css1sources[i] = 0; } - for (int i = 0; i < countof(musicsources); i++) { + for (size_t i = 0; i < Util::CountOf(musicsources); i++) { musicsources[i] = 0; } } @@ -458,7 +461,7 @@ void Mixer::Init(const char* device) format.channels = have.channels; format.freq = have.freq; const char* filename = get_file_path(PATH_ID_CSS1); - for (int i = 0; i < countof(css1sources); i++) { + for (size_t i = 0; i < Util::CountOf(css1sources); i++) { Source_Sample* source_sample = new Source_Sample; if (source_sample->LoadCSS1(filename, i)) { source_sample->Convert(format); // convert to audio output format, saves some cpu usage but requires a bit more memory, optional @@ -481,13 +484,13 @@ void Mixer::Close() } Unlock(); SDL_CloseAudioDevice(deviceid); - for (int i = 0; i < countof(css1sources); i++) { + for (size_t i = 0; i < Util::CountOf(css1sources); i++) { if (css1sources[i] && css1sources[i] != &source_null) { delete css1sources[i]; css1sources[i] = 0; } } - for (int i = 0; i < countof(musicsources); i++) { + for (size_t i = 0; i < Util::CountOf(musicsources); i++) { if (musicsources[i] && musicsources[i] != &source_null) { delete musicsources[i]; musicsources[i] = 0; @@ -530,9 +533,9 @@ void Mixer::Stop(Channel& channel) Unlock(); } -bool Mixer::LoadMusic(int pathId) +bool Mixer::LoadMusic(size_t pathId) { - if (pathId >= countof(musicsources)) { + if (pathId >= Util::CountOf(musicsources)) { return false; } if (!musicsources[pathId]) { @@ -574,7 +577,12 @@ void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length) void Mixer::MixChannel(Channel& channel, uint8* data, int length) { - if (channel.source && channel.source->Length() > 0 && !channel.done && gConfigSound.sound) { + // Do not mix channel if channel is a sound and sound is disabled + if (channel.group == MIXER_GROUP_SOUND && !gConfigSound.sound_enabled) { + return; + } + + if (channel.source && channel.source->Length() > 0 && !channel.done) { AudioFormat streamformat = channel.source->Format(); int loaded = 0; SDL_AudioCVT cvt; @@ -664,8 +672,18 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) float volumeadjust = volume; volumeadjust *= (gConfigSound.master_volume / 100.0f); - if (channel.group == MIXER_GROUP_MUSIC) { - volumeadjust *= (gConfigSound.music_volume / 100.0f); + switch (channel.group) { + case MIXER_GROUP_SOUND: + volumeadjust *= (gConfigSound.sound_volume / 100.0f); + + // Cap sound volume on title screen so music is more audible + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) { + volumeadjust = Math::Min(volumeadjust, 0.75f); + } + break; + case MIXER_GROUP_RIDE_MUSIC: + volumeadjust *= (gConfigSound.ride_music_volume / 100.0f); + break; } int startvolume = (int)(channel.oldvolume * volumeadjust); int endvolume = (int)(channel.volume * volumeadjust); @@ -797,14 +815,15 @@ void Mixer_Init(const char* device) gMixer.Init(device); } -void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone) +void* Mixer_Play_Effect(size_t id, int loop, int volume, float pan, double rate, int deleteondone) { if (gOpenRCT2Headless) return 0; - if (!gConfigSound.sound) { + if (!gConfigSound.sound_enabled) { return 0; } - if (id >= countof(gMixer.css1sources)) { + if (id >= Util::CountOf(gMixer.css1sources)) { + log_error("Tried to play an invalid sound id. %i", id); return 0; } gMixer.Lock(); @@ -884,9 +903,6 @@ void* Mixer_Play_Music(int pathId, int loop, int streaming) { if (gOpenRCT2Headless) return 0; - if (!gConfigSound.sound) { - return 0; - } if (streaming) { const utf8 *filename = get_file_path(pathId); @@ -900,7 +916,7 @@ void* Mixer_Play_Music(int pathId, int loop, int streaming) if (!channel) { delete source_samplestream; } else { - channel->SetGroup(MIXER_GROUP_MUSIC); + channel->SetGroup(MIXER_GROUP_RIDE_MUSIC); } return channel; } else { @@ -911,7 +927,7 @@ void* Mixer_Play_Music(int pathId, int loop, int streaming) if (gMixer.LoadMusic(pathId)) { Channel* channel = gMixer.Play(*gMixer.musicsources[pathId], MIXER_LOOP_INFINITE, false, false); if (channel) { - channel->SetGroup(MIXER_GROUP_MUSIC); + channel->SetGroup(MIXER_GROUP_RIDE_MUSIC); } return channel; } diff --git a/src/audio/mixer.h b/src/audio/mixer.h index 4b2aeccbac..e9131faa9f 100644 --- a/src/audio/mixer.h +++ b/src/audio/mixer.h @@ -35,8 +35,9 @@ extern "C" { #define MIXER_LOOP_INFINITE -1 enum { - MIXER_GROUP_NONE, - MIXER_GROUP_MUSIC, + MIXER_GROUP_SOUND, + MIXER_GROUP_RIDE_MUSIC, + MIXER_GROUP_TITLE_MUSIC, }; #ifdef __cplusplus @@ -151,7 +152,7 @@ private: bool deletesourceondone = false; bool stopping = false; int oldvolume = 0; - int group = MIXER_GROUP_NONE; + int group = MIXER_GROUP_SOUND; SpeexResamplerState* resampler = nullptr; Source* source = nullptr; }; @@ -166,7 +167,7 @@ public: void Unlock(); Channel* Play(Source& source, int loop, bool deleteondone, bool deletesourceondone); void Stop(Channel& channel); - bool LoadMusic(int pathid); + bool LoadMusic(size_t pathid); void SetVolume(float volume); Source* css1sources[SOUND_MAXID]; @@ -201,7 +202,7 @@ extern "C" #endif void Mixer_Init(const char* device); -void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone); +void* Mixer_Play_Effect(size_t id, int loop, int volume, float pan, double rate, int deleteondone); void Mixer_Stop_Channel(void* channel); void Mixer_Channel_Volume(void* channel, int volume); void Mixer_Channel_Pan(void* channel, float pan); diff --git a/src/cheats.c b/src/cheats.c index c6ced49833..f834831dcd 100644 --- a/src/cheats.c +++ b/src/cheats.c @@ -1,10 +1,402 @@ #include "cheats.h" +#include "config.h" +#include "game.h" +#include "interface/window.h" +#include "network/network.h" +#include "world/climate.h" +#include "world/footpath.h" +#include "world/scenery.h" bool gCheatsSandboxMode = false; bool gCheatsDisableClearanceChecks = false; bool gCheatsDisableSupportLimits = false; bool gCheatsShowAllOperatingModes = false; bool gCheatsShowVehiclesFromOtherTrackTypes = false; +bool gCheatsFastLiftHill = false; +bool gCheatsDisableBrakesFailure = false; +bool gCheatsDisableAllBreakdowns = false; +bool gCheatsUnlockAllPrices = false; +bool gCheatsBuildInPauseMode = false; +bool gCheatsIgnoreRideIntensity = false; +bool gCheatsDisableVandalism = false; +bool gCheatsNeverendingMarketing = false; +bool gCheatsFreezeClimate = false; + +int park_rating_spinner_value; + +#pragma region Cheat functions + +static void cheat_set_grass_length(int length) +{ + int x, y; + rct_map_element *mapElement; + + for (y = 0; y < 256; y++) { + for (x = 0; x < 256; x++) { + mapElement = map_get_surface_element_at(x, y); + if (!(mapElement->properties.surface.ownership & OWNERSHIP_OWNED)) + continue; + + if (map_element_get_terrain(mapElement) != TERRAIN_GRASS) + continue; + + if ((mapElement->properties.surface.terrain & 0x1F) > 0) + continue; + + mapElement->properties.surface.grass_length = length; + } + } + + gfx_invalidate_screen(); +} + +static void cheat_water_plants() +{ + map_element_iterator it; + + map_element_iterator_begin(&it); + do { + if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_SCENERY) { + it.element->properties.scenery.age = 0; + } + } while (map_element_iterator_next(&it)); + + gfx_invalidate_screen(); +} + +static void cheat_fix_vandalism() +{ + map_element_iterator it; + + map_element_iterator_begin(&it); + do { + if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH) + continue; + + if (!footpath_element_has_path_scenery(it.element)) + continue; + + it.element->flags &= ~MAP_ELEMENT_FLAG_BROKEN; + } while (map_element_iterator_next(&it)); + + gfx_invalidate_screen(); +} + +static void cheat_remove_litter() +{ + rct_litter* litter; + uint16 spriteIndex, nextSpriteIndex; + + for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_LITTER, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) { + litter = &(g_sprite_list[spriteIndex].litter); + nextSpriteIndex = litter->next; + sprite_remove((rct_sprite*)litter); + } + + map_element_iterator it; + rct_scenery_entry *sceneryEntry; + + map_element_iterator_begin(&it); + do { + if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH) + continue; + + if (!footpath_element_has_path_scenery(it.element)) + continue; + + 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; + + } while (map_element_iterator_next(&it)); + + gfx_invalidate_screen(); +} + +static void cheat_fix_rides() +{ + int rideIndex; + rct_ride *ride; + rct_peep *mechanic; + + FOR_ALL_RIDES(rideIndex, ride) + { + if ((ride->mechanic_status != RIDE_MECHANIC_STATUS_FIXING) && (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN))) + { + mechanic = ride_get_assigned_mechanic(ride); + + if (mechanic != NULL){ + remove_peep_from_ride(mechanic); + } + + ride_fix_breakdown(rideIndex, 0); + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; + } + } +} + +static void cheat_renew_rides() +{ + int i; + rct_ride *ride; + + FOR_ALL_RIDES(i, ride) + { + // Set build date to current date (so the ride is brand new) + ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); + // Set reliability to 100 + ride->reliability = (100 << 8); + } + window_invalidate_by_class(WC_RIDE); +} + +static void cheat_make_destructible() +{ + int i; + rct_ride *ride; + FOR_ALL_RIDES(i, ride) + { + if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) + ride->lifecycle_flags&=~RIDE_LIFECYCLE_INDESTRUCTIBLE; + if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) + ride->lifecycle_flags&=~RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK; + } + window_invalidate_by_class(WC_RIDE); +} + +static void cheat_reset_crash_status() +{ + int i; + rct_ride *ride; + + FOR_ALL_RIDES(i, ride){ + //reset crash status + if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) + ride->lifecycle_flags&=~RIDE_LIFECYCLE_CRASHED; + //reset crash history + ride->last_crash_type=RIDE_CRASH_TYPE_NONE; + } + window_invalidate_by_class(WC_RIDE); +} + +static void cheat_10_minute_inspections() +{ + int i; + rct_ride *ride; + + FOR_ALL_RIDES(i, ride) { + // Set inspection interval to 10 minutes + ride->inspection_interval = RIDE_INSPECTION_EVERY_10_MINUTES; + } + window_invalidate_by_class(WC_RIDE); +} + +static void cheat_increase_money(money32 amount) +{ + money32 currentMoney; + + currentMoney = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32)); + if (currentMoney < INT_MAX - amount) + currentMoney += amount; + else + currentMoney = INT_MAX; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32) = ENCRYPT_MONEY(currentMoney); + + window_invalidate_by_class(WC_FINANCES); + window_invalidate_by_class(WC_BOTTOM_TOOLBAR); +} + +static void cheat_clear_loan() +{ + // First give money + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_INCREASEMONEY, RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32), GAME_COMMAND_CHEAT, 0, 0); + + // Then pay the loan + money32 newLoan; + newLoan = MONEY(0, 00); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, newLoan, GAME_COMMAND_SET_CURRENT_LOAN, 0, 0); +} + +static void cheat_generate_guests(int count) +{ + int i; + + for (i = 0; i < count; i++) + generate_new_guest(); + + window_invalidate_by_class(WC_BOTTOM_TOOLBAR); +} + +static void cheat_set_guest_parameter(int parameter, int value) +{ + int spriteIndex; + rct_peep *peep; + + FOR_ALL_GUESTS(spriteIndex, peep) { + switch(parameter) { + case GUEST_PARAMETER_HAPPINESS: + peep->happiness = value; + break; + case GUEST_PARAMETER_ENERGY: + peep->energy = value; + break; + case GUEST_PARAMETER_HUNGER: + peep->hunger = value; + break; + case GUEST_PARAMETER_THIRST: + peep->thirst = value; + break; + case GUEST_PARAMETER_NAUSEA: + peep->nausea = value; + break; + case GUEST_PARAMETER_NAUSEA_TOLERANCE: + peep->nausea_tolerance = value; + break; + case GUEST_PARAMETER_BATHROOM: + peep->bathroom = value; + break; + case GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY: + peep->intensity = (15 << 4) | value; + break; + } + peep_update_sprite_type(peep); + } + +} + +static void cheat_give_all_guests(int object) +{ + int spriteIndex; + rct_peep *peep; + + FOR_ALL_GUESTS(spriteIndex, peep) { + switch(object) + { + case OBJECT_MONEY: + peep->cash_in_pocket = MONEY(1000,00); + break; + case OBJECT_PARK_MAP: + peep->item_standard_flags |= PEEP_ITEM_MAP; + break; + case OBJECT_BALLOON: + peep->item_standard_flags |= PEEP_ITEM_BALLOON; + peep->balloon_colour=scenario_rand_max(31); + peep_update_sprite_type(peep); + break; + case OBJECT_UMBRELLA: + peep->item_standard_flags |= PEEP_ITEM_UMBRELLA; + peep->umbrella_colour=scenario_rand_max(31); + peep_update_sprite_type(peep); + break; + } + } + window_invalidate_by_class(WC_PEEP); +} + +static void cheat_remove_all_guests() +{ + rct_peep *peep; + uint16 spriteIndex, nextSpriteIndex; + + for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) { + peep = &(g_sprite_list[spriteIndex].peep); + nextSpriteIndex = peep->next; + if (peep->type == PEEP_TYPE_GUEST) { + peep_remove(peep); + } + } + + int i; + rct_ride *ride; + + FOR_ALL_RIDES(i, ride) + { + ride_clear_for_construction(i); + ride_set_status(i, RIDE_STATUS_CLOSED); + + for(int i=0;i<4;i++) { + ride->queue_length[i] = 0; + ride->last_peep_in_queue[i]=0xFFFF; + } + } + window_invalidate_by_class(WC_RIDE); + gfx_invalidate_screen(); +} + +static void cheat_explode_guests() +{ + int sprite_index; + rct_peep *peep; + + FOR_ALL_GUESTS(sprite_index, peep) { + if (scenario_rand_max(6) == 0) { + peep->peep_flags |= PEEP_FLAGS_EXPLODE; + } + } +} + +static void cheat_set_staff_speed(uint8 value) +{ + uint16 spriteIndex; + rct_peep *peep; + + FOR_ALL_STAFF(spriteIndex, peep) { + peep->energy = value; + peep->energy_growth_rate = value; + } +} + +#pragma endregion + +void game_command_cheat(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + int cheat = *ecx; + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + switch (cheat) { + case CHEAT_SANDBOXMODE: gCheatsSandboxMode = !gCheatsSandboxMode; window_invalidate_by_class(WC_MAP); window_invalidate_by_class(WC_FOOTPATH); break; + case CHEAT_DISABLECLEARANCECHECKS: gCheatsDisableClearanceChecks = !gCheatsDisableClearanceChecks; break; + case CHEAT_DISABLESUPPORTLIMITS: gCheatsDisableSupportLimits = !gCheatsDisableSupportLimits; break; + case CHEAT_SHOWALLOPERATINGMODES: gCheatsShowAllOperatingModes = !gCheatsShowAllOperatingModes; break; + case CHEAT_SHOWVEHICLESFROMOTHERTRACKTYPES: gCheatsShowVehiclesFromOtherTrackTypes = !gCheatsShowVehiclesFromOtherTrackTypes; break; + case CHEAT_FASTLIFTHILL: gCheatsFastLiftHill = !gCheatsFastLiftHill; break; + case CHEAT_DISABLEBRAKESFAILURE: gCheatsDisableBrakesFailure = !gCheatsDisableBrakesFailure; break; + case CHEAT_DISABLEALLBREAKDOWNS: gCheatsDisableAllBreakdowns = !gCheatsDisableAllBreakdowns; break; + case CHEAT_UNLOCKALLPRICES: gCheatsUnlockAllPrices = !gCheatsUnlockAllPrices; window_invalidate_by_class(WC_RIDE); window_invalidate_by_class(WC_PARK_INFORMATION); break; + case CHEAT_BUILDINPAUSEMODE: gCheatsBuildInPauseMode = !gCheatsBuildInPauseMode; break; + case CHEAT_IGNORERIDEINTENSITY: gCheatsIgnoreRideIntensity = !gCheatsIgnoreRideIntensity; break; + case CHEAT_DISABLEVANDALISM: gCheatsDisableVandalism = !gCheatsDisableVandalism; break; + case CHEAT_INCREASEMONEY: cheat_increase_money(*edx); break; + case CHEAT_CLEARLOAN: cheat_clear_loan(); break; + case CHEAT_SETGUESTPARAMETER: cheat_set_guest_parameter(*edx, *edi); break; + case CHEAT_GENERATEGUESTS: cheat_generate_guests(*edx); break; + case CHEAT_REMOVEALLGUESTS: cheat_remove_all_guests(); break; + case CHEAT_EXPLODEGUESTS: cheat_explode_guests(); break; + case CHEAT_GIVEALLGUESTS: cheat_give_all_guests(*edx); break; + case CHEAT_SETGRASSLENGTH: cheat_set_grass_length(*edx); break; + case CHEAT_WATERPLANTS: cheat_water_plants(); break; + case CHEAT_FIXVANDALISM: cheat_fix_vandalism(); break; + case CHEAT_REMOVELITTER: cheat_remove_litter(); break; + case CHEAT_SETSTAFFSPEED: cheat_set_staff_speed(*edx); break; + case CHEAT_RENEWRIDES: cheat_renew_rides(); break; + case CHEAT_MAKEDESTRUCTIBLE: cheat_make_destructible(); break; + case CHEAT_FIXRIDES: cheat_fix_rides(); break; + case CHEAT_RESETCRASHSTATUS: cheat_reset_crash_status(); break; + case CHEAT_10MINUTEINSPECTIONS: cheat_10_minute_inspections(); break; + case CHEAT_WINSCENARIO: scenario_success(); break; + case CHEAT_FORCEWEATHER: climate_force_weather(*edx); break; + case CHEAT_FREEZECLIMATE: gCheatsFreezeClimate = !gCheatsFreezeClimate; break; + case CHEAT_NEVERENDINGMARKETING: gCheatsNeverendingMarketing = !gCheatsNeverendingMarketing; break; + case CHEAT_OPENCLOSEPARK: park_set_open(park_is_open() ? 0 : 1); break; + case CHEAT_HAVEFUN: RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) = OBJECTIVE_HAVE_FUN; break; + case CHEAT_SETFORCEDPARKRATING: if(*edx > -1) { park_rating_spinner_value = *edx; } set_forced_park_rating(*edx); break; + } + if (network_get_mode() == NETWORK_MODE_NONE) { + config_save_default(); + } + window_invalidate_by_class(WC_CHEATS); + } + *ebx = 0; +} void cheats_reset() { @@ -13,4 +405,13 @@ void cheats_reset() gCheatsDisableSupportLimits = false; gCheatsShowAllOperatingModes = false; gCheatsShowVehiclesFromOtherTrackTypes = false; + gCheatsFastLiftHill = false; + gCheatsDisableBrakesFailure = false; + gCheatsDisableAllBreakdowns = false; + gCheatsUnlockAllPrices = false; + gCheatsBuildInPauseMode = false; + gCheatsIgnoreRideIntensity = false; + gCheatsDisableVandalism = false; + gCheatsNeverendingMarketing = false; + gCheatsFreezeClimate = false; } diff --git a/src/cheats.h b/src/cheats.h index ab46cfb676..64e50bf480 100644 --- a/src/cheats.h +++ b/src/cheats.h @@ -28,6 +28,79 @@ extern bool gCheatsDisableClearanceChecks; extern bool gCheatsDisableSupportLimits; extern bool gCheatsShowAllOperatingModes; extern bool gCheatsShowVehiclesFromOtherTrackTypes; +extern bool gCheatsFastLiftHill; +extern bool gCheatsDisableBrakesFailure; +extern bool gCheatsDisableAllBreakdowns; +extern bool gCheatsUnlockAllPrices; +extern bool gCheatsBuildInPauseMode; +extern bool gCheatsIgnoreRideIntensity; +extern bool gCheatsDisableVandalism; +extern bool gCheatsNeverendingMarketing; +extern bool gCheatsFreezeClimate; + +enum { + CHEAT_SANDBOXMODE, + CHEAT_DISABLECLEARANCECHECKS, + CHEAT_DISABLESUPPORTLIMITS, + CHEAT_SHOWALLOPERATINGMODES, + CHEAT_SHOWVEHICLESFROMOTHERTRACKTYPES, + CHEAT_FASTLIFTHILL, + CHEAT_DISABLEBRAKESFAILURE, + CHEAT_DISABLEALLBREAKDOWNS, + CHEAT_UNLOCKALLPRICES, + CHEAT_BUILDINPAUSEMODE, + CHEAT_IGNORERIDEINTENSITY, + CHEAT_DISABLEVANDALISM, + CHEAT_INCREASEMONEY, + CHEAT_CLEARLOAN, + CHEAT_SETGUESTPARAMETER, + CHEAT_GENERATEGUESTS, + CHEAT_REMOVEALLGUESTS, + CHEAT_EXPLODEGUESTS, + CHEAT_GIVEALLGUESTS, + CHEAT_SETGRASSLENGTH, + CHEAT_WATERPLANTS, + CHEAT_FIXVANDALISM, + CHEAT_REMOVELITTER, + CHEAT_SETSTAFFSPEED, + CHEAT_RENEWRIDES, + CHEAT_MAKEDESTRUCTIBLE, + CHEAT_FIXRIDES, + CHEAT_RESETCRASHSTATUS, + CHEAT_10MINUTEINSPECTIONS, + CHEAT_WINSCENARIO, + CHEAT_FORCEWEATHER, + CHEAT_FREEZECLIMATE, + CHEAT_OPENCLOSEPARK, + CHEAT_HAVEFUN, + CHEAT_SETFORCEDPARKRATING, + CHEAT_NEVERENDINGMARKETING, +}; + +enum { + GUEST_PARAMETER_HAPPINESS, + GUEST_PARAMETER_ENERGY, + GUEST_PARAMETER_HUNGER, + GUEST_PARAMETER_THIRST, + GUEST_PARAMETER_NAUSEA, + GUEST_PARAMETER_NAUSEA_TOLERANCE, + GUEST_PARAMETER_BATHROOM, + GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY +}; + +enum { + OBJECT_MONEY, + OBJECT_PARK_MAP, + OBJECT_BALLOON, + OBJECT_UMBRELLA +}; + +#define CHEATS_MONEY_INCREMENT MONEY(5000,00) +#define CHEATS_TRAM_INCREMENT 250 + +extern int park_rating_spinner_value; + +void game_command_cheat(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); void cheats_reset(); diff --git a/src/cmdline.c b/src/cmdline.c deleted file mode 100644 index 58b233db03..0000000000 --- a/src/cmdline.c +++ /dev/null @@ -1,248 +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 . - *****************************************************************************/ - -#include -#include -#include "addresses.h" -#include "cmdline.h" -#include "interface/screenshot.h" -#include "network/network.h" -#include "openrct2.h" -#include "platform/platform.h" -#include "util/util.h" - -#ifdef ENABLE_TESTS - #include "../test/tests.h" -#else - static int cmdline_for_test_error(const char **argv, int argc) - { - printf("OpenRCT2 has not been built with the test suite.\n"); - return -1; - } -#endif - -typedef struct tm tm_t; -typedef struct argparse_option argparse_option_t; -typedef struct argparse argparse_t; - -typedef int (*cmdline_action)(const char **argv, int argc); - -int gExitCode = 0; - -#ifndef DISABLE_NETWORK -int gNetworkStart = NETWORK_MODE_NONE; -char gNetworkStartHost[128]; -int gNetworkStartPort = NETWORK_DEFAULT_PORT; -#endif // DISABLE_NETWORK - -static void print_launch_information(); -static void print_version(); -static int cmdline_call_action(const char **argv, int argc); - -static const char *const usage[] = { - "openrct2 [options] []", - "openrct2 [options]", - "openrct2 intro [options]", - "openrct2 edit [path] [options]", - NULL -}; - -/** - * A shared entry point to OpenRCT2. The command lines must be parsed before any further action is done. Invalid command lines - * will then terminate before any initialisation has even been done. - * @returns 1 if the game should run, otherwise 0. - */ -int cmdline_run(const char **argv, int argc) -{ - // - int version = 0, headless = 0, verbose = 0, width = 0, height = 0, port = 0; - char *server = NULL; - char *userDataPath = NULL; - - argparse_option_t options[] = { - OPT_HELP(), - OPT_BOOLEAN('v', "version", &version, "show version information and exit"), - OPT_BOOLEAN(0, "headless", &headless, "run OpenRCT2 headless"), - OPT_BOOLEAN(0, "verbose", &verbose, "log verbose messages"), - OPT_INTEGER('m', "mode", &sprite_mode, "the type of sprite conversion. 0 = default, 1 = simple closest pixel match, 2 = dithering"), - OPT_STRING(0, "server", &server, "server to connect to"), - OPT_INTEGER(0, "port", &port, "port"), - OPT_STRING(0, "user-data-path", &userDataPath, "path to the user data directory (containing config.ini)"), - OPT_END() - }; - - argparse_t argparse; - argparse_init(&argparse, options, usage, 0); - argc = argparse_parse(&argparse, argc, argv); - - if (version) { - print_version(); - return 0; - } - - if (headless) - gOpenRCT2Headless = true; - - if (verbose) - _log_levels[DIAGNOSTIC_LEVEL_VERBOSE] = 1; - - if (userDataPath != NULL) { - safe_strncpy(gCustomUserDataPath, userDataPath, sizeof(gCustomUserDataPath)); - } - -#ifndef DISABLE_NETWORK - if (port != 0) { - gNetworkStart = NETWORK_MODE_SERVER; - gNetworkStartPort = port; - } - - if (server != NULL) { - gNetworkStart = NETWORK_MODE_CLIENT; - safe_strncpy(gNetworkStartHost, server, sizeof(gNetworkStartHost)); - } -#endif // DISABLE_NETWORK - - if (argc != 0) { - // see comment next to cmdline_call_action for expected return codes - gExitCode = cmdline_call_action(argv, argc); - if (gExitCode < 0) { - // action failed, don't change exit code - // and don't start the game - return 0; - } else if (gExitCode > 0) { - // action successful, but don't start the game - // change exit code to success - gExitCode = 0; - return 0; - } - // start the game, so far exit code means success. - } - - // Headless mode requires a park to open - if (gOpenRCT2Headless) { - if (str_is_null_or_empty(gOpenRCT2StartupActionPath)) { - printf("You must specify a park to open in headless mode.\n"); - gExitCode = -1; - return 0; - } - } - - if (verbose) { - print_launch_information(); - } - return 1; -} - -static void print_launch_information() -{ - char buffer[256]; - time_t timer; - tm_t* tmInfo; - - // Print name and version information - openrct2_write_full_version_info(buffer, sizeof(buffer)); - printf("%s\n", buffer); - printf("%s (%s)\n", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); - printf("@ %s\n\n", OPENRCT2_TIMESTAMP); - - // Print current time - time(&timer); - tmInfo = localtime(&timer); - strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", tmInfo); - printf("VERBOSE: time is %s\n", buffer); - - // TODO Print other potential information (e.g. user, hardware) -} - -static void print_version() -{ - char buffer[256]; - openrct2_write_full_version_info(buffer, sizeof(buffer)); - printf("%s\n", buffer); - printf("%s (%s)\n", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); -} - -static int cmdline_for_intro(const char **argv, int argc) -{ - gOpenRCT2StartupAction = STARTUP_ACTION_INTRO; - return 0; -} - -static int cmdline_for_edit(const char **argv, int argc) -{ - gOpenRCT2StartupAction = STARTUP_ACTION_EDIT; - if (argc >= 1) - safe_strncpy(gOpenRCT2StartupActionPath, argv[0], 512); - - return 0; -} - -static int cmdline_for_none(const char **argv, int argc) -{ - assert(argc >= 1); - - if (platform_file_exists(argv[0])) { - gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; - safe_strncpy(gOpenRCT2StartupActionPath, argv[0], 512); - return 0; - } else { - fprintf(stderr, "error: %s does not exist\n", argv[0]); - return -1; - } -} - -// see comment next to cmdline_call_action for expected return codes -struct { const char *firstArg; cmdline_action action; } cmdline_table[] = { - { "intro", cmdline_for_intro }, - { "edit", cmdline_for_edit }, - { "sprite", cmdline_for_sprite }, - { "screenshot", cmdline_for_screenshot }, - -#ifdef ENABLE_TESTS - { "test", cmdline_for_test }, -#else - { "test", cmdline_for_test_error }, -#endif -}; - -/** - * This function delegates starting the game to different handlers, if found. - * - * Three cases of return values are supported: - * - result < 0 means failure, will exit with error code - * This case is useful when user provided wrong arguments or the requested - * action failed - * - result > 0 means success, won't start game, will exit program with success code - * This case is useful when you want to do some batch action and signalize - * success to the user. - * - result == 0 means success, will launch the game. - * This is default when ran with no arguments. - */ -static int cmdline_call_action(const char **argv, int argc) -{ - for (int i = 0; i < countof(cmdline_table); i++) { - if (_stricmp(cmdline_table[i].firstArg, argv[0]) != 0) - continue; - - return cmdline_table[i].action(argv + 1, argc - 1); - } - - return cmdline_for_none(argv, argc); -} diff --git a/src/cmdline.h b/src/cmdline.h deleted file mode 100644 index 91e2e33bc4..0000000000 --- a/src/cmdline.h +++ /dev/null @@ -1,38 +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 . - *****************************************************************************/ - -#ifndef _CMDLINE_H_ -#define _CMDLINE_H_ - -#include "common.h" - -/** The exit code for OpenRCT2 when it exits. */ -extern int gExitCode; - -int sprite_mode; - -extern int gNetworkStart; -extern char gNetworkStartHost[128]; -extern int gNetworkStartPort; - -int cmdline_run(const char **argv, int argc); -int cmdline_for_sprite(const char **argv, int argc); - -#endif \ No newline at end of file diff --git a/src/cmdline/CommandLine.cpp b/src/cmdline/CommandLine.cpp new file mode 100644 index 0000000000..64f001f6fe --- /dev/null +++ b/src/cmdline/CommandLine.cpp @@ -0,0 +1,579 @@ +extern "C" +{ + #include "../platform/platform.h" +} + +#include "../core/Console.hpp" +#include "../core/Math.hpp" +#include "../core/String.hpp" +#include "CommandLine.hpp" + +#pragma region CommandLineArgEnumerator + +CommandLineArgEnumerator::CommandLineArgEnumerator(const char * const * arguments, int count) +{ + _arguments = arguments; + _count = count; + _index = 0; +} + +void CommandLineArgEnumerator::Reset() +{ + _index = 0; +} + +bool CommandLineArgEnumerator::Backtrack() +{ + if (_index > 0) + { + _index--; + return true; + } + else + { + return false; + } +} + +bool CommandLineArgEnumerator::TryPop() +{ + if (_index < _count) + { + _index++; + return true; + } + else + { + return false; + } +} + +bool CommandLineArgEnumerator::TryPopInteger(sint32 * result) +{ + char const * arg; + if (TryPopString(&arg)) + { + *result = (sint32)atol(arg); + return true; + } + + return false; +} + +bool CommandLineArgEnumerator::TryPopReal(float * result) +{ + char const * arg; + if (TryPopString(&arg)) + { + *result = (float)atof(arg); + return true; + } + + return false; +} + +bool CommandLineArgEnumerator::TryPopString(const char * * result) +{ + if (_index < _count) + { + *result = _arguments[_index]; + _index++; + return true; + } + else + { + return false; + } +} + +#pragma endregion + +namespace CommandLine +{ + constexpr const char * HelpText = "openrct2 -ha shows help for all commands. " + "openrct2 -h will show help and details for a given command."; + + static void PrintHelpFor(const CommandLineCommand * commands); + static void PrintOptions(const CommandLineOptionDefinition *options); + static void PrintExamples(const CommandLineExample *examples); + static utf8 * GetOptionCaption(utf8 * buffer, size_t bufferSize, const CommandLineOptionDefinition *option); + + static const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, char shortName); + static const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, const char * longName); + + static bool ParseShortOption(const CommandLineOptionDefinition * options, CommandLineArgEnumerator *argEnumerator, const char *argument); + static bool ParseLongOption(const CommandLineOptionDefinition * options, CommandLineArgEnumerator * argEnumerator, const char * argument); + static bool ParseOptionValue(const CommandLineOptionDefinition * option, const char * valueString); + + static bool HandleSpecialArgument(const char * argument); + + void PrintHelp(bool allCommands) + { + PrintHelpFor(RootCommands); + PrintExamples(RootExamples); + + if (allCommands) + { + const CommandLineCommand * command; + for (command = RootCommands; command->Name != nullptr; command++) + { + if (command->SubCommands != nullptr) + { + size_t commandNameLength = String::LengthOf(command->Name); + for (size_t i = 0; i < commandNameLength; i++) + { + Console::Write("-"); + } + Console::WriteLine(); + Console::WriteLine(command->Name); + for (size_t i = 0; i < commandNameLength; i++) + { + Console::Write("-"); + } + Console::WriteLine(); + PrintHelpFor(command->SubCommands); + } + } + } + else + { + Console::WriteLine(HelpText); + } + } + + static void PrintHelpFor(const CommandLineCommand * commands) + { + const CommandLineCommand * command; + + // Print usage + const char * usageString = "usage: openrct2 "; + const size_t usageStringLength = String::LengthOf(usageString); + Console::Write(usageString); + + // Get the largest command name length and parameter length + size_t maxNameLength = 0; + size_t maxParamsLength = 0; + for (command = commands; command->Name != nullptr; command++) + { + maxNameLength = Math::Max(maxNameLength, String::LengthOf(command->Name)); + maxParamsLength = Math::Max(maxParamsLength, String::LengthOf(command->Parameters)); + } + + for (command = commands; command->Name != nullptr; command++) + { + if (command != commands) + { + Console::WriteSpace(usageStringLength); + } + + Console::Write(command->Name); + Console::WriteSpace(maxNameLength - String::LengthOf(command->Name) + 1); + + if (command->SubCommands == nullptr) + { + Console::Write(command->Parameters); + Console::WriteSpace(maxParamsLength - String::LengthOf(command->Parameters)); + + if (command->Options != nullptr) + { + Console::Write(" [options]"); + } + } + else + { + Console::Write("..."); + } + Console::WriteLine(); + } + Console::WriteLine(); + + if (commands->Options != nullptr) + { + PrintOptions(commands->Options); + } + } + + static void PrintOptions(const CommandLineOptionDefinition *options) + { + // Print options for main commands + size_t maxOptionLength = 0; + const CommandLineOptionDefinition * option = options; + for (; option->Type != 255; option++) + { + char buffer[128]; + GetOptionCaption(buffer, sizeof(buffer), option); + size_t optionCaptionLength = String::LengthOf(buffer); + maxOptionLength = Math::Max(maxOptionLength, optionCaptionLength); + } + + option = options; + for (; option->Type != 255; option++) + { + Console::WriteSpace(4); + + char buffer[128]; + GetOptionCaption(buffer, sizeof(buffer), option); + size_t optionCaptionLength = String::LengthOf(buffer); + Console::Write(buffer); + + Console::WriteSpace(maxOptionLength - optionCaptionLength + 4); + Console::Write(option->Description); + Console::WriteLine(); + } + Console::WriteLine(); + } + + static void PrintExamples(const CommandLineExample *examples) + { + size_t maxArgumentsLength = 0; + + const CommandLineExample * example; + for (example = examples; example->Arguments != nullptr; example++) + { + size_t argumentsLength = String::LengthOf(example->Arguments); + maxArgumentsLength = Math::Max(maxArgumentsLength, argumentsLength); + } + + Console::WriteLine("examples:"); + for (example = examples; example->Arguments != nullptr; example++) + { + Console::Write(" openrct2 "); + Console::Write(example->Arguments); + + size_t argumentsLength = String::LengthOf(example->Arguments); + Console::WriteSpace(maxArgumentsLength - argumentsLength + 4); + Console::Write(example->Description); + Console::WriteLine(); + } + + Console::WriteLine(); + } + + static utf8 * GetOptionCaption(utf8 * buffer, size_t bufferSize, const CommandLineOptionDefinition *option) + { + buffer[0] = 0; + + if (option->ShortName != '\0') + { + String::AppendFormat(buffer, bufferSize, "-%c, ", option->ShortName); + } + + String::Append(buffer, bufferSize, "--"); + String::Append(buffer, bufferSize, option->LongName); + + switch (option->Type) { + case CMDLINE_TYPE_INTEGER: + String::Append(buffer, bufferSize, "="); + break; + case CMDLINE_TYPE_REAL: + String::Append(buffer, bufferSize, "="); + break; + case CMDLINE_TYPE_STRING: + String::Append(buffer, bufferSize, "="); + break; + } + + return buffer; + } + + const CommandLineCommand * FindCommandFor(const CommandLineCommand * commands, CommandLineArgEnumerator *argEnumerator) + { + // Check if end of arguments or options have started + const char * firstArgument; + if (!argEnumerator->TryPopString(&firstArgument)) + { + return commands; + } + if (firstArgument[0] == '-') + { + argEnumerator->Backtrack(); + return commands; + } + + // Search through defined commands for one that matches + const CommandLineCommand * fallback = nullptr; + const CommandLineCommand * command = commands; + for (; command->Name != nullptr; command++) + { + if (command->Name[0] == '\0') + { + // If we don't find a command, this should be used + fallback = command; + } + else if (String::Equals(command->Name, firstArgument)) + { + if (command->SubCommands == nullptr) + { + // Found matching command + return command; + } + else + { + // Recurse for the sub command table + return FindCommandFor(command->SubCommands, argEnumerator); + } + } + } + + argEnumerator->Backtrack(); + return fallback; + } + + static bool ParseOptions(const CommandLineOptionDefinition * options, CommandLineArgEnumerator *argEnumerator) + { + bool firstOption = true; + + const char * argument; + while (argEnumerator->TryPopString(&argument)) + { + if (HandleSpecialArgument(argument)) + { + continue; + } + + if (argument[0] == '-') + { + if (argument[1] == '-') + { + if (!ParseLongOption(options, argEnumerator, &argument[2])) + { + return false; + } + } + else + { + if (!ParseShortOption(options, argEnumerator, argument)) + { + return false; + } + } + firstOption = false; + } + else if (!firstOption) + { + Console::Error::WriteLine("All options must be passed at the end of the command line."); + return false; + } + else + { + continue; + } + } + + return true; + } + + static bool ParseLongOption(const CommandLineOptionDefinition * options, + CommandLineArgEnumerator *argEnumerator, + const char *argument) + { + // Get just the option name + char optionName[64]; + const char * equalsCh = strchr(argument, '='); + if (equalsCh != nullptr) + { + String::Set(optionName, sizeof(optionName), argument, equalsCh - argument); + } + else + { + String::Set(optionName, sizeof(optionName), argument); + } + + // Find a matching option definition + const CommandLineOptionDefinition * option = FindOption(options, optionName); + if (option == nullptr) + { + Console::Error::Write("Unknown option: --"); + Console::Error::WriteLine(optionName); + return false; + } + + if (equalsCh == nullptr) + { + if (option->Type == CMDLINE_TYPE_SWITCH) + { + ParseOptionValue(option, nullptr); + } + else + { + const char * valueString = nullptr; + if (!argEnumerator->TryPopString(&valueString)) + { + Console::Error::Write("Expected value for option: "); + Console::Error::WriteLine(optionName); + return false; + } + + if (!ParseOptionValue(option, valueString)) + { + return false; + } + } + } + else + { + if (option->Type == CMDLINE_TYPE_SWITCH) + { + Console::Error::Write("Option is a switch: "); + Console::Error::WriteLine(optionName); + return false; + } + else + { + if (!ParseOptionValue(option, equalsCh + 1)) + { + return false; + } + } + } + + return true; + } + + static bool ParseShortOption(const CommandLineOptionDefinition * options, + CommandLineArgEnumerator *argEnumerator, + const char *argument) + { + const CommandLineOptionDefinition * option = nullptr; + + const char * shortOption = &argument[1]; + for (; *shortOption != '\0'; shortOption++) + { + option = FindOption(options, shortOption[0]); + if (option == nullptr) + { + Console::Error::Write("Unknown option: -"); + Console::Error::Write(shortOption[0]); + Console::Error::WriteLine(); + return false; + } + if (option->Type == CMDLINE_TYPE_SWITCH) + { + if (!ParseOptionValue(option, nullptr)) + { + return false; + } + } + else if (shortOption[1] != '\0') + { + if (!ParseOptionValue(option, &shortOption[1])) + { + return false; + } + return true; + } + } + + if (option != nullptr && option->Type != CMDLINE_TYPE_SWITCH) + { + const char * valueString = nullptr; + if (!argEnumerator->TryPopString(&valueString)) + { + Console::Error::Write("Expected value for option: "); + Console::Error::Write(option->ShortName); + Console::Error::WriteLine(); + return false; + } + + if (!ParseOptionValue(option, valueString)) + { + return false; + } + } + + return true; + } + + static bool ParseOptionValue(const CommandLineOptionDefinition * option, const char * valueString) + { + if (option->OutAddress == nullptr) return true; + + switch (option->Type) { + case CMDLINE_TYPE_SWITCH: + *((bool *)option->OutAddress) = true; + return true; + case CMDLINE_TYPE_INTEGER: + *((sint32 *)option->OutAddress) = (sint32)atol(valueString); + return true; + case CMDLINE_TYPE_REAL: + *((float *)option->OutAddress) = (float)atof(valueString); + return true; + case CMDLINE_TYPE_STRING: + *((utf8 * *)option->OutAddress) = String::Duplicate(valueString); + return true; + default: + Console::Error::Write("Unknown CMDLINE_TYPE for: "); + Console::Error::WriteLine(option->LongName); + return false; + } + } + + static bool HandleSpecialArgument(const char * argument) + { +#ifdef __MACOSX__ + if (String::Equals(argument, "-NSDocumentRevisionsDebugMode")) + { + return true; + } + if (String::StartsWith(argument, "-psn_")) + { + return true; + } +#endif + return false; + } + + + const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, char shortName) + { + for (const CommandLineOptionDefinition * option = options; option->Type != 255; option++) + { + if (option->ShortName == shortName) + { + return option; + } + } + return nullptr; + } + + const CommandLineOptionDefinition * FindOption(const CommandLineOptionDefinition * options, const char * longName) + { + for (const CommandLineOptionDefinition * option = options; option->Type != 255; option++) + { + if (String::Equals(option->LongName, longName)) + { + return option; + } + } + return nullptr; + } +} + +extern "C" +{ + int cmdline_run(const char * * argv, int argc) + { + auto argEnumerator = CommandLineArgEnumerator(argv, argc); + + // Pop process path + argEnumerator.TryPop(); + + const CommandLineCommand * command = CommandLine::FindCommandFor(CommandLine::RootCommands, &argEnumerator); + if (command->Options != nullptr) + { + auto argEnumeratorForOptions = CommandLineArgEnumerator(argEnumerator); + if (!CommandLine::ParseOptions(command->Options, &argEnumeratorForOptions)) + { + return EXITCODE_FAIL; + } + } + if (command == CommandLine::RootCommands && command->Func == nullptr) + { + return CommandLine::HandleCommandDefault(); + } + else + { + return command->Func(&argEnumerator); + } + } +} diff --git a/src/cmdline/CommandLine.hpp b/src/cmdline/CommandLine.hpp new file mode 100644 index 0000000000..3dc1f7a156 --- /dev/null +++ b/src/cmdline/CommandLine.hpp @@ -0,0 +1,94 @@ +#pragma once + +extern "C" +{ + #include "../common.h" +} + +/** + * Class for enumerating and retrieving values for a set of command line arguments. + */ +class CommandLineArgEnumerator +{ +private: + const char * const * _arguments; + uint16 _count; + uint16 _index; + +public: + const char * const * GetArguments() const { return _arguments; } + uint16 GetCount() const { return _count; } + uint16 GetIndex() const { return _index; } + + CommandLineArgEnumerator(const char * const * arguments, int count); + + void Reset(); + bool Backtrack(); + bool TryPop(); + bool TryPopInteger(sint32 * result); + bool TryPopReal(float * result); + bool TryPopString(const char * * result); +}; + +typedef int exitcode_t; +typedef exitcode_t (*CommandLineFunc)(CommandLineArgEnumerator *); + +enum +{ + EXITCODE_FAIL = -1, + EXITCODE_OK = 0, + EXITCODE_CONTINUE = 1, +}; + +struct CommandLineExample +{ + const char * Arguments; + const char * Description; +}; + +struct CommandLineOptionDefinition +{ + uint8 Type; + void * OutAddress; + char ShortName; + const char * LongName; + const char * Description; +}; + +struct CommandLineCommand +{ + const char * Name; + const char * Parameters; + const CommandLineOptionDefinition * Options; + const CommandLineCommand * SubCommands; + CommandLineFunc Func; +}; + +enum +{ + CMDLINE_TYPE_SWITCH, + CMDLINE_TYPE_INTEGER, + CMDLINE_TYPE_REAL, + CMDLINE_TYPE_STRING, +}; + +constexpr char NAC = '\0'; + +#define ExampleTableEnd { NULL, NULL } +#define OptionTableEnd { UINT8_MAX, NULL, NAC, NULL, NULL } +#define CommandTableEnd { NULL, NULL, NULL, NULL } + +#define DefineCommand(name, params, options, func) { name, params, options, NULL, func } +#define DefineSubCommand(name, subcommandtable) { name, "", NULL, subcommandtable, NULL } + +namespace CommandLine +{ + extern const CommandLineCommand RootCommands[]; + extern const CommandLineCommand ScreenshotCommands[]; + extern const CommandLineCommand SpriteCommands[]; + + extern const CommandLineExample RootExamples[]; + + void PrintHelp(bool allCommands = false); + exitcode_t HandleCommandDefault(); +} diff --git a/src/cmdline/RootCommands.cpp b/src/cmdline/RootCommands.cpp new file mode 100644 index 0000000000..446c9f7887 --- /dev/null +++ b/src/cmdline/RootCommands.cpp @@ -0,0 +1,374 @@ +#include + +extern "C" +{ + #include "../config.h" + #include "../openrct2.h" +} + +#include "../core/Console.hpp" +#include "../core/Memory.hpp" +#include "../core/Path.hpp" +#include "../core/String.hpp" +#include "../network/network.h" +#include "CommandLine.hpp" + +#ifndef DISABLE_NETWORK +int gNetworkStart = NETWORK_MODE_NONE; +char gNetworkStartHost[128]; +int gNetworkStartPort = NETWORK_DEFAULT_PORT; +#endif + +static bool _help = false; +static bool _version = false; +static bool _noInstall = false; +static bool _all = false; +static bool _about = false; +static bool _verbose = false; +static bool _headless = false; +#ifndef DISABLE_NETWORK +static uint32 _port = 0; +#endif +static utf8 * _password = nullptr; +static utf8 * _userDataPath = nullptr; +static utf8 * _openrctDataPath = nullptr; + +static const CommandLineOptionDefinition StandardOptions[] +{ + { CMDLINE_TYPE_SWITCH, &_help, 'h', "help", "show this help message and exit" }, + { CMDLINE_TYPE_SWITCH, &_version, 'v', "version", "show version information and exit" }, + { CMDLINE_TYPE_SWITCH, &_noInstall, 'n', "no-install", "do not install scenario if passed" }, + { CMDLINE_TYPE_SWITCH, &_all, 'a', "all", "show help for all commands" }, + { CMDLINE_TYPE_SWITCH, &_about, NAC, "about", "show information about " OPENRCT2_NAME }, + { CMDLINE_TYPE_SWITCH, &_verbose, NAC, "verbose", "log verbose messages" }, + { CMDLINE_TYPE_SWITCH, &_headless, NAC, "headless", "run " OPENRCT2_NAME " headless" }, +#ifndef DISABLE_NETWORK + { CMDLINE_TYPE_INTEGER, &_port, NAC, "port", "port to use for hosting or joining a server" }, +#endif + { CMDLINE_TYPE_STRING, &_password, NAC, "password", "password needed to join the server" }, + { CMDLINE_TYPE_STRING, &_userDataPath, NAC, "user-data-path", "path to the user data directory (containing config.ini)" }, + { CMDLINE_TYPE_STRING, &_openrctDataPath, NAC, "openrct-data-path", "path to the OpenRCT2 data directory (containing languages)" }, + OptionTableEnd +}; + +static exitcode_t HandleNoCommand(CommandLineArgEnumerator * enumerator); +static exitcode_t HandleCommandEdit(CommandLineArgEnumerator * enumerator); +static exitcode_t HandleCommandIntro(CommandLineArgEnumerator * enumerator); +static exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator); +static exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator); +static exitcode_t HandleCommandSetRCT2(CommandLineArgEnumerator * enumerator); + +static void PrintAbout(); +static void PrintVersion(); +static void PrintLaunchInformation(); + +const CommandLineCommand CommandLine::RootCommands[] +{ + // Main commands + DefineCommand("", "", StandardOptions, HandleNoCommand ), + DefineCommand("edit", "", StandardOptions, HandleCommandEdit ), + DefineCommand("intro", "", StandardOptions, HandleCommandIntro ), +#ifndef DISABLE_NETWORK + DefineCommand("host", "", StandardOptions, HandleCommandHost ), + DefineCommand("join", "", StandardOptions, HandleCommandJoin ), +#endif + DefineCommand("set-rct2", "", StandardOptions, HandleCommandSetRCT2), + + // Sub-commands + DefineSubCommand("screenshot", CommandLine::ScreenshotCommands), + DefineSubCommand("sprite", CommandLine::SpriteCommands ), + + CommandTableEnd +}; + +const CommandLineExample CommandLine::RootExamples[] +{ + { "./my_park.sv6", "open a saved park" }, + { "./SnowyPark.sc6", "install and open a scenario" }, + { "./ShuttleLoop.td6", "install a track" }, + { "https://openrct2.website/files/SnowyPark.sv6", "download and open a saved park" }, +#ifndef DISABLE_NETWORK + { "host ./my_park.sv6 --port 11753 --headless", "run a headless server for a saved park" }, +#endif + ExampleTableEnd +}; + +exitcode_t CommandLine::HandleCommandDefault() +{ + exitcode_t result = EXITCODE_CONTINUE; + + if (_about) + { + PrintAbout(); + result = EXITCODE_OK; + } else + { + if (_verbose) + { + _log_levels[DIAGNOSTIC_LEVEL_VERBOSE] = 1; + PrintLaunchInformation(); + } + + if (_version) + { + if (!_verbose) + { + PrintVersion(); + } + result = EXITCODE_OK; + } + } + + if (_help) + { + CommandLine::PrintHelp(_all); + result = EXITCODE_OK; + } + + gOpenRCT2Headless = _headless; + + if (_userDataPath != NULL) { + String::Set(gCustomUserDataPath, sizeof(gCustomUserDataPath), _userDataPath); + Memory::Free(_userDataPath); + } + + if (_openrctDataPath != NULL) { + String::Set(gCustomOpenrctDataPath, sizeof(gCustomOpenrctDataPath), _openrctDataPath); + Memory::Free(_openrctDataPath); + } + + if (_password != NULL) { + String::Set(gCustomPassword, sizeof(gCustomPassword), _password); + Memory::Free(_password); + } + + return result; +} + +exitcode_t HandleNoCommand(CommandLineArgEnumerator * enumerator) +{ + exitcode_t result = CommandLine::HandleCommandDefault(); + if (result != EXITCODE_CONTINUE) + { + return result; + } + + const char * parkUri; + if (enumerator->TryPopString(&parkUri) && parkUri[0] != '-') + { + String::Set(gOpenRCT2StartupActionPath, sizeof(gOpenRCT2StartupActionPath), parkUri); + gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; + } + + return EXITCODE_CONTINUE; +} + +exitcode_t HandleCommandEdit(CommandLineArgEnumerator * enumerator) +{ + exitcode_t result = CommandLine::HandleCommandDefault(); + if (result != EXITCODE_CONTINUE) + { + return result; + } + + const char * parkUri; + if (!enumerator->TryPopString(&parkUri)) + { + Console::Error::WriteLine("Expected path or URL to a saved park."); + return EXITCODE_FAIL; + } + String::Set(gOpenRCT2StartupActionPath, sizeof(gOpenRCT2StartupActionPath), parkUri); + + gOpenRCT2StartupAction = STARTUP_ACTION_EDIT; + return EXITCODE_CONTINUE; +} + +exitcode_t HandleCommandIntro(CommandLineArgEnumerator * enumerator) +{ + exitcode_t result = CommandLine::HandleCommandDefault(); + if (result != EXITCODE_CONTINUE) + { + return result; + } + + gOpenRCT2StartupAction = STARTUP_ACTION_INTRO; + return EXITCODE_CONTINUE; +} + +#ifndef DISABLE_NETWORK + +exitcode_t HandleCommandHost(CommandLineArgEnumerator * enumerator) +{ + exitcode_t result = CommandLine::HandleCommandDefault(); + if (result != EXITCODE_CONTINUE) + { + return result; + } + + const char * parkUri; + if (!enumerator->TryPopString(&parkUri)) + { + Console::Error::WriteLine("Expected path or URL to a scenario or saved park."); + return EXITCODE_FAIL; + } + + gOpenRCT2StartupAction = STARTUP_ACTION_OPEN; + String::Set(gOpenRCT2StartupActionPath, sizeof(gOpenRCT2StartupActionPath), parkUri); + + gNetworkStart = NETWORK_MODE_SERVER; + gNetworkStartPort = _port; + return EXITCODE_CONTINUE; +} + +exitcode_t HandleCommandJoin(CommandLineArgEnumerator * enumerator) +{ + exitcode_t result = CommandLine::HandleCommandDefault(); + if (result != EXITCODE_CONTINUE) + { + return result; + } + + const char * hostname; + if (!enumerator->TryPopString(&hostname)) + { + Console::Error::WriteLine("Expected a hostname or IP address to the server to connect to."); + return EXITCODE_FAIL; + } + + gNetworkStart = NETWORK_MODE_CLIENT; + gNetworkStartPort = _port; + String::Set(gNetworkStartHost, sizeof(gNetworkStartHost), hostname); + return EXITCODE_CONTINUE; +} + +#endif // DISABLE_NETWORK + +static exitcode_t HandleCommandSetRCT2(CommandLineArgEnumerator * enumerator) +{ + exitcode_t result = CommandLine::HandleCommandDefault(); + if (result != EXITCODE_CONTINUE) + { + return result; + } + + // Get the path that was passed + const utf8 * rawPath; + if (!enumerator->TryPopString(&rawPath)) + { + Console::Error::WriteLine("Expected a path."); + return EXITCODE_FAIL; + } + + utf8 path[MAX_PATH]; + Path::GetAbsolute(path, sizeof(path), rawPath); + + // Check if path exists + Console::WriteLine("Checking path..."); + if (!platform_directory_exists(path)) + { + Console::Error::WriteFormat("The path '%s' does not exist", path); + Console::Error::WriteLine(); + return EXITCODE_FAIL; + } + + // Check if g1.dat exists (naive but good check) + Console::WriteLine("Checking g1.dat..."); + + utf8 pathG1Check[MAX_PATH]; + String::Set(pathG1Check, sizeof(pathG1Check), path); + Path::Append(pathG1Check, sizeof(pathG1Check), "Data"); + Path::Append(pathG1Check, sizeof(pathG1Check), "g1.dat"); + if (!platform_file_exists(pathG1Check)) + { + Console::Error::WriteLine("RCT2 path not valid."); + Console::Error::WriteFormat("Unable to find %s.", pathG1Check); + Console::Error::WriteLine(); + return EXITCODE_FAIL; + } + + // Check user path that will contain the config + utf8 userPath[MAX_PATH]; + platform_resolve_user_data_path(); + platform_get_user_directory(userPath, NULL); + if (!platform_ensure_directory_exists(userPath)) { + Console::Error::WriteFormat("Unable to access or create directory '%s'.", userPath); + Console::Error::WriteLine(); + return EXITCODE_FAIL; + } + + // Update RCT2 path in config + + // TODO remove this when we get rid of config_apply_to_old_addresses + if (!openrct2_setup_rct2_segment()) { + Console::Error::WriteLine("Unable to load RCT2 data sector"); + return EXITCODE_FAIL; + } + + config_set_defaults(); + config_open_default(); + String::DiscardDuplicate(&gConfigGeneral.game_path, path); + if (config_save_default()) + { + Console::WriteFormat("Updating RCT2 path to '%s'.", path); + Console::WriteLine(); + Console::WriteLine("Updated config.ini"); + return EXITCODE_OK; + } + else + { + Console::Error::WriteLine("Unable to update config.ini"); + return EXITCODE_FAIL; + } +} + +static void PrintAbout() +{ + PrintVersion(); + Console::WriteLine(); + Console::WriteLine("OpenRCT2 is an amusement park simulation game based upon the popular game"); + Console::WriteLine("RollerCoaster Tycoon 2, written by Chris Sawyer. It attempts to mimic the "); + Console::WriteLine("original game as closely as possible while extending it with new features."); + Console::WriteLine("OpenRCT2 is licensed under the GNU General Public License version 3.0, but"); + Console::WriteLine("includes some 3rd party software under different licenses. See the file"); + Console::WriteLine("\"licence.txt\" shipped with the game for details."); + Console::WriteLine(); + Console::WriteLine("Website: https://openrct2.website"); + Console::WriteLine("GitHub: https://github.com/OpenRCT2/OpenRCT2"); + Console::WriteLine("Contributors: https://github.com/OpenRCT2/OpenRCT2/blob/develop/contributors.md"); + Console::WriteLine(); +} + +static void PrintVersion() +{ + char buffer[256]; + openrct2_write_full_version_info(buffer, sizeof(buffer)); + Console::WriteLine(buffer); + Console::WriteFormat("%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); + Console::WriteLine(); +} + +static void PrintLaunchInformation() +{ + char buffer[256]; + time_t timer; + struct tm * tmInfo; + + // Print name and version information + openrct2_write_full_version_info(buffer, sizeof(buffer)); + Console::WriteFormat("%s", buffer); + Console::WriteLine(); + Console::WriteFormat("%s (%s)", OPENRCT2_PLATFORM, OPENRCT2_ARCHITECTURE); + Console::WriteLine(); + Console::WriteFormat("@ %s", OPENRCT2_TIMESTAMP); + Console::WriteLine(); + Console::WriteLine(); + + // Print current time + time(&timer); + tmInfo = localtime(&timer); + strftime(buffer, sizeof(buffer), "%Y/%m/%d %H:%M:%S", tmInfo); + Console::WriteFormat("VERBOSE: time is %s", buffer); + Console::WriteLine(); + + // TODO Print other potential information (e.g. user, hardware) +} diff --git a/src/cmdline/ScreenshotCommands.cpp b/src/cmdline/ScreenshotCommands.cpp new file mode 100644 index 0000000000..f6e0142779 --- /dev/null +++ b/src/cmdline/ScreenshotCommands.cpp @@ -0,0 +1,27 @@ +extern "C" +{ + #include "../interface/screenshot.h" +} + +#include "CommandLine.hpp" + +static exitcode_t HandleScreenshot(CommandLineArgEnumerator *argEnumerator); + +const CommandLineCommand CommandLine::ScreenshotCommands[] +{ + // Main commands + DefineCommand("", " [ ]", nullptr, HandleScreenshot), + DefineCommand("", " giant ", nullptr, HandleScreenshot), + CommandTableEnd +}; + +static exitcode_t HandleScreenshot(CommandLineArgEnumerator *argEnumerator) +{ + const char * * argv = (const char * *)argEnumerator->GetArguments() + argEnumerator->GetIndex(); + int argc = argEnumerator->GetCount() - argEnumerator->GetIndex(); + int result = cmdline_for_screenshot(argv, argc); + if (result < 0) { + return EXITCODE_FAIL; + } + return EXITCODE_OK; +} diff --git a/src/cmdline/SpriteCommands.cpp b/src/cmdline/SpriteCommands.cpp new file mode 100644 index 0000000000..03d68ae7e9 --- /dev/null +++ b/src/cmdline/SpriteCommands.cpp @@ -0,0 +1,48 @@ +#include "../core/Memory.hpp" +#include "../core/String.hpp" +#include "CommandLine.hpp" + +#define SZ_DEFAULT "default" +#define SZ_CLOSEST "closest" +#define SZ_DITHERING "dithering" + +extern "C" +{ + int gSpriteMode = 0; + + int cmdline_for_sprite(const char **argv, int argc); +} + +static const char * _mode; + +static const CommandLineOptionDefinition SpriteOptions[] +{ + { CMDLINE_TYPE_STRING, &_mode, 'm', "mode", "the type of sprite conversion <" SZ_DEFAULT "|" SZ_CLOSEST "|" SZ_DITHERING ">" }, + OptionTableEnd +}; + +static exitcode_t HandleSprite(CommandLineArgEnumerator *argEnumerator); + +const CommandLineCommand CommandLine::SpriteCommands[] +{ + // Main commands + DefineCommand("details", " [idx]", SpriteOptions, HandleSprite), + DefineCommand("export", " ", SpriteOptions, HandleSprite), + DefineCommand("build", " [silent]", SpriteOptions, HandleSprite), + CommandTableEnd +}; + +static exitcode_t HandleSprite(CommandLineArgEnumerator *argEnumerator) +{ + if (String::Equals(_mode, SZ_CLOSEST, true)) gSpriteMode = 1; + else if (String::Equals(_mode, SZ_DITHERING, true)) gSpriteMode = 2; + Memory::Free(_mode); + + const char * * argv = (const char * *)argEnumerator->GetArguments() + argEnumerator->GetIndex() - 1; + int argc = argEnumerator->GetCount() - argEnumerator->GetIndex() + 1; + int result = cmdline_for_sprite(argv, argc); + if (result < 0) { + return EXITCODE_FAIL; + } + return EXITCODE_OK; +} diff --git a/src/cmdline_sprite.c b/src/cmdline_sprite.c index 789a86fa0a..b87c2e167e 100644 --- a/src/cmdline_sprite.c +++ b/src/cmdline_sprite.c @@ -18,17 +18,18 @@ * along with this program. If not, see . *****************************************************************************/ -#include -#include "cmdline.h" #include "drawing/drawing.h" +#include "image_io.h" +#include "openrct2.h" #include "platform/platform.h" #include "util/util.h" -#include "openrct2.h" #define MODE_DEFAULT 0 #define MODE_CLOSEST 1 #define MODE_DITHERING 2 +extern int gSpriteMode; + typedef struct { uint32 num_entries; uint32 total_size; @@ -168,33 +169,11 @@ bool sprite_file_export(int spriteIndex, const char *outPath) memcpy(spriteFilePalette, _standardPalette, 256 * 4); gfx_rle_sprite_to_buffer(spriteHeader->offset, pixels, (uint8*)spriteFilePalette, &dpi, IMAGE_TYPE_NO_BACKGROUND, 0, spriteHeader->height, 0, spriteHeader->width); - LodePNGState pngState; - unsigned int pngError; - unsigned char* pngData; - size_t pngSize; - - lodepng_state_init(&pngState); - pngState.info_raw.colortype = LCT_PALETTE; - lodepng_palette_add(&pngState.info_raw, 0, 0, 0, 0); - for (int i = 1; i < 256; i++) { - lodepng_palette_add( - &pngState.info_raw, - spriteFilePalette[i].r, - spriteFilePalette[i].g, - spriteFilePalette[i].b, - 255 - ); - } - - pngError = lodepng_encode(&pngData, &pngSize, pixels, spriteHeader->width, spriteHeader->height, &pngState); - if (pngError != 0) { - free(pngData); - fprintf(stderr, "Error creating PNG data, %u: %s", pngError, lodepng_error_text(pngError)); - return false; - } else { - lodepng_save_file(pngData, pngSize, outPath); - free(pngData); + if (image_io_png_write(&dpi, (rct_palette*)spriteFilePalette, outPath)) { return true; + } else { + fprintf(stderr, "Error writing PNG"); + return false; } } @@ -261,16 +240,10 @@ typedef struct { bool sprite_file_import(const char *path, rct_g1_element *outElement, uint8 **outBuffer, int *outBufferLength, int mode) { - unsigned char *pixels; - unsigned int width, height; - unsigned int pngError; - - memcpy(spriteFilePalette, _standardPalette, 256 * 4); - - pngError = lodepng_decode_file(&pixels, &width, &height, path, LCT_RGBA, 8); - if (pngError != 0) { - free(pixels); - fprintf(stderr, "Error creating PNG data, %u: %s", pngError, lodepng_error_text(pngError)); + uint8 *pixels; + uint32 width, height; + if (!image_io_png_read(&pixels, &width, &height, path)) { + fprintf(stderr, "Error reading PNG"); return false; } @@ -280,6 +253,8 @@ bool sprite_file_import(const char *path, rct_g1_element *outElement, uint8 **ou return false; } + memcpy(spriteFilePalette, _standardPalette, 256 * 4); + uint8 *buffer = malloc((height * 2) + (width * height * 16)); memset(buffer, 0, (height * 2) + (width * height * 16)); uint16 *yOffsets = (uint16*)buffer; @@ -424,7 +399,7 @@ int cmdline_for_sprite(const char **argv, int argc) if (_strcmpi(argv[0], "details") == 0) { if (argc < 2) { - fprintf(stderr, "usage: sprite details [idx]\n"); + fprintf(stdout, "usage: sprite details [idx]\n"); return -1; } else if (argc == 2) { const char *spriteFilePath = argv[1]; @@ -434,8 +409,8 @@ int cmdline_for_sprite(const char **argv, int argc) return -1; } - printf("sprites: %lu\n", spriteFileHeader.num_entries); - printf("data size: %lu\n", spriteFileHeader.total_size); + printf("sprites: %u\n", spriteFileHeader.num_entries); + printf("data size: %u\n", spriteFileHeader.total_size); sprite_file_close(); return 1; @@ -459,14 +434,14 @@ int cmdline_for_sprite(const char **argv, int argc) printf("height: %d\n", g1->height); printf("x offset: %d\n", g1->x_offset); printf("y offset: %d\n", g1->y_offset); - printf("data offset: 0x%lX\n", (uint32)g1->offset); + printf("data offset: 0x%X\n", (uint32)g1->offset); sprite_file_close(); return 1; } } else if (_strcmpi(argv[0], "export") == 0) { if (argc < 4) { - fprintf(stderr, "usage: sprite export \n"); + fprintf(stdout, "usage: sprite export \n"); return -1; } @@ -494,7 +469,7 @@ int cmdline_for_sprite(const char **argv, int argc) return 1; } else if (_strcmpi(argv[0], "exportall") == 0) { if (argc < 3) { - fprintf(stderr, "usage: sprite exportall \n"); + fprintf(stdout, "usage: sprite exportall \n"); return -1; } @@ -515,7 +490,7 @@ int cmdline_for_sprite(const char **argv, int argc) int maxIndex = (int)spriteFileHeader.num_entries; int numbers = (int)floor(log(maxIndex)); - safe_strncpy(outputPath, argv[2], MAX_PATH); + safe_strcpy(outputPath, argv[2], MAX_PATH); int pathLen = strlen(outputPath); if (pathLen >= MAX_PATH - numbers - 5){ @@ -526,7 +501,7 @@ int cmdline_for_sprite(const char **argv, int argc) for (int x = 0; x < numbers; x++){ outputPath[pathLen + x] = '0'; } - safe_strncpy(outputPath + pathLen + numbers, ".png", MAX_PATH); + safe_strcpy(outputPath + pathLen + numbers, ".png", MAX_PATH); for (int spriteIndex = 0; spriteIndex < maxIndex; spriteIndex++){ @@ -580,7 +555,7 @@ int cmdline_for_sprite(const char **argv, int argc) rct_g1_element spriteElement; uint8 *buffer; int bufferLength; - if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, sprite_mode)) + if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, gSpriteMode)) return -1; if (!sprite_file_open(spriteFilePath)) { @@ -607,7 +582,7 @@ int cmdline_for_sprite(const char **argv, int argc) return 1; } else if (_strcmpi(argv[0], "build") == 0) { if (argc < 3) { - fprintf(stderr, "usage: sprite build [silent]\n"); + fprintf(stdout, "usage: sprite build [silent]\n"); return -1; } @@ -624,11 +599,11 @@ int cmdline_for_sprite(const char **argv, int argc) spriteFileHeader.total_size = 0; sprite_file_save(spriteFilePath); - fprintf(stderr, "Building: %s\n", spriteFilePath); + fprintf(stdout, "Building: %s\n", spriteFilePath); int i = 0; do { // Create image path - safe_strncpy(imagePath, resourcePath, MAX_PATH); + safe_strcpy(imagePath, resourcePath, MAX_PATH); if (resourcePath[resourceLength - 1] == '/' || resourcePath[resourceLength - 1] == '\\') imagePath[resourceLength - 1] = 0; sprintf(imagePath, "%s%c%d.png", imagePath, platform_get_path_separator(), i); @@ -639,7 +614,7 @@ int cmdline_for_sprite(const char **argv, int argc) rct_g1_element spriteElement; uint8 *buffer; int bufferLength; - if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, sprite_mode)) { + if (!sprite_file_import(imagePath, &spriteElement, &buffer, &bufferLength, gSpriteMode)) { fprintf(stderr, "Could not import image file: %s\nCanceling\n", imagePath); return -1; } @@ -668,13 +643,13 @@ int cmdline_for_sprite(const char **argv, int argc) return -1; } if (!silent) - fprintf(stderr, "Added: %s\n", imagePath); + fprintf(stdout, "Added: %s\n", imagePath); } i++; } while (file != NULL); - fprintf(stderr, "Finished\n"); + fprintf(stdout, "Finished\n"); return 1; } else { fprintf(stderr, "Unknown sprite command."); diff --git a/src/common.h b/src/common.h index b488f7c8e7..e58c85ae93 100644 --- a/src/common.h +++ b/src/common.h @@ -34,4 +34,13 @@ #endif #define abstract = 0 +#ifdef __GNUC__ +#define FASTCALL __attribute__((fastcall)) +#elif _MSC_VER +#define FASTCALL __fastcall +#else +#pragma message "Not using fastcall calling convention, please check your compiler support" +#define FASTCALL +#endif + #endif diff --git a/src/config.c b/src/config.c index e21031a26d..1a2387b9f3 100644 --- a/src/config.c +++ b/src/config.c @@ -20,6 +20,7 @@ #include "addresses.h" #include "config.h" +#include "interface/keyboard_shortcut.h" #include "interface/themes.h" #include "interface/title_sequences.h" #include "localisation/language.h" @@ -104,6 +105,7 @@ config_enum_definition _screenShotFormatEnum[] = { config_enum_definition _measurementFormatEnum[] = { { "IMPERIAL", MEASUREMENT_FORMAT_IMPERIAL }, { "METRIC", MEASUREMENT_FORMAT_METRIC }, + { "SI", MEASUREMENT_FORMAT_SI }, END_OF_ENUM }; @@ -126,6 +128,10 @@ config_enum_definition _currencyEnum[] = { { "EUR", CURRENCY_EUROS }, { "KRW", CURRENCY_WON }, { "RUB", CURRENCY_ROUBLE }, + { "CZK", CURRENCY_CZECH_KORUNA }, + { "HKD", CURRENCY_HKD }, + { "TWD", CURRENCY_TWD }, + { "CNY", CURRENCY_YUAN }, END_OF_ENUM }; @@ -147,12 +153,15 @@ config_enum_definition _languageEnum[] = { { "ko", LANGUAGE_KOREAN }, { "ru-RU", LANGUAGE_RUSSIAN }, { "cz-CZ", LANGUAGE_CZECH }, + { "jp-JP", LANGUAGE_JAPANESE }, END_OF_ENUM }; config_enum_definition _dateFormatEnum[] = { { "DD/MM/YY", DATE_FORMAT_DMY }, { "MM/DD/YY", DATE_FORMAT_MDY }, + { "YY/MM/DD", DATE_FORMAT_YMD }, + { "YY/DD/MM", DATE_FORMAT_YDM }, END_OF_ENUM }; @@ -163,7 +172,7 @@ config_enum_definition _dateFormatEnum[] = { config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, always_show_gridlines), "always_show_gridlines", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, autosave_frequency), "autosave", CONFIG_VALUE_TYPE_UINT8, AUTOSAVE_EVERY_5MINUTES, NULL }, - { offsetof(general_configuration, confirmation_prompt), "confirmation_prompt", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, + { offsetof(general_configuration, confirmation_prompt), "confirmation_prompt", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, construction_marker_colour), "construction_marker_colour", CONFIG_VALUE_TYPE_UINT8, false, NULL }, { offsetof(general_configuration, currency_format), "currency_format", CONFIG_VALUE_TYPE_UINT8, CURRENCY_POUNDS, _currencyEnum }, { offsetof(general_configuration, edge_scrolling), "edge_scrolling", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, @@ -173,7 +182,7 @@ config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, game_path), "game_path", CONFIG_VALUE_TYPE_STRING, { .value_string = NULL }, NULL }, { offsetof(general_configuration, landscape_smoothing), "landscape_smoothing", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, { offsetof(general_configuration, language), "language", CONFIG_VALUE_TYPE_UINT16, LANGUAGE_ENGLISH_UK, _languageEnum }, - { offsetof(general_configuration, measurement_format), "measurement_format", CONFIG_VALUE_TYPE_UINT8, MEASUREMENT_FORMAT_IMPERIAL, _measurementFormatEnum }, + { offsetof(general_configuration, measurement_format), "measurement_format", CONFIG_VALUE_TYPE_UINT8, MEASUREMENT_FORMAT_METRIC, _measurementFormatEnum }, { offsetof(general_configuration, play_intro), "play_intro", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, save_plugin_data), "save_plugin_data", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, debugging_tools), "debugging_tools", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, @@ -190,15 +199,26 @@ config_property_definition _generalDefinitions[] = { { offsetof(general_configuration, date_format), "date_format", CONFIG_VALUE_TYPE_UINT8, DATE_FORMAT_DMY, _dateFormatEnum }, { offsetof(general_configuration, auto_staff_placement), "auto_staff", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, handymen_mow_default), "handymen_mow_default", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + { offsetof(general_configuration, default_inspection_interval), "default_inspection_interval", CONFIG_VALUE_TYPE_UINT8, 2, NULL }, { offsetof(general_configuration, last_run_version), "last_run_version", CONFIG_VALUE_TYPE_STRING, { .value_string = NULL }, NULL }, { offsetof(general_configuration, invert_viewport_drag), "invert_viewport_drag", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, load_save_sort), "load_save_sort", CONFIG_VALUE_TYPE_UINT8, SORT_NAME_ASCENDING, NULL }, { offsetof(general_configuration, minimize_fullscreen_focus_loss), "minimize_fullscreen_focus_loss",CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, { offsetof(general_configuration, day_night_cycle), "day_night_cycle", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, upper_case_banners), "upper_case_banners", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + { offsetof(general_configuration, disable_lightning_effect), "disable_lightning_effect", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, allow_loading_with_incorrect_checksum),"allow_loading_with_incorrect_checksum", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(general_configuration, steam_overlay_pause), "steam_overlay_pause", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, - { offsetof(general_configuration, window_scale), "window_scale", CONFIG_VALUE_TYPE_FLOAT, { .value_float = 1.0f }, NULL }, + { offsetof(general_configuration, window_scale), "window_scale", CONFIG_VALUE_TYPE_FLOAT, { .value_float = 1.0f }, NULL }, + { offsetof(general_configuration, scale_quality), "scale_quality", CONFIG_VALUE_TYPE_UINT8, 1, NULL }, + { offsetof(general_configuration, use_nn_at_integer_scales), "use_nn_at_integer_scales", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { 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[] = { @@ -214,25 +234,16 @@ config_property_definition _interfaceDefinitions[] = { }; config_property_definition _soundDefinitions[] = { - { offsetof(sound_configuration, title_music), "title_music", CONFIG_VALUE_TYPE_UINT8, 2, NULL }, - { offsetof(sound_configuration, sound), "sound", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, - { offsetof(sound_configuration, ride_music), "ride_music", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, - { offsetof(sound_configuration, audio_focus), "audio_focus", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(sound_configuration, master_volume), "master_volume", CONFIG_VALUE_TYPE_UINT8, 100, NULL }, - { offsetof(sound_configuration, music_volume), "music_volume", CONFIG_VALUE_TYPE_UINT8, 100, NULL }, + { offsetof(sound_configuration, title_music), "title_music", CONFIG_VALUE_TYPE_UINT8, 2, NULL }, + { offsetof(sound_configuration, sound_enabled), "sound", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(sound_configuration, sound_volume), "sound_volume", CONFIG_VALUE_TYPE_UINT8, 100, NULL }, + { offsetof(sound_configuration, ride_music_enabled), "ride_music", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(sound_configuration, ride_music_volume), "ride_music_volume", CONFIG_VALUE_TYPE_UINT8, 100, NULL }, + { offsetof(sound_configuration, audio_focus), "audio_focus", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(sound_configuration, device), "audio_device", CONFIG_VALUE_TYPE_STRING, { .value_string = NULL }, NULL }, }; -config_property_definition _cheatDefinitions[] = { - { offsetof(cheat_configuration, fast_lift_hill), "fast_lift_hill", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(cheat_configuration, disable_brakes_failure), "disable_brakes_failure", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(cheat_configuration, disable_all_breakdowns), "disable_all_breakdowns", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(cheat_configuration, unlock_all_prices), "unlock_all_prices", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(cheat_configuration, build_in_pause_mode), "build_in_pause_mode", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(cheat_configuration, ignore_ride_intensity), "ignore_ride_intensity", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(cheat_configuration, disable_vandalism), "disable_vandalism", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, -}; - config_property_definition _twitchDefinitions[] = { { offsetof(twitch_configuration, channel), "channel", CONFIG_VALUE_TYPE_STRING, { .value_string = NULL }, NULL }, { offsetof(twitch_configuration, enable_follower_peep_names), "follower_peep_names", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, @@ -245,6 +256,7 @@ config_property_definition _twitchDefinitions[] = { config_property_definition _networkDefinitions[] = { { offsetof(network_configuration, player_name), "player_name", CONFIG_VALUE_TYPE_STRING, {.value_string = "Player" }, NULL }, { offsetof(network_configuration, default_port), "default_port", CONFIG_VALUE_TYPE_UINT32, NETWORK_DEFAULT_PORT, NULL }, + { offsetof(network_configuration, default_password), "default_password", CONFIG_VALUE_TYPE_STRING, {.value_string = NULL }, NULL }, { offsetof(network_configuration, stay_connected), "stay_connected", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, { offsetof(network_configuration, advertise), "advertise", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, { offsetof(network_configuration, maxplayers), "maxplayers", CONFIG_VALUE_TYPE_UINT8, 16, NULL }, @@ -256,13 +268,33 @@ config_property_definition _networkDefinitions[] = { { offsetof(network_configuration, provider_website), "provider_website", CONFIG_VALUE_TYPE_STRING, {.value_string = NULL }, NULL } }; +config_property_definition _notificationsDefinitions[] = { + { offsetof(notification_configuration, park_award), "park_award", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, park_marketing_campaign_finished), "park_marketing_campaign_finished", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, park_warnings), "park_warnings", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, park_rating_warnings), "park_rating_warnings", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, ride_broken_down), "ride_broken_down", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, ride_crashed), "ride_crashed", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, ride_warnings), "ride_warnings", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, ride_researched), "ride_researched", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_warnings), "guest_warnings", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_lost), "guest_lost", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, + { offsetof(notification_configuration, guest_left_park), "guest_entered_left_park", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_queuing_for_ride), "guest_queuing_for_ride", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_on_ride), "guest_on_ride", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_left_ride), "guest_left_ride", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_bought_item), "guest_bought_item", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_used_facility), "guest_used_facility", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, + { offsetof(notification_configuration, guest_died), "guest_died", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL }, +}; + config_section_definition _sectionDefinitions[] = { { &gConfigGeneral, "general", _generalDefinitions, countof(_generalDefinitions) }, { &gConfigInterface, "interface", _interfaceDefinitions, countof(_interfaceDefinitions) }, { &gConfigSound, "sound", _soundDefinitions, countof(_soundDefinitions) }, - { &gConfigCheat, "cheat", _cheatDefinitions, countof(_cheatDefinitions) }, { &gConfigTwitch, "twitch", _twitchDefinitions, countof(_twitchDefinitions) }, - { &gConfigNetwork, "network", _networkDefinitions, countof(_networkDefinitions) } + { &gConfigNetwork, "network", _networkDefinitions, countof(_networkDefinitions) }, + { &gConfigNotifications, "notifications", _notificationsDefinitions, countof(_notificationsDefinitions) }, }; #pragma endregion @@ -270,14 +302,13 @@ config_section_definition _sectionDefinitions[] = { general_configuration gConfigGeneral; interface_configuration gConfigInterface; sound_configuration gConfigSound; -cheat_configuration gConfigCheat; twitch_configuration gConfigTwitch; network_configuration gConfigNetwork; -themes_configuration gConfigThemes; +notification_configuration gConfigNotifications; title_sequences_configuration gConfigTitleSequences; -bool config_open(const utf8string path); -bool config_save(const utf8string path); +static bool config_open(const utf8string path); +static bool config_save(const utf8string path); static void config_read_properties(config_section_definition **currentSection, const_utf8string line); static void config_save_property_value(SDL_RWops *file, uint8 type, value_union *value); static bool config_read_enum(void *dest, int destSize, const utf8 *key, int keySize, config_enum_definition *enumDefinitions); @@ -301,6 +332,11 @@ static void rwopswritec(SDL_RWops *file, char c) SDL_RWwrite(file, &c, 1, 1); } +static void rwopswritestr(SDL_RWops *file, const char *str) +{ + SDL_RWwrite(file, str, strlen(str), 1); +} + static void rwopsprintf(SDL_RWops *file, const char *format, ...) { va_list args; @@ -314,6 +350,30 @@ static void rwopsprintf(SDL_RWops *file, const char *format, ...) va_end(args); } +static void rwopswritenewline(SDL_RWops *file) +{ + rwopswritestr(file, platform_get_new_line()); +} + +static void rwopswritestresc(SDL_RWops *file, const char *str) { + int length = 0; + for (const char *c = str; *c != '\0'; ++c) { + if (*c == '\\') length += 2; + else ++length; + } + + char *escaped = malloc(length + 1); + int j=0; + for (const char *c = str; *c != '\0'; ++c) { + if (*c == '\\') escaped[j++] = '\\'; + escaped[j++] = *c; + } + escaped[length] = '\0'; + + rwopswritestr(file, escaped); + SafeFree(escaped); +} + void config_set_defaults() { int i, j; @@ -339,6 +399,15 @@ void config_set_defaults() else if (strcmp(property->property_name, "temperature_format") == 0){ destValue->value_uint8 = platform_get_locale_temperature_format(); } + else if (strcmp(property->property_name, "player_name") == 0) { + utf8* username = platform_get_username(); + + if (username) { + destValue->value_string = _strdup(username); + } else { + destValue->value_string = _strdup(language_get_string(STR_PLAYER_DEFAULT_NAME)); + } + } else { // Use static default if (property->type == CONFIG_VALUE_TYPE_STRING) { @@ -356,12 +425,32 @@ void config_set_defaults() } } +void config_release() +{ + for (int i = 0; i < countof(_sectionDefinitions); i++) { + config_section_definition *section = &_sectionDefinitions[i]; + for (int j = 0; j < section->property_definitions_count; j++) { + config_property_definition *property = §ion->property_definitions[j]; + value_union *destValue = (value_union*)((size_t)section->base_address + (size_t)property->offset); + if (property->type == CONFIG_VALUE_TYPE_STRING) { + utf8 **dst = (utf8**)&(destValue->value_string); + SafeFree(*dst); + } + } + } +} + +void config_get_default_path(utf8 *outPath) +{ + platform_get_user_directory(outPath, NULL); + strcat(outPath, "config.ini"); +} + bool config_open_default() { utf8 path[MAX_PATH]; - platform_get_user_directory(path, NULL); - strcat(path, "config.ini"); + config_get_default_path(path); if (config_open(path)) { config_apply_to_old_addresses(); return true; @@ -374,8 +463,7 @@ bool config_save_default() { utf8 path[MAX_PATH]; - platform_get_user_directory(path, NULL); - strcat(path, "config.ini"); + config_get_default_path(path); if (config_save(path)) { config_apply_to_old_addresses(); return true; @@ -448,24 +536,24 @@ bool config_save(const utf8string path) config_section_definition *section = &_sectionDefinitions[i]; rwopswritec(file, '['); - SDL_RWwrite(file, section->section_name, strlen(section->section_name), 1); + rwopswritestr(file, section->section_name); rwopswritec(file, ']'); - rwopswritec(file, '\n'); + rwopswritenewline(file); for (j = 0; j < section->property_definitions_count; j++) { config_property_definition *property = §ion->property_definitions[j]; - SDL_RWwrite(file, property->property_name, strlen(property->property_name), 1); - SDL_RWwrite(file, " = ", 3, 1); + rwopswritestr(file, property->property_name); + rwopswritestr(file, " = "); value = (value_union*)((size_t)section->base_address + (size_t)property->offset); if (property->enum_definitions != NULL) config_write_enum(file, property->type, value, property->enum_definitions); else config_save_property_value(file, property->type, value); - rwopswritec(file, '\n'); + rwopswritenewline(file); } - rwopswritec(file, '\n'); + rwopswritenewline(file); } SDL_RWclose(file); @@ -476,8 +564,8 @@ static void config_save_property_value(SDL_RWops *file, uint8 type, value_union { switch (type) { case CONFIG_VALUE_TYPE_BOOLEAN: - if (value->value_boolean) SDL_RWwrite(file, "true", 4, 1); - else SDL_RWwrite(file, "false", 5, 1); + if (value->value_boolean) rwopswritestr(file, "true"); + else rwopswritestr(file, "false"); break; case CONFIG_VALUE_TYPE_UINT8: rwopsprintf(file, "%u", value->value_uint8); @@ -505,8 +593,9 @@ static void config_save_property_value(SDL_RWops *file, uint8 type, value_union break; case CONFIG_VALUE_TYPE_STRING: rwopswritec(file, '"'); - if (value->value_string != NULL) - SDL_RWwrite(file, value->value_string, strlen(value->value_string), 1); + if (value->value_string != NULL) { + rwopswritestresc(file, value->value_string); + } rwopswritec(file, '"'); break; } @@ -535,8 +624,8 @@ bool config_get_section(const utf8string line, const utf8 **sectionName, int *se bool config_get_property_name_value(const utf8string line, utf8 **propertyName, int *propertyNameSize, utf8 **value, int *valueSize) { - utf8 *ch; - int c, lastC; + utf8 *ch, *clast; + int c; bool quotes; ch = line; @@ -545,8 +634,10 @@ bool config_get_property_name_value(const utf8string line, utf8 **propertyName, if (*ch == 0) return false; *propertyName = ch; + bool equals = false; while ((c = utf8_get_next(ch, (const utf8**)&ch)) != 0) { if (isspace(c) || c == '=') { + if (c == '=') equals = true; *propertyNameSize = ch - *propertyName - 1; break; } else if (c == '#') { @@ -556,9 +647,11 @@ bool config_get_property_name_value(const utf8string line, utf8 **propertyName, if (*ch == 0) return false; utf8_skip_whitespace(&ch); - if (*ch != '=') return false; - ch++; - utf8_skip_whitespace(&ch); + if (!equals) { + if (*ch != '=') return false; + ch++; + utf8_skip_whitespace(&ch); + } if (*ch == 0) return false; if (*ch == '"') { @@ -569,13 +662,15 @@ bool config_get_property_name_value(const utf8string line, utf8 **propertyName, } *value = ch; + clast = ch; while ((c = utf8_get_next(ch, (const utf8**)&ch)) != 0) { - if (isspace(c) || c == '#') { - if (!quotes) break; + if (!quotes) { + if (c == '#') break; + if (c != ' ') clast = ch; } - lastC = c; } - *valueSize = ch - *value - 1; + if (!quotes) *valueSize = clast - *value; + else *valueSize = ch - *value - 1; if (quotes) (*valueSize)--; return true; } @@ -610,6 +705,30 @@ config_property_definition *config_get_property_def(config_section_definition *s return NULL; } +static utf8string escape_string(const utf8 *value, int valueSize) { + int length = 0; + bool backslash = false; + for (int i=0; i < valueSize; ++i) { + if (value[i] == '\\') { + if (backslash) backslash = false; + else ++length, backslash = true; + } else ++length, backslash = false; + } + utf8string escaped = malloc(length + 1); + + int j=0; + backslash = false; + for (int i=0; i < valueSize; ++i) { + if (value[i] == '\\') { + if (backslash) backslash = false; + else escaped[j++] = value[i], backslash = true; + } else escaped[j++] = value[i], backslash = false; + } + escaped[length] = '\0'; + + return escaped; +} + void config_set_property(const config_section_definition *section, const config_property_definition *property, const utf8 *value, int valueSize) { value_union *destValue = (value_union*)((size_t)section->base_address + (size_t)property->offset); @@ -650,9 +769,7 @@ void config_set_property(const config_section_definition *section, const config_ break; case CONFIG_VALUE_TYPE_STRING: SafeFree(destValue->value_string); - destValue->value_string = malloc(valueSize + 1); - memcpy(destValue->value_string, value, valueSize); - destValue->value_string[valueSize] = 0; + destValue->value_string = escape_string(value, valueSize); break; } } @@ -698,7 +815,7 @@ static void config_write_enum(SDL_RWops *file, uint8 type, value_union *value, c uint32 enumValue = (value->value_uint32) & ((1 << (_configValueTypeSize[type] * 8)) - 1); while (enumDefinitions->key != NULL) { if (enumDefinitions->value.value_uint32 == enumValue) { - SDL_RWwrite(file, enumDefinitions->key, strlen(enumDefinitions->key), 1); + rwopswritestr(file, enumDefinitions->key); return; } enumDefinitions++; @@ -772,7 +889,7 @@ static bool config_find_rct2_path(utf8 *resultPath) for (i = 0; i < countof(searchLocations); i++) { if (platform_original_game_data_exists(searchLocations[i])) { - safe_strncpy(resultPath, searchLocations[i], MAX_PATH); + safe_strcpy(resultPath, searchLocations[i], MAX_PATH); return true; } } @@ -788,15 +905,25 @@ bool config_find_or_browse_install_directory() if (config_find_rct2_path(path)) { SafeFree(gConfigGeneral.game_path); gConfigGeneral.game_path = malloc(strlen(path) + 1); - safe_strncpy(gConfigGeneral.game_path, path, MAX_PATH); + safe_strcpy(gConfigGeneral.game_path, path, MAX_PATH); } else { - platform_show_messagebox("Unable to find RCT2 installation directory. Please select the directory where you installed RCT2!"); - installPath = platform_open_directory_browser("Please select your RCT2 directory"); - if (installPath == NULL) - return false; + while (1) { + platform_show_messagebox("Unable to find RCT2 installation directory. Please select the directory where you installed RCT2!"); + installPath = platform_open_directory_browser("Please select your RCT2 directory"); + if (installPath == NULL) + return false; - SafeFree(gConfigGeneral.game_path); - gConfigGeneral.game_path = installPath; + SafeFree(gConfigGeneral.game_path); + gConfigGeneral.game_path = installPath; + + if (platform_original_game_data_exists(installPath)) + return true; + + utf8 message[MAX_PATH] = { 0 }; + char separator = platform_get_path_separator(); + sprintf(message, "Could not find %s%cData%cg1.dat at this path", installPath, separator, separator); + platform_show_messagebox(message); + } } return true; @@ -815,10 +942,20 @@ void config_apply_to_old_addresses() RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = gConfigGeneral.measurement_format; RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_TEMPERATURE, sint8) = gConfigGeneral.temperature_format; RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CONSTRUCTION_MARKER, uint8) = gConfigGeneral.construction_marker_colour; - RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = (gConfigGeneral.measurement_format + 1) * 256; - if (gConfigGeneral.show_height_as_units) + if (gConfigGeneral.show_height_as_units) { RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = 0; - + } else { + switch (gConfigGeneral.measurement_format) { + default: + case MEASUREMENT_FORMAT_IMPERIAL: + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = 1 * 256; + break; + case MEASUREMENT_FORMAT_METRIC: + case MEASUREMENT_FORMAT_SI: + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_HEIGHT_MARKERS, sint16) = 2 * 256; + break; + } + } int configFlags = 0; if (gConfigGeneral.always_show_gridlines) configFlags |= CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES; @@ -839,6 +976,12 @@ void config_apply_to_old_addresses() #define SHIFT 0x100 #define CTRL 0x200 #define ALT 0x400 +#define CMD 0x800 +#ifdef __MACOSX__ + #define PLATFORM_MODIFIER CMD +#else + #define PLATFORM_MODIFIER CTRL +#endif // Current keyboard shortcuts uint16 gShortcutKeys[SHORTCUT_COUNT]; @@ -877,19 +1020,21 @@ static const uint16 _defaultShortcutKeys[SHORTCUT_COUNT] = { SDL_SCANCODE_S, // SHORTCUT_SHOW_STAFF_LIST SDL_SCANCODE_M, // SHORTCUT_SHOW_RECENT_MESSAGES SDL_SCANCODE_TAB, // SHORTCUT_SHOW_MAP - CTRL | SDL_SCANCODE_S, // SHORTCUT_SCREENSHOT + PLATFORM_MODIFIER | SDL_SCANCODE_S, // SHORTCUT_SCREENSHOT // New SDL_SCANCODE_MINUS, // SHORTCUT_REDUCE_GAME_SPEED, SDL_SCANCODE_EQUALS, // SHORTCUT_INCREASE_GAME_SPEED, - CTRL | ALT | SDL_SCANCODE_C, // SHORTCUT_OPEN_CHEAT_WINDOW, + PLATFORM_MODIFIER | ALT | SDL_SCANCODE_C, // SHORTCUT_OPEN_CHEAT_WINDOW, SDL_SCANCODE_T, // SHORTCUT_REMOVE_TOP_BOTTOM_TOOLBAR_TOGGLE, SDL_SCANCODE_UP, // SHORTCUT_SCROLL_MAP_UP SDL_SCANCODE_LEFT, // SHORTCUT_SCROLL_MAP_LEFT SDL_SCANCODE_DOWN, // SHORTCUT_SCROLL_MAP_DOWN SDL_SCANCODE_RIGHT, // SHORTCUT_SCROLL_MAP_RIGHT SDL_SCANCODE_C, // SHORTCUT_OPEN_CHAT_WINDOW - CTRL | SDL_SCANCODE_F10, // SHORTCUT_QUICK_SAVE_GAME + PLATFORM_MODIFIER | SDL_SCANCODE_F10, // SHORTCUT_QUICK_SAVE_GAME + + SHORTCUT_UNDEFINED, // SHORTCUT_SHOW_OPTIONS }; #define SHORTCUT_FILE_VERSION 1 @@ -922,7 +1067,11 @@ bool config_shortcut_keys_load() if (file != NULL) { result = SDL_RWread(file, &version, sizeof(version), 1) == 1; if (result && version == SHORTCUT_FILE_VERSION) { - result = SDL_RWread(file, gShortcutKeys, sizeof(gShortcutKeys), 1) == 1; + for (int i = 0; i < SHORTCUT_COUNT; i++) { + if (SDL_RWread(file, &gShortcutKeys[i], sizeof(uint16), 1) != 1) { + break; + } + } } else { result = false; } @@ -960,396 +1109,6 @@ bool config_shortcut_keys_save() #pragma endregion - -#pragma region Themes - -typedef struct { - size_t offset; - const_utf8string property_name; - uint8 type; - value_union default_value; - config_enum_definition *enum_definitions; -} theme_property_definition; - -typedef struct { - size_t offset; - const_utf8string section_name; - theme_property_definition *property_definitions; - int property_definitions_count; -} theme_section_definition; - - -theme_property_definition _themeWindowDefinitions[] = { - { offsetof(theme_window, colours[0]), "colour_0", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[1]), "colour_1", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[2]), "colour_2", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[3]), "colour_3", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[4]), "colour_4", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, - { offsetof(theme_window, colours[5]), "colour_5", CONFIG_VALUE_TYPE_UINT8, 0, NULL }, -}; - -theme_property_definition _themeFeaturesDefinitions[] = { - { offsetof(theme_features, rct1_ride_lights), "rct1_ride_lights", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(theme_features, rct1_park_lights), "rct1_park_lights", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, - { offsetof(theme_features, rct1_scenario_font), "rct1_scenario_font", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL }, -}; - - -theme_section_definition _themeSectionDefinitions[] = { - // Special definition for theme windows - { 0, "", _themeWindowDefinitions, countof(_themeWindowDefinitions) }, - { offsetof(theme_preset, features), "features", _themeFeaturesDefinitions, countof(_themeFeaturesDefinitions) }, -}; - -static bool themes_open(const_utf8string path); -static bool themes_save(const_utf8string path, int preset); -static void themes_read_properties(theme_preset *theme, theme_section_definition **currentSection, utf8string line); -static void themes_set_property(theme_preset *theme, const theme_section_definition *section, const theme_property_definition *property, utf8string value, int valueSize); -static theme_section_definition* themes_get_section_def(utf8string name, int size); -static theme_property_definition *themes_get_property_def(theme_section_definition *section, utf8string name, int size); - -void themes_set_default() -{ - utf8 path[MAX_PATH]; - - platform_get_user_directory(path, "themes"); - platform_ensure_directory_exists(path); - - gConfigThemes.num_presets = 2; - gConfigThemes.presets = malloc(sizeof(theme_preset) * gConfigThemes.num_presets); - - // Set RCT2 theme - safe_strncpy(gConfigThemes.presets[0].name, language_get_string(2741), THEME_PRESET_NAME_SIZE); - gConfigThemes.presets[0].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - - // Define the defaults for RCT2 here - gConfigThemes.presets[0].features.rct1_ride_lights = false; - gConfigThemes.presets[0].features.rct1_park_lights = false; - gConfigThemes.presets[0].features.rct1_scenario_font = false; - - - for (int i = 0; i < (int)gNumThemeWindows; i++) { - gConfigThemes.presets[0].windows[i] = gThemeWindowDefinitions[i].window; - } - - // Set RCT1 theme - safe_strncpy(gConfigThemes.presets[1].name, language_get_string(2740), THEME_PRESET_NAME_SIZE); - gConfigThemes.presets[1].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - - // Define the defaults for RCT1 here - gConfigThemes.presets[1].features.rct1_ride_lights = true; - gConfigThemes.presets[1].features.rct1_park_lights = true; - gConfigThemes.presets[1].features.rct1_scenario_font = true; - - - for (int i = 0; i < (int)gNumThemeWindows; i++) { - uint8 changed_colour = 0xFF; - for (int k = 0; gThemeWindowsRCT1[k].classification != 0xFF; k++) { - if (gThemeWindowsRCT1[k].classification == gThemeWindowDefinitions[i].classification) { - changed_colour = (uint8)k; - break; - } - } - gConfigThemes.presets[1].windows[i] = (changed_colour != 0xFF ? gThemeWindowsRCT1[changed_colour].window : gThemeWindowDefinitions[i].window); - } - } - -void themes_load_presets() -{ - utf8 path[MAX_PATH]; - file_info file; - int fileEnumHandle, i; - - platform_get_user_directory(path, "themes"); - strcat(path, "*.ini"); - fileEnumHandle = platform_enumerate_files_begin(path); - while (platform_enumerate_files_next(fileEnumHandle, &file)) { - platform_get_user_directory(path, "themes"); - strcat(path, file.path); - themes_open(path); - } - platform_enumerate_files_end(fileEnumHandle); - - if (strcmp(gConfigInterface.current_theme_preset, "*RCT2") == 0) { - theme_change_preset(0); - } - else if (strcmp(gConfigInterface.current_theme_preset, "*RCT1") == 0) { - theme_change_preset(1); - } - else { - for (i = 2; i < gConfigThemes.num_presets; i++) { - if (strcmp(gConfigInterface.current_theme_preset, gConfigThemes.presets[i].name) == 0) { - theme_change_preset(i); - break; - } - } - if (i == gConfigThemes.num_presets) { - theme_change_preset(0); - } - } -} - -bool themes_save_preset(int preset) -{ - utf8 path[MAX_PATH]; - - platform_get_user_directory(path, "themes"); - strcat(path, gConfigThemes.presets[preset].name); - strcat(path, ".ini"); - if (themes_save(path, preset)) { - return true; - } - - return false; -} - -bool themes_open(const_utf8string path) -{ - SDL_RWops *file; - utf8string lineBuffer; - size_t lineBufferCapacity; - size_t lineLength; - int c, preset; - theme_section_definition *currentSection; - - file = SDL_RWFromFile(path, "rb"); - if (file == NULL) - return false; - - // Check if the colour scheme is already loaded - // No nead to read the first two presets as they're hardcoded in - for (preset = 2; preset < gConfigThemes.num_presets; preset++) { - if (strcmp(path, gConfigThemes.presets[preset].name) == 0) { - break; - } - } - // Otherwise allocate one - if (preset == gConfigThemes.num_presets) { - gConfigThemes.num_presets++; - gConfigThemes.presets = realloc(gConfigThemes.presets, sizeof(theme_preset) * gConfigThemes.num_presets); - safe_strncpy(gConfigThemes.presets[preset].name, path_get_filename(path), THEME_PRESET_NAME_SIZE); - path_remove_extension(gConfigThemes.presets[preset].name); - gConfigThemes.presets[preset].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - gConfigThemes.presets[preset].features.rct1_ride_lights = false; - gConfigThemes.presets[preset].features.rct1_park_lights = false; - gConfigThemes.presets[preset].features.rct1_scenario_font = false; - for (int i = 0; i < (int)gNumThemeWindows; i++) { - gConfigThemes.presets[preset].windows[i] = gThemeWindowDefinitions[i].window; - } - } - - currentSection = NULL; - lineBufferCapacity = 64; - lineBuffer = malloc(lineBufferCapacity); - lineLength = 0; - - // Skim UTF-8 byte order mark - SDL_RWread(file, lineBuffer, 3, 1); - if (!(lineBuffer[0] == (utf8)0xEF && lineBuffer[1] == (utf8)0xBB && lineBuffer[2] == (utf8)0xBF)) - SDL_RWseek(file, 0, SEEK_SET); - - while ((c = rwopsreadc(file)) != EOF) { - if (c == '\n' || c == '\r') { - lineBuffer[lineLength++] = 0; - themes_read_properties(&gConfigThemes.presets[preset], ¤tSection, (utf8string)lineBuffer); - lineLength = 0; - } - else { - lineBuffer[lineLength++] = c; - } - - if (lineLength >= lineBufferCapacity) { - lineBufferCapacity *= 2; - lineBuffer = realloc(lineBuffer, lineBufferCapacity); - } - } - - if (lineLength > 0) { - lineBuffer[lineLength++] = 0; - themes_read_properties(&gConfigThemes.presets[preset], ¤tSection, lineBuffer); - } - - free(lineBuffer); - SDL_RWclose(file); - return true; -} - -static bool themes_save(const_utf8string path, int preset) -{ - SDL_RWops *file; - int i, j; - value_union *value; - - file = SDL_RWFromFile(path, "wb"); - if (file == NULL) { - log_error("Unable to write to theme file."); - return false; - } - - // Skip the window definition, we'll do that after - for (i = 1; i < countof(_themeSectionDefinitions); i++) { - theme_section_definition *section = &_themeSectionDefinitions[i]; - - rwopswritec(file, '['); - SDL_RWwrite(file, section->section_name, strlen(section->section_name), 1); - rwopswritec(file, ']'); - rwopswritec(file, '\n'); - - for (j = 0; j < section->property_definitions_count; j++) { - theme_property_definition *property = §ion->property_definitions[j]; - - SDL_RWwrite(file, property->property_name, strlen(property->property_name), 1); - SDL_RWwrite(file, " = ", 3, 1); - - value = (value_union*)((size_t)&gConfigThemes.presets[preset] + (size_t)section->offset + (size_t)property->offset); - - if (property->enum_definitions != NULL) - config_write_enum(file, property->type, value, property->enum_definitions); - else - config_save_property_value(file, property->type, value); - rwopswritec(file, '\n'); - } - rwopswritec(file, '\n'); - } - - for (i = 0; i < (int)gNumThemeWindows; i++) { - theme_section_definition *section = &_themeSectionDefinitions[0]; - - rwopswritec(file, '['); - SDL_RWwrite(file, gThemeWindowDefinitions[i].section_name, strlen(gThemeWindowDefinitions[i].section_name), 1); - rwopswritec(file, ']'); - rwopswritec(file, '\n'); - - for (j = 0; j < section->property_definitions_count; j++) { - theme_property_definition *property = §ion->property_definitions[j]; - - SDL_RWwrite(file, property->property_name, strlen(property->property_name), 1); - SDL_RWwrite(file, " = ", 3, 1); - - value = (value_union*)((size_t)gConfigThemes.presets[preset].windows + (size_t)(sizeof(theme_window) * i) + (size_t)property->offset); - - if (property->enum_definitions != NULL) - config_write_enum(file, property->type, value, property->enum_definitions); - else - config_save_property_value(file, property->type, value); - rwopswritec(file, '\n'); - } - } - - SDL_RWclose(file); - return true; -} - - -static void themes_read_properties(theme_preset *theme, theme_section_definition **currentSection, utf8string line) -{ - utf8 *ch = (utf8*)line; - utf8_skip_whitespace(&ch); - - if (*ch == '[') { - const utf8 *sectionName; - int sectionNameSize; - if (config_get_section(ch, §ionName, §ionNameSize)) - *currentSection = themes_get_section_def((utf8string)sectionName, sectionNameSize); - } else { - if (*currentSection != NULL) { - utf8 *propertyName, *value; - int propertyNameSize, valueSize; - if (config_get_property_name_value(ch, &propertyName, &propertyNameSize, &value, &valueSize)) { - theme_property_definition *property; - property = themes_get_property_def(*currentSection, propertyName, propertyNameSize); - if (property != NULL) - themes_set_property(theme, *currentSection, property, value, valueSize); - } - } - } -} -static void themes_set_property(theme_preset *theme, const theme_section_definition *section, const theme_property_definition *property, utf8string value, int valueSize) -{ - value_union *destValue = (value_union*)((size_t)theme + (size_t)section->offset + (size_t)property->offset); - - // Get getting the address from the windows pointer instead - if (section == &_themeSectionDefinitions[0]) - destValue = (value_union*)((size_t)theme->windows + (size_t)section->offset + (size_t)property->offset); - - if (property->enum_definitions != NULL) - if (config_read_enum(destValue, _configValueTypeSize[property->type], value, valueSize, property->enum_definitions)) - return; - - switch (property->type) { - case CONFIG_VALUE_TYPE_BOOLEAN: - if (_strnicmp(value, "false", valueSize) == 0) destValue->value_boolean = false; - else if (_strnicmp(value, "true", valueSize) == 0) destValue->value_boolean = true; - else destValue->value_boolean = strtol(value, NULL, 0) != 0; - break; - case CONFIG_VALUE_TYPE_UINT8: - destValue->value_uint8 = (uint8)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_UINT16: - destValue->value_uint16 = (uint16)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_UINT32: - destValue->value_uint32 = (uint32)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_SINT8: - destValue->value_sint8 = (sint8)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_SINT16: - destValue->value_sint16 = (sint16)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_SINT32: - destValue->value_sint32 = (sint32)strtol(value, NULL, 0); - break; - case CONFIG_VALUE_TYPE_FLOAT: - destValue->value_float = strtof(value, NULL); - break; - case CONFIG_VALUE_TYPE_DOUBLE: - destValue->value_double = strtod(value, NULL); - break; - case CONFIG_VALUE_TYPE_STRING: - SafeFree(destValue->value_string); - destValue->value_string = malloc(valueSize + 1); - memcpy(destValue->value_string, value, valueSize); - destValue->value_string[valueSize] = 0; - break; - } -} -static theme_section_definition* themes_get_section_def(utf8string name, int size) -{ - int i; - - // Skip the special definition - for (i = 1; i < countof(_themeSectionDefinitions); i++) { - const_utf8string sectionName = _themeSectionDefinitions[i].section_name; - if (sectionName[size] == 0 && _strnicmp(sectionName, name, size) == 0) - return &_themeSectionDefinitions[i]; - } - // Check for window definitions - for (i = 0; i < (int)gNumThemeWindows; i++) { - const_utf8string sectionName = gThemeWindowDefinitions[i].section_name; - if (sectionName[size] == 0 && _strnicmp(sectionName, name, size) == 0) { - _themeSectionDefinitions[0].offset = (size_t)(sizeof(theme_window) * i); - return &_themeSectionDefinitions[0]; - } - } - - return NULL; - } -static theme_property_definition *themes_get_property_def(theme_section_definition *section, utf8string name, int size) -{ - int i; - - for (i = 0; i < section->property_definitions_count; i++) { - const_utf8string propertyName = section->property_definitions[i].property_name; - if (propertyName[size] == 0 && _strnicmp(propertyName, name, size) == 0) - return §ion->property_definitions[i]; - } - - return NULL; -} - -#pragma endregion - #pragma region Title Sequences static void title_sequence_open(const char *path, const char *customName); @@ -1357,6 +1116,7 @@ static void title_sequence_open(const char *path, const char *customName); void title_sequences_set_default() { char path[MAX_PATH]; + char dataPath[MAX_PATH]; char sep = platform_get_path_separator(); platform_get_user_directory(path, "title sequences"); @@ -1365,12 +1125,26 @@ void title_sequences_set_default() gConfigTitleSequences.presets = malloc(0); gConfigTitleSequences.num_presets = 0; - // Load OpenRCT2 title sequence - sprintf(path, "%s%c%s%c%s%c%s%c", gExePath, sep, "data", sep, "title", sep, "rct2", sep); + platform_get_openrct_data_path(dataPath); + + // 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 - sprintf(path, "%s%c%s%c%s%c%s%c", gExePath, sep, "data", sep, "title", sep, "openrct2", sep); + // 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)); } @@ -1390,12 +1164,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) { @@ -1420,7 +1203,7 @@ static void title_sequence_open(const char *path, const char *customName) char separator = platform_get_path_separator(); // Check for the script file - safe_strncpy(scriptPath, path, MAX_PATH); + safe_strcpy(scriptPath, path, MAX_PATH); strcat(scriptPath, "script.txt"); if (!platform_file_exists(scriptPath)) { // No script file, title sequence is invalid @@ -1440,22 +1223,19 @@ static void title_sequence_open(const char *path, const char *customName) gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets); if (customName == NULL) { - char nameBuffer[MAX_PATH], *name; - safe_strncpy(nameBuffer, path, MAX_PATH); - name = nameBuffer + strlen(nameBuffer) - 1; - while (*name == '\\' || *name == '/') { - *name = 0; - name--; - } - while (*(name - 1) != '\\' && *(name - 1) != '/') { - name--; - } - safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); + char nameBuffer[MAX_PATH]; + safe_strcpy(nameBuffer, path, MAX_PATH); + // Get folder name + // First strip off the last folder separator + *strrchr(nameBuffer, platform_get_path_separator()) = '\0'; + // Then find the name of the folder + char *name = strrchr(nameBuffer, platform_get_path_separator()) + 1; + safe_strcpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); gConfigTitleSequences.presets[preset].path[0] = 0; } else { - safe_strncpy(gConfigTitleSequences.presets[preset].name, customName, TITLE_SEQUENCE_NAME_SIZE); - safe_strncpy(gConfigTitleSequences.presets[preset].path, path, MAX_PATH); + safe_strcpy(gConfigTitleSequences.presets[preset].name, customName, TITLE_SEQUENCE_NAME_SIZE); + safe_strcpy(gConfigTitleSequences.presets[preset].path, path, MAX_PATH); } gConfigTitleSequences.presets[preset].saves = malloc(0); @@ -1465,23 +1245,23 @@ static void title_sequence_open(const char *path, const char *customName) } // Get the save file list - safe_strncpy(titlePath, path, MAX_PATH); + safe_strcpy(titlePath, path, MAX_PATH); strcat(titlePath, "*.sv6"); fileEnumHandle = platform_enumerate_files_begin(titlePath); while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { gConfigTitleSequences.presets[preset].num_saves++; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); - safe_strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); + safe_strcpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1][TITLE_SEQUENCE_MAX_SAVE_LENGTH - 1] = '\0'; } platform_enumerate_files_end(fileEnumHandle); - safe_strncpy(titlePath, path, MAX_PATH); + safe_strcpy(titlePath, path, MAX_PATH); strcat(titlePath, "*.sc6"); fileEnumHandle = platform_enumerate_files_begin(titlePath); while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { gConfigTitleSequences.presets[preset].num_saves++; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); - safe_strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); + safe_strcpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], fileInfo.path, TITLE_SEQUENCE_MAX_SAVE_LENGTH); gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1][TITLE_SEQUENCE_MAX_SAVE_LENGTH - 1] = '\0'; } platform_enumerate_files_end(fileEnumHandle); @@ -1528,6 +1308,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) { @@ -1548,7 +1331,7 @@ void title_sequence_save_preset_script(int preset) platform_get_user_directory(path, "title sequences"); - strcat(path, path_get_filename(gConfigTitleSequences.presets[preset].name)); + strcat(path, gConfigTitleSequences.presets[preset].name); strncat(path, &separator, 1); strcat(path, "script.txt"); @@ -1563,33 +1346,34 @@ void title_sequence_save_preset_script(int preset) switch (command->command) { case TITLE_SCRIPT_LOAD: if (command->saveIndex == 0xFF) - rwopsprintf(file, "LOAD \r\n"); + rwopsprintf(file, "LOAD "); else - rwopsprintf(file, "LOAD %s\r\n", gConfigTitleSequences.presets[preset].saves[command->saveIndex]); + rwopsprintf(file, "LOAD %s", gConfigTitleSequences.presets[preset].saves[command->saveIndex]); break; case TITLE_SCRIPT_LOCATION: - rwopsprintf(file, "LOCATION %i %i\r\n", command->x, command->y); + rwopsprintf(file, "LOCATION %i %i", command->x, command->y); break; case TITLE_SCRIPT_ROTATE: - rwopsprintf(file, "ROTATE %i\r\n", command->rotations); + rwopsprintf(file, "ROTATE %i", command->rotations); break; case TITLE_SCRIPT_ZOOM: - rwopsprintf(file, "ZOOM %i\r\n", command->zoom); + rwopsprintf(file, "ZOOM %i", command->zoom); break; case TITLE_SCRIPT_SPEED: - rwopsprintf(file, "SPEED %i\r\n", command->speed); + rwopsprintf(file, "SPEED %i", command->speed); break; case TITLE_SCRIPT_WAIT: - rwopsprintf(file, "WAIT %i\r\n\r\n", command->seconds); + rwopsprintf(file, "WAIT %i", command->seconds); + rwopswritenewline(file); break; case TITLE_SCRIPT_RESTART: - rwopsprintf(file, "RESTART\r\n"); + rwopsprintf(file, "RESTART"); break; case TITLE_SCRIPT_END: - rwopsprintf(file, "END\r\n"); + rwopsprintf(file, "END"); break; - } + rwopswritenewline(file); } SDL_RWclose(file); diff --git a/src/config.h b/src/config.h index 951727ca21..e9890bece9 100644 --- a/src/config.h +++ b/src/config.h @@ -78,6 +78,7 @@ enum { SHORTCUT_SCROLL_MAP_RIGHT, SHORTCUT_OPEN_CHAT_WINDOW, SHORTCUT_QUICK_SAVE_GAME, + SHORTCUT_SHOW_OPTIONS, SHORTCUT_COUNT }; @@ -94,7 +95,8 @@ enum { enum { MEASUREMENT_FORMAT_IMPERIAL, - MEASUREMENT_FORMAT_METRIC + MEASUREMENT_FORMAT_METRIC, + MEASUREMENT_FORMAT_SI }; enum { @@ -108,7 +110,9 @@ enum { enum { DATE_FORMAT_DMY, - DATE_FORMAT_MDY + DATE_FORMAT_MDY, + DATE_FORMAT_YMD, + DATE_FORMAT_YDM }; enum { @@ -127,6 +131,11 @@ enum { SORT_DATE_DESCENDING, }; +enum { + SCENARIO_SELECT_MODE_DIFFICULTY, + SCENARIO_SELECT_MODE_ORIGIN, +}; + typedef struct { uint8 play_intro; uint8 confirmation_prompt; @@ -159,15 +168,25 @@ typedef struct { uint8 date_format; uint8 auto_staff_placement; uint8 handymen_mow_default; + uint8 default_inspection_interval; utf8string last_run_version; uint8 invert_viewport_drag; uint8 load_save_sort; uint8 minimize_fullscreen_focus_loss; uint8 day_night_cycle; uint8 upper_case_banners; + uint8 disable_lightning_effect; uint8 allow_loading_with_incorrect_checksum; uint8 steam_overlay_pause; float window_scale; + uint8 scale_quality; + uint8 use_nn_at_integer_scales; + 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 { @@ -183,25 +202,16 @@ typedef struct { } interface_configuration; typedef struct { - uint8 title_music; - uint8 sound; - uint8 ride_music; - uint8 audio_focus; uint8 master_volume; - uint8 music_volume; + uint8 title_music; + uint8 sound_enabled; + uint8 sound_volume; + uint8 ride_music_enabled; + uint8 ride_music_volume; + uint8 audio_focus; utf8string device; } sound_configuration; -typedef struct { - uint8 fast_lift_hill; - uint8 disable_brakes_failure; - uint8 disable_all_breakdowns; - uint8 unlock_all_prices; - uint8 build_in_pause_mode; - uint8 ignore_ride_intensity; - uint8 disable_vandalism; -} cheat_configuration; - typedef struct { utf8string channel; uint8 enable_follower_peep_names; @@ -214,6 +224,7 @@ typedef struct { typedef struct { utf8string player_name; uint32 default_port; + utf8string default_password; uint8 stay_connected; uint8 advertise; uint8 maxplayers; @@ -225,12 +236,25 @@ typedef struct { utf8string provider_website; } network_configuration; -typedef struct theme_window { - uint8 colours[6]; - - // Define any other settings for all windows here - -} theme_window; +typedef struct { + bool park_award; + bool park_marketing_campaign_finished; + bool park_warnings; + bool park_rating_warnings; + bool ride_broken_down; + bool ride_crashed; + bool ride_warnings; + bool ride_researched; + bool guest_warnings; + bool guest_lost; + bool guest_left_park; + bool guest_queuing_for_ride; + bool guest_on_ride; + bool guest_left_ride; + bool guest_bought_item; + bool guest_used_facility; + bool guest_died; +} notification_configuration; // Define structures for any other settings here typedef struct { @@ -239,22 +263,6 @@ typedef struct { uint8 rct1_scenario_font; } theme_features; -#define THEME_PRESET_NAME_SIZE 256 - -typedef struct theme_preset { - char name[THEME_PRESET_NAME_SIZE]; - theme_window *windows; - - // Add structures for any other settings here - theme_features features; - -} theme_preset; - -typedef struct { - theme_preset *presets; - uint16 num_presets; -} themes_configuration; - #define TITLE_SEQUENCE_MAX_SAVE_LENGTH 51 typedef struct { @@ -296,15 +304,16 @@ typedef struct { extern general_configuration gConfigGeneral; extern interface_configuration gConfigInterface; extern sound_configuration gConfigSound; -extern cheat_configuration gConfigCheat; extern twitch_configuration gConfigTwitch; extern network_configuration gConfigNetwork; -extern themes_configuration gConfigThemes; +extern notification_configuration gConfigNotifications; extern title_sequences_configuration gConfigTitleSequences; extern uint16 gShortcutKeys[SHORTCUT_COUNT]; +void config_get_default_path(utf8 *outPath); void config_set_defaults(); +void config_release(); bool config_open_default(); bool config_save_default(); @@ -316,10 +325,6 @@ bool config_shortcut_keys_save(); bool config_find_or_browse_install_directory(); -void themes_set_default(); -void themes_load_presets(); -bool themes_save_preset(int preset); - void title_sequences_set_default(); void title_sequences_load_presets(); void title_sequence_save_preset_script(int preset); diff --git a/src/core/Console.cpp b/src/core/Console.cpp new file mode 100644 index 0000000000..713e651378 --- /dev/null +++ b/src/core/Console.cpp @@ -0,0 +1,79 @@ +extern "C" +{ + #include "../platform/platform.h" +} + +#include "Console.hpp" + +namespace Console +{ + void Write(char c) + { + fputc(c, stdout); + } + + void Write(const utf8 * str) + { + fputs(str, stdout); + } + + void WriteSpace(size_t count) + { + for (size_t i = 0; i < count; i++) + { + Write(' '); + } + } + + void WriteFormat(const utf8 * format, ...) + { + va_list args; + + va_start(args, format); + vfprintf(stdout, format, args); + va_end(args); + } + + void WriteLine() + { + puts(""); + } + + void WriteLine(const utf8 * str) + { + puts(str); + } + + namespace Error + { + void Write(char c) + { + fputc(c, stderr); + } + + void Write(const utf8 * str) + { + fputs(str, stderr); + } + + void WriteFormat(const utf8 * format, ...) + { + va_list args; + + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + } + + void WriteLine() + { + fputs(platform_get_new_line(), stderr); + } + + void WriteLine(const utf8 * str) + { + fputs(str, stderr); + WriteLine(); + } + } +} \ No newline at end of file diff --git a/src/core/Console.hpp b/src/core/Console.hpp new file mode 100644 index 0000000000..36068ae204 --- /dev/null +++ b/src/core/Console.hpp @@ -0,0 +1,25 @@ +#pragma once + +extern "C" +{ + #include "../common.h" +} + +namespace Console +{ + void Write(char c); + void Write(const utf8 * str); + void WriteSpace(size_t count); + void WriteFormat(const utf8 * format, ...); + void WriteLine(); + void WriteLine(const utf8 * str); + + namespace Error + { + void Write(char c); + void Write(const utf8 * str); + void WriteFormat(const utf8 * format, ...); + void WriteLine(); + void WriteLine(const utf8 * str); + } +} diff --git a/src/core/Diagnostics.hpp b/src/core/Diagnostics.hpp new file mode 100644 index 0000000000..5019b8c0d8 --- /dev/null +++ b/src/core/Diagnostics.hpp @@ -0,0 +1,22 @@ +#pragma once + +#if _WIN32 +#include +#endif + +/** + * Utility methods for asserting and logging. + */ +namespace Debug +{ + void Break() + { +#if DEBUG +#if _WIN32 + if (IsDebuggerPresent()) { + DebugBreak(); + } +#endif +#endif + } +} diff --git a/src/core/Exception.hpp b/src/core/Exception.hpp index ac3d25d2ad..ed96db621e 100644 --- a/src/core/Exception.hpp +++ b/src/core/Exception.hpp @@ -1,19 +1,24 @@ #pragma once -#include #include "../common.h" -class Exception : public std::exception { -public: - Exception() : std::exception() { } - Exception(const char *message) : std::exception() { - _message = message; - } - virtual ~Exception() { } +#include - const char *what() const throw() override { return _message; } - const char *GetMessage() const { return _message; } +class Exception : public std::exception +{ +public: + Exception() : Exception(nullptr) { } + + Exception(const char * message) : std::exception() + { + _message = message; + } + + virtual ~Exception() { } + + const char * what() const throw() override { return _message; } + const char * GetMessage() const { return _message; } private: - const char *_message; + const char * _message; }; diff --git a/src/core/FileStream.hpp b/src/core/FileStream.hpp index e7b91d37d8..7224741ef1 100644 --- a/src/core/FileStream.hpp +++ b/src/core/FileStream.hpp @@ -1,94 +1,108 @@ #pragma once -#include #include "../common.h" + +#include #include "IStream.hpp" -enum { - FILE_MODE_OPEN, - FILE_MODE_WRITE +enum +{ + FILE_MODE_OPEN, + FILE_MODE_WRITE }; /** * A stream for reading and writing to files. Wraps an SDL_RWops, SDL2's cross platform file stream. */ -class FileStream : public IStream { +class FileStream : public IStream +{ private: - SDL_RWops *_file; - bool _canRead; - bool _canWrite; - bool _disposed; + SDL_RWops * _file; + bool _canRead; + bool _canWrite; + bool _disposed; public: - FileStream(const utf8 *path, int fileMode) { - const char *mode; - switch (fileMode) { - case FILE_MODE_OPEN: - mode = "rb"; - _canRead = true; - _canWrite = false; - break; - case FILE_MODE_WRITE: - mode = "wb"; - _canRead = false; - _canWrite = true; - break; - default: - throw; - } + FileStream(const utf8 * path, int fileMode) + { + const char * mode; + switch (fileMode) { + case FILE_MODE_OPEN: + mode = "rb"; + _canRead = true; + _canWrite = false; + break; + case FILE_MODE_WRITE: + mode = "wb"; + _canRead = false; + _canWrite = true; + break; + default: + throw; + } - _file = SDL_RWFromFile(path, mode); - if (_file == NULL) { - throw IOException(SDL_GetError()); - } + _file = SDL_RWFromFile(path, mode); + if (_file == nullptr) + { + throw IOException(SDL_GetError()); + } - _disposed = false; - } + _disposed = false; + } - ~FileStream() { - Dispose(); - } + ~FileStream() + { + Dispose(); + } - void Dispose() override { - if (!_disposed) { - _disposed = true; - SDL_RWclose(_file); - } - } + void Dispose() override + { + if (!_disposed) + { + _disposed = true; + SDL_RWclose(_file); + } + } - bool CanRead() const override { return _canRead; } - bool CanWrite() const override { return _canWrite; } + bool CanRead() const override { return _canRead; } + bool CanWrite() const override { return _canWrite; } - sint64 GetLength() const override { return SDL_RWsize(_file); } - sint64 GetPosition() const override { return SDL_RWtell(_file); } + uint64 GetLength() const override { return SDL_RWsize(_file); } + uint64 GetPosition() const override { return SDL_RWtell(_file); } - void SetPosition(sint64 position) override { - Seek(position, STREAM_SEEK_BEGIN); - } + void SetPosition(uint64 position) override + { + Seek(position, STREAM_SEEK_BEGIN); + } - void Seek(sint64 offset, int origin) override { - switch (origin) { - case STREAM_SEEK_BEGIN: - SDL_RWseek(_file, offset, RW_SEEK_SET); - break; - case STREAM_SEEK_CURRENT: - SDL_RWseek(_file, offset, RW_SEEK_CUR); - break; - case STREAM_SEEK_END: - SDL_RWseek(_file, offset, RW_SEEK_END); - break; - } - } + void Seek(sint64 offset, int origin) override + { + switch (origin) { + case STREAM_SEEK_BEGIN: + SDL_RWseek(_file, offset, RW_SEEK_SET); + break; + case STREAM_SEEK_CURRENT: + SDL_RWseek(_file, offset, RW_SEEK_CUR); + break; + case STREAM_SEEK_END: + SDL_RWseek(_file, offset, RW_SEEK_END); + break; + } + } - void Read(void *buffer, int length) override { - if (SDL_RWread(_file, buffer, length, 1) != 1) { - throw IOException("Attempted to read past end of file."); - } - } + void Read(void * buffer, uint64 length) override + { + if (SDL_RWread(_file, buffer, (size_t)length, 1) != 1) + { + throw IOException("Attempted to read past end of file."); + } + } - void Write(const void *buffer, int length) override { - if (SDL_RWwrite(_file, buffer, length, 1) != 1) { - throw IOException("Unable to write to file."); - } - } + void Write(const void * buffer, uint64 length) override + { + if (SDL_RWwrite(_file, buffer, (size_t)length, 1) != 1) + { + throw IOException("Unable to write to file."); + } + } }; diff --git a/src/core/Guard.hpp b/src/core/Guard.hpp new file mode 100644 index 0000000000..8556ce215a --- /dev/null +++ b/src/core/Guard.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + +#include "Console.hpp" +#include "Diagnostics.hpp" + +/** + * Utility methods for asserting function parameters. + */ +namespace Guard +{ + void Assert(bool expression, const char * message = nullptr) + { + if (expression) return; + + if (message != nullptr) + { + Console::Error::WriteLine(message); + } + +#if DEBUG + Debug::Break(); +#endif + assert(false); + } + + template + void ArgumentNotNull(T * argument, const char * message = nullptr) + { + Assert(argument != nullptr, message); + } + + template + void ArgumentInRange(T argument, T min, T max, const char * message = nullptr) + { + Assert(argument >= min && argument <= max, message); + } +}; diff --git a/src/core/IDisposable.hpp b/src/core/IDisposable.hpp index e0cfb58726..d6137daed3 100644 --- a/src/core/IDisposable.hpp +++ b/src/core/IDisposable.hpp @@ -5,6 +5,7 @@ /** * Represents an object that can be disposed. So things can explicitly close resources before the destructor kicks in. */ -interface IDisposable { - virtual void Dispose() abstract; +interface IDisposable +{ + virtual void Dispose() abstract; }; diff --git a/src/core/IStream.hpp b/src/core/IStream.hpp index 00911cc6aa..cf9a60a0e6 100644 --- a/src/core/IStream.hpp +++ b/src/core/IStream.hpp @@ -1,75 +1,82 @@ #pragma once #include "../common.h" + #include "Exception.hpp" #include "IDisposable.hpp" enum { - STREAM_SEEK_BEGIN, - STREAM_SEEK_CURRENT, - STREAM_SEEK_END + STREAM_SEEK_BEGIN, + STREAM_SEEK_CURRENT, + STREAM_SEEK_END }; /** * Represents a stream that can be read or written to. Implemented by types such as FileStream, NetworkStream or MemoryStream. */ -interface IStream : public IDisposable { - /////////////////////////////////////////////////////////////////////////// - // Interface methods - /////////////////////////////////////////////////////////////////////////// - // virtual ~IStream() abstract; +interface IStream : public IDisposable +{ + /////////////////////////////////////////////////////////////////////////// + // Interface methods + /////////////////////////////////////////////////////////////////////////// + // virtual ~IStream() abstract; - virtual bool CanRead() const abstract; - virtual bool CanWrite() const abstract; + virtual bool CanRead() const abstract; + virtual bool CanWrite() const abstract; - virtual sint64 GetLength() const abstract; - virtual sint64 GetPosition() const abstract; - virtual void SetPosition(sint64 position) abstract; - virtual void Seek(sint64 offset, int origin) abstract; + virtual uint64 GetLength() const abstract; + virtual uint64 GetPosition() const abstract; + virtual void SetPosition(uint64 position) abstract; + virtual void Seek(sint64 offset, int origin) abstract; - virtual void Read(void *buffer, int length) abstract; - virtual void Write(const void *buffer, int length) abstract; + virtual void Read(void * buffer, uint64 length) abstract; + virtual void Write(const void * buffer, uint64 length) abstract; - /////////////////////////////////////////////////////////////////////////// - // Helper methods - /////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////////////////////// - /** - * Reads the size of the given type from the stream directly into the given address. - */ - template - void Read(T *value) { - Read(value, sizeof(T)); - } + /** + * Reads the size of the given type from the stream directly into the given address. + */ + template + void Read(T * value) + { + Read(value, sizeof(T)); + } - /** - * Writes the size of the given type to the stream directly from the given address. - */ - template - void Write(const T *value) { - Write(value, sizeof(T)); - } + /** + * Writes the size of the given type to the stream directly from the given address. + */ + template + void Write(const T * value) + { + Write(value, sizeof(T)); + } - /** - * Reads the given type from the stream. Use this only for small types (e.g. sint8, sint64, double) - */ - template - T ReadValue() { - T buffer; - Read(&buffer); - return buffer; - } + /** + * Reads the given type from the stream. Use this only for small types (e.g. sint8, sint64, double) + */ + template + T ReadValue() + { + T buffer; + Read(&buffer); + return buffer; + } - /** - * Writes the given type to the stream. Use this only for small types (e.g. sint8, sint64, double) - */ - template - void WriteValue(const T value) { - Write(&value); - } + /** + * Writes the given type to the stream. Use this only for small types (e.g. sint8, sint64, double) + */ + template + void WriteValue(const T value) + { + Write(&value); + } }; -class IOException : public Exception { +class IOException : public Exception +{ public: - IOException(const char *message) : Exception(message) { } + IOException(const char * message) : Exception(message) { } }; diff --git a/src/core/Json.cpp b/src/core/Json.cpp new file mode 100644 index 0000000000..bfa0ba3f48 --- /dev/null +++ b/src/core/Json.cpp @@ -0,0 +1,45 @@ +#include "FileStream.hpp" +#include "Json.hpp" +#include "Memory.hpp" +#include "String.hpp" + +namespace Json +{ + json_t * ReadFromFile(const utf8 * path, size_t maxSize) + { + json_t * json = nullptr; + auto fs = FileStream(path, FILE_MODE_OPEN); + + size_t fileLength = (size_t)fs.GetLength(); + if (fileLength > maxSize) + { + throw IOException("Json file too large."); + } + + utf8 * fileData = Memory::Allocate(fileLength + 1); + fs.Read(fileData, fileLength); + fileData[fileLength] = '\0'; + + json_error_t jsonLoadError; + json = json_loads(fileData, 0, &jsonLoadError); + Memory::Free(fileData); + + if (json == nullptr) + { + throw JsonException(&jsonLoadError); + } + + return json; + } + + void WriteToFile(const utf8 * path, const json_t * json, size_t flags) + { + // Serialise JSON + const char * jsonOutput = json_dumps(json, flags); + + // Write to file + auto fs = FileStream(path, FILE_MODE_WRITE); + size_t jsonOutputSize = String::SizeOf(jsonOutput); + fs.Write(jsonOutput, jsonOutputSize); + } +} diff --git a/src/core/Json.hpp b/src/core/Json.hpp new file mode 100644 index 0000000000..e5beed4f9d --- /dev/null +++ b/src/core/Json.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +#include "../common.h" +#include "Exception.hpp" + +namespace Json +{ + // Don't try to load JSON files that exceed 64 MiB + constexpr uint64 MAX_JSON_SIZE = 64 * 1024 * 1024; + + json_t * ReadFromFile(const utf8 * path, size_t maxSize = MAX_JSON_SIZE); + void WriteToFile(const utf8 * path, const json_t * json, size_t flags = 0); +} + +class JsonException : public Exception +{ +private: + json_error_t _jsonError = { 0 }; + +public: + JsonException(const char * message) : Exception(message) { } + + JsonException(const json_error_t * jsonError) : JsonException(jsonError->text) + { + _jsonError = *jsonError; + } +}; diff --git a/src/core/List.hpp b/src/core/List.hpp new file mode 100644 index 0000000000..80fdf724f6 --- /dev/null +++ b/src/core/List.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include + +#include "../common.h" +#include "Guard.hpp" +#include "Memory.hpp" + +/** + * A container that stores elements in contiguous memory. Automatically reallocates memory when required. Equivalent to + * std::vector. + */ +template +class List : public std::vector +{ +public: + typedef typename std::vector::const_reference const_reference; + typedef typename std::vector::reference reference; + size_t GetCapacity() const { return this->capacity(); } + size_t GetCount() const { return this->size(); } + const T * GetItems() const { return this->data(); } + + List() : std::vector() { } + + List(size_t capacity) : std::vector(capacity) { } + + List(const T * items, size_t count) : std::vector(items, items + count) { } + + void EnsureCapacity(size_t capacity) + { + this->reserve(capacity); + } + + void ShrinkToLength() + { + this->shrink_to_fit(); + } + + void Clear() + { + this->clear(); + } + + void Add(T item) + { + this->push_back(item); + } + + void Insert(T item, size_t index) + { + Guard::ArgumentInRange(index, (size_t)0, this->size()); + this->insert(this->begin() + index, item); + } + + bool Remove(T item) + { + for (size_t i = 0; i < this->size(); i++) + { + if (*this[i] == item) + { + RemoveAt(i); + return true; + } + } + return false; + } + + void RemoveAt(size_t index) + { + Guard::ArgumentInRange(index, (size_t)0, this->size() - 1); + this->erase(this->begin() + index); + } + + const T * ToArray() const + { + return Memory::DuplicateArray(this->data(), this->size()); + } + + const_reference operator[](size_t index) const + { + Guard::ArgumentInRange(index, (size_t)0, this->size() - 1); + return std::vector::operator[](index); + } + + reference operator[](size_t index) + { + Guard::ArgumentInRange(index, (size_t)0, this->size() - 1); + return std::vector::operator[](index); + } +}; diff --git a/src/core/Math.hpp b/src/core/Math.hpp index 939159db08..ae096ec2a8 100644 --- a/src/core/Math.hpp +++ b/src/core/Math.hpp @@ -1,23 +1,27 @@ #pragma once +#include + /** * Common mathematical functions. */ -namespace Math { +namespace Math +{ + template + T Min(T a, T b) + { + return (std::min)(a, b); + } - template - T Min(T a, T b) { - return a < b ? a : b; - } - - template - T Max(T a, T b) { - return a > b ? a : b; - } - - template - T Clamp(T low, T x, T high) { - return Min(Max(low, x), high); - } + template + T Max(T a, T b) + { + return (std::max)(a, b); + } + template + T Clamp(T low, T x, T high) + { + return (std::min)((std::max)(low, x), high); + } } diff --git a/src/core/Memory.hpp b/src/core/Memory.hpp index 52cacc5286..713422a6d8 100644 --- a/src/core/Memory.hpp +++ b/src/core/Memory.hpp @@ -1,66 +1,112 @@ #pragma once +extern "C" +{ + #include "../common.h" +} + /** * Utility methods for memory management. Typically helpers and wrappers around the C standard library. */ -namespace Memory { - template - T *Allocate() { - return (T*)malloc(sizeof(T)); - } +namespace Memory +{ + template + T * Allocate() + { + return (T*)malloc(sizeof(T)); + } - template - T *Allocate(size_t size) { - return (T*)malloc(size); - } + template + T * Allocate(size_t size) + { + return (T*)malloc(size); + } - template - T *AllocateArray(size_t count) { - return (T*)malloc(count * sizeof(T)); - } + template + T * AllocateArray(size_t count) + { + return (T*)malloc(count * sizeof(T)); + } - template - T *Reallocate(T *ptr, size_t size) { - if (ptr == NULL) - return (T*)malloc(size); - else - return (T*)realloc((void*)ptr, size); - } + template + T * Reallocate(T * ptr, size_t size) + { + if (ptr == nullptr) + { + return (T*)malloc(size); + } + else + { + return (T*)realloc((void*)ptr, size); + } + } - template - T *ReallocateArray(T *ptr, size_t count) { - if (ptr == NULL) - return (T*)malloc(count * sizeof(T)); - else - return (T*)realloc((void*)ptr, count * sizeof(T)); - } + template + T * ReallocateArray(T * ptr, size_t count) + { + if (ptr == nullptr) + { + return (T*)malloc(count * sizeof(T)); + } + else + { + return (T*)realloc((void*)ptr, count * sizeof(T)); + } + } - template - void Free(T *ptr) { - free((void*)ptr); - } + template + void Free(T * ptr) + { + free((void*)ptr); + } - template - T *Copy(T *dst, const T *src, size_t size) { - if (size == 0) return (T*)dst; - return (T*)memcpy((void*)dst, (const void*)src, size); - } + template + T * Copy(T * dst, const T * src, size_t size) + { + if (size == 0) return (T*)dst; + return (T*)memcpy((void*)dst, (const void*)src, size); + } - template - T *CopyArray(T *dst, const T *src, size_t count) { - if (count == 0) return (T*)dst; - return (T*)memcpy((void*)dst, (const void*)src, count * sizeof(T)); - } + template + T * Duplicate(const T * src, size_t size) + { + T *result = Allocate(size); + return Copy(result, src, size); + } - template - T *Duplicate(const T *src, size_t size) { - T *result = Allocate(size); - return Copy(result, src, size); - } + template + T * Set(T * dst, uint8 value, size_t size) + { + return (T*)memset((void*)dst, (int)value, size); + } - template - T *DuplicateArray(const T *src, size_t count) { - T *result = AllocateArray(count); - return CopyArray(result, src, count); - } + template + T * CopyArray(T * dst, const T * src, size_t count) + { + // Use a loop so that copy constructors are called + // compiler should optimise to memcpy if possible + T * result = dst; + for (; count > 0; count--) + { + *dst++ = *src++; + } + return result; + } + + template + T * DuplicateArray(const T * src, size_t count) + { + T * result = AllocateArray(count); + return CopyArray(result, src, count); + } + + template + void FreeArray(T * ptr, size_t count) + { + for (size_t i = 0; i < count; i++) + { + ptr[i].~T(); + } + Free(ptr); + } } diff --git a/src/core/Path.cpp b/src/core/Path.cpp new file mode 100644 index 0000000000..514f53ddeb --- /dev/null +++ b/src/core/Path.cpp @@ -0,0 +1,100 @@ +extern "C" +{ + #include "../platform/platform.h" + #include "../localisation/localisation.h" + #include "../util/util.h" +} + +#include "Math.hpp" +#include "Memory.hpp" +#include "Path.hpp" +#include "String.hpp" +#include "Util.hpp" + +namespace Path +{ + utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src) + { + return safe_strcat_path(buffer, src, bufferSize); + } + + utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path) + { + const char pathSeperator = platform_get_path_separator(); + size_t lastPathSepIndex = String::LastIndexOf(path, pathSeperator); + if (lastPathSepIndex == SIZE_MAX) + { + return String::Set(buffer, bufferSize, String::Empty); + } + + size_t copyLength = Math::Min(lastPathSepIndex, bufferSize - 1); + Memory::Copy(buffer, path, copyLength); + buffer[copyLength] = '\0'; + return buffer; + } + + utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path) + { + const utf8 * lastDot = nullptr; + const utf8 * ch = path; + for (; *ch != '\0'; ch++) + { + if (*ch == '.') + { + lastDot = ch; + } + } + + if (lastDot == nullptr) + { + return String::Set(buffer, bufferSize, path); + } + + size_t truncatedLength = Math::Min(bufferSize - 1, lastDot - path); + Memory::Copy(buffer, path, truncatedLength); + buffer[truncatedLength] = '\0'; + return buffer; + } + + utf8 * GetAbsolute(utf8 *buffer, size_t bufferSize, const utf8 * relativePath) + { +#if __WINDOWS__ + wchar_t * relativePathW = utf8_to_widechar(relativePath); + wchar_t absolutePathW[MAX_PATH]; + DWORD length = GetFullPathNameW(relativePathW, Util::CountOf(absolutePathW), absolutePathW, NULL); + Memory::Free(relativePathW); + if (length == 0) + { + return String::Set(buffer, bufferSize, relativePath); + } + else + { + utf8 * absolutePath = widechar_to_utf8(absolutePathW); + String::Set(buffer, bufferSize, absolutePath); + Memory::Free(absolutePath); + return buffer; + } +#else + utf8 * absolutePath = realpath(relativePath, NULL); + if (absolutePath == nullptr) + { + return String::Set(buffer, bufferSize, relativePath); + } + else + { + String::Set(buffer, bufferSize, absolutePath); + Memory::Free(absolutePath); + return buffer; + } +#endif + } + + bool Equals(const utf8 * a, const utf8 * b) + { + bool ignoreCase = false; +#if __WINDOWS__ + ignoreCase = true; +#endif + return String::Equals(a, b, ignoreCase); + } +} diff --git a/src/core/Path.hpp b/src/core/Path.hpp new file mode 100644 index 0000000000..b3aa163f72 --- /dev/null +++ b/src/core/Path.hpp @@ -0,0 +1,15 @@ +#pragma once + +extern "C" +{ + #include "../common.h" +} + +namespace Path +{ + utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src); + utf8 * GetDirectory(utf8 * buffer, size_t bufferSize, const utf8 * path); + utf8 * GetFileNameWithoutExtension(utf8 * buffer, size_t bufferSize, const utf8 * path); + utf8 * GetAbsolute(utf8 * buffer, size_t bufferSize, const utf8 * relativePath); + bool Equals(const utf8 * a, const utf8 * b); +} diff --git a/src/core/Stopwatch.cpp b/src/core/Stopwatch.cpp new file mode 100644 index 0000000000..25a8b7d6f9 --- /dev/null +++ b/src/core/Stopwatch.cpp @@ -0,0 +1,134 @@ +#include + +#include "Stopwatch.hpp" + +uint64 Stopwatch::Frequency = 0; + +Stopwatch::Stopwatch() +{ + Reset(); +} + +uint64 Stopwatch::GetElapsedTicks() const +{ + uint64 result = _total; + if (_isRunning) + { + uint64 ticks = QueryCurrentTicks(); + if (ticks != 0) { + result += QueryCurrentTicks() - _last; + } + } + + return _total; +} + +uint64 Stopwatch::GetElapsedMilliseconds() const +{ + if (Frequency == 0) + { + Frequency = QueryFrequency(); + if (Frequency == 0) + { + return 0; + } + } + + return (GetElapsedTicks() * 1000) / Frequency; +} + +void Stopwatch::Reset() +{ + _isRunning = false; + _total = 0; + _last = 0; +} + +void Stopwatch::Start() +{ + if (_isRunning) return; + + uint64 ticks = QueryCurrentTicks(); + if (ticks != 0) + { + _last = ticks; + _isRunning = true; + } +} + +void Stopwatch::Restart() +{ + Reset(); + Start(); +} + +void Stopwatch::Stop() +{ + uint64 ticks = QueryCurrentTicks(); + if (ticks != 0) + { + _total += QueryCurrentTicks() - _last; + } + _isRunning = false; +} + +uint64 Stopwatch::QueryFrequency() +{ + return SDL_GetPerformanceFrequency(); +} + +uint64 Stopwatch::QueryCurrentTicks() +{ + return SDL_GetPerformanceCounter(); +} + +extern "C" +{ + #include "stopwatch.h" + + void stopwatch_create(stopwatch * stopwatch) + { + stopwatch->context = new Stopwatch(); + } + + void stopwatch_dispose(stopwatch * stopwatch) + { + delete ((Stopwatch*)stopwatch->context); + } + + uint64 stopwatch_GetElapsedTicks(stopwatch * stopwatch) + { + Stopwatch * ctx = (Stopwatch*)stopwatch->context; + return ctx->GetElapsedTicks(); + } + + uint64 stopwatch_GetElapsedMilliseconds(stopwatch * stopwatch) + { + Stopwatch * ctx = (Stopwatch*)stopwatch->context; + return ctx->GetElapsedMilliseconds(); + } + + void stopwatch_Reset(stopwatch * stopwatch) + { + Stopwatch * ctx = (Stopwatch*)stopwatch->context; + return ctx->Reset(); + } + + void stopwatch_Start(stopwatch * stopwatch) + { + Stopwatch * ctx = (Stopwatch*)stopwatch->context; + return ctx->Start(); + } + + void stopwatch_Restart(stopwatch * stopwatch) + { + Stopwatch * ctx = (Stopwatch*)stopwatch->context; + return ctx->Restart(); + } + + void stopwatch_Stop(stopwatch * stopwatch) + { + Stopwatch * ctx = (Stopwatch*)stopwatch->context; + return ctx->Stop(); + } +} diff --git a/src/core/Stopwatch.hpp b/src/core/Stopwatch.hpp new file mode 100644 index 0000000000..b08185c230 --- /dev/null +++ b/src/core/Stopwatch.hpp @@ -0,0 +1,36 @@ +#pragma once + +extern "C" +{ + #include "../common.h" +} + +/** + * Class to accuately measure elapsed time with high precision. + */ +class Stopwatch +{ +private: + /** Number of ticks in a second. */ + static uint64 Frequency; + + uint64 _total; + uint64 _last; + bool _isRunning; + + static uint64 QueryFrequency(); + static uint64 QueryCurrentTicks(); + +public: + bool IsRunning() const { return _isRunning; } + + Stopwatch(); + + uint64 GetElapsedTicks() const; + uint64 GetElapsedMilliseconds() const; + + void Reset(); + void Start(); + void Restart(); + void Stop(); +}; diff --git a/src/core/String.cpp b/src/core/String.cpp new file mode 100644 index 0000000000..d721bf2b24 --- /dev/null +++ b/src/core/String.cpp @@ -0,0 +1,205 @@ +extern "C" +{ + #include "../localisation/localisation.h" + #include "../util/util.h" +} + +#include "Math.hpp" +#include "Memory.hpp" +#include "String.hpp" + +namespace String +{ + bool IsNullOrEmpty(const utf8 * str) + { + return str == nullptr || str[0] == '\0'; + } + + bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase) + { + if (a == b) return true; + if (a == nullptr || b == nullptr) return false; + + if (ignoreCase) + { + return _stricmp(a, b) == 0; + } + else + { + return strcmp(a, b) == 0; + } + } + + bool StartsWith(const utf8 * str, const utf8 * match, bool ignoreCase) + { + if (ignoreCase) + { + while (*str != '\0' && *match != '\0') + { + if (tolower(*str++) != tolower(*match++)) + { + return false; + } + } + return true; + } + else + { + while (*str != '\0' && *match != '\0') + { + if (*str++ != *match++) + { + return false; + } + } + return true; + } + } + + size_t LastIndexOf(const utf8 * str, utf8 match) + { + const utf8 * lastOccurance = nullptr; + const utf8 * ch = str; + for (; *ch != '\0'; ch++) + { + if (*ch == match) + { + lastOccurance = ch; + } + } + + if (lastOccurance == nullptr) + { + return SIZE_MAX; + } + else + { + return (size_t)(lastOccurance - str); + } + } + + size_t LengthOf(const utf8 * str) + { + return utf8_length(str); + } + + size_t SizeOf(const utf8 * str) + { + return strlen(str); + } + + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src) + { + return safe_strcpy(buffer, src, bufferSize); + } + + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src, size_t srcSize) + { + utf8 * dst = buffer; + size_t minSize = Math::Min(bufferSize - 1, srcSize); + for (size_t i = 0; i < minSize; i++) + { + *dst++ = *src; + if (*src == '\0') break; + src++; + } + *dst = '\0'; + return buffer; + } + + utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src) + { + return safe_strcat(buffer, src, bufferSize); + } + + utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...) + { + va_list args; + + va_start(args, format); + vsnprintf(buffer, bufferSize, format, args); + va_end(args); + + // Terminate buffer in case formatted string overflowed + buffer[bufferSize - 1] = '\0'; + + return buffer; + } + + utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...) + { + va_list args; + + utf8 * dst = buffer; + size_t i; + for (i = 0; i < bufferSize; i++) + { + if (*dst == '\0') break; + dst++; + } + + if (i < bufferSize - 1) + { + va_start(args, format); + vsnprintf(buffer, bufferSize - i - 1, format, args); + va_end(args); + + // Terminate buffer in case formatted string overflowed + buffer[bufferSize - 1] = '\0'; + } + + return buffer; + } + + utf8 * Duplicate(const utf8 * src) + { + size_t srcSize = SizeOf(src); + return Memory::DuplicateArray(src, srcSize + 1); + } + + utf8 * DiscardUse(utf8 * * ptr, utf8 * replacement) + { + Memory::Free(*ptr); + *ptr = replacement; + return replacement; + } + + utf8 * DiscardDuplicate(utf8 * * ptr, const utf8 * replacement) + { + return DiscardUse(ptr, String::Duplicate(replacement)); + } + + utf8 * SkipBOM(utf8 * buffer) + { + return (utf8*)SkipBOM((const utf8 *)buffer); + } + + const utf8 * SkipBOM(const utf8 * buffer) + { + if ((unsigned char)buffer[0] == 0xEF && (unsigned char)buffer[1] == 0xBB && (unsigned char)buffer[2] == 0xBF) + { + return buffer + 3; + } + return buffer; + } + + size_t GetCodepointLength(codepoint_t codepoint) + { + return utf8_get_codepoint_length(codepoint); + } + + codepoint_t GetNextCodepoint(utf8 * ptr, utf8 * * nextPtr) + { + return GetNextCodepoint((const utf8 *)ptr, (const utf8 * *)nextPtr); + } + + codepoint_t GetNextCodepoint(const utf8 * ptr, const utf8 * * nextPtr) + { + return utf8_get_next(ptr, nextPtr); + } + + utf8 * WriteCodepoint(utf8 * dst, codepoint_t codepoint) + { + return utf8_write_codepoint(dst, codepoint); + } +} diff --git a/src/core/String.hpp b/src/core/String.hpp new file mode 100644 index 0000000000..8708176937 --- /dev/null +++ b/src/core/String.hpp @@ -0,0 +1,51 @@ +#pragma once + +extern "C" +{ + #include "../common.h" +} + +namespace String +{ + constexpr const utf8 * Empty = ""; + + bool IsNullOrEmpty(const utf8 * str); + bool Equals(const utf8 * a, const utf8 * b, bool ignoreCase = false); + bool StartsWith(const utf8 * str, const utf8 * match, bool ignoreCase = false); + size_t LastIndexOf(const utf8 * str, utf8 match); + + /** + * Gets the length of the given string in codepoints. + */ + size_t LengthOf(const utf8 * str); + + /** + * Gets the size of the given string in bytes excluding the null terminator. + */ + size_t SizeOf(const utf8 * str); + + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src); + utf8 * Set(utf8 * buffer, size_t bufferSize, const utf8 * src, size_t srcSize); + utf8 * Append(utf8 * buffer, size_t bufferSize, const utf8 * src); + utf8 * Format(utf8 * buffer, size_t bufferSize, const utf8 * format, ...); + utf8 * AppendFormat(utf8 * buffer, size_t bufferSize, const utf8 * format, ...); + utf8 * Duplicate(const utf8 * src); + + /** + * Helper method to free the string a string pointer points to and set it to a replacement string. + */ + utf8 * DiscardUse(utf8 * * ptr, utf8 * replacement); + + /** + * Helper method to free the string a string pointer points to and set it to a copy of a replacement string. + */ + utf8 * DiscardDuplicate(utf8 * * ptr, const utf8 * replacement); + + utf8 * SkipBOM(utf8 * buffer); + const utf8 * SkipBOM(const utf8 * buffer); + + size_t GetCodepointLength(codepoint_t codepoint); + codepoint_t GetNextCodepoint(utf8 * ptr, utf8 * * nextPtr = nullptr); + codepoint_t GetNextCodepoint(const utf8 * ptr, const utf8 * * nextPtr = nullptr); + utf8 * WriteCodepoint(utf8 * dst, codepoint_t codepoint); +} diff --git a/src/core/StringBuilder.hpp b/src/core/StringBuilder.hpp index b92f4001b0..b5828fcd51 100644 --- a/src/core/StringBuilder.hpp +++ b/src/core/StringBuilder.hpp @@ -1,135 +1,158 @@ #pragma once #include "../common.h" + #include "../localisation/localisation.h" #include "Math.hpp" #include "Memory.hpp" +#include "String.hpp" /** * Class for constructing strings efficiently. A buffer is automatically allocated and reallocated when characters or strings * are appended. Use GetString to copy the current state of the string builder to a new fire-and-forget string. */ -class StringBuilder final { +class StringBuilder final +{ public: - StringBuilder() { - _buffer = NULL; - _capacity = 0; - _length = 0; - } + StringBuilder() + { + _buffer = nullptr; + _capacity = 0; + _length = 0; + } - StringBuilder(int capacity) : StringBuilder() { - EnsureCapacity(capacity); - } + StringBuilder(size_t capacity) : StringBuilder() + { + EnsureCapacity(capacity); + } - ~StringBuilder() { - if (_buffer != NULL) Memory::Free(_buffer); - } + ~StringBuilder() + { + Memory::Free(_buffer); + } - /** - * Appends the given character to the current string. - */ - void Append(int codepoint) { - int codepointLength = utf8_get_codepoint_length(codepoint); - EnsureCapacity(_length + codepointLength + 1); - utf8_write_codepoint(_buffer + _length, codepoint); - _length += codepointLength; - _buffer[_length] = 0; - } + void Append(int codepoint) + { + Append((codepoint_t)codepoint); + } - /** - * Appends the given string to the current string. - */ - void Append(const utf8 *text) { - int textLength = strlen(text); - Append(text, textLength); - } + /** + * Appends the given character to the current string. + */ + void Append(codepoint_t codepoint) + { + codepoint_t codepointLength = String::GetCodepointLength(codepoint); + EnsureCapacity(_length + codepointLength + 1); + String::WriteCodepoint(_buffer + _length, codepoint); + _length += codepointLength; + _buffer[_length] = 0; + } - /** - * Appends the given string of the given length to the current string. Essentially used to ignore null terminators or copy - * the data faster as the length is already known. - * @param text Pointer to the UTF-8 text to append. - * @param textLength Number of bytes to copy. (Can be used to append single bytes rather than codepoints) - */ - void Append(const utf8 *text, int textLength) { - EnsureCapacity(_length + textLength + 1); - Memory::Copy(_buffer + _length, text, textLength); - _length += textLength; - _buffer[_length] = 0; - } + /** + * Appends the given string to the current string. + */ + void Append(const utf8 * text) + { + size_t textLength = String::SizeOf(text); + Append(text, textLength); + } - /** - * Appends the string of a given StringBuilder to the current string. - */ - void Append(const StringBuilder *sb) { - Append(sb->GetBuffer(), sb->GetLength()); - } + /** + * Appends the given string of the given length to the current string. Essentially used to ignore null terminators or copy + * the data faster as the length is already known. + * @param text Pointer to the UTF-8 text to append. + * @param textLength Number of bytes to copy. (Can be used to append single bytes rather than codepoints) + */ + void Append(const utf8 * text, size_t textLength) + { + EnsureCapacity(_length + textLength + 1); + Memory::Copy(_buffer + _length, text, textLength); + _length += textLength; + _buffer[_length] = 0; + } - /** - * Clears the current string, but preserves the allocated memory for another string. - */ - void Clear() { - _length = 0; - if (_capacity >= 1) { - _buffer[_length] = 0; - } - } + /** + * Appends the string of a given StringBuilder to the current string. + */ + void Append(const StringBuilder * sb) + { + Append(sb->GetBuffer(), sb->GetLength()); + } - /** - * Like Clear, only will guarantee freeing of the underlying buffer. - */ - void Reset() { - _length = 0; - _capacity = 0; - if (_buffer != NULL) { - Memory::Free(_buffer); - } - } + /** + * Clears the current string, but preserves the allocated memory for another string. + */ + void Clear() + { + _length = 0; + if (_capacity >= 1) + { + _buffer[_length] = 0; + } + } - /** - * Returns the current string buffer as a new fire-and-forget string. - */ - utf8 *GetString() const { - // If buffer is null, length should be 0 which will create a new one byte memory block containing a null terminator - utf8 *result = Memory::AllocateArray(_length + 1); - Memory::CopyArray(result, _buffer, _length); - result[_length] = 0; - return result; - } + /** + * Like Clear, only will guarantee freeing of the underlying buffer. + */ + void Reset() + { + _length = 0; + _capacity = 0; + if (_buffer != nullptr) + { + Memory::Free(_buffer); + _buffer = nullptr; + } + } - /** - * Gets the current state of the StringBuilder. Warning: this represents the StringBuilder's current working buffer and will - * be deallocated when the StringBuilder is destructed. - */ - const utf8 *GetBuffer() const { - // buffer may be null, so return an immutable empty string - if (_buffer == NULL) return ""; - return _buffer; - } + /** + * Returns the current string buffer as a new fire-and-forget string. + */ + utf8 * GetString() const + { + // If buffer is null, length should be 0 which will create a new one byte memory block containing a null terminator + utf8 * result = Memory::AllocateArray(_length + 1); + Memory::CopyArray(result, _buffer, _length); + result[_length] = 0; + return result; + } - /** - * Gets the amount of allocated memory for the string buffer. - */ - size_t GetCapacity() const { return _capacity; } + /** + * Gets the current state of the StringBuilder. Warning: this represents the StringBuilder's current working buffer and will + * be deallocated when the StringBuilder is destructed. + */ + const utf8 * GetBuffer() const + { + // buffer may be null, so return an immutable empty string + if (_buffer == nullptr) return ""; + return _buffer; + } - /** - * Gets the length of the current string. - */ - size_t GetLength() const { return _length; } + /** + * Gets the amount of allocated memory for the string buffer. + */ + size_t GetCapacity() const { return _capacity; } + + /** + * Gets the length of the current string. + */ + size_t GetLength() const { return _length; } private: - utf8 *_buffer; - size_t _capacity; - size_t _length; + utf8 * _buffer; + size_t _capacity; + size_t _length; - void EnsureCapacity(size_t capacity) - { - if (_capacity > capacity) return; + void EnsureCapacity(size_t capacity) + { + if (_capacity > capacity) return; - _capacity = Math::Max((size_t)8, _capacity); - while (_capacity < capacity) { - _capacity *= 2; - } + _capacity = Math::Max((size_t)8, _capacity); + while (_capacity < capacity) + { + _capacity *= 2; + } - _buffer = Memory::ReallocateArray(_buffer, _capacity); - } + _buffer = Memory::ReallocateArray(_buffer, _capacity); + } }; diff --git a/src/core/StringReader.hpp b/src/core/StringReader.hpp index 196470cc87..b2abd5926f 100644 --- a/src/core/StringReader.hpp +++ b/src/core/StringReader.hpp @@ -3,56 +3,62 @@ #include "../common.h" #include "../localisation/localisation.h" #include "../util/util.h" +#include "String.hpp" -interface IStringReader { - virtual bool TryPeek(int *outCodepoint) abstract; - virtual bool TryRead(int *outCodepoint) abstract; - virtual void Skip() abstract; - virtual bool CanRead() const abstract; +interface IStringReader +{ + virtual bool TryPeek(codepoint_t * outCodepoint) abstract; + virtual bool TryRead(codepoint_t * outCodepoint) abstract; + virtual void Skip() abstract; + virtual bool CanRead() const abstract; }; -class UTF8StringReader final : public IStringReader { +class UTF8StringReader final : public IStringReader +{ public: - UTF8StringReader(const utf8 *text) { - // Skip UTF-8 byte order mark - if (strlen(text) >= 3 && utf8_is_bom(text)) { - text += 3; - } + UTF8StringReader(const utf8 * text) + { + text = String::SkipBOM(text); - _text = text; - _current = text; - } + _text = text; + _current = text; + } - bool TryPeek(int *outCodepoint) override { - if (_current == NULL) return false; + bool TryPeek(codepoint_t * outCodepoint) override + { + if (_current == nullptr) return false; - int codepoint = utf8_get_next(_current, NULL); - *outCodepoint = codepoint; - return true; - } + codepoint_t codepoint = String::GetNextCodepoint(_current); + *outCodepoint = codepoint; + return true; + } - bool TryRead(int *outCodepoint) override { - if (_current == NULL) return false; + bool TryRead(codepoint_t * outCodepoint) override + { + if (_current == nullptr) return false; - int codepoint = utf8_get_next(_current, &_current); - *outCodepoint = codepoint; - if (codepoint == 0) { - _current = NULL; - return false; - } - return true; - } + codepoint_t codepoint = String::GetNextCodepoint(_current, &_current); + *outCodepoint = codepoint; + if (codepoint == 0) + { + _current = nullptr; + return false; + } + return true; + } - void Skip() override { - int codepoint; - TryRead(&codepoint); - } + void Skip() override + { + codepoint_t codepoint; + TryRead(&codepoint); + } - bool CanRead() const override { - return _current != NULL; - } + bool CanRead() const override + { + return _current != nullptr; + } private: - const utf8 *_text; - const utf8 *_current; + const utf8 *_text; + const utf8 *_current; }; diff --git a/src/core/Util.hpp b/src/core/Util.hpp new file mode 100644 index 0000000000..4a8df1ce1c --- /dev/null +++ b/src/core/Util.hpp @@ -0,0 +1,20 @@ +#ifndef _UTIL_HPP_ +#define _UTIL_HPP_ + +#include + +/** + * Common utility functions. + */ +namespace Util { + +// Based on http://www.g-truc.net/post-0708.html +template +constexpr size_t CountOf(T const (&)[N]) noexcept +{ + return N; +} + +} // namespace Util + +#endif // _UTIL_HPP_ diff --git a/src/core/stopwatch.h b/src/core/stopwatch.h new file mode 100644 index 0000000000..c36dd33b6a --- /dev/null +++ b/src/core/stopwatch.h @@ -0,0 +1,24 @@ +#ifndef _STOPWATCH_H_ +#define _STOPWATCH_H_ + +#include "../common.h" + +///////////////////////////// +// C wrapper for Stopwatch // +///////////////////////////// + +typedef struct { + void *context; +} stopwatch; + +void stopwatch_create(stopwatch *stopwatch); +void stopwatch_dispose(stopwatch *stopwatch); + +uint64 stopwatch_GetElapsedTicks(stopwatch *stopwatch); +uint64 stopwatch_GetElapsedMilliseconds(stopwatch *stopwatch); +void stopwatch_Reset(stopwatch *stopwatch); +void stopwatch_Start(stopwatch *stopwatch); +void stopwatch_Restart(stopwatch *stopwatch); +void stopwatch_Stop(stopwatch *stopwatch); + +#endif diff --git a/src/core/textinputbuffer.c b/src/core/textinputbuffer.c new file mode 100644 index 0000000000..5ddaaf051f --- /dev/null +++ b/src/core/textinputbuffer.c @@ -0,0 +1,114 @@ +#include "../localisation/localisation.h" +#include "textinputbuffer.h" + +void textinputbuffer_init(textinputbuffer * tib, utf8 * buffer, size_t size) +{ + assert(buffer != NULL); + assert(size > 0); + + tib->buffer = buffer; + tib->max_size = size - 1; + tib->current_size = strlen(buffer); + tib->selection_offset = tib->current_size; + tib->selection_size = 0; + + textinputbuffer_recalculate_length(tib); +} + +void textinputbuffer_clear(textinputbuffer * tib) +{ + tib->buffer[0] = 0; + tib->current_size = 0; + tib->length = 0; + tib->selection_offset = 0; + tib->selection_size = 0; +} + +void textinputbuffer_remove_selected(textinputbuffer * tib) +{ + utf8 * targetShiftPtr = tib->buffer + tib->selection_offset; + utf8 * sourceShiftPtr = targetShiftPtr + tib->selection_size; + size_t shiftSize = tib->current_size - tib->selection_offset - tib->selection_size + 1; + memmove(targetShiftPtr, sourceShiftPtr, shiftSize); + tib->selection_size = 0; + textinputbuffer_recalculate_length(tib); +} + +void textinputbuffer_insert_codepoint(textinputbuffer * tib, uint32 codepoint) +{ + size_t codepointLength = utf8_get_codepoint_length(codepoint); + size_t remainingSize = tib->max_size - tib->current_size; + if (codepointLength <= remainingSize) { + utf8 * insertPtr = tib->buffer + tib->selection_offset; + + if (tib->selection_offset < tib->current_size) { + // Shift bytes (including null terminator) right to make room for new codepoint + utf8 * targetShiftPtr = insertPtr + codepointLength; + size_t shiftSize = tib->current_size - tib->selection_offset + 1; + memmove(targetShiftPtr, insertPtr, shiftSize); + } else { + // Character is appended onto the end, so set byte after it to null terminator + tib->buffer[tib->current_size + codepointLength] = 0; + } + + utf8_write_codepoint(insertPtr, codepoint); + tib->selection_offset += codepointLength; + tib->current_size += codepointLength; + tib->length++; + } +} + +void textinputbuffer_insert(textinputbuffer * tib, utf8 * source) +{ + const utf8 *ch = source; + uint32 codepoint; + while ((codepoint = utf8_get_next(ch, &ch)) != 0) { + textinputbuffer_insert_codepoint(tib, codepoint); + } +} + +void textinputbuffer_cursor_left(textinputbuffer * tib) +{ + size_t selectionOffset = tib->selection_offset; + if (selectionOffset > 0) { + const utf8 * ch = tib->buffer + selectionOffset; + do { + ch--; + selectionOffset--; + } while (!utf8_is_codepoint_start(ch) && selectionOffset > 0); + + tib->selection_offset = selectionOffset; + } +} + +void textinputbuffer_cursor_right(textinputbuffer * tib) +{ + size_t selectionOffset = tib->selection_offset; + size_t selectionMaxOffset = tib->current_size; + if (selectionOffset < selectionMaxOffset) { + const utf8 * ch = tib->buffer + selectionOffset; + do { + ch++; + selectionOffset++; + } while (!utf8_is_codepoint_start(ch) && selectionOffset < selectionMaxOffset); + + tib->selection_size = max(0, tib->selection_size - (selectionOffset - tib->selection_offset)); + tib->selection_offset = selectionOffset; + } +} + +void textinputbuffer_cursor_home(textinputbuffer * tib) +{ + tib->selection_offset = 0; +} + +void textinputbuffer_cursor_end(textinputbuffer * tib) +{ + tib->selection_offset = tib->current_size; +} + +void textinputbuffer_recalculate_length(textinputbuffer * tib) +{ + tib->current_size = strlen(tib->buffer); + tib->length = utf8_length(tib->buffer); +} diff --git a/src/core/textinputbuffer.h b/src/core/textinputbuffer.h new file mode 100644 index 0000000000..582e8f8933 --- /dev/null +++ b/src/core/textinputbuffer.h @@ -0,0 +1,28 @@ +#ifndef _TEXTINPUTBUFFER_H_ +#define _TEXTINPUTBUFFER_H_ + +#include "../common.h" + +typedef struct { + utf8 * buffer; + size_t max_size; // Maximum number of bytes (excluding null terminator) + size_t current_size; // Number of bytes (excluding null terminator) + + uint32 length; // Number of codepoints + + size_t selection_offset; // Selection start, in bytes + size_t selection_size; // Selection length in bytes +} textinputbuffer; + +void textinputbuffer_init(textinputbuffer * tib, utf8 * buffer, size_t size); +void textinputbuffer_clear(textinputbuffer * tib); +void textinputbuffer_remove_selected(textinputbuffer * tib); +void textinputbuffer_insert_codepoint(textinputbuffer * tib, uint32 codepoint); +void textinputbuffer_insert(textinputbuffer * tib, utf8 * source); +void textinputbuffer_cursor_left(textinputbuffer * tib); +void textinputbuffer_cursor_right(textinputbuffer * tib); +void textinputbuffer_cursor_home(textinputbuffer * tib); +void textinputbuffer_cursor_end(textinputbuffer * tib); +void textinputbuffer_recalculate_length(textinputbuffer * tib); + +#endif diff --git a/src/cursors.c b/src/cursors.c index 720f40833a..a19b7a21cf 100644 --- a/src/cursors.c +++ b/src/cursors.c @@ -530,4 +530,4 @@ unsigned char hand_closed_cursor_mask[32 * 4] = { 0x07, 0x1F, 0xFF, 0xF0, 0x0F, 0x9F, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xE0, -}; \ No newline at end of file +}; diff --git a/src/cursors.h b/src/cursors.h index b3714cfaa1..8ea87a23e9 100644 --- a/src/cursors.h +++ b/src/cursors.h @@ -182,4 +182,4 @@ extern unsigned char hand_closed_cursor_mask[32 * 4]; #define HAND_CLOSED_CURSOR_HOTX 5 #define HAND_CLOSED_CURSOR_HOTY 1 -#endif \ No newline at end of file +#endif diff --git a/src/diagnostic.h b/src/diagnostic.h index 00c03bd154..3d95520adf 100644 --- a/src/diagnostic.h +++ b/src/diagnostic.h @@ -30,7 +30,7 @@ enum { DIAGNOSTIC_LEVEL_COUNT }; -/* +/** * Compile-time debug levels. * * When compiling, just add -DDEBUG={0,1,2,3} (where 0 means disabled) @@ -75,9 +75,17 @@ enum { extern int _log_levels[DIAGNOSTIC_LEVEL_COUNT]; +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + void diagnostic_log(int diagnosticLevel, const char *format, ...); void diagnostic_log_with_location(int diagnosticLevel, const char *file, const char *function, int line, const char *format, ...); +#ifdef __cplusplus +} +#endif // __cplusplus + #ifdef _MSC_VER #define diagnostic_log_macro(level, format, ...) diagnostic_log_with_location(level, __FILE__, __FUNCTION__, __LINE__, format, __VA_ARGS__) diff --git a/src/drawing/drawing.c b/src/drawing/drawing.c index 51ddca2b61..3c98306f68 100644 --- a/src/drawing/drawing.c +++ b/src/drawing/drawing.c @@ -63,7 +63,7 @@ uint8 text_palette[0x8] = { }; // Previously 0x97FCBC use it to get the correct palette from g1_elements -const uint16 palette_to_g1_offset[] = { +const uint16 palette_to_g1_offset[PALETTE_TO_G1_OFFSET_COUNT] = { 0x1333, 0x1334, 0x1335, 0x1336, 0x1337, 0x1338, 0x1339, 0x133A, 0x133B, 0x133C, 0x133D, 0x133E, @@ -152,7 +152,10 @@ void gfx_transpose_palette(int pal, unsigned char product) platform_update_palette((uint8*)RCT2_ADDRESS_PALETTE, 10, 236); } -/* rct2: 0x006837E3 */ +/** + * + * rct2: 0x006837E3 + */ void load_palette(){ rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0]; @@ -234,9 +237,13 @@ void gfx_set_dirty_blocks(sint16 left, sint16 top, sint16 right, sint16 bottom) top >>= RCT2_GLOBAL(0x009ABDF1, sint8); bottom >>= RCT2_GLOBAL(0x009ABDF1, sint8); - for (y = top; y <= bottom; y++) - for (x = left; x <= right; x++) - screenDirtyBlocks[y * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32) + x] = 0xFF; + uint32 dirtyBlockColumns = RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32); + for (y = top; y <= bottom; y++) { + uint32 yOffset = y * dirtyBlockColumns; + for (x = left; x <= right; x++) { + screenDirtyBlocks[yOffset + x] = 0xFF; + } + } } /** @@ -245,25 +252,35 @@ void gfx_set_dirty_blocks(sint16 left, sint16 top, sint16 right, sint16 bottom) */ void gfx_draw_all_dirty_blocks() { - unsigned int x, y, xx, yy, columns, rows; + uint32 x, y, xx, yy, columns, rows; + uint32 dirtyBlockColumns = RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32); + uint32 dirtyBlockRows = RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_ROWS, uint32); uint8 *screenDirtyBlocks = gfx_get_dirty_blocks(); - for (x = 0; x < RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32); x++) { - for (y = 0; y < RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_ROWS, uint32); y++) { - if (screenDirtyBlocks[y * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32) + x] == 0) + for (x = 0; x < dirtyBlockColumns; x++) { + for (y = 0; y < dirtyBlockRows; y++) { + uint32 yOffset = y * dirtyBlockColumns; + if (screenDirtyBlocks[yOffset + x] == 0) { continue; + } // Determine columns - for (xx = x; xx < RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32); xx++) - if (screenDirtyBlocks[y * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32) + xx] == 0) + for (xx = x; xx < dirtyBlockColumns; xx++) { + if (screenDirtyBlocks[yOffset + xx] == 0) { break; + } + } columns = xx - x; // Check rows - for (yy = y; yy < RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_ROWS, uint32); yy++) - for (xx = x; xx < x + columns; xx++) - if (screenDirtyBlocks[yy * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32) + xx] == 0) + for (yy = y; yy < dirtyBlockRows; yy++) { + uint32 yyOffset = yy * dirtyBlockColumns; + for (xx = x; xx < x + columns; xx++) { + if (screenDirtyBlocks[yyOffset + xx] == 0) { goto endRowCheck; + } + } + } endRowCheck: rows = yy - y; @@ -274,21 +291,26 @@ void gfx_draw_all_dirty_blocks() static void gfx_draw_dirty_blocks(int x, int y, int columns, int rows) { - int left, top, right, bottom; + uint32 left, top, right, bottom; + uint32 dirtyBlockColumns = RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32); uint8 *screenDirtyBlocks = gfx_get_dirty_blocks(); // Unset dirty blocks - for (top = y; top < y + rows; top++) - for (left = x; left < x + columns; left++) - screenDirtyBlocks[top * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32) + left] = 0; + for (top = y; top < y + (uint32)rows; top++) { + uint32 topOffset = top * dirtyBlockColumns; + for (left = x; left < x + (uint32)columns; left++) { + screenDirtyBlocks[topOffset + left] = 0; + } + } // Determine region in pixels left = max(0, x * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_WIDTH, uint16)); top = max(0, y * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_HEIGHT, uint16)); right = min(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16), left + (columns * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_WIDTH, uint16))); bottom = min(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16), top + (rows * RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_HEIGHT, uint16))); - if (right <= left || bottom <= top) + if (right <= left || bottom <= top) { return; + } // Draw region gfx_redraw_screen_rect(left, top, right, bottom); @@ -335,57 +357,53 @@ void gfx_redraw_screen_rect(short left, short top, short right, short bottom) * height (dx) * drawpixelinfo (edi) */ -rct_drawpixelinfo* clip_drawpixelinfo(rct_drawpixelinfo* dpi, int left, int width, int top, int height) +bool clip_drawpixelinfo(rct_drawpixelinfo *dst, rct_drawpixelinfo *src, int x, int y, int width, int height) { - rct_drawpixelinfo* newDrawPixelInfo = rct2_malloc(sizeof(rct_drawpixelinfo)); + int right = x + width; + int bottom = y + height; - int right = left + width; - int bottom = top + height; + dst->bits = src->bits; + dst->x = src->x; + dst->y = src->y; + dst->width = src->width; + dst->height = src->height; + dst->pitch = src->pitch; + dst->zoom_level = 0; - newDrawPixelInfo->bits = dpi->bits; - newDrawPixelInfo->x = dpi->x; - newDrawPixelInfo->y = dpi->y; - newDrawPixelInfo->width = dpi->width; - newDrawPixelInfo->height = dpi->height; - newDrawPixelInfo->pitch = dpi->pitch; - newDrawPixelInfo->zoom_level = 0; - - if (left > newDrawPixelInfo->x) { - uint16 clippedFromLeft = left - newDrawPixelInfo->x; - newDrawPixelInfo->width -= clippedFromLeft; - newDrawPixelInfo->x = left; - newDrawPixelInfo->pitch += clippedFromLeft; - newDrawPixelInfo->bits += clippedFromLeft; + if (x > dst->x) { + uint16 clippedFromLeft = x - dst->x; + dst->width -= clippedFromLeft; + dst->x = x; + dst->pitch += clippedFromLeft; + dst->bits += clippedFromLeft; } - int stickOutWidth = newDrawPixelInfo->x + newDrawPixelInfo->width - right; + int stickOutWidth = dst->x + dst->width - right; if (stickOutWidth > 0) { - newDrawPixelInfo->width -= stickOutWidth; - newDrawPixelInfo->pitch += stickOutWidth; + dst->width -= stickOutWidth; + dst->pitch += stickOutWidth; } - if (top > newDrawPixelInfo->y) { - uint16 clippedFromTop = top - newDrawPixelInfo->y; - newDrawPixelInfo->height -= clippedFromTop; - newDrawPixelInfo->y = top; - uint32 bitsPlus = (newDrawPixelInfo->pitch + newDrawPixelInfo->width) * clippedFromTop; - newDrawPixelInfo->bits += bitsPlus; + if (y > dst->y) { + uint16 clippedFromTop = y - dst->y; + dst->height -= clippedFromTop; + dst->y = y; + uint32 bitsPlus = (dst->pitch + dst->width) * clippedFromTop; + dst->bits += bitsPlus; } - int bp = newDrawPixelInfo->y + newDrawPixelInfo->height - bottom; + int bp = dst->y + dst->height - bottom; if (bp > 0) { - newDrawPixelInfo->height -= bp; + dst->height -= bp; } - if (newDrawPixelInfo->width > 0 && newDrawPixelInfo->height > 0) { - newDrawPixelInfo->x -= left; - newDrawPixelInfo->y -= top; - - return newDrawPixelInfo; + if (dst->width > 0 && dst->height > 0) { + dst->x -= x; + dst->y -= y; + return true; } - rct2_free(newDrawPixelInfo); - return NULL; + return false; } /*** @@ -482,7 +500,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; @@ -503,10 +521,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 ); @@ -519,7 +537,7 @@ void gfx_draw_pickedup_peep() * * rct2: 0x00681DE2 */ -void gfx_draw_sprite_raw_masked(rct_drawpixelinfo *dpi, int x, int y, int maskImage, int colourImage) +void FASTCALL gfx_draw_sprite_raw_masked(rct_drawpixelinfo *dpi, int x, int y, int maskImage, int colourImage) { int left, top, right, bottom, width, height; rct_g1_element *imgMask = &g1Elements[maskImage & 0x7FFFF]; diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index 69d8c85c3a..d0cf9e729e 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -69,6 +69,20 @@ typedef struct { void *data; } rct_gx; +typedef struct { + uint8 blue; + uint8 green; + uint8 red; + uint8 alpha; +} rct_palette_entry; + +typedef struct { + rct_palette_entry entries[256]; +} rct_palette; + +#define SPRITE_ID_PALETTE_COLOUR_1(colourId) ((IMAGE_TYPE_USE_PALETTE << 28) | ((colourId) << 19)) + +#define PALETTE_TO_G1_OFFSET_COUNT 144 extern const uint16 palette_to_g1_offset[]; extern const uint8 peep_palette[]; extern uint8 text_palette[]; @@ -80,7 +94,7 @@ extern rct_g1_element *g1Elements; extern rct_gx g2; // -rct_drawpixelinfo* clip_drawpixelinfo(rct_drawpixelinfo* dpi, int left, int width, int top, int height); +bool clip_drawpixelinfo(rct_drawpixelinfo *dst, rct_drawpixelinfo *src, int x, int y, int width, int height); void gfx_set_dirty_blocks(sint16 left, sint16 top, sint16 right, sint16 bottom); void gfx_draw_all_dirty_blocks(); void gfx_redraw_screen_rect(short left, short top, short right, short bottom); @@ -107,12 +121,14 @@ void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, short left, short top, short ri // sprite int gfx_load_g1(); int gfx_load_g2(); +void gfx_unload_g1(); +void gfx_unload_g2(); void sub_68371D(); -void gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, uint8* source_pointer, uint8* dest_pointer, rct_g1_element* source_image, rct_drawpixelinfo *dest_dpi, int height, int width, int image_type); -void gfx_rle_sprite_to_buffer(const uint8* source_bits_pointer, uint8* dest_bits_pointer, const uint8* palette_pointer, const rct_drawpixelinfo *dpi, int image_type, int source_y_start, int height, int source_x_start, int width); -void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); -void gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer); -void gfx_draw_sprite_raw_masked(rct_drawpixelinfo *dpi, int x, int y, int maskImage, int colourImage); +void FASTCALL gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, uint8* source_pointer, uint8* dest_pointer, rct_g1_element* source_image, rct_drawpixelinfo *dest_dpi, int height, int width, int image_type); +void FASTCALL gfx_rle_sprite_to_buffer(const uint8* source_bits_pointer, uint8* dest_bits_pointer, const uint8* palette_pointer, const rct_drawpixelinfo *dpi, int image_type, int source_y_start, int height, int source_x_start, int width); +void FASTCALL gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour); +void FASTCALL gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer); +void FASTCALL gfx_draw_sprite_raw_masked(rct_drawpixelinfo *dpi, int x, int y, int maskImage, int colourImage); // string int clip_text(char *buffer, int width); @@ -136,6 +152,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(); diff --git a/src/drawing/drawing_fast.cpp b/src/drawing/drawing_fast.cpp new file mode 100644 index 0000000000..8490099e48 --- /dev/null +++ b/src/drawing/drawing_fast.cpp @@ -0,0 +1,188 @@ +extern "C" +{ + #include "drawing.h" +} + +// This will have -1 (0xffffffff) for (val <= 0), 0 otherwise, so it can act as a mask +// This is expected to generate +// sar eax, 0x1f (arithmetic shift right by 31) +#define less_or_equal_zero_mask(val) (((val - 1) >> (sizeof(val) * 8 - 1))) + +template +static void FASTCALL DrawRLESprite2(const uint8* source_bits_pointer, + uint8* dest_bits_pointer, + const uint8* palette_pointer, + const rct_drawpixelinfo *dpi, + int source_y_start, + int height, + int source_x_start, + int width) +{ + int zoom_amount = 1 << zoom_level; + int zoom_mask = 0xFFFFFFFF << zoom_level; + uint8* next_dest_pointer = dest_bits_pointer; + + int line_width = (dpi->width >> zoom_level) + dpi->pitch; + + const int source_y_start_mask = less_or_equal_zero_mask(source_y_start + 1); + source_y_start += zoom_amount & source_y_start_mask; + next_dest_pointer += line_width & source_y_start_mask; + height -= zoom_amount & source_y_start_mask; + + //For every line in the image + for (int i = 0; i < height; i += zoom_amount) { + int y = source_y_start + i; + uint8 i2 = i >> zoom_level; + + //The first part of the source pointer is a list of offsets to different lines + //This will move the pointer to the correct source line. + const uint8 *next_source_pointer = source_bits_pointer + ((uint16*)source_bits_pointer)[y]; + uint8* loop_dest_pointer = next_dest_pointer + line_width * i2; + + uint8 last_data_line = 0; + + //For every data section in the line + while (!last_data_line) { + const uint8* source_pointer = next_source_pointer; + uint8* dest_pointer = loop_dest_pointer; + + int no_pixels = *source_pointer++; + //gap_size is the number of non drawn pixels you require to + //jump over on your destination + uint8 gap_size = *source_pointer++; + //The last bit in no_pixels tells you if you have reached the end of a line + last_data_line = no_pixels & 0x80; + //Clear the last data line bit so we have just the no_pixels + no_pixels &= 0x7f; + //Have our next source pointer point to the next data section + next_source_pointer = source_pointer + no_pixels; + + //Calculates the start point of the image + int x_start = gap_size - source_x_start; + const int x_diff = x_start & ~zoom_mask; + const int x_mask = ~less_or_equal_zero_mask(x_diff); + + no_pixels -= x_diff; + x_start += ~zoom_mask & x_mask; + source_pointer += (x_start&~zoom_mask) & x_mask; + + // This will have -1 (0xffffffff) for (x_start <= 0), 0 otherwise + int sign = less_or_equal_zero_mask(x_start); + + dest_pointer += (x_start >> zoom_level) & ~sign; + + //If the start is negative we require to remove part of the image. + //This is done by moving the image pointer to the correct position. + source_pointer -= x_start & sign; + //The no_pixels will be reduced in this operation + no_pixels += x_start & sign; + //Reset the start position to zero as we have taken into account all moves + x_start &= ~sign; + + int x_end = x_start + no_pixels; + //If the end position is further out than the whole image + //end position then we need to shorten the line again + const int pixels_till_end = x_end - width; + //Shorten the line + no_pixels -= pixels_till_end & ~(less_or_equal_zero_mask(pixels_till_end)); + + //Finally after all those checks, copy the image onto the drawing surface + //If the image type is not a basic one we require to mix the pixels + if (image_type & IMAGE_TYPE_USE_PALETTE) {//In the .exe these are all unraveled loops + for (; no_pixels > 0; no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++) { + uint8 al = *source_pointer; + uint8 ah = *dest_pointer; + if (image_type & IMAGE_TYPE_MIX_BACKGROUND) + al = palette_pointer[(((uint16)al << 8) | ah) - 0x100]; + else + al = palette_pointer[al]; + *dest_pointer = al; + } + } else if (image_type & IMAGE_TYPE_MIX_BACKGROUND) {//In the .exe these are all unraveled loops + //Doesnt use source pointer ??? mix with background only? + //Not Tested + + for (; no_pixels > 0; no_pixels -= zoom_amount, dest_pointer++) { + uint8 pixel = *dest_pointer; + pixel = palette_pointer[pixel]; + *dest_pointer = pixel; + } + } else + { + if (zoom_amount == 1) { + no_pixels &= ~less_or_equal_zero_mask(no_pixels); + memcpy(dest_pointer, source_pointer, no_pixels); + } else { + for (; no_pixels > 0; no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++) { + *dest_pointer = *source_pointer; + } + } + } + } + } +} + +#define DrawRLESpriteHelper2(image_type, zoom_level) \ + DrawRLESprite2(source_bits_pointer, dest_bits_pointer, palette_pointer, dpi, source_y_start, height, source_x_start, width) + +template +static void FASTCALL DrawRLESprite1(const uint8* source_bits_pointer, + uint8* dest_bits_pointer, + const uint8* palette_pointer, + const rct_drawpixelinfo *dpi, + int source_y_start, + int height, + int source_x_start, + int width) +{ + int zoom_level = dpi->zoom_level; + switch (zoom_level) { + case 0: DrawRLESpriteHelper2(image_type, 0); break; + case 1: DrawRLESpriteHelper2(image_type, 1); break; + case 2: DrawRLESpriteHelper2(image_type, 2); break; + case 3: DrawRLESpriteHelper2(image_type, 3); break; + default: assert(false); break; + } +} + +#define DrawRLESpriteHelper1(image_type) \ + DrawRLESprite1(source_bits_pointer, dest_bits_pointer, palette_pointer, dpi, source_y_start, height, source_x_start, width) + +extern "C" +{ + /** + * Transfers readied images onto buffers + * This function copies the sprite data onto the screen + * rct2: 0x0067AA18 + */ + void FASTCALL gfx_rle_sprite_to_buffer(const uint8* source_bits_pointer, + uint8* dest_bits_pointer, + const uint8* palette_pointer, + const rct_drawpixelinfo *dpi, + int image_type, + int source_y_start, + int height, + int source_x_start, + int width) + { + if (image_type & IMAGE_TYPE_USE_PALETTE) + { + if (image_type & IMAGE_TYPE_MIX_BACKGROUND) + { + DrawRLESpriteHelper1(IMAGE_TYPE_USE_PALETTE | IMAGE_TYPE_MIX_BACKGROUND); + } + else + { + DrawRLESpriteHelper1(IMAGE_TYPE_USE_PALETTE); + } + } + else if (image_type & IMAGE_TYPE_MIX_BACKGROUND) + { + DrawRLESpriteHelper1(IMAGE_TYPE_MIX_BACKGROUND); + } + else + { + DrawRLESpriteHelper1(0); + } + } +} diff --git a/src/drawing/font.h b/src/drawing/font.h index de7abc298b..e680bb4322 100644 --- a/src/drawing/font.h +++ b/src/drawing/font.h @@ -23,6 +23,7 @@ enum { typedef struct { const utf8 *filename; + const utf8 *font_name; int ptSize; int offset_x; int offset_y; diff --git a/src/drawing/line.c b/src/drawing/line.c index c4697f7dea..fca92c9ab7 100644 --- a/src/drawing/line.c +++ b/src/drawing/line.c @@ -20,7 +20,7 @@ #include "drawing.h" -/* +/** * Draws a horizontal line of specified colour to a buffer. * rct2: 0x0068474C */ diff --git a/src/drawing/rain.c b/src/drawing/rain.c index 7aaed208a8..89e5db3e1c 100644 --- a/src/drawing/rain.c +++ b/src/drawing/rain.c @@ -226,4 +226,4 @@ static void draw_heavy_rain(int left, int top, int width, int height) y_start += top; gfx_draw_rain(left, top, width, height, x_start, y_start); -} \ No newline at end of file +} diff --git a/src/drawing/rect.c b/src/drawing/rect.c index ab68699560..5c3c5deb7d 100644 --- a/src/drawing/rect.c +++ b/src/drawing/rect.c @@ -227,7 +227,7 @@ void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bot } /** - * Draw a rectangle, with optional border or fill + * Draw a rectangle, with optional border or fill * * rct2: 0x006E6F81 * dpi (edi) diff --git a/src/drawing/scrolling_text.c b/src/drawing/scrolling_text.c index 72a7293d7f..65dfe1974e 100644 --- a/src/drawing/scrolling_text.c +++ b/src/drawing/scrolling_text.c @@ -76,7 +76,7 @@ static int scrolling_text_get_matching_or_oldest(rct_string_id stringId, uint16 if ( scrollText->string_id == stringId && scrollText->string_args_0 == RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) && - scrollText->string_args_1 == RCT2_GLOBAL(0x13CE956, uint32) && + scrollText->string_args_1 == RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) && scrollText->position == scroll && scrollText->mode == scrollingMode ) { @@ -152,7 +152,7 @@ int scrolling_text_setup(rct_string_id stringId, uint16 scroll, uint16 scrolling void scrolling_text_set_bitmap_for_sprite(utf8 *text, int scroll, uint8 *bitmap, sint16 *scrollPositionOffsets) { - uint8 characterColour = scrolling_text_get_colour(RCT2_GLOBAL(0x013CE959, uint8)); + uint8 characterColour = scrolling_text_get_colour(RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 7, uint8)); utf8 *ch = text; while (true) { @@ -228,7 +228,7 @@ void scrolling_text_set_bitmap_for_ttf(utf8 *text, int scroll, uint8 *bitmap, si *dstCh = 0; if (colour == 0) { - colour = scrolling_text_get_colour(RCT2_GLOBAL(0x013CE959, uint8)); + colour = scrolling_text_get_colour(RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 7, uint8)); } else { colour = RCT2_GLOBAL(0x009FF048, uint8*)[(colour - FORMAT_COLOUR_CODE_START) * 4]; } diff --git a/src/drawing/sprite.c b/src/drawing/sprite.c index aaa09f1cd2..177f909535 100644 --- a/src/drawing/sprite.c +++ b/src/drawing/sprite.c @@ -54,7 +54,7 @@ int gfx_load_g1() SDL_RWread(file, g1Elements, header.num_entries * sizeof(rct_g1_element), 1); // Read element data - _g1Buffer = rct2_malloc(header.total_size); + _g1Buffer = malloc(header.total_size); SDL_RWread(file, _g1Buffer, header.total_size, 1); SDL_RWclose(file); @@ -74,6 +74,16 @@ int gfx_load_g1() return 0; } +void gfx_unload_g1() +{ + SafeFree(_g1Buffer); +} + +void gfx_unload_g2() +{ + SafeFree(g2.elements); +} + int gfx_load_g2() { log_verbose("loading g2 graphics"); @@ -82,7 +92,10 @@ int gfx_load_g2() unsigned int i; char path[MAX_PATH]; - sprintf(path, "%s%cdata%cg2.dat", gExePath, platform_get_path_separator(), platform_get_path_separator()); + char dataPath[MAX_PATH]; + + platform_get_openrct_data_path(dataPath); + sprintf(path, "%s%cg2.dat", dataPath, platform_get_path_separator()); file = SDL_RWFromFile(path, "rb"); if (file != NULL) { if (SDL_RWread(file, &g2.header, 8, 1) == 1) { @@ -129,7 +142,7 @@ void sub_68371D() * image. * rct2: 0x0067A690 */ -void gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, uint8* source_pointer, uint8* dest_pointer, rct_g1_element* source_image, rct_drawpixelinfo *dest_dpi, int height, int width, int image_type){ +void FASTCALL gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, uint8* source_pointer, uint8* dest_pointer, rct_g1_element* source_image, rct_drawpixelinfo *dest_dpi, int height, int width, int image_type){ uint16 zoom_level = dest_dpi->zoom_level; uint8 zoom_amount = 1 << zoom_level; uint32 dest_line_width = (dest_dpi->width / zoom_amount) + dest_dpi->pitch; @@ -257,128 +270,6 @@ void gfx_bmp_sprite_to_buffer(uint8* palette_pointer, uint8* unknown_pointer, ui return; } -/** - * Transfers readied images onto buffers - * This function copies the sprite data onto the screen - * rct2: 0x0067AA18 - */ -void gfx_rle_sprite_to_buffer(const uint8* source_bits_pointer, uint8* dest_bits_pointer, const uint8* palette_pointer, const rct_drawpixelinfo *dpi, int image_type, int source_y_start, int height, int source_x_start, int width){ - int zoom_level = dpi->zoom_level; - int zoom_amount = 1 << zoom_level; - int zoom_mask = 0xFFFFFFFF << zoom_level; - uint8* next_dest_pointer = dest_bits_pointer; - - int line_width = (dpi->width >> zoom_level) + dpi->pitch; - - if (source_y_start < 0){ - source_y_start += zoom_amount; - next_dest_pointer += line_width; - height -= zoom_amount; - } - - //For every line in the image - for (int y = source_y_start; y < (height + source_y_start); y += zoom_amount){ - - //The first part of the source pointer is a list of offsets to different lines - //This will move the pointer to the correct source line. - const uint8 *next_source_pointer = source_bits_pointer + ((uint16*)source_bits_pointer)[y]; - - uint8 last_data_line = 0; - - //For every data section in the line - while (!last_data_line){ - const uint8* source_pointer = next_source_pointer; - uint8* dest_pointer = next_dest_pointer; - - int no_pixels = *source_pointer++; - //gap_size is the number of non drawn pixels you require to - //jump over on your destination - uint8 gap_size = *source_pointer++; - //The last bit in no_pixels tells you if you have reached the end of a line - last_data_line = no_pixels & 0x80; - //Clear the last data line bit so we have just the no_pixels - no_pixels &= 0x7f; - //Have our next source pointer point to the next data section - next_source_pointer = source_pointer + no_pixels; - - //Calculates the start point of the image - int x_start = gap_size - source_x_start; - - if (x_start & ~zoom_mask){ - no_pixels -= (x_start&~zoom_mask); - x_start += ~zoom_mask; - source_pointer += (x_start&~zoom_mask); - if (no_pixels <= 0) continue; - } - - if (x_start > 0){ - //Since the start is positive - //We need to move the drawing surface to the correct position - dest_pointer += x_start >> zoom_level; - } - else{ - //If the start is negative we require to remove part of the image. - //This is done by moving the image pointer to the correct position. - source_pointer -= x_start; - //The no_pixels will be reduced in this operation - no_pixels += x_start; - //If there are no pixels there is nothing to draw this data section - if (no_pixels <= 0) continue; - //Reset the start position to zero as we have taken into account all moves - x_start = 0; - } - - int x_end = x_start + no_pixels; - //If the end position is further out than the whole image - //end position then we need to shorten the line again - if (x_end > width){ - //Shorten the line - no_pixels -= x_end - width; - //If there are no pixels there is nothing to draw. - if (no_pixels <= 0) continue; - } - - //Finally after all those checks, copy the image onto the drawing surface - //If the image type is not a basic one we require to mix the pixels - if (image_type & IMAGE_TYPE_USE_PALETTE){//In the .exe these are all unraveled loops - for (; no_pixels > 0; no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++){ - uint8 al = *source_pointer; - uint8 ah = *dest_pointer; - if (image_type & IMAGE_TYPE_MIX_BACKGROUND) - al = palette_pointer[(((uint16)al << 8) | ah) - 0x100]; - else - al = palette_pointer[al]; - *dest_pointer = al; - } - } - else if (image_type & IMAGE_TYPE_MIX_BACKGROUND){//In the .exe these are all unraveled loops - //Doesnt use source pointer ??? mix with background only? - //Not Tested - - for (; no_pixels > 0; no_pixels -= zoom_amount, dest_pointer++){ - uint8 pixel = *dest_pointer; - pixel = palette_pointer[pixel]; - *dest_pointer = pixel; - } - } - else - { - if (zoom_amount == 1) { - memcpy(dest_pointer, source_pointer, no_pixels); - } - else { - for (; no_pixels > 0; no_pixels -= zoom_amount, source_pointer += zoom_amount, dest_pointer++) { - *dest_pointer = *source_pointer; - } - } - } - } - - //Add a line to the drawing surface pointer - next_dest_pointer += line_width; - } -} - /** * * rct2: 0x0067A28E @@ -395,7 +286,7 @@ void gfx_rle_sprite_to_buffer(const uint8* source_bits_pointer, uint8* dest_bits * dpi (esi) * tertiary_colour (ebp) */ -void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour) +void FASTCALL gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 tertiary_colour) { int image_type = (image_id & 0xE0000000) >> 28; int image_sub_type = (image_id & 0x1C000000) >> 26; @@ -427,6 +318,10 @@ void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 uint32 primary_offset = palette_to_g1_offset[(image_id >> 19) & 0x1F]; uint32 secondary_offset = palette_to_g1_offset[(image_id >> 24) & 0x1F]; + +#if DEBUG_LEVEL_2 + assert(tertiary_colour < PALETTE_TO_G1_OFFSET_COUNT); +#endif // DEBUG_LEVEL_2 uint32 tertiary_offset = palette_to_g1_offset[tertiary_colour]; rct_g1_element* primary_colour = &g1Elements[primary_offset]; @@ -475,7 +370,7 @@ void gfx_draw_sprite(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint32 * x (cx) * y (dx) */ -void gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer) +void FASTCALL gfx_draw_sprite_palette_set(rct_drawpixelinfo *dpi, int image_id, int x, int y, uint8* palette_pointer, uint8* unknown_pointer) { int image_element = image_id & 0x7FFFF; int image_type = (image_id & 0xE0000000) >> 28; diff --git a/src/drawing/string.c b/src/drawing/string.c index cda6348f9c..37b4c6a326 100644 --- a/src/drawing/string.c +++ b/src/drawing/string.c @@ -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); @@ -88,7 +89,7 @@ int gfx_get_string_width_new_lined(utf8 *text) } /** - * Return the width of the string in buffer + * Return the width of the string in buffer * * rct2: 0x006C2321 * buffer (esi) @@ -99,7 +100,7 @@ int gfx_get_string_width(char* buffer) } /** - * Clip the text in buffer to width, add ellipsis and return the new width of the clipped string + * Clip the text in buffer to width, add ellipsis and return the new width of the clipped string * * rct2: 0x006C2460 * buffer (esi) @@ -152,11 +153,11 @@ int gfx_clip_string(utf8 *text, int width) } /** - * Wrap the text in buffer to width, returns width of longest line. + * Wrap the text in buffer to width, returns width of longest line. * - * Inserts NULL where line should break (as \n is used for something else), - * so the number of lines is returned in num_lines. font_height seems to be - * a control character for line height. + * Inserts NULL where line should break (as \n is used for something else), + * so the number of lines is returned in num_lines. font_height seems to be + * a control character for line height. * * rct2: 0x006C21E2 * buffer (esi) @@ -334,24 +335,7 @@ void gfx_draw_string_right(rct_drawpixelinfo* dpi, int format, void* args, int c */ void gfx_draw_string_centred(rct_drawpixelinfo *dpi, int format, int x, int y, int colour, void *args) { - char* buffer; - int text_width; - - buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); - format_string(buffer, format, args); - - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 0xE0; - - // Measure text width - text_width = gfx_get_string_width(buffer); - - // Draw the text centred - if (text_width <= 0xFFFF && text_width >= 0) { - x -= text_width / 2; - gfx_draw_string(dpi, buffer, colour, x, y); - } else { - log_warning("improper text width %d for string %s", text_width, buffer); - } + gfx_draw_string_centred_wrapped(dpi, args, x, y, INT32_MAX, format, colour); } /** @@ -369,12 +353,12 @@ int gfx_draw_string_centred_wrapped(rct_drawpixelinfo *dpi, void *args, int x, i { int font_height, line_height, line_width, line_y, num_lines; // Location of font sprites - uint16* current_font_sprite_base; + sint16* current_font_sprite_base; char* buffer = RCT2_ADDRESS(0x009C383D, char); - current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16); - *current_font_sprite_base = 0xE0; + current_font_sprite_base = RCT2_ADDRESS(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16); + if (*current_font_sprite_base >= 0) *current_font_sprite_base = 0xE0; gfx_draw_string(dpi, buffer, colour, dpi->x, dpi->y); @@ -463,7 +447,7 @@ void gfx_draw_string_left(rct_drawpixelinfo *dpi, int format, void *args, int co buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); format_string(buffer, format, args); - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = 224; gfx_draw_string(dpi, buffer, colour, x, y); } @@ -504,7 +488,7 @@ void colour_char(uint8 colour, uint16* current_font_flags, uint8* palette_pointe /** * Changes the palette so that the next character changes colour - * This is specific to changing to a predefined window related colour + * This is specific to changing to a predefined window related colour */ void colour_char_window(uint8 colour, uint16* current_font_flags,uint8* palette_pointer) { @@ -582,7 +566,7 @@ void draw_string_centred_underline(rct_drawpixelinfo *dpi, int format, void *arg /** * - * rct2: 0x006C1DB7 + * rct2: 0x006C1DB7 * * left : cx * top : dx @@ -600,18 +584,14 @@ void draw_string_centred_raw(rct_drawpixelinfo *dpi, int x, int y, int numLines, int width = gfx_get_string_width(text); gfx_draw_string(dpi, text, 254, x - (width / 2), y); - char c; - while ((c = *text++) != 0) { - if (c >= 32) continue; - if (c <= 4) { - text++; - continue; - } - if (c <= 16) continue; - text += 2; - if (c <= 22) continue; - text += 2; + const utf8 *ch = text; + const utf8 *nextCh = 0; + int codepoint = 0; + + while ((codepoint = utf8_get_next(ch, (const utf8**)&nextCh)) != 0) { + ch = nextCh; } + text = (char*)(ch + 1); y += font_get_line_height(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16)); } @@ -682,7 +662,7 @@ int string_get_height_raw(char *buffer) /** * - * rct2: 0x006C1F57 + * rct2: 0x006C1F57 * * colour : al * format : bx @@ -888,8 +868,11 @@ bool ttf_initialise() for (int i = 0; i < 4; i++) { TTFFontDescriptor *fontDesc = &(gCurrentTTFFontSet->size[i]); - utf8 fontPath[MAX_PATH] = "C:\\Windows\\Fonts\\"; - strcat(fontPath, fontDesc->filename); + utf8 fontPath[MAX_PATH]; + if (!platform_get_font_path(fontDesc, fontPath)) { + log_error("Unable to load font '%s'", fontDesc->font_name); + return false; + } fontDesc->font = TTF_OpenFont(fontPath, fontDesc->ptSize); if (fontDesc->font == NULL) { @@ -1038,21 +1021,44 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, te int srcScanSkip = surface->pitch - width; int dstScanSkip = dpi->width + dpi->pitch - width; - for (int yy = 0; yy < height; yy++) { - for (int xx = 0; xx < width; xx++) { - if (*src != 0) { - *dst = colour; - if (info->flags & TEXT_DRAW_FLAG_INSET) { - *(dst + width + dstScanSkip + 1) = info->palette[3]; - } else if (info->flags & TEXT_DRAW_FLAG_OUTLINE) { - *(dst + width + dstScanSkip + 1) = info->palette[3]; + uint8 *dst_orig = dst; + uint8 *src_orig = src; + + // Draw shadow/outline + if (info->flags & TEXT_DRAW_FLAG_OUTLINE) { + for (int yy = 0; yy < height - 0; yy++) { + for (int xx = 0; xx < width - 0; xx++) { + if (*src != 0) { + *(dst + 1) = info->palette[3]; // right + *(dst - 1) = info->palette[3]; // left + *(dst - width - dstScanSkip) = info->palette[3]; // top + *(dst + width + dstScanSkip) = info->palette[3]; // bottom } + src++; + dst++; } - src++; - dst++; + // Skip any remaining bits + src += srcScanSkip; + dst += dstScanSkip; + } + } + { + dst = dst_orig; + src = src_orig; + for (int yy = 0; yy < height; yy++) { + for (int xx = 0; xx < width; xx++) { + if (*src != 0) { + if (info->flags & TEXT_DRAW_FLAG_INSET) { + *(dst + width + dstScanSkip + 1) = info->palette[3]; + } + *dst = colour; + } + src++; + dst++; + } + src += srcScanSkip; + dst += dstScanSkip; } - src += srcScanSkip; - dst += dstScanSkip; } if (SDL_MUSTLOCK(surface)) { @@ -1082,7 +1088,7 @@ static const utf8 *ttf_process_format_code(rct_drawpixelinfo *dpi, const utf8 *t break; case FORMAT_ADJUST_PALETTE: { - uint16 eax = palette_to_g1_offset[*nextCh++]; + uint16 eax = palette_to_g1_offset[(uint8)*nextCh++]; rct_g1_element *g1Element = &g1Elements[eax]; uint32 ebx = g1Element->offset[249] + 256; if (!(info->flags & TEXT_DRAW_FLAG_OUTLINE)) { @@ -1352,3 +1358,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_strcpy(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_strcpy(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_strcpy(buffer + 3, path + begin, bufferSize - 3); + if (gfx_get_string_width(buffer) <= availableWidth) { + return; + } + } + + safe_strcpy(buffer, path, bufferSize); +} diff --git a/src/drawing/supports.c b/src/drawing/supports.c new file mode 100644 index 0000000000..f2200a3539 --- /dev/null +++ b/src/drawing/supports.c @@ -0,0 +1,355 @@ +#include "../addresses.h" +#include "../interface/viewport.h" +#include "supports.h" + +typedef struct { + uint16 full; + uint16 half; + uint16 flat; + uint16 slope; +} supports_id_desc; + +/* 0x0097B1C4 */ +const supports_id_desc WoodenSupportImageIds[] = { + { 3392, 3393, 3394, 3536 }, + { 3390, 3391, 3394, 3514 }, + { 3558, 3559, 3560, 3570 }, + { 3561, 3562, 3563, 3592 }, + { 3564, 3565, 3566, 3614 }, + { 3567, 3568, 3569, 3636 }, + { 3677, 3678, 3680, 3739 }, + { 3675, 3676, 3679, 3717 }, + { 3761, 3762, 3763, 3773 }, + { 3764, 3765, 3766, 3795 }, + { 3767, 3768, 3769, 3817 }, + { 3770, 3771, 3772, 3839 }, +}; + +/* 0x0097B224 */ +const uint16 WoodenCurveSupportImageIds[] = { + 3465, + 3465, + 0, + 0, + 0, + 0, + 3681, + 3681, + 0, + 0, + 0, + 0, +}; + +typedef struct { + uint8 var_0; + uint8 var_1; + uint8 var_2; + uint8 var_3; + uint8 var_4; + uint8 var_5; + uint8 var_6; + uint8 var_7; +} unk_supports_desc; + +/* 0x0097B23C */ +const unk_supports_desc byte_97B23C[] = { + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 10, 0, 0, 10, 32, 44, 1, 1 }, + { 0, 10, 0, 32, 10, 44, 1, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 10, 0, 0, 10, 32, 44, 1, 1 }, + { 0, 10, 0, 32, 10, 44, 1, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 10, 0, 2, 10, 32, 76, 1, 1 }, + { 0, 10, 2, 32, 10, 76, 1, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 4, 0, 1 }, + { 0, 0, 0, 1, 1, 4, 0, 1 }, + { 0, 0, 0, 1, 1, 4, 0, 1 }, + { 0, 0, 0, 1, 1, 4, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 0, 0, 0, 1, 1, 8, 0, 1 }, + { 2, 2, 1, 28, 28, 2, 0, 1 }, +}; + +/* 0x0097B3C4 */ +const uint16 word_97B3C4[] = { + 0, + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 14, + 0, + 0, + 0, + 17, + 0, + 16, + 15, + 0, +}; + +/** + * Adds paint structs for wooden supports. + * rct2: 0x006629BC + * @param supportType (edi) Type and direction of supports. + * @param special (ax) Used for curved supports. + * @param height (dx) The height of the supports. + * @param imageColourFlags (ebp) The colour and palette flags for the support sprites. + * @param underground (Carry flag) true if underground. + * @returns (al) true if any supports have been drawn, otherwise false. + */ +bool wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool* underground) +{ + if (underground != NULL){ + *underground = false; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_VIEWPORT_FLAGS, uint16) & VIEWPORT_FLAG_INVISIBLE_SUPPORTS) { + return false; + } + + if (!(RCT2_GLOBAL(0x0141E9DB, uint8) & 1)) { + return false; + } + + int z = floor2(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) + 15, 16); + height -= z; + if (height < 0) { + if (underground != NULL) { + *underground = true; + } + return false; + } + height /= 16; + + bool hasSupports = false; + bool drawFlatPiece = false; + int rotation = get_current_rotation(); + + // Draw base support (usually shaped to the slope) + int slope = RCT2_GLOBAL(0x0141E9DA, uint8); + if (slope & (1 << 5)) { + // Above scenery (just put a base piece above it) + drawFlatPiece = true; + } else if (slope & (1 << 4)) { + // Steep diagonal (place the correct shaped support for the slope) + height -= 2; + if (height < 0) { + if (underground != NULL) { + *underground = true; + } + return false; + } + + int imageId = WoodenSupportImageIds[supportType].slope; + if (imageId == 0) { + drawFlatPiece = true; + } else { + imageId += word_97B3C4[slope & 0x1F]; + imageId |= imageColourFlags; + + RCT2_GLOBAL(0x009DEA52, uint16) = 0; + RCT2_GLOBAL(0x009DEA54, uint16) = 0; + RCT2_GLOBAL(0x009DEA56, uint16) = z + 2; + sub_98197C(imageId, 0, 0, 32, 32, 11, z, rotation); + + RCT2_GLOBAL(0x009DEA52, uint16) = 0; + RCT2_GLOBAL(0x009DEA54, uint16) = 0; + RCT2_GLOBAL(0x009DEA56, uint16) = z + 16 + 2; + sub_98197C(imageId + 4, 0, 0, 32, 32, 11, z + 16, rotation); + + hasSupports = true; + } + z += 32; + } else if ((slope & 0x0F) != 0) { + // 1 to 3 quarters up + height--; + if (height < 0) { + if (underground != NULL) { + *underground = true; + } + return false; + } + + int imageId = WoodenSupportImageIds[supportType].slope; + if (imageId == 0) { + drawFlatPiece = true; + } else { + imageId += word_97B3C4[slope & 0x1F]; + imageId |= imageColourFlags; + + RCT2_GLOBAL(0x009DEA52, uint16) = 0; + RCT2_GLOBAL(0x009DEA54, uint16) = 0; + RCT2_GLOBAL(0x009DEA56, uint16) = z + 2; + sub_98196C(imageId, 0, 0, 32, 32, 11, z, rotation); + hasSupports = true; + } + z += 16; + } + + // Draw flat base support + if (drawFlatPiece) { + int imageId = WoodenSupportImageIds[supportType].flat | imageColourFlags; + sub_98196C(imageId, 0, 0, 32, 32, 0, z - 2, rotation); + hasSupports = true; + } + + // Draw repeated supports for left over space + while (height != 0) { + if ((z & 16) == 0 && height >= 2 && z + 16 != RCT2_GLOBAL(0x00141E9DC, uint16)) { + // Full support + int imageId = WoodenSupportImageIds[supportType].full | imageColourFlags; + uint8 ah = special == 2 ? 23 : 28; + sub_98196C(imageId, 0, 0, 32, 32, ah, z, rotation); + hasSupports = true; + z += 32; + height -= 2; + } else { + // Half support + int imageId = WoodenSupportImageIds[supportType].half | imageColourFlags; + uint8 ah = special == 1 ? 7 : 12; + sub_98196C(imageId, 0, 0, 32, 32, ah, z, rotation); + hasSupports = true; + z += 16; + height -= 1; + } + } + + // Draw special pieces, e.g. curved supports + if (special != 0) { + special = (special - 1) & 0xFFFF; + + int imageId = WoodenCurveSupportImageIds[supportType]; + if (imageId != 0 && byte_97B23C[special].var_7 != 0) { + imageId += special; + imageId |= imageColourFlags; + + RCT2_GLOBAL(0x009DEA52, uint16) = byte_97B23C[special].var_0; + RCT2_GLOBAL(0x009DEA54, uint16) = byte_97B23C[special].var_1; + RCT2_GLOBAL(0x009DEA56, uint16) = byte_97B23C[special].var_2 + z; + uint16 lengthY = byte_97B23C[special].var_3; + uint16 lengthX = byte_97B23C[special].var_4; + uint8 ah = byte_97B23C[special].var_5; + if (byte_97B23C[special].var_6 == 0 || RCT2_GLOBAL(0x009DEA58, uint32) == 0) { + sub_98197C(imageId, 0, 0, lengthX, lengthY, ah, z, rotation); + hasSupports = true; + } else { + hasSupports = true; + if (!sub_98198C(imageId, 0, 0, lengthX, lengthY, ah, z, rotation)) { + int edi = RCT2_GLOBAL(0x009DEA58, uint32); + RCT2_GLOBAL(edi + 0x20, uint32) = imageColourFlags; + } + } + } + } + + return hasSupports; +} + +/** + * Wooden supports + * rct2: 0x00662D5C + */ +bool wooden_b_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags) +{ + int eax = special, ebx = 0, ecx = 0, edx = height, esi = 0, _edi = supportType, ebp = imageColourFlags; + RCT2_CALLFUNC_X(0x00662D5C, &eax, &ebx, &ecx, &edx, &esi, &_edi, &ebp); + return eax & 0xFF; +} + +/** + * Metal pole supports + * rct2: 0x00663105 + */ +bool metal_a_wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags) +{ + int eax = special, ebx = 0, ecx = 0, edx = height, esi = 0, _edi = supportType, ebp = imageColourFlags; + RCT2_CALLFUNC_X(0x00663105, &eax, &ebx, &ecx, &edx, &esi, &_edi, &ebp); + return eax & 0xFF; +} + +/** + * Metal pole supports + * rct2: 0x00663584 + */ +bool metal_b_wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags) +{ + int eax = special, ebx = 0, ecx = 0, edx = height, esi = 0, _edi = supportType, ebp = imageColourFlags; + RCT2_CALLFUNC_X(0x00663584, &eax, &ebx, &ecx, &edx, &esi, &_edi, &ebp); + return eax & 0xFF; +} + +/** + * Some kind of supports + * rct2: 0x006A2ECC + */ +bool sub_6A2ECC(int supportType, int special, int height, uint32 imageColourFlags) +{ + int eax = special, ebx = 0, ecx = 0, edx = height, esi = 0, _edi = supportType, ebp = imageColourFlags; + RCT2_CALLFUNC_X(0x006A2ECC, &eax, &ebx, &ecx, &edx, &esi, &_edi, &ebp); + return eax & 0xFF; +} + +/** + * + * rct2: 0x006A326B + */ +bool path_wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags) +{ + int eax = special, ebx = 0, ecx = 0, edx = height, esi = 0, _edi = supportType, ebp = imageColourFlags; + RCT2_CALLFUNC_X(0x006A326B, &eax, &ebx, &ecx, &edx, &esi, &_edi, &ebp); + return eax & 0xFF; +} diff --git a/src/drawing/supports.h b/src/drawing/supports.h new file mode 100644 index 0000000000..abc23cd094 --- /dev/null +++ b/src/drawing/supports.h @@ -0,0 +1,8 @@ +#ifndef _DRAWING_SUPPORTS_H_ +#define _DRAWING_SUPPORTS_H_ + +#include "../common.h" + +bool wooden_a_supports_paint_setup(int supportType, int special, int height, uint32 imageColourFlags, bool* underground); + +#endif diff --git a/src/editor.c b/src/editor.c index 7b566001ca..6b279347d7 100644 --- a/src/editor.c +++ b/src/editor.c @@ -91,7 +91,7 @@ void editor_load() gfx_invalidate_screen(); RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, sint16) = 0; - safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(2749), 0x40); + safe_strcpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(2749), 0x40); } /** @@ -119,8 +119,8 @@ void editor_convert_save_to_scenario_callback(int result) RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_NO_MONEY_SCENARIO; RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) |= PARK_FLAGS_NO_MONEY; - safe_strncpy(s6Info->name, (const char*)RCT2_ADDRESS_SCENARIO_NAME, 64); - safe_strncpy(s6Info->details, (const char*)RCT2_ADDRESS_SCENARIO_DETAILS, 256); + safe_strcpy(s6Info->name, (const char*)RCT2_ADDRESS_SCENARIO_NAME, 64); + safe_strcpy(s6Info->details, (const char*)RCT2_ADDRESS_SCENARIO_DETAILS, 256); s6Info->objective_type = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8); s6Info->objective_arg_1 = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8); s6Info->objective_arg_2 = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_CURRENCY, sint32); @@ -129,7 +129,7 @@ void editor_convert_save_to_scenario_callback(int result) rct_stex_entry* stex = g_stexEntries[0]; if ((int)stex != 0xFFFFFFFF) { - object_unload((rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]); + object_unload_chunk((rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]); reset_loaded_objects(); format_string(s6Info->details, STR_NO_DETAILS_YET, NULL); @@ -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(); @@ -154,6 +154,9 @@ void trackdesigner_load() { rct_window *mainWindow; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TRACK_DESIGNER; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, sint16) = 0; + object_unload_all(); map_init(150); set_all_land_owned(); @@ -169,7 +172,6 @@ void trackdesigner_load() date_reset(); window_guest_list_init_vars_b(); window_staff_list_init_vars(); - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TRACK_DESIGNER; RCT2_GLOBAL(0x0141F570, uint8) = 0; window_new_ride_init_vars(); viewport_init_all(); @@ -180,7 +182,6 @@ void trackdesigner_load() mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION; load_palette(); gfx_invalidate_screen(); - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, sint16) = 0; } /** @@ -191,6 +192,9 @@ void trackmanager_load() { rct_window *mainWindow; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TRACK_MANAGER; + RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, sint16) = 0; + object_unload_all(); map_init(150); set_all_land_owned(); @@ -206,7 +210,6 @@ void trackmanager_load() date_reset(); window_guest_list_init_vars_b(); window_staff_list_init_vars(); - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_TRACK_MANAGER; RCT2_GLOBAL(0x0141F570, uint8) = 0; window_new_ride_init_vars(); viewport_init_all(); @@ -217,7 +220,6 @@ void trackmanager_load() mainWindow->flags &= ~WF_SCROLLING_TO_LOCATION; load_palette(); gfx_invalidate_screen(); - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, sint16) = 0; } /** @@ -235,23 +237,21 @@ static void set_all_land_owned() * * rct2: 0x006758C0 */ -void editor_load_landscape(const char *path) +bool editor_load_landscape(const utf8 *path) { window_close_construction_windows(); char *extension = strrchr(path, '.'); if (extension != NULL) { if (_stricmp(extension, ".sv4") == 0) { - editor_load_landscape_from_sv4(path); - return; + return editor_load_landscape_from_sv4(path); } else if (_stricmp(extension, ".sc4") == 0) { - editor_load_landscape_from_sc4(path); - return; + return editor_load_landscape_from_sc4(path); } } // Load SC6 / SV6 - editor_read_s6(path); + return editor_read_s6(path); } /** @@ -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); } @@ -464,7 +464,7 @@ static int editor_read_s6(const char *path) rct_stex_entry* stex = g_stexEntries[0]; if ((int)stex != 0xFFFFFFFF) { - object_unload((rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]); + object_unload_chunk((rct_object_entry*)&object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0]); reset_loaded_objects(); format_string(s6Info->details, STR_NO_DETAILS_YET, NULL); @@ -567,8 +567,8 @@ static void editor_finalise_main_view() static bool editor_check_object_group_at_least_one_selected(int objectType) { - uint32 numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); - rct_object_entry *entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + uint32 numObjects = gInstalledObjectsCount; + rct_object_entry *entry = gInstalledObjects; uint8 *objectFlag = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); for (uint32 i = 0; i < numObjects; i++) { if ((entry->flags & 0x0F) == objectType && (*objectFlag & 1)) { diff --git a/src/editor.h b/src/editor.h index 83b0f46f8c..e89bde1c4b 100644 --- a/src/editor.h +++ b/src/editor.h @@ -41,7 +41,7 @@ void editor_load(); void editor_convert_save_to_scenario(); void trackdesigner_load(); void trackmanager_load(); -void editor_load_landscape(const char *path); +bool editor_load_landscape(const utf8 *path); void editor_open_windows_for_current_step(); diff --git a/src/game.c b/src/game.c index e39bc2b0f5..cc99c79a70 100644 --- a/src/game.c +++ b/src/game.c @@ -20,6 +20,7 @@ #include "addresses.h" #include "audio/audio.h" +#include "cheats.h" #include "config.h" #include "game.h" #include "editor.h" @@ -46,7 +47,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,11 +57,16 @@ #include "world/scenery.h" #include "world/sprite.h" #include "world/water.h" +#include + +#define NUMBER_OF_AUTOSAVES_TO_KEEP 9 int gGameSpeed = 1; float gDayNightCycle = 0; bool gInUpdateCode = false; +extern void game_command_callback_place_banner(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp); + GAME_COMMAND_CALLBACK_POINTER* game_command_callback = 0; GAME_COMMAND_CALLBACK_POINTER* game_command_callback_table[] = { 0, @@ -69,7 +74,10 @@ GAME_COMMAND_CALLBACK_POINTER* game_command_callback_table[] = { game_command_callback_ride_construct_placed_front, game_command_callback_ride_construct_placed_back, game_command_callback_ride_remove_track_piece, + game_command_callback_place_banner, + game_command_callback_place_ride_entrance_or_exit, }; +int game_command_playerid = -1; int game_command_callback_get_index(GAME_COMMAND_CALLBACK_POINTER* callback) { @@ -126,7 +134,7 @@ void update_palette_effects() rct_water_type* water_type = (rct_water_type*)object_entry_groups[OBJECT_TYPE_WATER].chunks[0]; if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) == 1) { - // change palette to lighter color during lightning + // change palette to lighter colour during lightning int palette = 1532; if ((sint32)water_type != -1) { @@ -140,9 +148,7 @@ void update_palette_effects() RCT2_ADDRESS(RCT2_ADDRESS_PALETTE + xoffset, uint8)[(i * 4) + 1] = -((0xFF - g1_element.offset[(i * 3) + 1]) / 2) - 1; RCT2_ADDRESS(RCT2_ADDRESS_PALETTE + xoffset, uint8)[(i * 4) + 2] = -((0xFF - g1_element.offset[(i * 3) + 2]) / 2) - 1; } - RCT2_GLOBAL(0x014241BC, uint32) = 2; platform_update_palette(RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8), 10, 236); - RCT2_GLOBAL(0x014241BC, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8)++; } else { if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) == 2) { @@ -228,20 +234,14 @@ void update_palette_effects() vd += 4; } - RCT2_GLOBAL(0x014241BC, uint32) = 2; platform_update_palette(RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8), 230, 16); - RCT2_GLOBAL(0x014241BC, uint32) = 0; if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) == 2) { - RCT2_GLOBAL(0x014241BC, uint32) = 2; platform_update_palette(RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8), 10, 236); - RCT2_GLOBAL(0x014241BC, uint32) = 0; RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint8) = 0; } } if (RCT2_GLOBAL(0x009E2C4C, uint32) == 2 || RCT2_GLOBAL(0x009E2C4C, uint32) == 1) { - if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_CAP_BPP, uint32) != 8) { - RCT2_GLOBAL(0x009E2C78, int) = 1; - } + RCT2_GLOBAL(0x009E2C78, int) = 1; } } @@ -288,11 +288,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 +310,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 @@ -406,18 +406,14 @@ static int game_check_affordability(int cost) { if (cost <= 0)return cost; if (RCT2_GLOBAL(0x141F568, uint8) & 0xF0)return cost; + if (cost <= (sint32)(DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32))))return cost; - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32)&(1 << 8))){ - if (cost <= (sint32)(DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32))))return cost; - } RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = cost; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 827; return MONEY32_UNDEFINED; } -static GAME_COMMAND_POINTER* new_game_command_table[62]; - /** * * rct2: 0x006677F2 @@ -449,6 +445,10 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * original_edi = *edi; original_ebp = *ebp; + if (command >= countof(new_game_command_table)) { + return MONEY32_UNDEFINED; + } + flags = *ebx; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0xFFFF; @@ -465,6 +465,10 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * scenery_remove_ghost_tool_placement(); } + if (game_command_playerid == -1) { + game_command_playerid = network_get_current_player_id(); + } + *ebx &= ~GAME_COMMAND_FLAG_APPLY; // First call for validity and price check @@ -505,11 +509,16 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * // Second call to actually perform the operation new_game_command_table[command](eax, ebx, ecx, edx, esi, edi, ebp); - if (game_command_callback) { - game_command_callback(*eax, *ebx, *ecx, *edx, *esi, *edi, *ebp); - game_command_callback = 0; + // Do the callback (required for multiplayer to work correctly), but only for top level commands + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1) { + if (game_command_callback && !(flags & GAME_COMMAND_FLAG_GHOST)) { + game_command_callback(*eax, *ebx, *ecx, *edx, *esi, *edi, *ebp); + game_command_callback = 0; + } } + game_command_playerid = -1; + *edx = *ebx; if (*edx != MONEY32_UNDEFINED && *edx < cost) @@ -531,6 +540,11 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * } } + if (network_get_mode() == NETWORK_MODE_SERVER && !(flags & GAME_COMMAND_FLAG_NETWORKED) && !(flags & GAME_COMMAND_FLAG_GHOST)) { + network_set_player_last_action(network_get_player_index(network_get_current_player_id()), command); + network_add_player_money_spent(network_get_current_player_id(), cost); + } + return cost; } } @@ -539,9 +553,12 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int * // Decrement nest count RCT2_GLOBAL(0x009A8C28, uint8)--; + + // Clear the game command callback to prevent the next command triggering it + game_command_callback = 0; // Show error window - if (RCT2_GLOBAL(0x009A8C28, uint8) == 0 && (flags & GAME_COMMAND_FLAG_APPLY) && RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8) && !(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)) + if (RCT2_GLOBAL(0x009A8C28, uint8) == 0 && (flags & GAME_COMMAND_FLAG_APPLY) && RCT2_GLOBAL(0x0141F568, uint8) == RCT2_GLOBAL(0x013CA740, uint8) && !(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) window_error_open(RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16), RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16)); return MONEY32_UNDEFINED; @@ -594,40 +611,6 @@ static void game_load_or_quit(int *eax, int *ebx, int *ecx, int *edx, int *esi, *ebx = 0; } -/** - * - * rct2: 0x00674F40 - */ -static int open_landscape_file_dialog() -{ - int result; - format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, STR_LOAD_LANDSCAPE_DIALOG_TITLE, 0); - safe_strncpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_LANDSCAPES_PATH, MAX_PATH); - format_string((char*)0x0141EE68, STR_RCT2_LANDSCAPE_FILE, 0); - audio_pause_sounds(); - result = platform_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6;*.SV4;*.SC6", (char*)0x0141EE68); - audio_unpause_sounds(); - // window_proc - return result; -} - -/** - * - * rct2: 0x00674EB6 - */ -static int open_load_game_dialog() -{ - int result; - format_string((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, STR_LOAD_GAME_DIALOG_TITLE, 0); - safe_strncpy((char*)0x0141EF68, (char*)RCT2_ADDRESS_SAVED_GAMES_PATH, MAX_PATH); - format_string((char*)0x0141EE68, STR_RCT2_SAVED_GAME, 0); - audio_pause_sounds(); - result = platform_open_common_file_dialog(1, (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, (char*)0x0141EF68, "*.SV6", (char*)0x0141EE68); - audio_unpause_sounds(); - // window_proc - return result; -} - /** * * rct2: 0x0066DC0F @@ -635,33 +618,45 @@ static int open_load_game_dialog() static void load_landscape() { window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE, NULL); - return; +} - if (open_landscape_file_dialog() == 0) { - gfx_invalidate_screen(); - } else { - // Set default filename - char *esi = (char*)0x0141EF67; - while (1) { - esi++; - if (*esi == '.') +static void utf8_to_rct2_self(char *buffer, size_t length) +{ + char tempBuffer[512]; + utf8_to_rct2(tempBuffer, buffer); + + size_t i = 0; + const char *src = tempBuffer; + char *dst = buffer; + while (*src != 0 && i < length - 1) { + if (*src == (char)0xFF) { + if (i < length - 3) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + } else { break; - if (*esi != 0) - continue; - strcpy(esi, ".SC6"); - break; - } - safe_strncpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68, MAX_PATH); - - editor_load_landscape((char*)0x0141EF68); - if (1) { - gfx_invalidate_screen(); - rct2_endupdate(); + } + i += 3; } else { - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, uint16) = 0; - rct2_endupdate(); + *dst++ = *src++; + i++; } } + do { + *dst++ = '\0'; + i++; + } while (i < length); +} + +static void rct2_to_utf8_self(char *buffer, size_t length) +{ + char tempBuffer[512]; + if (length > 0) { + rct2_to_utf8(tempBuffer, buffer); + strncpy(buffer, tempBuffer, length - 1); + buffer[length - 1] = '\0'; + } } /** @@ -669,16 +664,17 @@ static void load_landscape() */ void game_convert_strings_to_utf8() { - utf8 buffer[512]; + // Scenario details + rct2_to_utf8_self(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_COMPLETED_BY, char), 32); + rct2_to_utf8_self(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_NAME, char), 64); + rct2_to_utf8_self(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char), 256); // User strings for (int i = 0; i < MAX_USER_STRINGS; i++) { utf8 *userString = &gUserStrings[i * USER_STRING_MAX_LENGTH]; if (!str_is_null_or_empty(userString)) { - rct2_to_utf8(buffer, userString); - memcpy(userString, buffer, 31); - userString[31] = 0; + rct2_to_utf8_self(userString, 32); } } @@ -687,9 +683,7 @@ void game_convert_strings_to_utf8() rct_news_item *newsItem = news_item_get(i); if (!str_is_null_or_empty(newsItem->text)) { - rct2_to_utf8(buffer, newsItem->text); - memcpy(newsItem->text, buffer, 255); - newsItem->text[255] = 0; + rct2_to_utf8_self(newsItem->text, 256); } } } @@ -699,16 +693,17 @@ void game_convert_strings_to_utf8() */ void game_convert_strings_to_rct2(rct_s6_data *s6) { - char buffer[512]; + // Scenario details + utf8_to_rct2_self(s6->scenario_completed_name, sizeof(s6->scenario_completed_name)); + utf8_to_rct2_self(s6->scenario_name, sizeof(s6->scenario_name)); + utf8_to_rct2_self(s6->scenario_description, sizeof(s6->scenario_description)); // User strings for (int i = 0; i < MAX_USER_STRINGS; i++) { char *userString = &s6->custom_strings[i * USER_STRING_MAX_LENGTH]; if (!str_is_null_or_empty(userString)) { - utf8_to_rct2(buffer, userString); - memcpy(userString, buffer, 31); - userString[31] = 0; + utf8_to_rct2_self(userString, 32); } } @@ -717,9 +712,7 @@ void game_convert_strings_to_rct2(rct_s6_data *s6) rct_news_item *newsItem = &s6->news_items[i]; if (!str_is_null_or_empty(newsItem->text)) { - utf8_to_rct2(buffer, newsItem->text); - memcpy(newsItem->text, buffer, 255); - newsItem->text[255] = 0; + utf8_to_rct2_self(newsItem->text, 256); } } } @@ -770,10 +763,9 @@ 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 @@ -790,6 +782,7 @@ int game_load_sv6(SDL_RWops* rw) // #2407: Resetting screen time to not open a save prompt shortly after loading a park. RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, uint16) = 0; + gLastAutoSaveTick = SDL_GetTicks(); return 1; } @@ -816,7 +809,8 @@ void game_fix_save_vars() { if (mapElement == NULL) { log_error("Null map element at x = %d and y = %d. Fixing...", x, y); - map_element_insert(x, y, 14, 0); + mapElement = map_element_insert(x, y, 14, 0); + assert(mapElement != NULL); } } } @@ -861,13 +855,28 @@ int game_load_network(SDL_RWops* rw) // Read other data not in normal save files RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32) = SDL_ReadLE32(rw); + _guestGenerationProbability = SDL_ReadLE32(rw); + _suggestedGuestMaximum = SDL_ReadLE32(rw); + gCheatsSandboxMode = SDL_ReadU8(rw); + gCheatsDisableClearanceChecks = SDL_ReadU8(rw); + gCheatsDisableSupportLimits = SDL_ReadU8(rw); + gCheatsShowAllOperatingModes = SDL_ReadU8(rw); + gCheatsShowVehiclesFromOtherTrackTypes = SDL_ReadU8(rw); + gCheatsFastLiftHill = SDL_ReadU8(rw); + gCheatsDisableBrakesFailure = SDL_ReadU8(rw); + gCheatsDisableAllBreakdowns = SDL_ReadU8(rw); + gCheatsUnlockAllPrices = SDL_ReadU8(rw); + gCheatsBuildInPauseMode = SDL_ReadU8(rw); + gCheatsIgnoreRideIntensity = SDL_ReadU8(rw); + gCheatsDisableVandalism = SDL_ReadU8(rw); + gCheatsNeverendingMarketing = SDL_ReadU8(rw); + gCheatsFreezeClimate = SDL_ReadU8(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 @@ -878,6 +887,8 @@ int game_load_network(SDL_RWops* rw) map_update_tile_pointers(); reset_0x69EBE4(); openrct2_reset_object_tween_locations(); + game_convert_strings_to_utf8(); + gLastAutoSaveTick = SDL_GetTicks(); return 1; } @@ -885,36 +896,42 @@ int game_load_network(SDL_RWops* rw) * * rct2: 0x00675E1B */ -int game_load_save(const char *path) +bool game_load_save(const utf8 *path) { log_verbose("loading saved game, %s", path); - safe_strncpy((char*)0x0141EF68, path, MAX_PATH); - safe_strncpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, path, MAX_PATH); + safe_strcpy((char*)0x0141EF68, path, MAX_PATH); + safe_strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, path, MAX_PATH); - safe_strncpy(gScenarioSavePath, path, MAX_PATH); + safe_strcpy(gScenarioSavePath, path, MAX_PATH); SDL_RWops* rw = SDL_RWFromFile(path, "rb"); if (rw == NULL) { log_error("unable to open %s", path); RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 255; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_FILE_CONTAINS_INVALID_DATA; - return 0; + return false; } - if (!game_load_sv6(rw)) { - title_load(); - rct2_endupdate(); - SDL_RWclose(rw); - return 0; - } + bool result = game_load_sv6(rw); SDL_RWclose(rw); - game_load_init(); - if (network_get_mode() == NETWORK_MODE_SERVER) { - network_send_map(); + if (result) { + game_load_init(); + network_free_string_ids(); + if (network_get_mode() == NETWORK_MODE_SERVER) { + network_send_map(); + } + if (network_get_mode() == NETWORK_MODE_CLIENT) { + network_close(); + } + return true; + } else { + // If loading the SV6 failed, the current park state will be corrupted + // so just go back to the title screen. + title_load(); + return false; } - return 1; } void game_load_init() @@ -962,9 +979,9 @@ void game_load_init() scenario_set_filename((char*)0x0135936C); } -/* +/** * - * rct2: 0x0069E9A7 + * rct2: 0x0069E9A7 * Call after a rotation or loading of a save to reset sprite quadrants */ void reset_all_sprite_quadrant_placements() @@ -974,67 +991,6 @@ void reset_all_sprite_quadrant_placements() sprite_move(spr->unknown.x, spr->unknown.y, spr->unknown.z, spr); } -/** - * - * rct2: 0x0066DBB7 - */ -static void load_game() -{ - window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME, NULL); - return; - - if (open_load_game_dialog() == 0) { - gfx_invalidate_screen(); - } else { - // Set default filename - char *esi = (char*)0x0141EF67; - while (1) { - esi++; - if (*esi == '.') - break; - if (*esi != 0) - continue; - strcpy(esi, ".SV6"); - break; - } - safe_strncpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, (char*)0x0141EF68, MAX_PATH); - - if (game_load_save((char *)0x0141EF68)) { - gfx_invalidate_screen(); - rct2_endupdate(); - } else { - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_AGE, uint16) = 0; - rct2_endupdate(); - } - } -} - -/** - * - * rct2: 0x006750E9 - */ -static int show_save_game_dialog(char *resultPath) -{ - rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; - - int result; - char title[256]; - char filename[MAX_PATH]; - char filterName[256]; - - format_string(title, STR_SAVE_GAME_1040, NULL); - safe_strncpy(filename, RCT2_ADDRESS(RCT2_ADDRESS_SAVED_GAMES_PATH_2, char), MAX_PATH); - format_string(filterName, STR_RCT2_SAVED_GAME, NULL); - - audio_pause_sounds(); - result = platform_open_common_file_dialog(0, title, filename, "*.SV6", filterName); - audio_unpause_sounds(); - - if (result) - safe_strncpy(resultPath, filename, MAX_PATH); - return result; -} - void save_game() { if (!gFirstTimeSave) { @@ -1042,7 +998,7 @@ void save_game() SDL_RWops* rw = SDL_RWFromFile(gScenarioSavePath, "wb+"); if (rw != NULL) { - scenario_save(rw, 0x80000000); + scenario_save(rw, 0x80000000 | (gConfigGeneral.save_plugin_data ? 1 : 0)); log_verbose("Saved to %s", gScenarioSavePath); SDL_RWclose(rw); @@ -1056,19 +1012,105 @@ void save_game() } void save_game_as() { - window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME, gScenarioSavePath); + char name[MAX_PATH]; + safe_strcpy(name, path_get_filename(gScenarioSavePath), MAX_PATH); + path_remove_extension(name); + window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME, name); } +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); + safe_strcpy(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)) { @@ -1108,8 +1150,6 @@ void rct2_exit_reason(rct_string_id title, rct_string_id body){ */ void rct2_exit() { - //audio_close(); - //Post quit message does not work in 0x6e3879 as its windows only. openrct2_finish(); } @@ -1122,26 +1162,25 @@ void game_load_or_quit_no_save_prompt() 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_SCREEN_FLAGS, uint8) & 2) + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) { load_landscape(); - else - load_game(); + } else { + window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME, NULL); + } } 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_CALLPROC_EBPSAFE(0x0040705E); Function not required resets cursor position. - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) &= ~INPUT_FLAG_5; + if (gInputFlags & INPUT_FLAG_5) { + gInputFlags &= ~INPUT_FLAG_5; } gGameSpeed = 1; title_load(); - rct2_endupdate(); } else { rct2_exit(); } } -static GAME_COMMAND_POINTER* new_game_command_table[62] = { +GAME_COMMAND_POINTER* new_game_command_table[66] = { game_command_set_ride_appearance, game_command_set_land_height, game_pause_toggle, @@ -1203,5 +1242,9 @@ static GAME_COMMAND_POINTER* new_game_command_table[62] = { game_command_set_banner_name, game_command_set_sign_name, game_command_set_banner_style, - game_command_set_sign_style + game_command_set_sign_style, + game_command_set_player_group, + game_command_modify_groups, + game_command_kick_player, + game_command_cheat }; diff --git a/src/game.h b/src/game.h index f2ef77a7e0..80fa4472d9 100644 --- a/src/game.h +++ b/src/game.h @@ -87,7 +87,11 @@ enum GAME_COMMAND { GAME_COMMAND_SET_BANNER_NAME, GAME_COMMAND_SET_SIGN_NAME, GAME_COMMAND_SET_BANNER_STYLE, - GAME_COMMAND_SET_SIGN_STYLE + GAME_COMMAND_SET_SIGN_STYLE, + GAME_COMMAND_SET_PLAYER_GROUP, + GAME_COMMAND_MODIFY_GROUPS, + GAME_COMMAND_KICK_PLAYER, + GAME_COMMAND_CHEAT }; enum { @@ -111,6 +115,9 @@ typedef void (GAME_COMMAND_CALLBACK_POINTER)(int eax, int ebx, int ecx, int edx, extern GAME_COMMAND_CALLBACK_POINTER* game_command_callback; int game_command_callback_get_index(GAME_COMMAND_CALLBACK_POINTER* callback); GAME_COMMAND_CALLBACK_POINTER* game_command_callback_get_callback(int index); +extern int game_command_playerid; + +extern GAME_COMMAND_POINTER* new_game_command_table[66]; extern int gGameSpeed; extern float gDayNightCycle; @@ -134,7 +141,7 @@ void game_reduce_game_speed(); void game_load_or_quit_no_save_prompt(); int game_load_sv6(SDL_RWops* rw); int game_load_network(SDL_RWops* rw); -int game_load_save(const char *path); +bool game_load_save(const utf8 *path); void game_load_init(); void game_pause_toggle(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void pause_toggle(); diff --git a/src/hook.c b/src/hook.c index be83f39dc3..191516d301 100644 --- a/src/hook.c +++ b/src/hook.c @@ -18,11 +18,14 @@ * along with this program. If not, see . *****************************************************************************/ -#ifdef _WIN32 +#include "common.h" + +#ifdef __WINDOWS__ #include #else #include -#endif // _WIN32 +#endif // __WINDOWS__ + #include "hook.h" #include "platform/platform.h" @@ -30,6 +33,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; @@ -53,73 +64,6 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in int rargssize = numrargs * 4; - data[i++] = 0x50; // push eax - - // move stack down for possible existing arguments - for (int j = 0; j < stacksize; j++) { - data[i++] = 0x8B; // mov eax, [esp+x] - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)((4 * (stacksize - j)) + 4); - - data[i++] = 0x89; // mov [esp+x], eax - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)((4 * (stacksize - j)) - ((registerssaved + stacksize) * 4)); - } - - if (numrargs > 0) { - // push the registers to be on the stack to access as arguments - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = -((registerssaved + stacksize) * 4) + 4; - - for (signed int j = numrargs - 1; j >= 0; j--) { - switch (registerargs[j]) { - case EAX: data[i++] = 0x50; break; - case EBX: data[i++] = 0x53; break; - case ECX: data[i++] = 0x51; break; - case EDX: data[i++] = 0x52; break; - case ESI: data[i++] = 0x56; break; - case EDI: data[i++] = 0x57; break; - case EBP: data[i++] = 0x55; break; - } - } - - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = rargssize + ((registerssaved + stacksize) * 4) - 4; - } - - - data[i++] = 0xE8; // call - data[i++] = 0x00; - data[i++] = 0x00; - data[i++] = 0x00; - data[i++] = 0x00; - - int sizec = i; - - data[i++] = 0x8B; // push eax, [esp] - puts eip in eax - data[i++] = 0x04; - data[i++] = 0xE4; - - data[i++] = 0x83; // add eax, x - data[i++] = 0xC0; - int sizeoffset = i; - data[i++] = 0; // set to returnlocation offset later - - data[i++] = 0x89; // mov [esp-20h], eax - put return address on stack - data[i++] = 0x44; - data[i++] = 0xE4; - data[i++] = (signed char)(-(registerssaved * 4) - rargssize - (stacksize * 4)) + 4; - - data[i++] = 0x83; // add esp, x - data[i++] = 0xC4; - data[i++] = 4; - - data[i++] = 0x58; // pop eax - if (!(registersreturned & EAX)) { data[i++] = 0x50; // push eax } @@ -142,14 +86,52 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0x57; // push edi } - data[i++] = 0x83; // sub esp, x - data[i++] = 0xEC; - data[i++] = 4 + (stacksize * 4) + rargssize; + data[i++] = 0x50; //push eax + data[i++] = 0x89; //mov eax, esp + data[i++] = 0xE0; + data[i++] = 0x83; //sub eax, (0xC + numargs*4) & 0xF + data[i++] = 0xE8; + data[i++] = (0xC + numrargs * 4) & 0xF; + data[i++] = 0x83; //and eax, 0xC + data[i++] = 0xE0; + data[i++] = 0x0C; + data[i++] = 0xA3; //mov [0x9ABDA8], eax + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; + data[i++] = 0x58; //pop eax + data[i++] = 0x2B; //sub esp, [0x9ABDA8] + data[i++] = 0x25; + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; - data[i++] = 0xE9; // jmp - *((int *)&data[i]) = (newaddress - address - i - 4); i += 4; + // work out distance to nearest 0xC + // (esp - numargs * 4) & 0xC + // move to align - 4 + // save that amount - data[sizeoffset] = i - sizec; + if (numrargs > 0) { + // push the registers to be on the stack to access as arguments + for (signed int j = numrargs - 1; j >= 0; j--) { + switch (registerargs[j]) { + case EAX: data[i++] = 0x50; break; + case EBX: data[i++] = 0x53; break; + case ECX: data[i++] = 0x51; break; + case EDX: data[i++] = 0x52; break; + case ESI: data[i++] = 0x56; break; + case EDI: data[i++] = 0x57; break; + case EBP: data[i++] = 0x55; break; + } + } + } + + data[i++] = 0xE8; // call + + write_address_strictalias(&data[i], newaddress - address - i - 4); + i += 4; // returnlocation: @@ -190,6 +172,13 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0xEC; data[i++] = (signed char)(stacksize * -4) - rargssize; + data[i++] = 0x03; //add esp, [0x9ABDA8] + data[i++] = 0x25; + data[i++] = 0xA8; + data[i++] = 0xBD; + data[i++] = 0x9A; + data[i++] = 0x00; + if (!(registersreturned & EDI)) { data[i++] = 0x5F; // pop edi } @@ -214,19 +203,19 @@ void hookfunc(int address, int newaddress, int stacksize, int registerargs[], in data[i++] = 0xC3; // retn -#ifdef _WIN32 +#ifdef __WINDOWS__ WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0); #else // We own the pages with PROT_WRITE | PROT_EXEC, we can simply just memcpy the data memcpy((void *)address, data, i); -#endif // _WIN32 +#endif // __WINDOWS__ } void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister) { if (!g_hooktableaddress) { size_t size = g_maxhooks * 100; -#ifdef _WIN32 +#ifdef __WINDOWS__ g_hooktableaddress = VirtualAllocEx(GetCurrentProcess(), NULL, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else g_hooktableaddress = mmap(NULL, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); @@ -235,7 +224,7 @@ void addhook(int address, int newaddress, int stacksize, int registerargs[], int perror("mmap"); exit(1); } -#endif // _WIN32 +#endif // __WINDOWS__ } if (g_hooktableoffset > g_maxhooks) { return; @@ -244,14 +233,29 @@ 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 +#ifdef __WINDOWS__ WriteProcessMemory(GetCurrentProcess(), (LPVOID)address, data, i, 0); #else // We own the pages with PROT_WRITE | PROT_EXEC, we can simply just memcpy the data + int err = mprotect((void *)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_WRITE); + if (err != 0) + { + perror("mprotect"); + } + memcpy((void *)address, data, i); -#endif // _WIN32 + + err = mprotect((void *)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_EXEC); + if (err != 0) + { + perror("mprotect"); + } +#endif // __WINDOWS__ hookfunc(hookaddress, newaddress, stacksize, registerargs, registersreturned, eaxDestinationRegister); g_hooktableoffset++; } diff --git a/src/hook.h b/src/hook.h index 7f2289f059..4e5bd3776c 100644 --- a/src/hook.h +++ b/src/hook.h @@ -34,4 +34,4 @@ enum REGISTER_ARGS { void addhook(int address, int newaddress, int stacksize, int registerargs[], int registersreturned, int eaxDestinationRegister); -#endif \ No newline at end of file +#endif diff --git a/src/image_io.c b/src/image_io.c new file mode 100644 index 0000000000..bbfc434ffa --- /dev/null +++ b/src/image_io.c @@ -0,0 +1,298 @@ +#include + +#include "image_io.h" + +static void my_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length); +static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length); +static void my_png_flush(png_structp png_ptr); + +bool image_io_png_read(uint8 **pixels, uint32 *width, uint32 *height, const utf8 *path) +{ + png_structp png_ptr; + png_infop info_ptr; + unsigned int sig_read = 0; + + // Setup PNG structures + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + return false; + } + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_read_struct(&png_ptr, NULL, NULL); + return false; + } + + // Open PNG file + SDL_RWops *fp = SDL_RWFromFile(path, "rb"); + if (fp == NULL) { + return false; + } + + // Set error handling + if (setjmp(png_jmpbuf(png_ptr))) { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + SDL_RWclose(fp); + return false; + } + + // Setup png reading + png_set_read_fn(png_ptr, fp, my_png_read_data); + png_set_sig_bytes(png_ptr, sig_read); + + // To simplify the reading process, convert 4-16 bit data to 24-32 bit data + png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, NULL); + + // Read header + png_uint_32 pngWidth, pngHeight; + int bit_depth, colour_type, interlace_type; + png_get_IHDR(png_ptr, info_ptr, &pngWidth, &pngHeight, &bit_depth, &colour_type, &interlace_type, NULL, NULL); + + // Read pixels as 32bpp RGBA data + png_size_t rowBytes = png_get_rowbytes(png_ptr, info_ptr); + png_bytepp rowPointers = png_get_rows(png_ptr, info_ptr); + uint8 *pngPixels = (uint8*)malloc(pngWidth * pngHeight * 4); + uint8 *dst = pngPixels; + if (colour_type == PNG_COLOR_TYPE_RGB) { + // 24-bit PNG (no alpha) + assert(rowBytes == pngWidth * 3); + for (png_uint_32 i = 0; i < pngHeight; i++) { + uint8 *src = rowPointers[i]; + for (png_uint_32 x = 0; x < pngWidth; x++) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + *dst++ = 255; + } + } + } else { + // 32-bit PNG (with alpha) + assert(rowBytes == pngWidth * 4); + for (png_uint_32 i = 0; i < pngHeight; i++) { + memcpy(dst, rowPointers[i], rowBytes); + dst += rowBytes; + } + } + + // Close the PNG + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + SDL_RWclose(fp); + + // Return the output data + *pixels = (uint8*)pngPixels; + if (width != NULL) *width = pngWidth; + if (height != NULL) *height = pngHeight; + return true; +} + +bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path) +{ + // Get image size + int stride = dpi->width + dpi->pitch; + + // Setup PNG + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + return false; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } + + png_colorp png_palette = (png_colorp)png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH * sizeof(png_color)); + for (int i = 0; i < 256; i++) { + const rct_palette_entry *entry = &palette->entries[i]; + png_palette[i].blue = entry->blue; + png_palette[i].green = entry->green; + png_palette[i].red = entry->red; + } + + png_set_PLTE(png_ptr, info_ptr, png_palette, PNG_MAX_PALETTE_LENGTH); + + // Open file for writing + SDL_RWops *file = SDL_RWFromFile(path, "wb"); + if (file == NULL) { + png_free(png_ptr, png_palette); + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return false; + } + png_set_write_fn(png_ptr, file, my_png_write_data, my_png_flush); + + // Set error handler + if (setjmp(png_jmpbuf(png_ptr))) { + png_free(png_ptr, png_palette); + png_destroy_write_struct(&png_ptr, &info_ptr); + SDL_RWclose(file); + return false; + } + + // Write header + png_set_IHDR( + png_ptr, info_ptr, dpi->width, dpi->height, 8, + PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT + ); + png_byte transparentIndex = 0; + png_set_tRNS(png_ptr, info_ptr, &transparentIndex, 1, NULL); + png_write_info(png_ptr, info_ptr); + + // Write pixels + uint8 *bits = dpi->bits; + for (int y = 0; y < dpi->height; y++) { + png_write_row(png_ptr, (png_byte *)bits); + bits += stride; + } + + // Finish + png_write_end(png_ptr, NULL); + SDL_RWclose(file); + + png_free(png_ptr, png_palette); + png_destroy_write_struct(&png_ptr, &info_ptr); + return true; +} + +static void my_png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + SDL_RWops *file = (SDL_RWops*)png_get_io_ptr(png_ptr); + SDL_RWread(file, data, length, 1); +} + +static void my_png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +{ + SDL_RWops *file = (SDL_RWops*)png_get_io_ptr(png_ptr); + SDL_RWwrite(file, data, length, 1); +} + +static void my_png_flush(png_structp png_ptr) +{ + +} + +// Bitmap header structs, for cross platform purposes +typedef struct { + uint16 bfType; + uint32 bfSize; + uint16 bfReserved1; + uint16 bfReserved2; + uint32 bfOffBits; +} BitmapFileHeader; + +typedef struct { + uint32 biSize; + sint32 biWidth; + sint32 biHeight; + uint16 biPlanes; + uint16 biBitCount; + uint32 biCompression; + uint32 biSizeImage; + sint32 biXPelsPerMeter; + sint32 biYPelsPerMeter; + uint32 biClrUsed; + uint32 biClrImportant; +} BitmapInfoHeader; + +/** + * + * rct2: 0x00683D20 + */ +bool image_io_bmp_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path) +{ + BitmapFileHeader header; + BitmapInfoHeader info; + + int i, y, width, height, stride; + uint8 *buffer, *row; + SDL_RWops *fp; + unsigned int bytesWritten; + + // Open binary file for writing + if ((fp = SDL_RWFromFile(path, "wb")) == NULL){ + return false; + } + + // Allocate buffer + buffer = malloc(0xFFFF); + if (buffer == NULL) { + SDL_RWclose(fp); + return false; + } + + // Get image size + width = dpi->width; + height = dpi->height; + stride = dpi->width + dpi->pitch; + + // File header + memset(&header, 0, sizeof(header)); + header.bfType = 0x4D42; + header.bfSize = height * stride + 1038; + header.bfOffBits = 1038; + + bytesWritten = SDL_RWwrite(fp, &header, sizeof(BitmapFileHeader), 1); + if (bytesWritten != 1) { + SDL_RWclose(fp); + SafeFree(buffer); + log_error("failed to save screenshot"); + return false; + } + + // Info header + memset(&info, 0, sizeof(info)); + info.biSize = sizeof(info); + info.biWidth = width; + info.biHeight = height; + info.biPlanes = 1; + info.biBitCount = 8; + info.biXPelsPerMeter = 2520; + info.biYPelsPerMeter = 2520; + info.biClrUsed = 246; + + bytesWritten = SDL_RWwrite(fp, &info, sizeof(BitmapInfoHeader), 1); + if (bytesWritten != 1) { + SDL_RWclose(fp); + SafeFree(buffer); + log_error("failed to save screenshot"); + return false; + } + + // Palette + memset(buffer, 0, 246 * 4); + for (i = 0; i < 246; i++) { + const rct_palette_entry *entry = &palette->entries[i]; + buffer[i * 4 + 0] = entry->blue; + buffer[i * 4 + 1] = entry->green; + buffer[i * 4 + 2] = entry->red; + } + + bytesWritten = SDL_RWwrite(fp, buffer, sizeof(char), 246 * 4); + if (bytesWritten != 246*4){ + SDL_RWclose(fp); + SafeFree(buffer); + log_error("failed to save screenshot"); + return false; + } + + // Image, save upside down + for (y = dpi->height - 1; y >= 0; y--) { + row = dpi->bits + y * (dpi->width + dpi->pitch); + + memset(buffer, 0, stride); + memcpy(buffer, row, dpi->width); + + bytesWritten = SDL_RWwrite(fp, buffer, sizeof(char), stride); + if (bytesWritten != stride){ + SDL_RWclose(fp); + SafeFree(buffer); + log_error("failed to save screenshot"); + return false; + } + } + + SDL_RWclose(fp); + free(buffer); + return true; +} diff --git a/src/image_io.h b/src/image_io.h new file mode 100644 index 0000000000..fa8c086b05 --- /dev/null +++ b/src/image_io.h @@ -0,0 +1,12 @@ +#ifndef _IMAGE_IO_H_ +#define _IMAGE_IO_H_ + +#include "common.h" +#include "drawing/drawing.h" + +bool image_io_png_read(uint8 **pixels, uint32 *width, uint32 *height, const utf8 *path); + +bool image_io_png_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path); +bool image_io_bmp_write(const rct_drawpixelinfo *dpi, const rct_palette *palette, const utf8 *path); + +#endif diff --git a/src/input.c b/src/input.c index 68fe6541a9..c5279f291f 100644 --- a/src/input.c +++ b/src/input.c @@ -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,18 +43,48 @@ #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; +enum { + MOUSE_STATE_RELEASED, + MOUSE_STATE_LEFT_PRESS, + MOUSE_STATE_LEFT_RELEASE, + MOUSE_STATE_RIGHT_PRESS, + MOUSE_STATE_RIGHT_RELEASE +}; typedef struct { - uint32 x, y; - uint32 state; //1 = LeftDown 2 = LeftUp 3 = RightDown 4 = RightUp + uint32 x; + uint32 y; + uint32 state; } rct_mouse_data; -rct_mouse_data* mouse_buffer = RCT2_ADDRESS(RCT2_ADDRESS_INPUT_QUEUE, rct_mouse_data); +static rct_mouse_data _mouseInputQueue[64]; +static uint8 _mouseInputQueueReadIndex = 0; +static uint8 _mouseInputQueueWriteIndex = 0; + +static uint32 _ticksSinceDragStart; +static widget_ref _dragWidget; +static uint8 _dragScrollIndex; +static sint32 _originalWindowWidth; +static sint32 _originalWindowHeight; + +static uint8 _currentScrollIndex; +static uint8 _currentScrollArea; + +uint8 gInputState; +uint8 gInputFlags; +uint8 gInputPlaceObjectModifier; + +sint32 gInputDragLastX; +sint32 gInputDragLastY; + +widget_ref gHoverWidget; +widget_ref gPressedWidget; + +uint16 gTooltipNotShownTicks; +uint16 gTooltipTimeout; +widget_ref gTooltipWidget; +sint32 gTooltipCursorX; +sint32 gTooltipCursorY; static void game_get_next_input(int *x, int *y, int *state); static void input_widget_over(int x, int y, rct_window *w, int widgetIndex); @@ -73,7 +102,7 @@ void game_handle_edge_scroll(); void game_handle_key_scroll(); static void input_widget_left(int x, int y, rct_window *w, int widgetIndex); void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_window* w, rct_widget* widget); -void sub_6ED990(char cursor_id); +void sub_6ED990(uint8 cursor_id); static void input_window_position_continue(rct_window *w, int lastX, int lastY, int newX, int newY); static void input_window_position_end(rct_window *w, int x, int y); static void input_window_resize_begin(rct_window *w, int widgetIndex, int x, int y); @@ -92,8 +121,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(); -static void sub_6EA2AA(rct_window *w, int widgetIndex, int x, int y, int edi); #pragma region Mouse input @@ -116,17 +143,17 @@ void game_handle_input() window_event_unknown_07_call(w); sub_6EA73F(); - update_cursor_position(); for (;;) { game_get_next_input(&x, &y, &state); - if (state == 0) + if (state == 0) { break; + } 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) { @@ -149,63 +176,67 @@ void game_handle_input() */ static void game_get_next_input(int *x, int *y, int *state) { - rct_mouse_data* eax = get_mouse_input(); - if (eax == NULL) { + rct_mouse_data *input = get_mouse_input(); + if (input == NULL) { *x = gCursorState.x; *y = gCursorState.y; *state = 0; - return; + } else { + *x = input->x; + *y = input->y; + *state = input->state; } - - *x = eax->x; - *y = eax->y; - *state = eax->state; - - // NOTE this function lacks tutorial logic } /** * * rct2: 0x00407074 */ -static rct_mouse_data* get_mouse_input() +static rct_mouse_data *get_mouse_input() { - uint32 read_index = RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_READ_INDEX, uint32); - - // check if that location has been written to yet - if (read_index == RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_WRITE_INDEX, uint32)) + // Check if that location has been written to yet + if (_mouseInputQueueReadIndex == _mouseInputQueueWriteIndex) { return NULL; - - RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_READ_INDEX, uint32) = (read_index + 1) % 64; - return &mouse_buffer[read_index]; + } else { + rct_mouse_data *result = &_mouseInputQueue[_mouseInputQueueReadIndex]; + _mouseInputQueueReadIndex = (_mouseInputQueueReadIndex + 1) % countof(_mouseInputQueue); + return result; + } } -/* rct2: 0x006E957F +/** + * + * 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; - _dragX = x; - _dragY = y; - _dragWindowClass = w->classification; - _dragWindowNumber = w->number; - _dragWidgetIndex = widgetIndex; - RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 0; +static void input_scroll_drag_begin(int x, int y, rct_window* w, rct_widget* widget, int widgetIndex) +{ + gInputState = INPUT_STATE_SCROLL_RIGHT; + gInputDragLastX = x; + gInputDragLastY = y; + _dragWidget.window_classification = w->classification; + _dragWidget.window_number = w->number; + _dragWidget.widget_index = widgetIndex; + _ticksSinceDragStart = 0; _dragScrollIndex = window_get_scroll_data_index(w, widgetIndex); platform_hide_cursor(); } -/* Based on (heavily changed) rct2: 0x006E9E0E & 0x006E9ED0 */ -static void input_scroll_drag_continue(int x, int y, rct_window* w) { - uint8 widgetIndex = _dragWidgetIndex; +/** + * Based on (heavily changed) + * rct2: 0x006E9E0E, 0x006E9ED0 + */ +static void input_scroll_drag_continue(int x, int y, rct_window* w) +{ + rct_widgetindex widgetIndex = _dragWidget.widget_index; uint8 scrollIndex = _dragScrollIndex; rct_widget* widget = &w->widgets[widgetIndex]; rct_scroll* scroll = &w->scrolls[scrollIndex]; int dx, dy; - dx = x - _dragX; - dy = y - _dragY; + dx = x - gInputDragLastX; + dy = y - gInputDragLastY; if (scroll->flags & HSCROLLBAR_VISIBLE) { sint16 size = widget->right - widget->left - 1; @@ -225,33 +256,32 @@ static void input_scroll_drag_continue(int x, int y, rct_window* w) { widget_scroll_update_thumbs(w, widgetIndex); window_invalidate_by_number(w->classification, w->number); - platform_set_cursor_position(_dragX, _dragY); + platform_set_cursor_position(gInputDragLastX, gInputDragLastY); } -/* rct2: 0x006E8ACB*/ -static void input_scroll_right(int x, int y, int state) { - rct_window* w = window_find_by_number( - _dragWindowClass, - _dragWindowNumber - ); - +/** + * + * rct2: 0x006E8ACB + */ +static void input_scroll_right(int x, int y, int state) +{ + rct_window* w = window_find_by_number(_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; } switch (state) { - case 0: - RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, sint16); - if (x == 0 && y == 0) - return; - RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 1000; - - input_scroll_drag_continue(x, y, w); + case MOUSE_STATE_RELEASED: + _ticksSinceDragStart += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, sint16); + if (x != 0 || y != 0) { + _ticksSinceDragStart = 1000; + input_scroll_drag_continue(x, y, w); + } break; - case 4: - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + case MOUSE_STATE_RIGHT_RELEASE: + gInputState = INPUT_STATE_RESET; platform_show_cursor(); break; } @@ -272,59 +302,60 @@ 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 case INPUT_STATE_NORMAL: switch (state) { - case 0: + case MOUSE_STATE_RELEASED: input_widget_over(x, y, w, widgetIndex); break; - case 1: + case MOUSE_STATE_LEFT_PRESS: input_widget_left(x, y, w, widgetIndex); break; - case 3: + case MOUSE_STATE_RIGHT_PRESS: window_close_by_class(WC_TOOLTIP); - if (w != NULL) + if (w != NULL) { w = window_bring_to_front(w); - - if (widgetIndex == -1) - break; - - if (widget->type == WWT_VIEWPORT) { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_MANAGER | SCREEN_FLAGS_TITLE_DEMO))) - input_viewport_drag_begin(w, x, y); } - else if (widget->type == WWT_SCROLL) { - input_scroll_drag_begin(x, y, w, widget, widgetIndex); + + if (widgetIndex != -1) { + switch (widget->type) { + case WWT_VIEWPORT: + if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_TRACK_MANAGER | SCREEN_FLAGS_TITLE_DEMO))) { + input_viewport_drag_begin(w, x, y); + } + break; + case WWT_SCROLL: + input_scroll_drag_begin(x, y, w, widget, widgetIndex); + break; + } } break; } - break; case INPUT_STATE_WIDGET_PRESSED: 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; - } - else { - input_window_position_continue(w, _dragX, _dragY, x, y); - if (state == 2) + gInputState = INPUT_STATE_RESET; + } else { + input_window_position_continue(w, gInputDragLastX, gInputDragLastY, x, y); + if (state == MOUSE_STATE_LEFT_RELEASE) { input_window_position_end(w, x, y); + } } break; case INPUT_STATE_VIEWPORT_RIGHT: - if (state == 0) { + if (state == MOUSE_STATE_RELEASED) { input_viewport_drag_continue(); - } - else if (state == 4) { + } else if (state == MOUSE_STATE_RIGHT_RELEASE) { input_viewport_drag_end(); - if (RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) < 500) { + if (_ticksSinceDragStart < 500) { // If the user pressed the right mouse button for less than 500 ticks, interpret as right click viewport_interaction_right_click(x, y); } @@ -334,72 +365,75 @@ 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_VIEWPORT_LEFT: - w = window_find_by_number( - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWCLASS, rct_windowclass), - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_WINDOWNUMBER, rct_windownumber) - ); - if (!w){ - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0; + w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number); + if (w == NULL) { + gInputState = INPUT_STATE_RESET; break; } - if (state == 0){ - if (!w->viewport){ - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0; + switch (state) { + case MOUSE_STATE_RELEASED: + if (w->viewport == NULL) { + 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; + if (w->classification != _dragWidget.window_classification || + w->number != _dragWidget.window_number || + !(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) + ) { + break; + } w = window_find_by_number( RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) - ); - if (w == NULL) + ); + if (w == NULL) { break; - - window_event_tool_drag_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint32), x, y); - } - else if (state == 2){ - - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = 0; - if (RCT2_GLOBAL(0x9DE52E, rct_windownumber) != w->number)break; - if ((RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) & 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) - break; - 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)) - break; - viewport_interaction_left_click(x, y); + window_event_tool_drag_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y); + break; + case MOUSE_STATE_LEFT_RELEASE: + gInputState = INPUT_STATE_RESET; + if (_dragWidget.window_number == w->number) { + 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_up_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y); + } + } else if (!(gInputFlags & INPUT_FLAG_4)) { + viewport_interaction_left_click(x, y); + } } + break; } break; case INPUT_STATE_SCROLL_LEFT: - if (state == 0) + switch (state) { + case MOUSE_STATE_RELEASED: input_scroll_continue(w, widgetIndex, state, x, y); - else if (state == 2) + break; + case MOUSE_STATE_LEFT_RELEASE: input_scroll_end(); + break; + } 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; - } - else { - if (state == 2) + gInputState = INPUT_STATE_RESET; + } else { + if (state == MOUSE_STATE_LEFT_RELEASE) { input_window_resize_end(); - - if (state == 0 || state == 2) + } + if (state == MOUSE_STATE_RELEASED || state == MOUSE_STATE_LEFT_RELEASE) { input_window_resize_continue(w, x, y); + } } break; case INPUT_STATE_SCROLL_RIGHT: @@ -412,12 +446,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; - _dragX = x - w->x; - _dragY = y - w->y; - _dragWindowClass = w->classification; - _dragWindowNumber = w->number; - _dragWidgetIndex = widgetIndex; + gInputState = INPUT_STATE_POSITIONING_WINDOW; + gInputDragLastX = x - w->x; + gInputDragLastY = y - w->y; + _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) @@ -430,22 +464,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; - _dragX = x; - _dragY = y; - _dragWindowClass = w->classification; - _dragWindowNumber = w->number; - _dragWidgetIndex = widgetIndex; + gInputState = INPUT_STATE_RESIZING; + gInputDragLastX = x; + gInputDragLastY = y; + _dragWidget.window_classification = w->classification; + _dragWidget.window_number = w->number; + _dragWidget.widget_index = widgetIndex; _originalWindowWidth = w->width; _originalWindowHeight = w->height; } @@ -455,8 +487,8 @@ static void input_window_resize_continue(rct_window *w, int x, int y) int dx, dy, targetWidth, targetHeight; if (y < RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 2) { - dx = x - _dragX; - dy = y - _dragY; + dx = x - gInputDragLastX; + dy = y - gInputDragLastY; targetWidth = _originalWindowWidth + dx; targetHeight = _originalWindowHeight + dy; @@ -470,11 +502,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 @@ -484,14 +514,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; - RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 0; - platform_get_cursor_position(&_dragX, &_dragY); + gInputState = INPUT_STATE_VIEWPORT_RIGHT; + _dragWidget.window_classification = w->classification; + _dragWidget.window_number = w->number; + _ticksSinceDragStart = 0; + platform_get_cursor_position(&gInputDragLastX, &gInputDragLastY); platform_hide_cursor(); - // RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_5; + // gInputFlags |= INPUT_FLAG_5; } static void input_viewport_drag_continue() @@ -502,23 +532,29 @@ static void input_viewport_drag_continue() platform_get_cursor_position(&newDragX, &newDragY); - dx = newDragX - _dragX; - dy = newDragY - _dragY; - w = window_find_by_number(_dragWindowClass, _dragWindowNumber); - assert(w != NULL); + dx = newDragX - gInputDragLastX; + dy = newDragY - gInputDragLastY; + w = window_find_by_number(_dragWidget.window_classification, _dragWidget.window_number); + + // #3294: Window can be closed during a drag session, so just finish + // the session if the window no longer exists + if (w == NULL) { + input_viewport_drag_end(); + return; + } viewport = w->viewport; - RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) += RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_LAST_UPDATE, sint16); + _ticksSinceDragStart += 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 // If the drag time is less than 500 the "drag" is usually interpreted as a right click. // As the user moved the mouse, don't interpret it as right click in any case. - RCT2_GLOBAL(RCT2_ADDRESS_TICKS_SINCE_DRAG_START, sint16) = 1000; + _ticksSinceDragStart = 1000; dx <<= viewport->zoom + 1; dy <<= viewport->zoom + 1; @@ -532,12 +568,12 @@ static void input_viewport_drag_continue() } } - platform_set_cursor_position(_dragX, _dragY); + platform_set_cursor_position(gInputDragLastX, gInputDragLastY); } static void input_viewport_drag_end() { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; platform_show_cursor(); } @@ -551,19 +587,19 @@ 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; - 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; + gInputState = INPUT_STATE_SCROLL_LEFT; + gPressedWidget.window_classification = w->classification; + gPressedWidget.window_number = w->number; + gPressedWidget.widget_index = widgetIndex; + gTooltipCursorX = x; + gTooltipCursorY = y; int eax, ebx, scroll_area, scroll_id; scroll_id = 0; // safety widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &scroll_area, &scroll_id); - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) = scroll_area; - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32) = scroll_id * sizeof(rct_scroll); + _currentScrollArea = scroll_area; + _currentScrollIndex = scroll_id; window_event_unknown_15_call(w, scroll_id, scroll_area); if (scroll_area == SCROLL_PART_VIEW){ window_event_scroll_mousedown_call(w, scroll_id, eax, ebx); @@ -624,41 +660,34 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int assert(w != NULL); widget = &w->widgets[widgetIndex]; - if (widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32)){ - invalidate_scroll(); - return; - } - if (w->classification != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8)){ - invalidate_scroll(); - return; - } - if (w->number != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16)){ + if (w->classification != gPressedWidget.window_classification || + w->number != gPressedWidget.window_number || + widgetIndex != gPressedWidget.widget_index + ) { invalidate_scroll(); return; } 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; - input_scroll_part_update_hthumb(w, widgetIndex, x, scroll_id); + if (_currentScrollArea == SCROLL_PART_HSCROLLBAR_THUMB){ + int originalTooltipCursorX = gTooltipCursorX; + gTooltipCursorX = x; + input_scroll_part_update_hthumb(w, widgetIndex, x - originalTooltipCursorX, scroll_id); return; } - if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16) == SCROLL_PART_VSCROLLBAR_THUMB){ - int temp_y = y; - y -= RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16); - RCT2_GLOBAL(RCT2_ADDRESS_TOOLTIP_CURSOR_Y, uint16) = temp_y; - input_scroll_part_update_vthumb(w, widgetIndex, y, scroll_id); + if (_currentScrollArea == SCROLL_PART_VSCROLLBAR_THUMB){ + int originalTooltipCursorY = gTooltipCursorY; + gTooltipCursorY = y; + input_scroll_part_update_vthumb(w, widgetIndex, y - originalTooltipCursorY, scroll_id); return; } x = x2; y = y2; - if (scroll_part != RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_AREA, uint16)){ + if (scroll_part != _currentScrollArea) { invalidate_scroll(); return; } @@ -673,10 +702,6 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int case SCROLL_PART_HSCROLLBAR_RIGHT: input_scroll_part_update_hright(w, widgetIndex, scroll_id); break; - case SCROLL_PART_HSCROLLBAR_LEFT_TROUGH: - case SCROLL_PART_HSCROLLBAR_RIGHT_TROUGH: - return; - break; case SCROLL_PART_HSCROLLBAR_THUMB: case SCROLL_PART_VSCROLLBAR_TOP: input_scroll_part_update_vtop(w, widgetIndex, scroll_id); @@ -684,24 +709,18 @@ static void input_scroll_continue(rct_window *w, int widgetIndex, int state, int case SCROLL_PART_VSCROLLBAR_BOTTOM: input_scroll_part_update_vbottom(w, widgetIndex, scroll_id); break; - case SCROLL_PART_VSCROLLBAR_TOP_TROUGH: - case SCROLL_PART_VSCROLLBAR_BOTTOM_TROUGH: - return; - break; - default: - return; } } static void input_scroll_end() { - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) = INPUT_STATE_RESET; + gInputState = INPUT_STATE_RESET; invalidate_scroll(); } /** * - * rct: 0x006E98F2 + * rct2: 0x006E98F2 */ static void input_scroll_part_update_hthumb(rct_window *w, int widgetIndex, int x, int scroll_id) { @@ -738,7 +757,7 @@ static void input_scroll_part_update_hthumb(rct_window *w, int widgetIndex, int /** * - * rct: 0x006E99A9 + * rct2: 0x006E99A9 */ static void input_scroll_part_update_vthumb(rct_window *w, int widgetIndex, int y, int scroll_id) { @@ -776,16 +795,14 @@ static void input_scroll_part_update_vthumb(rct_window *w, int widgetIndex, int /** * - * rct: 0x006E9A60 + * rct2: 0x006E9A60 */ static void input_scroll_part_update_hleft(rct_window *w, int widgetIndex, int scroll_id) { assert(w != NULL); if (window_find_by_number(w->classification, w->number)) { w->scrolls[scroll_id].flags |= HSCROLLBAR_LEFT_PRESSED; - if (w->scrolls[scroll_id].h_left < 0) - w->scrolls[scroll_id].h_left = 0; - else if (w->scrolls[scroll_id].h_left >= 3) + if (w->scrolls[scroll_id].h_left >= 3) w->scrolls[scroll_id].h_left -= 3; widget_scroll_update_thumbs(w, widgetIndex); widget_invalidate_by_number(w->classification, w->number, widgetIndex); @@ -794,7 +811,7 @@ static void input_scroll_part_update_hleft(rct_window *w, int widgetIndex, int s /** * - * rct: 0x006E9ABF + * rct2: 0x006E9ABF */ static void input_scroll_part_update_hright(rct_window *w, int widgetIndex, int scroll_id) { @@ -819,16 +836,14 @@ static void input_scroll_part_update_hright(rct_window *w, int widgetIndex, int /** * - * rct: 0x006E9C37 + * rct2: 0x006E9C37 */ static void input_scroll_part_update_vtop(rct_window *w, int widgetIndex, int scroll_id) { assert(w != NULL); if (window_find_by_number(w->classification, w->number)) { w->scrolls[scroll_id].flags |= VSCROLLBAR_UP_PRESSED; - if (w->scrolls[scroll_id].v_top < 0) - w->scrolls[scroll_id].v_top = 0; - else if (w->scrolls[scroll_id].v_top >= 3) + if (w->scrolls[scroll_id].v_top >= 3) w->scrolls[scroll_id].v_top -= 3; widget_scroll_update_thumbs(w, widgetIndex); widget_invalidate_by_number(w->classification, w->number, widgetIndex); @@ -837,7 +852,7 @@ static void input_scroll_part_update_vtop(rct_window *w, int widgetIndex, int sc /** * - * rct: 0x006E9C96 + * rct2: 0x006E9C96 */ static void input_scroll_part_update_vbottom(rct_window *w, int widgetIndex, int scroll_id) { @@ -883,12 +898,12 @@ static void input_widget_over(int x, int y, rct_window *w, int widgetIndex) input_widget_over_change_check(windowClass, windowNumber, widgetIndex); if (w != NULL && widgetIndex != -1 && widget->type == WWT_SCROLL) { - int eax, ebx, ecx, edx; - widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &ecx, &edx); + int eax, ebx, scroll_part, edx; + widget_scroll_get_part(w, widget, x, y, &eax, &ebx, &scroll_part, &edx); - if (ecx < 0) - input_update_tooltip(w, widgetIndex, x, y); - else if (ecx == 0) { + if (scroll_part != SCROLL_PART_VIEW) + window_tooltip_close(); + else { window_event_scroll_mouseover_call(w, edx, eax, ebx); input_update_tooltip(w, widgetIndex, x, y); } @@ -897,9 +912,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; } /** @@ -913,18 +928,17 @@ static void input_widget_over_change_check(rct_windowclass windowClass, rct_wind return; // Check if the widget that the cursor was over, has changed - if ( - windowClass != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) || - windowNumber != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) || - widgetIndex != RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint16) - ) { + if (windowClass != gHoverWidget.window_classification || + windowNumber != gHoverWidget.window_number || + widgetIndex != gHoverWidget.widget_index + ) { // Invalidate last widget cursor was on if widget is a flat button input_widget_over_flatbutton_invalidate(); // Set new cursor over widget - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) = windowClass; - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) = windowNumber; - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint16) = widgetIndex; + gHoverWidget.window_classification = windowClass; + gHoverWidget.window_number = windowNumber; + gHoverWidget.widget_index = widgetIndex; // Invalidate new widget cursor is on if widget is a flat button if (windowClass != 255) @@ -938,20 +952,16 @@ static void input_widget_over_change_check(rct_windowclass windowClass, rct_wind */ static void input_widget_over_flatbutton_invalidate() { - rct_window *w = window_find_by_number( - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) - ); - if (w == NULL) - return; - - window_event_invalidate_call(w); - if (w->widgets[RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber)].type == WWT_FLATBTN) { - widget_invalidate_by_number( - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass), - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber), - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, rct_windownumber) + rct_window *w = window_find_by_number(gHoverWidget.window_classification, gHoverWidget.window_number); + if (w != NULL) { + window_event_invalidate_call(w); + if (w->widgets[gHoverWidget.widget_index].type == WWT_FLATBTN) { + widget_invalidate_by_number( + gHoverWidget.window_classification, + gHoverWidget.window_number, + gHoverWidget.widget_index ); + } } } @@ -997,19 +1007,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; - 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) { + gInputState = INPUT_STATE_VIEWPORT_LEFT; + gInputDragLastX = x; + gInputDragLastY = y; + _dragWidget.window_classification = windowClass; + _dragWidget.window_number = windowNumber; + 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, uint32), x, y); - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_4; + window_event_tool_down_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y); + gInputFlags |= INPUT_FLAG_4; } } break; @@ -1024,11 +1034,11 @@ static void input_widget_left(int x, int y, rct_window *w, int widgetIndex) audio_play_sound_panned(SOUND_CLICK_1, w->x + (widget->left + widget->right) / 2, 0, 0, 0); // Set new cursor down widget - 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; + gPressedWidget.window_classification = windowClass; + gPressedWidget.window_number = windowNumber; + gPressedWidget.widget_index = widgetIndex; + gInputFlags |= INPUT_FLAG_WIDGET_PRESSED; + gInputState = INPUT_STATE_WIDGET_PRESSED; RCT2_GLOBAL(0x009DE528, uint16) = 1; widget_invalidate_by_number(windowClass, windowNumber, widgetIndex); @@ -1064,7 +1074,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; @@ -1080,11 +1090,11 @@ void process_mouse_over(int x, int y) if (subWindow == NULL) break; - ebx = ebx & 0xFFFFFF00; + ebx = 0; edi = cursorId; esi = (int)subWindow; - // Not sure what this is for, no windows actually implement a handler - // RCT2_CALLFUNC_X(subWindow->event_handlers[WE_UNKNOWN_0E], &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + // Window event WE_UNKNOWN_0E was called here, but no windows actually implemented a handler and + // its not known what it was for cursorId = edi; if ((ebx & 0xFF) != 0) { @@ -1146,17 +1156,17 @@ 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, uint8), - RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, uint16) + RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), + RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) ); if (!w) tool_cancel(); else - window_event_tool_update_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint32), x, y); + window_event_tool_update_call(w, RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16), x, y); } } @@ -1172,18 +1182,18 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi rct_windowclass cursor_w_class; rct_windownumber cursor_w_number; - cursor_w_class = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass); - cursor_w_number = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, rct_windownumber); - int cursor_widgetIndex = RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32); + cursor_w_class = gPressedWidget.window_classification; + cursor_w_number = gPressedWidget.window_number; + int cursor_widgetIndex = gPressedWidget.widget_index; 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; } - switch (state){ - case 0: + switch (state) { + case MOUSE_STATE_RELEASED: if (!w || cursor_w_class != w->classification || cursor_w_number != w->number || widgetIndex != cursor_widgetIndex) break; @@ -1200,14 +1210,20 @@ 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) { + if (gInputState == INPUT_STATE_DROPDOWN_ACTIVE) { + gDropdownHighlightedIndex = gDropdownDefaultIndex; + window_invalidate_by_class(WC_DROPDOWN); + } + 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) { + case MOUSE_STATE_LEFT_RELEASE: + case MOUSE_STATE_RIGHT_PRESS: + if (gInputState == INPUT_STATE_DROPDOWN_ACTIVE) { if (w) { int dropdown_index = 0; @@ -1229,9 +1245,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; } } @@ -1239,26 +1255,34 @@ 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; + + if (dropdown_index == -1) { + if (!dropdown_is_disabled(gDropdownDefaultIndex)) { + dropdown_index = gDropdownDefaultIndex; + } + } window_event_dropdown_call(cursor_w, cursor_widgetIndex, dropdown_index); } dropdown_cleanup: window_close_by_class(WC_DROPDOWN); } - if (state == 3) return; + if (state == MOUSE_STATE_RIGHT_PRESS) { + 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; @@ -1280,22 +1304,27 @@ void input_state_widget_pressed(int x, int y, int state, int widgetIndex, rct_wi return; } - RCT2_GLOBAL(0x9DE528, uint16) = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) != 5){ + RCT2_GLOBAL(0x009DE528, uint16) = 0; + 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; } - if (!w) return; + gDropdownHighlightedIndex = -1; + window_invalidate_by_class(WC_DROPDOWN); + if (w == NULL) { + return; + } if (w->classification == WC_DROPDOWN){ int dropdown_index = dropdown_index_from_point(x, y, w); - - if (dropdown_index == -1) return; + if (dropdown_index == -1) { + return; + } if (gDropdownIsColour && gDropdownLastColourHover != dropdown_index) { gDropdownLastColourHover = dropdown_index; @@ -1321,36 +1350,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); + } } } @@ -1375,14 +1402,19 @@ void title_handle_keyboard_input() if (!gConsoleOpen) { // Handle modifier keys and key scrolling - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0; + gInputPlaceObjectModifier = PLACE_OBJECT_MODIFIER_NONE; if (RCT2_GLOBAL(0x009E2B64, uint32) != 1) { if (gKeysState[SDL_SCANCODE_LSHIFT] || gKeysState[SDL_SCANCODE_RSHIFT]) - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 1; + gInputPlaceObjectModifier |= PLACE_OBJECT_MODIFIER_SHIFT_Z; if (gKeysState[SDL_SCANCODE_LCTRL] || gKeysState[SDL_SCANCODE_RCTRL]) - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 2; + gInputPlaceObjectModifier |= PLACE_OBJECT_MODIFIER_COPY_Z; if (gKeysState[SDL_SCANCODE_LALT] || gKeysState[SDL_SCANCODE_RALT]) - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 4; + gInputPlaceObjectModifier |= 4; +#ifdef __MACOSX__ + if (gKeysState[SDL_SCANCODE_LGUI] || gKeysState[SDL_SCANCODE_RGUI]) { + gInputPlaceObjectModifier |= 8; + } +#endif } } @@ -1402,14 +1434,20 @@ void title_handle_keyboard_input() continue; } - key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8; + key |= gInputPlaceObjectModifier << 8; w = window_find_by_class(WC_CHANGE_KEYBOARD_SHORTCUT); if (w != NULL) { keyboard_shortcut_set(key); - } - else if (key == gShortcutKeys[SHORTCUT_SCREENSHOT]) { - keyboard_shortcut_handle_command(SHORTCUT_SCREENSHOT); + } else { + w = window_find_by_class(WC_TEXTINPUT); + if (w != NULL) { + window_text_input_key(w, key); + } + + if (key == gShortcutKeys[SHORTCUT_SCREENSHOT]) { + keyboard_shortcut_handle_command(SHORTCUT_SCREENSHOT); + } } } } @@ -1425,23 +1463,30 @@ 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 (gInputState == INPUT_STATE_NORMAL && gConfigGeneral.edge_scrolling) { + if (!(gInputPlaceObjectModifier & (PLACE_OBJECT_MODIFIER_SHIFT_Z | PLACE_OBJECT_MODIFIER_COPY_Z))) { + game_handle_edge_scroll(); + } + } // Handle modifier keys and key scrolling - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0; + gInputPlaceObjectModifier = PLACE_OBJECT_MODIFIER_NONE; if (RCT2_GLOBAL(0x009E2B64, uint32) != 1) { - if (gKeysState[SDL_SCANCODE_LSHIFT] || gKeysState[SDL_SCANCODE_RSHIFT]) - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) |= 1; - if (gKeysState[SDL_SCANCODE_LCTRL] || gKeysState[SDL_SCANCODE_RCTRL]) - 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(); + if (gKeysState[SDL_SCANCODE_LSHIFT] || gKeysState[SDL_SCANCODE_RSHIFT]) { + gInputPlaceObjectModifier |= PLACE_OBJECT_MODIFIER_SHIFT_Z; + } + if (gKeysState[SDL_SCANCODE_LCTRL] || gKeysState[SDL_SCANCODE_RCTRL]) { + gInputPlaceObjectModifier |= PLACE_OBJECT_MODIFIER_COPY_Z; + } + if (gKeysState[SDL_SCANCODE_LALT] || gKeysState[SDL_SCANCODE_RALT]) { + gInputPlaceObjectModifier |= 4; + } +#ifdef __MACOSX__ + if (gKeysState[SDL_SCANCODE_LGUI] || gKeysState[SDL_SCANCODE_RGUI]) { + gInputPlaceObjectModifier |= 8; + } +#endif + game_handle_key_scroll(); } } @@ -1466,16 +1511,12 @@ void game_handle_keyboard_input() continue; } - key |= RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) << 8; + key |= gInputPlaceObjectModifier << 8; 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 { + } else { w = window_find_by_class(WC_TEXTINPUT); if (w != NULL) { window_text_input_key(w, key); @@ -1484,78 +1525,6 @@ void game_handle_keyboard_input() } } } - - if (RCT2_GLOBAL(RCT2_ADDRESS_ON_TUTORIAL, uint8) == 0) - return; - - // Tutorial and the modifier key - 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); - } -} - -static void sub_6EA2AA(rct_window *w, int widgetIndex, int x, int y, int edi) -{ - 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); } /** @@ -1581,8 +1550,8 @@ int get_next_key() * * rct2: 0x006ED990 */ -void sub_6ED990(char cursor_id){ - if (RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, uint8) == INPUT_STATE_RESIZING) +void sub_6ED990(uint8 cursor_id){ + if (gInputState == INPUT_STATE_RESIZING) { cursor_id = CURSOR_DIAGONAL_ARROWS; //resize icon } @@ -1592,9 +1561,7 @@ void sub_6ED990(char cursor_id){ return; } RCT2_GLOBAL(RCT2_ADDRESS_CURENT_CURSOR, uint8) = cursor_id; - RCT2_GLOBAL(0x14241BC, uint32) = 2; platform_set_cursor(cursor_id); - RCT2_GLOBAL(0x14241BC, uint32) = 0; } @@ -1605,20 +1572,12 @@ void sub_6ED990(char cursor_id){ */ void invalidate_scroll() { - rct_window* wind = window_find_by_number( - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8), - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16) - ); - if (wind == NULL) return; - - int scroll_id = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SCROLL_ID, uint32); - //Reset to basic scroll - wind->scrolls[scroll_id / sizeof(rct_scroll)].flags &= 0xFF11; - - window_invalidate_by_number( - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, uint8), - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWNUMBER, uint16) - ); + rct_window* w = window_find_by_number(gPressedWidget.window_classification, gPressedWidget.window_number); + if (w != NULL) { + // Reset to basic scroll + w->scrolls[_currentScrollIndex].flags &= 0xFF11; + window_invalidate_by_number(gPressedWidget.window_classification, gPressedWidget.window_number); + } } /** @@ -1626,19 +1585,18 @@ void invalidate_scroll() */ void store_mouse_input(int state) { - uint32 write_index = RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_WRITE_INDEX, uint32); - uint32 next_write_index = (write_index + 1) % 64; + uint32 writeIndex = _mouseInputQueueWriteIndex; + uint32 nextWriteIndex = (writeIndex + 1) % countof(_mouseInputQueue); - // check if the queue is full - if (next_write_index == RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_READ_INDEX, uint32)) - return; + // Check if the queue is full + if (nextWriteIndex != _mouseInputQueueReadIndex) { + rct_mouse_data *item = &_mouseInputQueue[writeIndex]; + item->x = RCT2_GLOBAL(0x01424318, uint32); + item->y = RCT2_GLOBAL(0x0142431C, uint32); + item->state = state; - rct_mouse_data* item = &mouse_buffer[write_index]; - item->x = RCT2_GLOBAL(0x01424318, uint32); - item->y = RCT2_GLOBAL(0x0142431C, uint32); - item->state = state; - - RCT2_GLOBAL(RCT2_ADDRESS_MOUSE_WRITE_INDEX, uint32) = next_write_index; + _mouseInputQueueWriteIndex = nextWriteIndex; + } } void game_handle_edge_scroll() @@ -1676,11 +1634,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; } } @@ -1701,6 +1659,7 @@ void game_handle_key_scroll() textWindow = window_find_by_class(WC_TEXTINPUT); if (textWindow || gUsingWidgetTextBox) return; + if (gChatOpen) return; scrollX = 0; scrollY = 0; @@ -1709,6 +1668,7 @@ void game_handle_key_scroll() const int SHIFT = 0x100; const int CTRL = 0x200; const int ALT = 0x400; + const int CMD = 0x800; uint16 shortcutKey = gShortcutKeys[shortcutId]; uint8 scancode = shortcutKey & 0xFF; @@ -1725,6 +1685,11 @@ void game_handle_key_scroll() if (shortcutKey & ALT) { if (!gKeysState[SDL_SCANCODE_LALT] && !gKeysState[SDL_SCANCODE_RALT]) continue; } +#ifdef __MACOSX__ + if (shortcutKey & CMD) { + if (!gKeysState[SDL_SCANCODE_LGUI] && !gKeysState[SDL_SCANCODE_RGUI]) continue; + } +#endif switch (shortcutId) { case SHORTCUT_SCROLL_MAP_UP: @@ -1745,29 +1710,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; } } diff --git a/src/input.h b/src/input.h index 493b0faaa7..b02baa6377 100644 --- a/src/input.h +++ b/src/input.h @@ -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,6 +60,34 @@ enum { INPUT_FLAG_VIEWPORT_SCROLLING = (1 << 7) }; +enum { + PLACE_OBJECT_MODIFIER_NONE = 0, + PLACE_OBJECT_MODIFIER_SHIFT_Z = (1 << 0), + PLACE_OBJECT_MODIFIER_COPY_Z = (1 << 1), +}; + +typedef struct { + rct_windowclass window_classification; + rct_windownumber window_number; + rct_widgetindex widget_index; +} widget_ref; + +extern uint8 gInputState; +extern uint8 gInputFlags; +extern uint8 gInputPlaceObjectModifier; + +extern sint32 gInputDragLastX; +extern sint32 gInputDragLastY; + +extern widget_ref gHoverWidget; +extern widget_ref gPressedWidget; + +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(); @@ -55,4 +96,4 @@ void store_mouse_input(int state); void input_window_position_begin(rct_window *w, int widgetIndex, int x, int y); -#endif \ No newline at end of file +#endif diff --git a/src/interface/Theme.cpp b/src/interface/Theme.cpp new file mode 100644 index 0000000000..34df45b23f --- /dev/null +++ b/src/interface/Theme.cpp @@ -0,0 +1,847 @@ +#include + +extern "C" +{ + #include "../common.h" + #include "../config.h" + #include "themes.h" + #include "window.h" +} + +#include "../core/Json.hpp" +#include "../core/List.hpp" +#include "../core/Math.hpp" +#include "../core/Memory.hpp" +#include "../core/Path.hpp" +#include "../core/String.hpp" +#include "../core/Util.hpp" + +struct WindowThemeDesc; + +// Don't try to load theme files that exceed 64 MiB +constexpr uint64 MAX_THEME_SIZE = 64 * 1024 * 1024; + +/** + * Represents a window theming style such as the colour scheme. + */ +struct WindowTheme +{ + colour_t Colours[6]; +}; + +/** + * Represents the style for a particular type of window. + */ +struct UIThemeWindowEntry +{ + rct_windowclass WindowClass; + WindowTheme Theme; + + + json_t * ToJson() const; + static UIThemeWindowEntry FromJson(const WindowThemeDesc * wtDesc, const json_t * json); +}; + +/** + * Represents a user interface theme. Contains window colour schemes and appearance features. + */ +class UITheme +{ +public: + utf8 * Name; + List Entries; + uint8 Flags; + + UITheme(const utf8 * name); + UITheme(const UITheme & copy); + ~UITheme(); + + void SetName(const utf8 * name); + const UIThemeWindowEntry * GetEntry(rct_windowclass windowClass) const; + void SetEntry(const UIThemeWindowEntry * entry); + void RemoveEntry(rct_windowclass windowClass); + + json_t * ToJson() const; + bool WriteToFile(const utf8 * path) const; + + static UITheme * FromJson(const json_t * json); + static UITheme * FromFile(const utf8 * path); + static UITheme CreatePredefined(const utf8 * name, const UIThemeWindowEntry * entries, uint8 flags); +}; + +/** + * Represents the theme descriptor for a specific window type including the default colour scheme. + */ +struct WindowThemeDesc +{ + rct_windowclass WindowClass; + const utf8 * WindowClassSZ; + rct_string_id WindowName; + uint8 NumColours; + WindowTheme DefaultTheme; +}; + +#pragma region Window Theme Descriptors + +#define COLOURS_1(c0) 1, { { (c0), 0, 0, 0, 0, 0 } } +#define COLOURS_2(c0, c1) 2, { { (c0), (c1), 0, 0, 0, 0 } } +#define COLOURS_3(c0, c1, c2) 3, { { (c0), (c1), (c2), 0, 0, 0 } } +#define COLOURS_4(c0, c1, c2, c3) 4, { { (c0), (c1), (c2), (c3), 0, 0 } } +#define COLOURS_5(c0, c1, c2, c3, c4) 5, { { (c0), (c1), (c2), (c3), (c4), 0 } } +#define COLOURS_6(c0, c1, c2, c3, c4, c5) 6, { { (c0), (c1), (c2), (c3), (c4), (c5) } } + +#define THEME_DEF_END { 0xFF, { 0, 0, 0, 0, 0, 0 } } + +#define TWINDOW(window_class, window_name, window_string_id, theme) { window_class, window_name, window_string_id, theme } + +#define THEME_WC(wc) wc, #wc + +WindowThemeDesc WindowThemeDescriptors[] = +{ + // WindowClass, WindowClassSZ WindowName NumColours, DefaultTheme + { THEME_WC(WC_TOP_TOOLBAR), 5245, COLOURS_4(COLOUR_LIGHT_BLUE, COLOUR_DARK_GREEN, COLOUR_DARK_BROWN, COLOUR_GREY ) }, + { THEME_WC(WC_BOTTOM_TOOLBAR), 5246, COLOURS_4(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), COLOUR_BLACK, COLOUR_BRIGHT_GREEN ) }, + { THEME_WC(WC_RIDE), 5203, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_GREY ) }, + { THEME_WC(WC_RIDE_CONSTRUCTION), 5199, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_RIDE_LIST), 5204, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, + { THEME_WC(WC_SAVE_PROMPT), 5223, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, + { THEME_WC(WC_CONSTRUCT_RIDE), 5201, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, + { THEME_WC(WC_DEMOLISH_RIDE_PROMPT), 5224, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, + { THEME_WC(WC_SCENERY), 5197, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_GREEN, COLOUR_DARK_GREEN ) }, + { THEME_WC(WC_OPTIONS), 5219, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_FOOTPATH), 5198, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_LAND), 5193, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_WATER), 5194, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_PEEP), 5205, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, + { THEME_WC(WC_GUEST_LIST), 5206, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, + { THEME_WC(WC_STAFF_LIST), 5208, COLOURS_3(COLOUR_GREY, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE ) }, + { THEME_WC(WC_FIRE_PROMPT), 5225, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, + { THEME_WC(WC_PARK_INFORMATION), 5253, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, + { THEME_WC(WC_FINANCES), 5187, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, + { THEME_WC(WC_TITLE_MENU), 5249, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, + { THEME_WC(WC_TITLE_EXIT), 5250, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, + { THEME_WC(WC_RECENT_NEWS), 5192, COLOURS_3(COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK ) }, + { THEME_WC(WC_SCENARIO_SELECT), 5252, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, + { THEME_WC(WC_TRACK_DESIGN_LIST), 5202, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, + { THEME_WC(WC_TRACK_DESIGN_PLACE), 5200, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_NEW_CAMPAIGN), 5188, COLOURS_3(COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, + { THEME_WC(WC_KEYBOARD_SHORTCUT_LIST), 5220, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_CHANGE_KEYBOARD_SHORTCUT), 5221, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_MAP), 5190, COLOURS_2(COLOUR_DARK_GREEN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_BANNER), 5209, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_EDITOR_OBJECT_SELECTION), 5210, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, + { THEME_WC(WC_EDITOR_INVENTION_LIST), 5211, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, + { THEME_WC(WC_EDITOR_SCENARIO_OPTIONS), 5212, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, + { THEME_WC(WC_EDTIOR_OBJECTIVE_OPTIONS), 5213, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, + { THEME_WC(WC_MANAGE_TRACK_DESIGN), 5215, COLOURS_3(COLOUR_GREY, COLOUR_GREY, COLOUR_GREY ) }, + { THEME_WC(WC_TRACK_DELETE_PROMPT), 5226, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, + { THEME_WC(WC_INSTALL_TRACK), 5216, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, + { THEME_WC(WC_CLEAR_SCENERY), 5195, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_CHEATS), 5217, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, + { THEME_WC(WC_RESEARCH), 5189, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, + { THEME_WC(WC_VIEWPORT), 5191, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_MAPGEN), 5214, COLOURS_3(COLOUR_DARK_GREEN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, + { THEME_WC(WC_LOADSAVE), 5222, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_LOADSAVE_OVERWRITE_PROMPT), 5227, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, + { THEME_WC(WC_TITLE_OPTIONS), 5251, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, + { THEME_WC(WC_LAND_RIGHTS), 5196, COLOURS_3(COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, + { THEME_WC(WC_THEMES), 5218, COLOURS_3(COLOUR_GREY, COLOUR_DARK_GREEN, COLOUR_DARK_GREEN ) }, + { THEME_WC(WC_STAFF), 5207, COLOURS_3(COLOUR_GREY, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE ) }, + { THEME_WC(WC_EDITOR_TRACK_BOTTOM_TOOLBAR), 5247, COLOURS_3(TRANSLUCENT(COLOUR_LIGHT_BLUE), TRANSLUCENT(COLOUR_LIGHT_BLUE), TRANSLUCENT(COLOUR_LIGHT_BLUE) ) }, + { THEME_WC(WC_EDITOR_SCENARIO_BOTTOM_TOOLBAR), 5248, COLOURS_3(TRANSLUCENT(COLOUR_LIGHT_BROWN), TRANSLUCENT(COLOUR_LIGHT_BROWN), TRANSLUCENT(COLOUR_MOSS_GREEN) ) }, + { THEME_WC(WC_TITLE_EDITOR), 5433, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, + { THEME_WC(WC_TILE_INSPECTOR), 5314, COLOURS_2(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_CHANGELOG), 5344, COLOURS_2(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_MULTIPLAYER), 5502, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_PLAYER), 5736, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_NETWORK_STATUS), 5735, COLOURS_1(COLOUR_LIGHT_BLUE ) }, + { THEME_WC(WC_SERVER_LIST), 5498, COLOURS_2(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, +}; + +#pragma endregion + +#pragma region Pre-defined Themes + +#define COLOURS_RCT1(c0, c1, c2, c3, c4, c5) { { (c0), (c1), (c2), (c3), (c4), (c5) } } + +UIThemeWindowEntry PredefinedThemeRCT1_Entries[] = +{ + { WC_TOP_TOOLBAR, COLOURS_RCT1(COLOUR_GREY, COLOUR_GREY, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_BOTTOM_TOOLBAR, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_YELLOW, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_RIDE, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_SATURATED_GREEN, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_RIDE_LIST, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_CONSTRUCT_RIDE, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_PEEP, COLOURS_RCT1(COLOUR_LIGHT_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_GUEST_LIST, COLOURS_RCT1(COLOUR_LIGHT_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_STAFF_LIST, COLOURS_RCT1(COLOUR_DARK_GREEN, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_FINANCES, COLOURS_RCT1(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_TITLE_MENU, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_TITLE_EXIT, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_NEW_CAMPAIGN, COLOURS_RCT1(COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_TITLE_OPTIONS, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + { WC_STAFF, COLOURS_RCT1(COLOUR_DARK_GREEN, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, + THEME_DEF_END +}; + +UIThemeWindowEntry PredefinedThemeRCT2_Entries[] = +{ + THEME_DEF_END +}; + +const UITheme PredefinedThemeRCT1 = UITheme::CreatePredefined( + "RCT1", PredefinedThemeRCT1_Entries, UITHEME_FLAG_USE_LIGHTS_RIDE | + UITHEME_FLAG_USE_LIGHTS_PARK | + UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT); + +const UITheme PredefinedThemeRCT2 = UITheme::CreatePredefined( + "RCT2", PredefinedThemeRCT2_Entries, 0); + +const UITheme * PredefinedThemes[] = { + &PredefinedThemeRCT1, + &PredefinedThemeRCT2, + nullptr +}; + +#pragma endregion + +static const WindowThemeDesc * GetWindowThemeDescriptor(rct_windowclass windowClass) +{ + for (size_t i = 0; i < Util::CountOf(WindowThemeDescriptors); i++) + { + const WindowThemeDesc * desc = &WindowThemeDescriptors[i]; + if (desc->WindowClass == windowClass) + { + return desc; + } + } + return nullptr; +} + +static const WindowThemeDesc * GetWindowThemeDescriptor(const utf8 * windowClassSZ) +{ + for (size_t i = 0; i < Util::CountOf(WindowThemeDescriptors); i++) + { + const WindowThemeDesc * desc = &WindowThemeDescriptors[i]; + if (String::Equals(desc->WindowClassSZ, windowClassSZ)) + { + return desc; + } + } + return nullptr; +} + +static void ThrowThemeLoadException() +{ + throw Exception("Invalid JSON UI theme entry."); +} + +#pragma region UIThemeEntry + +json_t * UIThemeWindowEntry::ToJson() const +{ + const WindowThemeDesc * wtDesc = GetWindowThemeDescriptor(WindowClass); + + json_t * jsonColours = json_array(); + for (uint8 i = 0; i < wtDesc->NumColours; i++) { + colour_t colour = Theme.Colours[i]; + json_array_append_new(jsonColours, json_integer(colour)); + } + + json_t * jsonEntry = json_object(); + json_object_set_new(jsonEntry, "colours", jsonColours); + + return jsonEntry; +} + +UIThemeWindowEntry UIThemeWindowEntry::FromJson(const WindowThemeDesc * wtDesc, const json_t * json) +{ + json_t * jsonColours = json_object_get(json, "colours"); + if (jsonColours == nullptr) + { + ThrowThemeLoadException(); + } + + uint8 numColours = (uint8)json_array_size(jsonColours); + numColours = Math::Min(numColours, wtDesc->NumColours); + + UIThemeWindowEntry result; + result.WindowClass = wtDesc->WindowClass; + result.Theme = wtDesc->DefaultTheme; + + for (uint8 i = 0; i < numColours; i++) + { + result.Theme.Colours[i] = (colour_t)json_integer_value(json_array_get(jsonColours, i)); + } + + return result; +} + +#pragma endregion + +#pragma region UITheme + +UITheme::UITheme(const utf8 * name) +{ + Name = String::Duplicate(name); + Flags = 0; +} + +UITheme::UITheme(const UITheme & copy) +{ + Name = String::Duplicate(copy.Name); + Flags = copy.Flags; + Entries = copy.Entries; +} + +UITheme::~UITheme() +{ + Memory::Free(Name); +} + +void UITheme::SetName(const utf8 * name) +{ + String::DiscardDuplicate(&Name, name); +} + +const UIThemeWindowEntry * UITheme::GetEntry(rct_windowclass windowClass) const +{ + for (size_t i = 0; i < Entries.GetCount(); i++) + { + const UIThemeWindowEntry * entry = &Entries[i]; + if (entry->WindowClass == windowClass) + { + return entry; + } + } + return nullptr; +} + +void UITheme::SetEntry(const UIThemeWindowEntry * newEntry) +{ + // Try to replace existing entry + for (size_t i = 0; i < Entries.GetCount(); i++) + { + UIThemeWindowEntry * entry = &Entries[i]; + if (entry->WindowClass == newEntry->WindowClass) + { + *entry = *newEntry; + return; + } + } + + Entries.Add(*newEntry); +} + +void UITheme::RemoveEntry(rct_windowclass windowClass) +{ + // Remove existing entry + for (size_t i = 0; i < Entries.GetCount(); i++) + { + UIThemeWindowEntry * entry = &Entries[i]; + if (entry->WindowClass == windowClass) + { + Entries.RemoveAt(i); + break; + } + } +} + +json_t * UITheme::ToJson() const +{ + // Create entries + json_t * jsonEntries = json_object(); + for (const UIThemeWindowEntry & entry : Entries) + { + const WindowThemeDesc * wtDesc = GetWindowThemeDescriptor(entry.WindowClass); + json_object_set_new(jsonEntries, wtDesc->WindowClassSZ, entry.ToJson()); + } + + // Create theme object + json_t * jsonTheme = json_object(); + json_object_set_new(jsonTheme, "name", json_string(Name)); + json_object_set_new(jsonTheme, "entries", jsonEntries); + + json_object_set_new(jsonTheme, "useLightsRide", json_boolean(Flags & UITHEME_FLAG_USE_LIGHTS_RIDE)); + json_object_set_new(jsonTheme, "useLightsPark", json_boolean(Flags & UITHEME_FLAG_USE_LIGHTS_PARK)); + json_object_set_new(jsonTheme, + "useAltScenarioSelectFont", + json_boolean(Flags & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT)); + + return jsonTheme; +} + +bool UITheme::WriteToFile(const utf8 * path) const +{ + json_t * jsonTheme = ToJson(); + bool result; + try + { + Json::WriteToFile(path, jsonTheme, JSON_INDENT(4) | JSON_PRESERVE_ORDER); + result = true; + } + catch (Exception ex) + { + log_error("Unable to save %s: %s", path, ex.GetMessage()); + result = false; + } + + json_decref(jsonTheme); + return result; +} + +UITheme * UITheme::FromJson(const json_t * json) +{ + const char * themeName = json_string_value(json_object_get(json, "name")); + if (themeName == nullptr) + { + ThrowThemeLoadException(); + } + + json_t * jsonEntries = json_object_get(json, "entries"); + size_t numEntries = json_object_size(jsonEntries); + + UITheme * result = nullptr; + try + { + result = new UITheme(themeName); + + if (json_is_true(json_object_get(json, "useLightsRide"))) + { + result->Flags |= UITHEME_FLAG_USE_LIGHTS_RIDE; + } + if (json_is_true(json_object_get(json, "useLightsPark"))) + { + result->Flags |= UITHEME_FLAG_USE_LIGHTS_PARK; + } + if (json_is_true(json_object_get(json, "useAltScenarioSelectFont"))) + { + result->Flags |= UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT; + } + + const char * jkey; + json_t * jvalue; + size_t i = 0; + json_object_foreach(jsonEntries, jkey, jvalue) + { + const WindowThemeDesc * wtDesc = GetWindowThemeDescriptor(jkey); + if (wtDesc == nullptr) continue; + + UIThemeWindowEntry entry = UIThemeWindowEntry::FromJson(wtDesc, jvalue); + result->SetEntry(&entry); + } + + return result; + } + catch (Exception ex) + { + delete result; + throw ex; + } +} + +UITheme * UITheme::FromFile(const utf8 * path) +{ + json_t * json = nullptr; + UITheme * result = nullptr; + try + { + json = Json::ReadFromFile(path); + result = UITheme::FromJson(json); + } + catch (Exception ex) + { + log_error("Unable to read theme: %s", path); + result = nullptr; + } + + json_decref(json); + return result; +} + +UITheme UITheme::CreatePredefined(const utf8 * name, const UIThemeWindowEntry * entries, uint8 flags) +{ + auto theme = UITheme(name); + theme.Flags = flags | UITHEME_FLAG_PREDEFINED; + + size_t numEntries = 0; + for (const UIThemeWindowEntry * entry = entries; entry->WindowClass != 255; entry++) + { + numEntries++; + } + + theme.Entries = List(entries, numEntries); + return theme; +} + +#pragma endregion + +namespace ThemeManager +{ + struct AvailableTheme + { + utf8 Path[MAX_PATH]; + utf8 Name[96]; + }; + + utf8 * CurrentThemePath; + UITheme * CurrentTheme; + List AvailableThemes; + size_t ActiveAvailableThemeIndex = SIZE_MAX; + size_t NumPredefinedThemes = 0; + + void GetThemeFileName(utf8 * buffer, size_t bufferSize, const utf8 * name); + bool EnsureThemeDirectoryExists(); + void GetThemePath(utf8 * buffer, size_t bufferSize); + + void GetAvailableThemes(List * outThemes) + { + Guard::ArgumentNotNull(outThemes); + + outThemes->Clear(); + + NumPredefinedThemes = 0; + for (const UITheme * * predefinedTheme = PredefinedThemes; *predefinedTheme != nullptr; predefinedTheme++) + { + AvailableTheme theme; + String::Set(theme.Path, sizeof(theme.Path), String::Empty); + String::Set(theme.Name, sizeof(theme.Name), (*predefinedTheme)->Name); + outThemes->Add(theme); + + NumPredefinedThemes++; + } + + utf8 themesPattern[MAX_PATH]; + GetThemePath(themesPattern, sizeof(themesPattern)); + Path::Append(themesPattern, sizeof(themesPattern), "*.json"); + + int handle = platform_enumerate_files_begin(themesPattern); + if (handle != INVALID_HANDLE) + { + file_info fileInfo; + while (platform_enumerate_files_next(handle, &fileInfo)) + { + AvailableTheme theme; + Path::GetFileNameWithoutExtension(theme.Name, sizeof(theme.Name), fileInfo.path); + GetThemeFileName(theme.Path, sizeof(theme.Path), theme.Name); + + outThemes->Add(theme); + + if (Path::Equals(CurrentThemePath, fileInfo.path)) + { + ActiveAvailableThemeIndex = outThemes->GetCount() - 1; + } + } + platform_enumerate_files_end(handle); + } + } + + void LoadTheme(UITheme * theme) + { + if (CurrentTheme == theme) + { + return; + } + + if (CurrentTheme != nullptr) + { + if (!(CurrentTheme->Flags & UITHEME_FLAG_PREDEFINED)) + { + delete CurrentTheme; + } + } + + CurrentTheme = theme; + String::DiscardUse(&CurrentThemePath, nullptr); + + gfx_invalidate_screen(); + } + + void LoadTheme(const utf8 * path) + { + UITheme * theme = UITheme::FromFile(path); + if (theme == nullptr) + { + // Fall-back to default + theme = (UITheme *)&PredefinedThemeRCT2; + LoadTheme(theme); + } + else + { + LoadTheme(theme); + String::DiscardDuplicate(&CurrentThemePath, path); + } + } + + bool LoadThemeByName(const utf8 * name) + { + for (size_t i = 0; i < ThemeManager::AvailableThemes.GetCount(); i++) + { + if (String::Equals(name, ThemeManager::AvailableThemes[i].Name)) + { + const utf8 * path = ThemeManager::AvailableThemes[i].Path; + if (String::IsNullOrEmpty(path)) + { + LoadTheme((UITheme *)PredefinedThemes[i]); + } + else + { + LoadTheme(ThemeManager::AvailableThemes[i].Path); + } + ActiveAvailableThemeIndex = i; + return true; + } + } + return false; + } + + void Initialise() + { + ThemeManager::GetAvailableThemes(&ThemeManager::AvailableThemes); + LoadTheme((UITheme *)&PredefinedThemeRCT2); + ActiveAvailableThemeIndex = 1; + + bool configValid = false; + if (!String::IsNullOrEmpty(gConfigInterface.current_theme_preset)) + { + if (LoadThemeByName(gConfigInterface.current_theme_preset)) + { + configValid = true; + } + } + + if (!configValid) + { + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(1)); + } + } + + void GetThemeFileName(utf8 * buffer, size_t bufferSize, const utf8 * name) + { + GetThemePath(buffer, bufferSize); + Path::Append(buffer, bufferSize, name); + String::Append(buffer, bufferSize, ".json"); + } + + bool EnsureThemeDirectoryExists() + { + utf8 path[MAX_PATH]; + GetThemePath(path, sizeof(path)); + return platform_ensure_directory_exists(path); + } + + void GetThemePath(utf8 * buffer, size_t bufferSize) + { + platform_get_user_directory(buffer, "themes"); + } +} + +extern "C" +{ + void theme_manager_load_available_themes() + { + ThemeManager::GetAvailableThemes(&ThemeManager::AvailableThemes); + } + + size_t theme_manager_get_num_available_themes() + { + return ThemeManager::AvailableThemes.GetCount(); + } + + const utf8 * theme_manager_get_available_theme_path(size_t index) + { + return ThemeManager::AvailableThemes[index].Path; + } + + const utf8 * theme_manager_get_available_theme_name(size_t index) + { + return ThemeManager::AvailableThemes[index].Name; + } + + size_t theme_manager_get_active_available_theme_index() + { + return ThemeManager::ActiveAvailableThemeIndex; + } + + void theme_manager_set_active_available_theme(size_t index) + { + if (index < ThemeManager::NumPredefinedThemes) + { + ThemeManager::LoadTheme((UITheme *)PredefinedThemes[index]); + } + else + { + const utf8 * path = ThemeManager::AvailableThemes[index].Path; + ThemeManager::LoadTheme(path); + + // HACK Check if theme load failed and fell back to RCT2 + if (ThemeManager::CurrentThemePath == nullptr) + { + index = 1; + } + } + ThemeManager::ActiveAvailableThemeIndex = index; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(index)); + } + + uint8 theme_get_colour(rct_windowclass wc, uint8 index) + { + const UIThemeWindowEntry * entry = ThemeManager::CurrentTheme->GetEntry(wc); + if (entry == nullptr) + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + return desc->DefaultTheme.Colours[index]; + } + else + { + return entry->Theme.Colours[index]; + } + } + + void theme_set_colour(rct_windowclass wc, uint8 index, colour_t colour) + { + UIThemeWindowEntry entry; + entry.WindowClass = wc; + + auto currentEntry = (UIThemeWindowEntry *)ThemeManager::CurrentTheme->GetEntry(wc); + if (currentEntry != nullptr) + { + entry.Theme = currentEntry->Theme; + } + else + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + entry.Theme = desc->DefaultTheme; + } + + entry.Theme.Colours[index] = colour; + ThemeManager::CurrentTheme->SetEntry(&entry); + + theme_save(); + } + + uint8 theme_get_flags() + { + return ThemeManager::CurrentTheme->Flags; + } + + void theme_set_flags(uint8 flags) + { + ThemeManager::CurrentTheme->Flags = flags; + theme_save(); + } + + void theme_save() + { + ThemeManager::EnsureThemeDirectoryExists(); + ThemeManager::CurrentTheme->WriteToFile(ThemeManager::CurrentThemePath); + } + + void theme_rename(const utf8 * name) + { + const utf8 * oldPath = ThemeManager::CurrentThemePath; + utf8 newPath[MAX_PATH]; + + ThemeManager::EnsureThemeDirectoryExists(); + ThemeManager::GetThemeFileName(newPath, sizeof(newPath), name); + platform_file_move(oldPath, newPath); + String::DiscardDuplicate(&ThemeManager::CurrentThemePath, newPath); + + ThemeManager::CurrentTheme->SetName(name); + ThemeManager::CurrentTheme->WriteToFile(ThemeManager::CurrentThemePath); + + theme_manager_load_available_themes(); + for (size_t i = 0; i < ThemeManager::AvailableThemes.GetCount(); i++) + { + if (Path::Equals(newPath, ThemeManager::AvailableThemes[i].Path)) + { + ThemeManager::ActiveAvailableThemeIndex = i; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(1)); + break; + } + } + } + + void theme_duplicate(const utf8 * name) + { + utf8 newPath[MAX_PATH]; + + ThemeManager::EnsureThemeDirectoryExists(); + ThemeManager::GetThemeFileName(newPath, sizeof(newPath), name); + + // Copy the theme, save it and then load it back in + UITheme * newTheme = new UITheme(*ThemeManager::CurrentTheme); + newTheme->SetName(name); + newTheme->Flags &= ~UITHEME_FLAG_PREDEFINED; + newTheme->WriteToFile(newPath); + delete newTheme; + + ThemeManager::LoadTheme(newPath); + + theme_manager_load_available_themes(); + for (size_t i = 0; i < ThemeManager::AvailableThemes.GetCount(); i++) + { + if (Path::Equals(newPath, ThemeManager::AvailableThemes[i].Path)) + { + ThemeManager::ActiveAvailableThemeIndex = i; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(i)); + break; + } + } + } + + void theme_delete() + { + platform_file_delete(ThemeManager::CurrentThemePath); + ThemeManager::LoadTheme((UITheme *)&PredefinedThemeRCT2); + ThemeManager::ActiveAvailableThemeIndex = 1; + String::DiscardDuplicate(&gConfigInterface.current_theme_preset, theme_manager_get_available_theme_name(1)); + } + + void theme_manager_initialise() + { + ThemeManager::Initialise(); + } + + uint8 theme_desc_get_num_colours(rct_windowclass wc) + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + return desc->NumColours; + } + + rct_string_id theme_desc_get_name(rct_windowclass wc) + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(wc); + return desc->WindowName; + } + + void colour_scheme_update(rct_window * window) + { + colour_scheme_update_by_class(window, window->classification); + } + + void colour_scheme_update_by_class(rct_window * window, rct_windowclass classification) + { + const WindowTheme * windowTheme; + const UIThemeWindowEntry * entry = ThemeManager::CurrentTheme->GetEntry(classification); + if (entry != nullptr) + { + windowTheme = &entry->Theme; + } + else + { + const WindowThemeDesc * desc = GetWindowThemeDescriptor(classification); + windowTheme = &desc->DefaultTheme; + } + + bool transparent = false; + for (int i = 0; i < 6; i++) { + window->colours[i] = windowTheme->Colours[i]; + if (windowTheme->Colours[i] & COLOUR_FLAG_TRANSLUCENT) { + transparent = true; + } + } + // Some windows need to be transparent even if the colours aren't. + // There doesn't seem to be any side-effects for all windows being transparent + window->flags |= WF_TRANSPARENT; + } +} diff --git a/src/interface/chat.c b/src/interface/chat.c index eb656b22eb..0166239cf9 100644 --- a/src/interface/chat.c +++ b/src/interface/chat.c @@ -68,34 +68,36 @@ void chat_draw() _chatLeft = 10; _chatTop = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 40 - ((CHAT_HISTORY_SIZE + 1) * 10); _chatRight = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 10; - _chatBottom = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 40; + _chatBottom = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 45; char lineBuffer[CHAT_INPUT_SIZE + 10]; char* lineCh = lineBuffer; int x = _chatLeft; - int y = _chatBottom - (10 * 2); + int y = _chatBottom - (15 * 2); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16) = 0; - for (int i = 0; i < CHAT_HISTORY_SIZE; i++, y -= 10) { + for (int i = 0; i < CHAT_HISTORY_SIZE; i++, y -= 15) { if (!gChatOpen && SDL_TICKS_PASSED(SDL_GetTicks(), chat_history_get_time(i) + 10000)) { break; } - safe_strncpy(lineBuffer, chat_history_get(i), CHAT_INPUT_SIZE + 10); + safe_strcpy(lineBuffer, chat_history_get(i), CHAT_INPUT_SIZE + 10); gfx_set_dirty_blocks(x, y, x + gfx_get_string_width(lineBuffer), y + 12); gfx_draw_string(dpi, lineBuffer, 255, x, y); } if (gChatOpen) { lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); lineCh = utf8_write_codepoint(lineCh, FORMAT_CELADON); - safe_strncpy(lineCh, _chatCurrentLine, CHAT_INPUT_SIZE); - y = _chatBottom - 10; + safe_strcpy(lineCh, _chatCurrentLine, CHAT_INPUT_SIZE); + y = _chatBottom - 15; gfx_set_dirty_blocks(x, y, x + gfx_get_string_width(lineBuffer) + 7, y + 12); + gfx_draw_string(dpi, lineBuffer, 255, x, y); if (_chatCaretTicks < 15) { + memcpy(lineBuffer, _chatCurrentLine, gTextInput.selection_offset); + lineBuffer[gTextInput.selection_offset] = 0; int caretX = x + gfx_get_string_width(lineBuffer); - int caretY = y + 10; + int caretY = y + 15; gfx_fill_rect(dpi, caretX, caretY, caretX + 6, caretY + 1, 0x38); } - gfx_draw_string(dpi, lineBuffer, 255, x, y); } } diff --git a/src/interface/chat.h b/src/interface/chat.h index b288558b00..d5e31afa51 100644 --- a/src/interface/chat.h +++ b/src/interface/chat.h @@ -18,4 +18,4 @@ void chat_history_add(const char *src); void chat_input(int c); -#endif \ No newline at end of file +#endif diff --git a/src/interface/colour.h b/src/interface/colour.h index 5cb9b3bc84..433194f7fe 100644 --- a/src/interface/colour.h +++ b/src/interface/colour.h @@ -81,4 +81,4 @@ extern rct_colour_map_b *ColourMapB; void colours_init_maps(); -#endif \ No newline at end of file +#endif diff --git a/src/interface/console.c b/src/interface/console.c index 730e30c94c..bcab0202e1 100644 --- a/src/interface/console.c +++ b/src/interface/console.c @@ -124,7 +124,7 @@ void console_update() } // Remove unwated characters in console input - utf8_remove_format_codes(_consoleCurrentLine); + utf8_remove_format_codes(_consoleCurrentLine, false); } // Flash the caret @@ -214,8 +214,8 @@ void console_draw(rct_drawpixelinfo *dpi) // Draw caret if (_consoleCaretTicks < 15) { - memcpy(lineBuffer, _consoleCurrentLine, gTextInputCursorPosition); - lineBuffer[gTextInputCursorPosition] = 0; + memcpy(lineBuffer, _consoleCurrentLine, gTextInput.selection_offset); + lineBuffer[gTextInput.selection_offset] = 0; int caretX = x + gfx_get_string_width(lineBuffer); int caretY = y + lineHeight; @@ -249,15 +249,15 @@ void console_input(int c) _consoleHistoryIndex--; memcpy(_consoleCurrentLine, _consoleHistory[_consoleHistoryIndex], 256); } - gTextInputCursorPosition = strlen(_consoleCurrentLine); - gTextInputLength = gTextInputCursorPosition; + textinputbuffer_recalculate_length(&gTextInput); + gTextInput.selection_offset = strlen(_consoleCurrentLine); break; case SDL_SCANCODE_DOWN: if (_consoleHistoryIndex < _consoleHistoryCount - 1) { _consoleHistoryIndex++; memcpy(_consoleCurrentLine, _consoleHistory[_consoleHistoryIndex], 256); - gTextInputCursorPosition = strlen(_consoleCurrentLine); - gTextInputLength = gTextInputCursorPosition; + textinputbuffer_recalculate_length(&gTextInput); + gTextInput.selection_offset = strlen(_consoleCurrentLine); } else { _consoleHistoryIndex = _consoleHistoryCount; console_clear_input(); @@ -389,8 +389,9 @@ void console_refresh_caret() static void console_clear_input() { _consoleCurrentLine[0] = 0; - gTextInputCursorPosition = 0; - gTextInputLength = 0; + if (gConsoleOpen) { + platform_start_text_input(_consoleCurrentLine, sizeof(_consoleCurrentLine)); + } } static void console_history_add(const utf8 *src) @@ -530,6 +531,9 @@ static int cc_get(const utf8 **argv, int argc) console_printf("location %d %d", mapCoord.x, mapCoord.y); } } + else if (strcmp(argv[0], "window_scale") == 0) { + console_printf("window_scale %.3f", gConfigGeneral.window_scale); + } else { console_writeline_warning("Invalid variable."); } @@ -570,7 +574,7 @@ static int cc_set(const utf8 **argv, int argc) console_execute_silent("get max_loan"); } else if (strcmp(argv[0], "guest_initial_cash") == 0 && invalidArguments(&invalidArgs, double_valid[0])) { - RCT2_GLOBAL(RCT2_ADDRESS_GUEST_INITIAL_CASH, money16) = clamp(MONEY((int)double_val[0], ((int)(double_val[0] * 100)) % 100), MONEY(0, 0), MONEY(15000, 0)); + RCT2_GLOBAL(RCT2_ADDRESS_GUEST_INITIAL_CASH, money16) = clamp(MONEY((int)double_val[0], ((int)(double_val[0] * 100)) % 100), MONEY(0, 0), MONEY(1000, 0)); console_execute_silent("get guest_initial_cash"); } else if (strcmp(argv[0], "guest_initial_happiness") == 0 && invalidArguments(&invalidArgs, int_valid[0])) { @@ -630,11 +634,11 @@ static int cc_set(const utf8 **argv, int argc) console_execute_silent("get park_open"); } else if (strcmp(argv[0], "land_rights_cost") == 0 && invalidArguments(&invalidArgs, double_valid[0])) { - RCT2_GLOBAL(RCT2_ADDRESS_LAND_COST, money16) = clamp(MONEY((int)double_val[0], ((int)(double_val[0] * 100)) % 100), MONEY(0, 0), MONEY(15000, 0)); + RCT2_GLOBAL(RCT2_ADDRESS_LAND_COST, money16) = clamp(MONEY((int)double_val[0], ((int)(double_val[0] * 100)) % 100), MONEY(0, 0), MONEY(200, 0)); console_execute_silent("get land_rights_cost"); } else if (strcmp(argv[0], "construction_rights_cost") == 0 && invalidArguments(&invalidArgs, double_valid[0])) { - RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCTION_RIGHTS_COST, money16) = clamp(MONEY((int)double_val[0], ((int)(double_val[0] * 100)) % 100), MONEY(0, 0), MONEY(15000, 0)); + RCT2_GLOBAL(RCT2_ADDRESS_CONSTRUCTION_RIGHTS_COST, money16) = clamp(MONEY((int)double_val[0], ((int)(double_val[0] * 100)) % 100), MONEY(0, 0), MONEY(200, 0)); console_execute_silent("get construction_rights_cost"); } else if (strcmp(argv[0], "climate") == 0) { @@ -686,6 +690,14 @@ static int cc_set(const utf8 **argv, int argc) console_execute_silent("get location"); } } + else if (strcmp(argv[0], "window_scale") == 0 && invalidArguments(&invalidArgs, double_valid[0])) { + float newScale = (float)(0.001*trunc(1000*double_val[0])); + gConfigGeneral.window_scale = clamp(newScale, 0.5f, 5.0f); + config_save_default(); + gfx_invalidate_screen(); + platform_trigger_resize(); + console_execute_silent("get window_scale"); + } else if (invalidArgs) { console_writeline_error("Invalid arguments."); } @@ -713,17 +725,17 @@ static int cc_twitch(const utf8 **argv, int argc) static void editor_load_selected_objects_console() { uint8 *selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry *installed_entry = gInstalledObjects; - if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) == 0) + if (gInstalledObjectsCount == 0) return; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i != 0; i--, selection_flags++) { + for (int i = gInstalledObjectsCount; i != 0; i--, selection_flags++) { if (*selection_flags & 1) { uint8 entry_index, entry_type; if (!find_object_in_entry_group(installed_entry, &entry_type, &entry_index)){ int chunk_size; - if (!object_load(-1, installed_entry, &chunk_size)) { + if (!object_load_chunk(-1, installed_entry, &chunk_size)) { log_error("Failed to load entry %.8s", installed_entry->name); } } @@ -735,9 +747,9 @@ static void editor_load_selected_objects_console() static int cc_load_object(const utf8 **argv, int argc) { if (argc > 0) { - utf8 path[260]; + utf8 path[MAX_PATH]; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), argv[0]); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), argv[0]); // Require pointer to start of filename utf8* last_char = path + strlen(path); strcat(path, ".DAT\0"); @@ -762,17 +774,17 @@ static int cc_load_object(const utf8 **argv, int argc) { } else { // Load the obect - if (!object_load(entryGroupIndex, &entry, NULL)) { + if (!object_load_chunk(entryGroupIndex, &entry, NULL)) { console_writeline_error("Could not load object file."); } else { reset_loaded_objects(); if (type == OBJECT_TYPE_RIDE) { // Automatically research the ride so it's supported by the game. - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; int rideType; - rideEntry = GET_RIDE_ENTRY(entryGroupIndex); + rideEntry = get_ride_entry(entryGroupIndex); for (int j = 0; j < 3; j++) { rideType = rideEntry->ride_type[j]; @@ -911,7 +923,8 @@ utf8* console_variable_table[] = { "console_small_font", "test_unfinished_tracks", "no_test_crashes", - "location" + "location", + "window_scale" }; utf8* console_window_table[] = { "object_selection", @@ -1033,8 +1046,10 @@ void console_execute_silent(const utf8 *src) return; // Aliases for hiding the console - if(strcmp(argv[0],"quit") == 0 || strcmp(argv[0],"exit") == 0) - argv[0]="hide"; + if(strcmp(argv[0],"quit") == 0 || strcmp(argv[0],"exit") == 0) { + free(argv[0]); + argv[0] = _strdup("hide"); + } bool validCommand = false; for (int i = 0; i < countof(console_command_table); i++) { diff --git a/src/interface/console.h b/src/interface/console.h index 82c7870eac..5f24a17c88 100644 --- a/src/interface/console.h +++ b/src/interface/console.h @@ -26,4 +26,4 @@ void console_clear_line(); void console_refresh_caret(); void console_scroll(int delta); -#endif \ No newline at end of file +#endif diff --git a/src/interface/graph.c b/src/interface/graph.c index 7e1fc5cb31..dc9cae385e 100644 --- a/src/interface/graph.c +++ b/src/interface/graph.c @@ -36,7 +36,7 @@ static void graph_draw_months_uint8(rct_drawpixelinfo *dpi, uint8 *history, int if (history[i] != 0 && history[i] != 255 && yearOver32 % 4 == 0) { // Draw month text RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = ((yearOver32 / 4) + 8) % 8 + STR_MONTH_SHORT_MAR; - gfx_draw_string_centred(dpi, 2222, x, y - 10, 0, (void*)0x013CE952); + gfx_draw_string_centred(dpi, 2222, x, y - 10, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); // Draw month mark gfx_fill_rect(dpi, x, y, x, y + 3, 10); @@ -173,4 +173,4 @@ void graph_draw_money32(rct_drawpixelinfo *dpi, money32 *history, int count, int graph_draw_months_money32(dpi, history, count, baseX, baseY); graph_draw_line_a_money32(dpi, history, count, baseX, baseY, modifier, offset); graph_draw_line_b_money32(dpi, history, count, baseX, baseY, modifier, offset); -} \ No newline at end of file +} diff --git a/src/interface/graph.h b/src/interface/graph.h index e6c9aee74e..ca2dc79dc1 100644 --- a/src/interface/graph.h +++ b/src/interface/graph.h @@ -27,4 +27,4 @@ void graph_draw_uint8(rct_drawpixelinfo *dpi, uint8 *history, int count, int baseX, int baseY); void graph_draw_money32(rct_drawpixelinfo *dpi, money32 *history, int count, int baseX, int baseY, int modifier, int offset); -#endif \ No newline at end of file +#endif diff --git a/src/interface/keyboard_shortcut.c b/src/interface/keyboard_shortcut.c index 606b45a181..911076d234 100644 --- a/src/interface/keyboard_shortcut.c +++ b/src/interface/keyboard_shortcut.c @@ -43,9 +43,9 @@ void keyboard_shortcut_set(int key) int i; // Unmap shortcut that already uses this key - for (i = 0; i < 32; i++) { + for (i = 0; i < SHORTCUT_COUNT; i++) { if (key == gShortcutKeys[i]) { - gShortcutKeys[i] = 0xFFFF; + gShortcutKeys[i] = SHORTCUT_UNDEFINED; break; } } @@ -87,7 +87,7 @@ void keyboard_shortcut_format_string(char *buffer, uint16 shortcutKey) char formatBuffer[256]; *buffer = 0; - if (shortcutKey == 0xFFFF) return; + if (shortcutKey == SHORTCUT_UNDEFINED) return; if (shortcutKey & 0x100) { format_string(formatBuffer, STR_SHIFT_PLUS, NULL); strcat(buffer, formatBuffer); @@ -97,7 +97,15 @@ void keyboard_shortcut_format_string(char *buffer, uint16 shortcutKey) strcat(buffer, formatBuffer); } if (shortcutKey & 0x400) { +#ifdef __MACOSX__ + format_string(formatBuffer, STR_OPTION_PLUS, NULL); +#else format_string(formatBuffer, STR_ALT_PLUS, NULL); +#endif + strcat(buffer, formatBuffer); + } + if (shortcutKey & 0x800) { + format_string(formatBuffer, STR_CMD_PLUS, NULL); strcat(buffer, formatBuffer); } strcat(buffer, SDL_GetScancodeName(shortcutKey & 0xFF)); @@ -136,7 +144,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 +480,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() @@ -514,6 +524,11 @@ static void shortcut_quick_save_game() } } +static void shortcut_show_options() +{ + window_options_open(); +} + static const shortcut_action shortcut_table[SHORTCUT_COUNT] = { shortcut_close_top_most_window, shortcut_close_all_floating_windows, @@ -560,6 +575,7 @@ static const shortcut_action shortcut_table[SHORTCUT_COUNT] = { NULL, shortcut_open_chat_window, shortcut_quick_save_game, + shortcut_show_options, }; #pragma endregion diff --git a/src/interface/keyboard_shortcut.h b/src/interface/keyboard_shortcut.h index 3b9dc2599e..006f4d41df 100644 --- a/src/interface/keyboard_shortcut.h +++ b/src/interface/keyboard_shortcut.h @@ -21,9 +21,11 @@ #ifndef _INTERFACE_KEYBOARD_SHORTCUT_H_ #define _INTERFACE_KEYBOARD_SHORTCUT_H_ +#define SHORTCUT_UNDEFINED 0xFFFF + void keyboard_shortcut_set(int key); void keyboard_shortcut_handle(int key); void keyboard_shortcut_handle_command(int shortcutIndex); void keyboard_shortcut_format_string(char *buffer, uint16 shortcutKey); -#endif \ No newline at end of file +#endif diff --git a/src/interface/screenshot.c b/src/interface/screenshot.c index 79c1ae2ccf..fdda32edbe 100644 --- a/src/interface/screenshot.c +++ b/src/interface/screenshot.c @@ -17,13 +17,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . *****************************************************************************/ -#pragma pack(1) -#include #include "../addresses.h" +#include "../audio/audio.h" #include "../config.h" #include "../drawing/drawing.h" #include "../game.h" +#include "../image_io.h" #include "../localisation/localisation.h" #include "../openrct2.h" #include "../platform/platform.h" @@ -52,15 +52,10 @@ void screenshot_check() screenshotIndex = screenshot_dump(); if (screenshotIndex != -1) { - rct_string_id stringId = 3165; - sprintf((char*)language_get_string(stringId), "SCR%d%s", screenshotIndex, _screenshot_format_extension[gConfigGeneral.screenshot_format]); - - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = stringId; - // RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_SCR_BMP; - // RCT2_GLOBAL(0x013CE952 + 2, uint16) = screenshotIndex; RCT2_GLOBAL(0x009A8C29, uint8) |= 1; - - window_error_open(STR_SCREENSHOT_SAVED_AS, -1); + + // TODO use a more obvious sound like a camera shutter + audio_play_sound(SOUND_CLICK_1, 0, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2); } else { window_error_open(STR_SCREENSHOT_FAILED, -1); } @@ -71,6 +66,18 @@ void screenshot_check() } } +static void screenshot_get_rendered_palette(rct_palette* palette) { + for (int i = 0; i < 256; i++) { + const SDL_Color *renderedEntry = &gPalette[i]; + rct_palette_entry *entry = &palette->entries[i]; + + entry->red = renderedEntry->r; + entry->green = renderedEntry->g; + entry->blue = renderedEntry->b; + entry->alpha = renderedEntry->a; + } +} + static int screenshot_get_next_path(char *path, int format) { char screenshotPath[MAX_PATH]; @@ -109,250 +116,50 @@ int screenshot_dump() } } -// Bitmap header structs, for cross platform purposes -typedef struct { - uint16 bfType; - uint32 bfSize; - uint16 bfReserved1; - uint16 bfReserved2; - uint32 bfOffBits; -} BitmapFileHeader; - -typedef struct { - uint32 biSize; - sint32 biWidth; - sint32 biHeight; - uint16 biPlanes; - uint16 biBitCount; - uint32 biCompression; - uint32 biSizeImage; - sint32 biXPelsPerMeter; - sint32 biYPelsPerMeter; - uint32 biClrUsed; - uint32 biClrImportant; -} BitmapInfoHeader; - /** * * rct2: 0x00683D20 */ int screenshot_dump_bmp() { - BitmapFileHeader header; - BitmapInfoHeader info; - - int i, y, index, width, height, stride; - char path[MAX_PATH]; - uint8 *buffer, *row; - SDL_RWops *fp; - unsigned int bytesWritten; - // Get a free screenshot path - if ((index = screenshot_get_next_path(path, SCREENSHOT_FORMAT_BMP)) == -1) - return -1; - - // Open binary file for writing - if ((fp = SDL_RWFromFile(path, "wb")) == NULL){ + int index; + char path[MAX_PATH] = ""; + if ((index = screenshot_get_next_path(path, SCREENSHOT_FORMAT_BMP)) == -1) { return -1; } - // Allocate buffer - buffer = malloc(0xFFFF); - if (buffer == NULL) { - SDL_RWclose(fp); - return -1; - } - - // Get image size - width = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16); - height = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16); - stride = (width + 3) & 0xFFFFFFFC; - - // File header - memset(&header, 0, sizeof(header)); - header.bfType = 0x4D42; - header.bfSize = height * stride + 1038; - header.bfOffBits = 1038; - - bytesWritten = SDL_RWwrite(fp, &header, sizeof(BitmapFileHeader), 1); - if (bytesWritten != 1) { - SDL_RWclose(fp); - SafeFree(buffer); - log_error("failed to save screenshot"); - return -1; - } - - // Info header - memset(&info, 0, sizeof(info)); - info.biSize = sizeof(info); - info.biWidth = width; - info.biHeight = height; - info.biPlanes = 1; - info.biBitCount = 8; - info.biXPelsPerMeter = 2520; - info.biYPelsPerMeter = 2520; - info.biClrUsed = 246; - - bytesWritten = SDL_RWwrite(fp, &info, sizeof(BitmapInfoHeader), 1); - if (bytesWritten != 1) { - SDL_RWclose(fp); - SafeFree(buffer); - log_error("failed to save screenshot"); - return -1; - } - - // Palette - memset(buffer, 0, 246 * 4); - for (i = 0; i < 246; i++) { - buffer[i * 4 + 0] = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 0]; - buffer[i * 4 + 1] = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 1]; - buffer[i * 4 + 2] = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 2]; - } - - bytesWritten = SDL_RWwrite(fp, buffer, sizeof(char), 246 * 4); - if (bytesWritten != 246*4){ - SDL_RWclose(fp); - SafeFree(buffer); - log_error("failed to save screenshot"); - return -1; - } - - // Image, save upside down rct_drawpixelinfo *dpi = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); - for (y = dpi->height - 1; y >= 0; y--) { - row = dpi->bits + y * (dpi->width + dpi->pitch); - memset(buffer, 0, stride); - memcpy(buffer, row, dpi->width); + rct_palette renderedPalette; + screenshot_get_rendered_palette(&renderedPalette); - bytesWritten = SDL_RWwrite(fp, buffer, sizeof(char), stride); - if (bytesWritten != stride){ - SDL_RWclose(fp); - SafeFree(buffer); - log_error("failed to save screenshot"); - return -1; - } + if (image_io_bmp_write(dpi, &renderedPalette, path)) { + return index; + } else { + return -1; } - - SDL_RWclose(fp); - free(buffer); - - return index; } int screenshot_dump_png() { + // Get a free screenshot path + int index; + char path[MAX_PATH] = ""; + if ((index = screenshot_get_next_path(path, SCREENSHOT_FORMAT_PNG)) == -1) { + return -1; + } + rct_drawpixelinfo *dpi = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); - int i, index, width, height, padding; - char path[MAX_PATH] = ""; - unsigned int error; - unsigned char r, g, b, a = 255; + rct_palette renderedPalette; + screenshot_get_rendered_palette(&renderedPalette); - unsigned char* png; - size_t pngSize; - LodePNGState state; - - // Get a free screenshot path - if ((index = screenshot_get_next_path(path, SCREENSHOT_FORMAT_PNG)) == -1) + if (image_io_png_write(dpi, &renderedPalette, path)) { + return index; + } else { return -1; - - - lodepng_state_init(&state); - state.info_raw.colortype = LCT_PALETTE; - - // Get image size - width = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16); - height = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16); - - padding = dpi->pitch; - - for (i = 0; i < 256; i++) { - b = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 0]; - g = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 1]; - r = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 2]; - - lodepng_palette_add(&state.info_raw, r, g, b, a); } - - uint8* pixels = dpi->bits; - - if (padding > 0) { - pixels = malloc(width * height); - if (!pixels) { - return -1; - } - uint8* src = dpi->bits; - uint8* dst = pixels; - for (int y = height; y > 0; y--) { - for (int x = width; x > 0; x--) { - *dst++ = *src++; - } - src += padding; - } - } - - error = lodepng_encode(&png, &pngSize, pixels, width, height, &state); - if (error) { - log_error("Unable to save screenshot, %u: %s", lodepng_error_text(error)); - index = -1; - } else { - SDL_RWops *file = SDL_RWFromFile(path, "wb"); - if (file == NULL) { - log_error("Unable to save screenshot, %s", SDL_GetError()); - index = -1; - } else { - SDL_RWwrite(file, png, pngSize, 1); - SDL_RWclose(file); - } - } - - free(png); - if ((utf8*)pixels != (utf8*)dpi->bits) { - free(pixels); - } - return index; -} - -bool screenshot_write_png(rct_drawpixelinfo *dpi, const char *path) -{ - unsigned int error; - unsigned char* png; - size_t pngSize; - LodePNGState state; - - lodepng_state_init(&state); - state.info_raw.colortype = LCT_PALETTE; - - // Get image size - int stride = (dpi->width + 3) & ~3; - - for (int i = 0; i < 256; i++) { - unsigned char r, g, b, a = 255; - - b = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 0]; - g = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 1]; - r = RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8)[i * 4 + 2]; - - lodepng_palette_add(&state.info_raw, r, g, b, a); - } - - error = lodepng_encode(&png, &pngSize, dpi->bits, stride, dpi->height, &state); - if (error != 0) { - free(png); - return false; - } else { - SDL_RWops *file = SDL_RWFromFile(path, "wb"); - if (file == NULL) { - free(png); - return false; - } - SDL_RWwrite(file, png, pngSize, 1); - SDL_RWclose(file); - } - - free(png); - return true; } void screenshot_giant() @@ -436,7 +243,10 @@ void screenshot_giant() return; } - screenshot_write_png(&dpi, path); + rct_palette renderedPalette; + screenshot_get_rendered_palette(&renderedPalette); + + image_io_png_write(&dpi, &renderedPalette, path); free(dpi.bits); @@ -487,6 +297,8 @@ int cmdline_for_screenshot(const char **argv, int argc) customZoom = atoi(argv[6]); customRotation = atoi(argv[7]) & 3; + } else { + customZoom = 0; } } @@ -570,7 +382,10 @@ int cmdline_for_screenshot(const char **argv, int argc) viewport_render(&dpi, &viewport, 0, 0, viewport.width, viewport.height); - screenshot_write_png(&dpi, outputPath); + rct_palette renderedPalette; + screenshot_get_rendered_palette(&renderedPalette); + + image_io_png_write(&dpi, &renderedPalette, outputPath); free(dpi.bits); } diff --git a/src/interface/screenshot.h b/src/interface/screenshot.h index 81feb53801..4a973d516d 100644 --- a/src/interface/screenshot.h +++ b/src/interface/screenshot.h @@ -27,4 +27,4 @@ int screenshot_dump(); void screenshot_giant(); int cmdline_for_screenshot(const char **argv, int argc); -#endif \ No newline at end of file +#endif diff --git a/src/interface/themes.c b/src/interface/themes.c deleted file mode 100644 index 96ef4f6742..0000000000 --- a/src/interface/themes.c +++ /dev/null @@ -1,245 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2014 Ted John, Peter Hill -* 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 . -*****************************************************************************/ - -#include "../localisation/string_ids.h" -#include "../util/util.h" -#include "colour.h" -#include "window.h" -#include "themes.h" - -#define COLOURS_1(c0) 1, { { (c0), 0, 0, 0, 0, 0 } } -#define COLOURS_2(c0, c1) 2, { { (c0), (c1), 0, 0, 0, 0 } } -#define COLOURS_3(c0, c1, c2) 3, { { (c0), (c1), (c2), 0, 0, 0 } } -#define COLOURS_4(c0, c1, c2, c3) 4, { { (c0), (c1), (c2), (c3), 0, 0 } } -#define COLOURS_5(c0, c1, c2, c3, c4) 5, { { (c0), (c1), (c2), (c3), (c4), 0 } } -#define COLOURS_6(c0, c1, c2, c3, c4, c5) 6, { { (c0), (c1), (c2), (c3), (c4), (c5) } } - -#define THEME_DEF_END { 0xFF, { 0, 0, 0, 0, 0, 0 } } - -#define TWINDOW(window_class, window_name, window_string_id, theme) { window_class, window_name, window_string_id, theme } - -theme_window_definition gThemeWindowDefinitions[] = { - /* Window Class ini section name stringid window defaults */ - { WC_TOP_TOOLBAR, "top_toolbar", 5245, COLOURS_4(COLOUR_LIGHT_BLUE, COLOUR_DARK_GREEN, COLOUR_DARK_BROWN, COLOUR_GREY ) }, - { WC_BOTTOM_TOOLBAR, "bottom_toolbar", 5246, COLOURS_4(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), COLOUR_BLACK, COLOUR_BRIGHT_GREEN ) }, - { WC_RIDE, "ride", 5203, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_GREY ) }, - { WC_RIDE_CONSTRUCTION, "ride_construction", 5199, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_RIDE_LIST, "ride_list", 5204, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_SAVE_PROMPT, "save_prompt", 5223, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_CONSTRUCT_RIDE, "new_ride", 5201, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_DEMOLISH_RIDE_PROMPT, "demolish_ride_prompt", 5224, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_SCENERY, "scenery", 5197, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_GREEN, COLOUR_DARK_GREEN ) }, - { WC_OPTIONS, "options", 5219, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_FOOTPATH, "footpath", 5198, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_LAND, "land", 5193, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_WATER, "water", 5194, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_PEEP, "guest", 5205, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, - { WC_GUEST_LIST, "guest_list", 5206, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, - { WC_STAFF_LIST, "staff_list", 5208, COLOURS_3(COLOUR_GREY, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE ) }, - { WC_FIRE_PROMPT, "staff_fire_prompt", 5225, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_PARK_INFORMATION, "park_information", 5253, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_FINANCES, "finances", 5187, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_TITLE_MENU, "title_menu", 5249, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, - { WC_TITLE_EXIT, "title_exit", 5250, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, - { WC_RECENT_NEWS, "recent_news", 5192, COLOURS_3(COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK ) }, - { WC_SCENARIO_SELECT, "scenario_select", 5252, COLOURS_3(COLOUR_GREY, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_TRACK_DESIGN_LIST, "track_design_list", 5202, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_TRACK_DESIGN_PLACE, "track_design_place", 5200, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_NEW_CAMPAIGN, "new_campaign", 5188, COLOURS_3(COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_KEYBOARD_SHORTCUT_LIST, "keyboard_shortcuts", 5220, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_CHANGE_KEYBOARD_SHORTCUT, "change_keyboard_shortcut", 5221, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_MAP, "map", 5190, COLOURS_2(COLOUR_DARK_GREEN, COLOUR_DARK_BROWN ) }, - { WC_BANNER, "banner", 5209, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_EDITOR_OBJECT_SELECTION, "editor_object_selection", 5210, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_EDITOR_INVENTION_LIST, "editor_invention_list", 5211, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_EDITOR_SCENARIO_OPTIONS, "editor_scenario_options", 5212, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_EDTIOR_OBJECTIVE_OPTIONS, "editor_objection_options", 5213, COLOURS_3(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY ) }, - { WC_MANAGE_TRACK_DESIGN, "manage_track_design", 5215, COLOURS_3(COLOUR_GREY, COLOUR_GREY, COLOUR_GREY ) }, - { WC_TRACK_DELETE_PROMPT, "track_delete_prompt", 5226, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_INSTALL_TRACK, "install_track", 5216, COLOURS_3(COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED ) }, - { WC_CLEAR_SCENERY, "clear_scenery", 5195, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_CHEATS, "cheats", 5217, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_RESEARCH, "research", 5189, COLOURS_3(COLOUR_GREY, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_VIEWPORT, "viewport", 5191, COLOURS_3(COLOUR_DARK_BROWN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_MAPGEN, "map_generation", 5214, COLOURS_3(COLOUR_DARK_GREEN, COLOUR_DARK_BROWN, COLOUR_DARK_BROWN ) }, - { WC_LOADSAVE, "loadsave", 5222, COLOURS_3(COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE, COLOUR_LIGHT_BLUE ) }, - { WC_LOADSAVE_OVERWRITE_PROMPT, "loadsave_overwrite_prompt", 5227, COLOURS_1(TRANSLUCENT(COLOUR_BORDEAUX_RED) ) }, - { WC_TITLE_OPTIONS, "title_options", 5251, COLOURS_3(TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN), TRANSLUCENT(COLOUR_DARK_GREEN) ) }, - { WC_LAND_RIGHTS, "land_rights", 5196, COLOURS_3(COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW, COLOUR_DARK_YELLOW ) }, - { WC_THEMES, "themes", 5218, COLOURS_3(COLOUR_GREY, COLOUR_DARK_GREEN, COLOUR_DARK_GREEN ) }, - { WC_STAFF, "staff", 5207, COLOURS_3(COLOUR_GREY, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE ) }, - { WC_EDITOR_TRACK_BOTTOM_TOOLBAR, "editor_track_bottom_toolbar", 5247, COLOURS_3(TRANSLUCENT(COLOUR_LIGHT_BLUE), TRANSLUCENT(COLOUR_LIGHT_BLUE), TRANSLUCENT(COLOUR_LIGHT_BLUE) ) }, - { WC_EDITOR_SCENARIO_BOTTOM_TOOLBAR, "editor_scenario_bottom_toolbar", 5248, COLOURS_3(TRANSLUCENT(COLOUR_LIGHT_BROWN), TRANSLUCENT(COLOUR_LIGHT_BROWN), TRANSLUCENT(COLOUR_MOSS_GREEN) ) }, - { WC_TITLE_EDITOR, "title_sequences", 5433, COLOURS_3(COLOUR_GREY, COLOUR_OLIVE_GREEN, COLOUR_OLIVE_GREEN ) }, -}; - -#define COLOURS_RCT1(c0, c1, c2, c3, c4, c5) { { (c0), (c1), (c2), (c3), (c4), (c5) } } - -theme_window_preset gThemeWindowsRCT1[] = { - { WC_TOP_TOOLBAR, COLOURS_RCT1(COLOUR_GREY, COLOUR_GREY, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_BOTTOM_TOOLBAR, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_YELLOW, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_RIDE, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_SATURATED_GREEN, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_RIDE_LIST, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_CONSTRUCT_RIDE, COLOURS_RCT1(COLOUR_BORDEAUX_RED, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_PEEP, COLOURS_RCT1(COLOUR_LIGHT_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_GUEST_LIST, COLOURS_RCT1(COLOUR_LIGHT_BROWN, COLOUR_BORDEAUX_RED, COLOUR_BORDEAUX_RED, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_STAFF_LIST, COLOURS_RCT1(COLOUR_DARK_GREEN, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_FINANCES, COLOURS_RCT1(COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_TITLE_MENU, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_TITLE_EXIT, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_NEW_CAMPAIGN, COLOURS_RCT1(COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_GREY, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_TITLE_OPTIONS, COLOURS_RCT1(TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), TRANSLUCENT(COLOUR_GREY), COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - { WC_STAFF, COLOURS_RCT1(COLOUR_DARK_GREEN, COLOUR_LIGHT_PURPLE, COLOUR_LIGHT_PURPLE, COLOUR_BLACK, COLOUR_BLACK, COLOUR_BLACK) }, - THEME_DEF_END -}; - -uint16 gCurrentTheme = 0; -uint32 gNumThemeWindows = sizeof(gThemeWindowDefinitions) / sizeof(theme_window_definition); - - -theme_preset* theme_get_preset() -{ - return &gConfigThemes.presets[gCurrentTheme]; -} - -theme_window_definition* theme_window_definition_get_by_class(rct_windowclass classification) -{ - for (int i = 0; i < (int)gNumThemeWindows; i++) { - if (gThemeWindowDefinitions[i].classification == classification) { - return &gThemeWindowDefinitions[i]; - } - } - return NULL; -} - -theme_window* theme_window_get_by_class(rct_windowclass classification) -{ - for (int i = 0; i < (int)gNumThemeWindows; i++) { - if (gThemeWindowDefinitions[i].classification == classification) { - return &gConfigThemes.presets[gCurrentTheme].windows[i]; - } - } - return NULL; -} - -void colour_scheme_update(rct_window *window) -{ - theme_window* theme = theme_window_get_by_class(window->classification); - - bool transparent = false; - for (int i = 0; i < 6; i++) { - window->colours[i] = theme->colours[i]; - if (theme->colours[i] & 0x80) { - transparent = true; - } - } - // Some windows need to be transparent even if the colours aren't. - // There doesn't seem to be any side-effects for all windows being transparent - window->flags |= WF_TRANSPARENT; -} - -void colour_scheme_update_by_class(rct_window *window, rct_windowclass classification) -{ - theme_window* theme = theme_window_get_by_class(classification); - - bool transparent = false; - for (int i = 0; i < 6; i++) { - window->colours[i] = theme->colours[i]; - if (theme->colours[i] & 0x80) { - transparent = true; - } - } - // Some windows need to be transparent even if the colours aren't. - // There doesn't seem to be any side-effects for all windows being transparent - window->flags |= WF_TRANSPARENT; -} - -void theme_change_preset(int preset) -{ - if (preset >= 0 && preset < gConfigThemes.num_presets) { - switch (preset) { - case 0: - gConfigInterface.current_theme_preset = "*RCT2"; - break; - case 1: - gConfigInterface.current_theme_preset = "*RCT1"; - break; - default: - gConfigInterface.current_theme_preset = gConfigThemes.presets[preset].name; - break; - } - gCurrentTheme = preset; - } - window_invalidate_all(); -} - -void theme_create_preset(int duplicate, const char *name) -{ - int preset = gConfigThemes.num_presets; - gConfigThemes.num_presets++; - gConfigThemes.presets = realloc(gConfigThemes.presets, sizeof(theme_preset) * gConfigThemes.num_presets); - safe_strncpy(gConfigThemes.presets[preset].name, name, THEME_PRESET_NAME_SIZE); - gConfigThemes.presets[preset].windows = malloc(sizeof(theme_window) * gNumThemeWindows); - for (int i = 0; i < (int)gNumThemeWindows; i++) { - gConfigThemes.presets[preset].windows[i] = gConfigThemes.presets[duplicate].windows[i]; - } - gConfigThemes.presets[preset].features = gConfigThemes.presets[duplicate].features; - themes_save_preset(preset); - theme_change_preset(preset); -} - -void theme_delete_preset(int preset) -{ - if (preset >= 2) { - utf8 path[MAX_PATH]; - platform_get_user_directory(path, "themes"); - strcat(path, gConfigThemes.presets[preset].name); - strcat(path, ".ini"); - platform_file_delete(path); - - free(gConfigThemes.presets[preset].windows); - - for (int i = preset; i < gConfigThemes.num_presets - 1; i++) { - gConfigThemes.presets[i] = gConfigThemes.presets[i + 1]; - } - gConfigThemes.num_presets--; - theme_change_preset(0); - } -} - -void theme_rename_preset(int preset, const char *newName) -{ - if (preset >= 2) { - utf8 src[MAX_PATH], dest[MAX_PATH]; - platform_get_user_directory(src, "themes"); - platform_get_user_directory(dest, "themes"); - strcat(src, gConfigThemes.presets[preset].name); - strcat(dest, newName); - strcat(src, ".ini"); - strcat(dest, ".ini"); - platform_file_move(src, dest); - - safe_strncpy(gConfigThemes.presets[preset].name, newName, THEME_PRESET_NAME_SIZE); - - if (preset == gCurrentTheme) { - gConfigInterface.current_theme_preset = gConfigThemes.presets[preset].name; - } - } -} diff --git a/src/interface/themes.h b/src/interface/themes.h index 4ca788aade..3de9401afc 100644 --- a/src/interface/themes.h +++ b/src/interface/themes.h @@ -18,47 +18,40 @@ * along with this program. If not, see . *****************************************************************************/ -#ifndef _COLOUR_SCHEMES_H_ -#define _COLOUR_SCHEMES_H_ +#ifndef _THEMES_H_ +#define _THEMES_H_ #include "../common.h" #include "window.h" -#include "../config.h" -typedef struct { - rct_windowclass classification; - char *section_name; - rct_string_id name; - uint8 num_colours; - theme_window window; -} theme_window_definition; - -typedef struct { - rct_windowclass classification; - theme_window window; -} theme_window_preset; - -// The definitions for window themes as well as the RCT2 preset -extern theme_window_definition gThemeWindowDefinitions[]; -// The preset for RCT1 window themes -extern theme_window_preset gThemeWindowsRCT1[]; - -// The index of the current theme -extern uint16 gCurrentTheme; -// The number of theme-able windows -extern uint32 gNumThemeWindows; - -theme_preset* theme_get_preset(); -theme_window_definition* theme_window_definition_get_by_class(rct_windowclass classification); -theme_window* theme_window_get_by_class(rct_windowclass classification); +enum { + UITHEME_FLAG_PREDEFINED = 1 << 0, + UITHEME_FLAG_USE_LIGHTS_RIDE = 1 << 1, + UITHEME_FLAG_USE_LIGHTS_PARK = 1 << 2, + UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT = 1 << 3, +}; void colour_scheme_update(rct_window *window); void colour_scheme_update_by_class(rct_window *window, rct_windowclass classification); -void theme_change_preset(int preset); -void theme_create_preset(int duplicate, const char *name); -void theme_delete_preset(int preset); -void theme_rename_preset(int preset, const char *newName); +void theme_manager_initialise(); +void theme_manager_load_available_themes(); +size_t theme_manager_get_num_available_themes(); +const utf8 * theme_manager_get_available_theme_path(size_t index); +const utf8 * theme_manager_get_available_theme_name(size_t index); +size_t theme_manager_get_active_available_theme_index(); +void theme_manager_set_active_available_theme(size_t index); +colour_t theme_get_colour(rct_windowclass wc, uint8 index); +void theme_set_colour(rct_windowclass wc, uint8 index, colour_t colour); +uint8 theme_get_flags(); +void theme_set_flags(uint8 flags); +void theme_save(); +void theme_rename(const utf8 * name); +void theme_duplicate(const utf8 * name); +void theme_delete(); -#endif \ No newline at end of file +uint8 theme_desc_get_num_colours(rct_windowclass wc); +rct_string_id theme_desc_get_name(rct_windowclass wc); + +#endif diff --git a/src/interface/title_sequences.c b/src/interface/title_sequences.c index 5d3b05cbb3..71617c912a 100644 --- a/src/interface/title_sequences.c +++ b/src/interface/title_sequences.c @@ -47,7 +47,7 @@ bool title_sequence_save_exists(int preset, const char *name) { utf8 newName[MAX_PATH]; char *extension = (char*)path_get_extension(name); - safe_strncpy(newName, name, MAX_PATH); + safe_strcpy(newName, name, MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newName, ".sv6"); for (int i = 0; i < gConfigTitleSequences.presets[preset].num_saves; i++) { @@ -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: @@ -86,7 +95,7 @@ void title_sequence_create_preset(const char *name) int preset = gConfigTitleSequences.num_presets; gConfigTitleSequences.num_presets++; gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets); - safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); + safe_strcpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); gConfigTitleSequences.presets[preset].path[0] = 0; gConfigTitleSequences.presets[preset].saves = malloc(0); @@ -112,7 +121,7 @@ void title_sequence_duplicate_preset(int duplicate, const char *name) int preset = gConfigTitleSequences.num_presets; gConfigTitleSequences.num_presets++; gConfigTitleSequences.presets = realloc(gConfigTitleSequences.presets, sizeof(title_sequence) * (size_t)gConfigTitleSequences.num_presets); - safe_strncpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); + safe_strcpy(gConfigTitleSequences.presets[preset].name, name, TITLE_SEQUENCE_NAME_SIZE); gConfigTitleSequences.presets[preset].path[0] = 0; size_t savesSize = sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * gConfigTitleSequences.presets[duplicate].num_saves; @@ -144,7 +153,7 @@ void title_sequence_duplicate_preset(int duplicate, const char *name) char separator = platform_get_path_separator(); for (int i = 0; i < gConfigTitleSequences.presets[preset].num_saves; i++) { if (gConfigTitleSequences.presets[duplicate].path[0]) { - safe_strncpy(srcPath, gConfigTitleSequences.presets[duplicate].path, MAX_PATH); + safe_strcpy(srcPath, gConfigTitleSequences.presets[duplicate].path, MAX_PATH); strcat(srcPath, gConfigTitleSequences.presets[duplicate].saves[i]); } else { @@ -210,7 +219,7 @@ void title_sequence_rename_preset(int preset, const char *newName) strcat(dest, newName); platform_file_move(src, dest); - safe_strncpy(gConfigTitleSequences.presets[preset].name, newName, TITLE_SEQUENCE_NAME_SIZE); + safe_strcpy(gConfigTitleSequences.presets[preset].name, newName, TITLE_SEQUENCE_NAME_SIZE); // Rename the config preset name if needed if (preset == gCurrentPreviewTitleSequence) { @@ -224,7 +233,7 @@ void title_sequence_add_save(int preset, const char *path, const char *newName) { utf8 newPath[MAX_PATH]; char *extension = (char*)path_get_extension(newName); - safe_strncpy(newPath, newName, MAX_PATH); + safe_strcpy(newPath, newName, MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newPath, ".sv6"); if (preset >= TITLE_SEQUENCE_DEFAULT_PRESETS && preset < gConfigTitleSequences.num_presets && filename_valid_characters(newPath) && !title_sequence_save_exists(preset, newPath) && platform_file_exists(path)) { @@ -242,7 +251,7 @@ void title_sequence_add_save(int preset, const char *path, const char *newName) gConfigTitleSequences.presets[preset].num_saves++; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); - safe_strncpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH); + safe_strcpy(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH); // Add the appropriate extension if needed if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(gConfigTitleSequences.presets[preset].saves[gConfigTitleSequences.presets[preset].num_saves - 1], ".sv6"); @@ -272,7 +281,7 @@ void title_sequence_remove_save(int preset, int index) } for (int i = index; i < gConfigTitleSequences.presets[preset].num_saves - 1; i++) { - safe_strncpy(gConfigTitleSequences.presets[preset].saves[i], gConfigTitleSequences.presets[preset].saves[i + 1], TITLE_SEQUENCE_MAX_SAVE_LENGTH); + safe_strcpy(gConfigTitleSequences.presets[preset].saves[i], gConfigTitleSequences.presets[preset].saves[i + 1], TITLE_SEQUENCE_MAX_SAVE_LENGTH); } gConfigTitleSequences.presets[preset].num_saves--; gConfigTitleSequences.presets[preset].saves = realloc(gConfigTitleSequences.presets[preset].saves, sizeof(char[TITLE_SEQUENCE_MAX_SAVE_LENGTH]) * (size_t)gConfigTitleSequences.presets[preset].num_saves); @@ -302,7 +311,7 @@ void title_sequence_rename_save(int preset, int index, const char *newName) strcat(dest, ".sv6"); platform_file_move(src, dest); - safe_strncpy(gConfigTitleSequences.presets[preset].saves[index], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH); + safe_strcpy(gConfigTitleSequences.presets[preset].saves[index], newName, TITLE_SEQUENCE_MAX_SAVE_LENGTH); // Add the appropriate extension if needed if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(gConfigTitleSequences.presets[preset].saves[index], ".sv6"); diff --git a/src/interface/title_sequences.h b/src/interface/title_sequences.h index 3c46ebbda2..f17633f419 100644 --- a/src/interface/title_sequences.h +++ b/src/interface/title_sequences.h @@ -65,4 +65,4 @@ void title_sequence_delete_command(int preset, int index); void title_sequence_move_down_command(int preset, int index); void title_sequence_move_up_command(int preset, int index); -#endif \ No newline at end of file +#endif diff --git a/src/interface/viewport.c b/src/interface/viewport.c index 87a52f7c07..11e78c37ac 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -21,6 +21,8 @@ #include "../addresses.h" #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" @@ -81,8 +83,8 @@ struct paint_struct{ }; /** - * This is not a viewport function. It is used to setup many variables for - * multiple things. + * This is not a viewport function. It is used to setup many variables for + * multiple things. * rct2: 0x006E6EAC */ void viewport_init_all() @@ -100,11 +102,11 @@ void viewport_init_all() RCT2_GLOBAL(RCT2_ADDRESS_ACTIVE_VIEWPORT_PTR_ARRAY, rct_viewport*) = NULL; // ? - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, sint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_STATE, sint8) = 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; + gInputFlags = 0; + gInputState = INPUT_STATE_RESET; + gPressedWidget.window_classification = 255; + 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(); @@ -113,13 +115,14 @@ void viewport_init_all() } /** - * rct:0x006EB0C1 - * x : ax - * y : bx - * z : cx - * out_x : ax - * out_y : bx - * Converts between 3d point of a sprite to 2d coordinates for centering on that sprite + * Converts between 3d point of a sprite to 2d coordinates for centering on that + * sprite + * rct2: 0x006EB0C1 + * x : ax + * y : bx + * z : cx + * out_x : ax + * out_y : bx */ void center_2d_coordinates(int x, int y, int z, int* out_x, int* out_y, rct_viewport* viewport){ int start_x = x; @@ -146,21 +149,21 @@ void center_2d_coordinates(int x, int y, int z, int* out_x, int* out_y, rct_view } /** +* Viewport will look at sprite or at coordinates as specified in flags 0b_1X +* for sprite 0b_0X for coordinates * * rct2: 0x006EB009 * x: ax * y: eax (top 16) * width: bx * height: ebx (top 16) -* zoom: cl (8 bits) +* zoom: cl (8 bits) * center_x: edx lower 16 bits * center_y: edx upper 16 bits * center_z: ecx upper 16 bits * sprite: edx lower 16 bits * flags: edx top most 2 bits 0b_X1 for zoom clear see below for 2nd bit. * w: esi -* -* Viewport will look at sprite or at coordinates as specified in flags 0b_1X for sprite 0b_0X for coordinates */ void viewport_create(rct_window *w, int x, int y, int width, int height, int zoom, int center_x, int center_y, int center_z, char flags, sint16 sprite) { @@ -229,8 +232,10 @@ void viewport_update_pointers() } /** - * edx is assumed to be (and always is) the current rotation, so it is not needed as parameter. - * rct2: 0x00689174 + * + * rct2: 0x00689174 + * edx is assumed to be (and always is) the current rotation, so it is not + * needed as parameter. */ void sub_689174(sint16* x, sint16* y, sint16 *z) { @@ -269,7 +274,7 @@ void sub_683326(int left, int top, int right, int bottom) * shifts pixels from the region in a direction. Used when a viewport moves; * consider putting in src/drawing/drawing.c or src/drawing/rect.c * - * rct2: 0x00683359 + * rct2: 0x00683359 * ax = x * bx = y; * cx = width; @@ -753,10 +758,10 @@ void painter_setup(){ RCT2_GLOBAL(0xF1AD24, uint32) = 0; } -/*** +/** * - * rct2: 0x00688596 - * Part of 0x688485 + * rct2: 0x00688596 + * Part of 0x688485 */ void paint_attached_ps(paint_struct* ps, paint_struct* attached_ps, rct_drawpixelinfo* dpi){ for (; attached_ps; attached_ps = attached_ps->next_attached_ps){ @@ -851,12 +856,25 @@ void sub_688485(){ } -/* rct2: 0x006874B0, 0x00687618, 0x0068778C, 0x00687902, 0x0098199C */ -int sub_98199C(sint8 al, sint8 ah, int image_id, sint8 cl, int height, sint16 length_y, sint16 length_x, uint32 rotation){ +/** + * + * rct2: 0x006874B0, 0x00687618, 0x0068778C, 0x00687902, 0x0098199C + * + * @param image_id (ebx) + * @param x_offset (al) + * @param y_offset (cl) + * @param length_x (di) + * @param length_y (si) + * @param z_offset (ah) + * @param height (edx) + * @param rotation + * @return ?? + */ +int sub_98199C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation) { RCT2_CALLPROC_X(RCT2_ADDRESS(0x98199C, uint32_t)[get_current_rotation()], - al | (ah << 8), - image_id, - cl, + x_offset | (z_offset << 8), + image_id, + y_offset, height, length_y, length_x, @@ -864,9 +882,48 @@ int sub_98199C(sint8 al, sint8 ah, int image_id, sint8 cl, int height, sint16 le return 1; } -/* rct2: 0x00686806, 0x006869B2, 0x00686B6F, 0x00686D31, 0x0098197C */ -int sub_98197C(sint8 al, sint8 ah, int image_id, sint8 cl, int height, sint16 length_y, sint16 length_x, uint32 rotation){ - int ebp = ah + RCT2_GLOBAL(0x9DEA56, sint16); +/** + * rct2: 0x006861AC, 0x00686337, 0x006864D0, 0x0068666B, 0x0098196C + * + * @param image_id (ebx) + * @param x_offset (al) + * @param y_offset (cl) + * @param length_x (di) + * @param length_y (si) + * @param z_offset (ah) + * @param height (edx) + * @param rotation + * @return ?? + */ +int sub_98196C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation) +{ + RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098196C, uint32)[get_current_rotation()], + x_offset | (z_offset << 8), + image_id, + y_offset, + height, + length_y, + length_x, + rotation + ); + return 1; +} + +/** + * rct2: 0x00686806, 0x006869B2, 0x00686B6F, 0x00686D31, 0x0098197C + * + * @param image_id (ebx) + * @param x_offset (al) + * @param y_offset (cl) + * @param length_x (di) + * @param length_y (si) + * @param z_offset (ah) + * @param height (edx) + * @param rotation + * @return ?? + */ +int sub_98197C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation){ + int ebp = z_offset + RCT2_GLOBAL(0x9DEA56, sint16); RCT2_GLOBAL(0xF1AD28, paint_struct*) = 0; RCT2_GLOBAL(0xF1AD2C, uint32) = 0; @@ -889,8 +946,8 @@ int sub_98197C(sint8 al, sint8 ah, int image_id, sint8 cl, int height, sint16 le } rct_xyz16 coord_3d = { - .x = al, - .y = cl, + .x = x_offset, + .y = y_offset, .z = height }; @@ -1027,32 +1084,60 @@ int sub_98197C(sint8 al, sint8 ah, int image_id, sint8 cl, int height, sint16 le return 0; } +/** + * + * rct2: 0x00686EF0, 0x00687056, 0x006871C8, 0x0068733C, 0x0098198C + * + * @param image_id (ebx) + * @param x_offset (al) + * @param y_offset (cl) + * @param length_x (di) + * @param length_y (si) + * @param z_offset (ah) + * @param height (edx) + * @param rotation + * @return ?? + */ +int sub_98198C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation) +{ + RCT2_CALLPROC_X(RCT2_ADDRESS(0x0098196C, uint32)[get_current_rotation()], + x_offset | (z_offset << 8), + image_id, + y_offset, + height, + length_y, + length_x, + rotation + ); + return 1; +} + /** * * rct2: 0x006D4244 */ void viewport_vehicle_paint_setup(rct_vehicle *vehicle, int imageDirection) { - rct_ride_type *rideEntry; - const rct_ride_type_vehicle *vehicleEntry; + rct_ride_entry *rideEntry; + const rct_ride_entry_vehicle *vehicleEntry; int x = vehicle->x; int y = vehicle->y; int z = vehicle->z; - if (vehicle->var_0C & 0x80) { + if (vehicle->flags & SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE) { uint32 ebx = 22965 + vehicle->var_C5; RCT2_GLOBAL(0x9DEA52, uint16) = 0; RCT2_GLOBAL(0x9DEA54, uint16) = 0; RCT2_GLOBAL(0x9DEA56, uint16) = z + 2; - sub_98197C(0, 0, ebx, 0, z, 1, 1, get_current_rotation()); + sub_98197C(ebx, 0, 0, 1, 1, 0, z, get_current_rotation()); return; } if (vehicle->ride_subtype == 0xFF) { vehicleEntry = &CableLiftVehicle; } else { - rideEntry = GET_RIDE_ENTRY(vehicle->ride_subtype); + rideEntry = get_ride_entry(vehicle->ride_subtype); vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_11) { @@ -1061,7 +1146,7 @@ void viewport_vehicle_paint_setup(rct_vehicle *vehicle, int imageDirection) } } - uint32 rct2VehiclePtrFormat = ((uint32)vehicleEntry) - offsetof(rct_ride_type, vehicles); + uint32 rct2VehiclePtrFormat = ((uint32)vehicleEntry) - offsetof(rct_ride_entry, vehicles); RCT2_GLOBAL(0x00F64DFC, uint32) = rct2VehiclePtrFormat; switch (vehicleEntry->car_visual) { case VEHICLE_VISUAL_DEFAULT: RCT2_CALLPROC_X(0x006D45F8, x, imageDirection, y, z, (int)vehicle, rct2VehiclePtrFormat, 0); break; @@ -1102,7 +1187,7 @@ void viewport_misc_paint_setup(rct_sprite *misc, int imageDirection) } /** -* Litter Paint Setup +* Litter Paint Setup * rct2: 0x006736FC */ void viewport_litter_paint_setup(rct_litter *litter, int imageDirection) @@ -1124,34 +1209,31 @@ void viewport_litter_paint_setup(rct_litter *litter, int imageDirection) RCT2_GLOBAL(0x9DEA54, uint16) = 0xFFFC; RCT2_GLOBAL(0x9DEA56, uint16) = litter->z + 2; - sub_98197C(0, 0xFF, image_id, 0, litter->z, 4, 4, get_current_rotation()); + sub_98197C(image_id, 0, 0, 4, 4, 0xFF, litter->z, get_current_rotation()); } /** -* Paint Quadrant +* Paint Quadrant * rct2: 0x0069E8B0 */ -void sprite_paint_setup(uint16 eax, uint16 ecx){ - uint32 _eax = eax, _ecx = ecx; +void sprite_paint_setup(const uint16 eax, const uint16 ecx){ rct_drawpixelinfo* dpi; + if ((eax & 0xe000) | (ecx & 0xe000)) return; + + const int idx = ((eax << 3) & 0xff00) | (ecx >> 5); + int sprite_idx = RCT2_ADDRESS(0xF1EF60, uint16)[idx]; + if (sprite_idx == SPRITE_INDEX_NULL) return; if (RCT2_GLOBAL(0x9DEA6F, uint8) & 1) return; - dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_VIEWPORT_FLAGS, uint16) & VIEWPORT_FLAG_INVISIBLE_SPRITES) return; + dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); if (dpi->zoom_level > 2) return; - if (eax > 0x2000)return; - if (ecx > 0x2000)return; - - //push eax, ecx - eax = (eax & 0x1FE0) << 3 | (ecx >> 5); - int sprite_idx = RCT2_ADDRESS(0xF1EF60, uint16)[eax]; - if (sprite_idx == SPRITE_INDEX_NULL) return; for (rct_sprite* spr = &g_sprite_list[sprite_idx]; sprite_idx != SPRITE_INDEX_NULL; sprite_idx = spr->unknown.next_in_quadrant){ spr = &g_sprite_list[sprite_idx]; @@ -1168,7 +1250,6 @@ void sprite_paint_setup(uint16 eax, uint16 ecx){ image_direction &= 0x1F; RCT2_GLOBAL(0x9DE578, uint32) = (uint32)spr; - int ebp = spr->unknown.sprite_identifier; RCT2_GLOBAL(0x9DE568, sint16) = spr->unknown.x; RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8) = VIEWPORT_INTERACTION_ITEM_SPRITE; @@ -1194,22 +1275,10 @@ void sprite_paint_setup(uint16 eax, uint16 ecx){ } } -/* rct2: 0x006629BC - * returns al - * ebp : image_id - * ax : unknown - * dx : height - * edi : unknown +/** + * + * rct2: 0x0066508C, 0x00665540 */ -bool sub_6629BC(int height, uint16 ax, uint32 image_id, int edi){ - int eax = ax, ebx = 0, ecx = 0, edx = height, esi = 0, _edi = edi, ebp = image_id; - - RCT2_CALLFUNC_X(0x006629BC, &eax, &ebx, &ecx, &edx, &esi, &_edi, &ebp); - - return eax & 0xFF; -} - -/* rct2: 0x0066508C & 0x00665540 */ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_map_element* map_element) { rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); @@ -1220,7 +1289,7 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma return; } - rct_ride* ride = GET_RIDE(map_element->properties.entrance.ride_index); + rct_ride* ride = get_ride(map_element->properties.entrance.ride_index); if (ride->entrance_style == RIDE_ENTRANCE_STYLE_NONE) return; const rct_ride_entrance_definition *style = &RideEntranceDefinitions[ride->entrance_style]; @@ -1241,7 +1310,7 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma if (map_element->flags & MAP_ELEMENT_FLAG_GHOST){ RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8) = VIEWPORT_INTERACTION_ITEM_NONE; - image_id = RCT2_ADDRESS(0x993CC4, uint32_t)[RCT2_GLOBAL(0x9AACBF, uint8)]; + image_id = RCT2_ADDRESS(0x993CC4, uint32_t)[gConfigGeneral.construction_marker_colour]; RCT2_GLOBAL(0x009E32BC, uint32) = image_id; if (transparant_image_id) transparant_image_id = image_id; @@ -1267,7 +1336,7 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma sint16 lengthY = (direction & 1) ? 28 : 2; sint16 lengthX = (direction & 1) ? 2 : 28; - sub_98197C(0, ah, image_id, 0, height, lengthY, lengthX, get_current_rotation()); + sub_98197C(image_id, 0, 0, lengthX, lengthY, ah, height, get_current_rotation()); if (transparant_image_id){ if (is_exit){ @@ -1280,7 +1349,7 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98199C(0, ah, transparant_image_id, 0, height, lengthY, lengthX, 0); + sub_98199C(transparant_image_id, 0, 0, lengthX, lengthY, ah, height, 0); } image_id += 4; @@ -1289,7 +1358,7 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma RCT2_GLOBAL(0x009DEA54, uint16) = (direction & 1) ? 2 : 28; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, ah, image_id, 0, height, lengthY, lengthX, get_current_rotation()); + sub_98197C(image_id, 0, 0, lengthX, lengthY, ah, height, get_current_rotation()); if (transparant_image_id){ transparant_image_id += 4; @@ -1297,7 +1366,7 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma RCT2_GLOBAL(0x009DEA54, uint16) = (direction & 1) ? 2 : 28; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98199C(0, ah, transparant_image_id, 0, height, lengthY, lengthX, 0); + sub_98199C(transparant_image_id, 0, 0, lengthX, lengthY, ah, height, 0); } uint32 eax = 0xFFFF0600 | ((height / 16) & 0xFF); @@ -1315,7 +1384,7 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma map_element->properties.entrance.ride_index != 0xFF){ RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = 0; - RCT2_GLOBAL(0x13CE956, uint32) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = 0; rct_string_id string_id = STR_RIDE_ENTRANCE_CLOSED; @@ -1343,20 +1412,14 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma RCT2_GLOBAL(0x009DEA52, uint16) = 2; RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, uint16) = height + style->height; - sub_98199C(0, 0x33, scrolling_text_setup(string_id, scroll, style->scrolling_mode), 0, height + style->height, 0x1C, 0x1C, 0); + sub_98199C(scrolling_text_setup(string_id, scroll, style->scrolling_mode), 0, 0, 0x1C, 0x1C, 0x33, height + style->height, 0); } image_id = RCT2_GLOBAL(0x009E32BC, uint32); - if (!image_id){ - image_id = 0x20B80000; - } - - if (direction & 1){ - sub_6629BC(height, 0, image_id, 1); - } - else{ - sub_6629BC(height, 0, image_id, 0); + if (image_id == 0) { + image_id = SPRITE_ID_PALETTE_COLOUR_1(COLOUR_SATURATED_BROWN); } + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); RCT2_GLOBAL(0x141E9B4, uint16) = 0xFFFF; RCT2_GLOBAL(0x141E9B8, uint16) = 0xFFFF; @@ -1369,13 +1432,16 @@ void viewport_ride_entrance_exit_paint_setup(uint8 direction, int height, rct_ma RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += is_exit ? 40 : 56; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height){ - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height){ + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x006658ED */ +/** + * + * rct2: 0x006658ED + */ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_element* map_element){ if (RCT2_GLOBAL(0x9DEA6F, uint8_t) & 1) return; @@ -1385,7 +1451,7 @@ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_ele uint32 image_id, ghost_id = 0; if (map_element->flags & MAP_ELEMENT_FLAG_GHOST){ RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8) = VIEWPORT_INTERACTION_ITEM_NONE; - ghost_id = RCT2_ADDRESS(0x993CC4, uint32)[RCT2_GLOBAL(0x9AACBF, uint8)]; + ghost_id = RCT2_ADDRESS(0x993CC4, uint32)[gConfigGeneral.construction_marker_colour]; RCT2_GLOBAL(0x009E32BC, uint32) = ghost_id; } @@ -1404,7 +1470,7 @@ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_ele RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, sint16) = height; - sub_98197C(0, 0, image_id, 0, height, 0x1C, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 0x1C, 0, height, get_current_rotation()); entrance = (rct_entrance_type*)object_entry_groups[OBJECT_TYPE_PARK_ENTRANCE].chunks[0]; image_id = (entrance->image_id + direction * 3) | ghost_id; @@ -1413,7 +1479,7 @@ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_ele RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, sint16) = height + 32; - sub_98197C(0, 0x2F, image_id, 0, height, 0x1C, 0x1C, get_current_rotation()); + sub_98197C(image_id, 0, 0, 0x1C, 0x1C, 0x2F, height, get_current_rotation()); if ((direction + 1) & (1 << 1)) break; @@ -1421,12 +1487,12 @@ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_ele break; rct_string_id park_text_id = 1730; - RCT2_GLOBAL(0x0013CE952, uint32) = 0; - RCT2_GLOBAL(0x0013CE956, uint32) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = 0; if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN){ - RCT2_GLOBAL(0x0013CE952, rct_string_id) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id); - RCT2_GLOBAL(0x0013CE954, rct_string_id) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, rct_string_id); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, rct_string_id) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, rct_string_id); park_text_id = 1731; } @@ -1449,7 +1515,7 @@ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_ele RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, sint16) = height + entrance->text_height; - sub_98199C(0, 0x2F, scrolling_text_setup(park_text_id, scroll, entrance->scrolling_mode + direction / 2), 0, height + entrance->text_height, 0x1C, 0x1C, 0); + sub_98199C(scrolling_text_setup(park_text_id, scroll, entrance->scrolling_mode + direction / 2), 0, 0, 0x1C, 0x1C, 0x2F, height + entrance->text_height, 0); break; case 1: case 2: @@ -1460,21 +1526,15 @@ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_ele RCT2_GLOBAL(0x009DEA54, uint16) = 3; RCT2_GLOBAL(0x009DEA56, sint16) = height; - sub_98197C(0, 0x4F, image_id, 0, height, di, 0x1A, get_current_rotation()); + sub_98197C(image_id, 0, 0, 0x1A, di, 0x4F, height, get_current_rotation()); break; } image_id = ghost_id; - if (!image_id){ - image_id = 0x20B80000; - } - - if (direction & 1){ - sub_6629BC(height, 0, image_id, 1); - } - else{ - sub_6629BC(height, 0, image_id, 0); + if (image_id == 0) { + image_id = SPRITE_ID_PALETTE_COLOUR_1(COLOUR_SATURATED_BROWN); } + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); RCT2_GLOBAL(0x141E9B4, uint16) = 0xFFFF; RCT2_GLOBAL(0x141E9B8, uint16) = 0xFFFF; @@ -1487,8 +1547,8 @@ void viewport_park_entrance_paint_setup(uint8 direction, int height, rct_map_ele RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 80; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height){ - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height){ + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } @@ -1504,7 +1564,11 @@ void viewport_track_paint_setup(uint8 direction, int height, rct_map_element *ma int rideIndex, trackType, trackColourScheme, trackSequence; rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); + if (ride->type == RIDE_TYPE_NULL) { + log_error("Attempted to paint invalid ride: %d", rideIndex); + return; + } // HACK Set entrance style to plain if none to stop glitch until entrance track piece is implemented bool isEntranceStyleNone = false; @@ -1528,7 +1592,7 @@ void viewport_track_paint_setup(uint8 direction, int height, rct_map_element *ma RCT2_GLOBAL(0x009DEA52, uint16) = 1000; RCT2_GLOBAL(0x009DEA54, uint16) = 1000; RCT2_GLOBAL(0x009DEA56, uint16) = 2047; - sub_98197C(16, 0, ebx, 16, height + ax + 3, 1, 1, get_current_rotation()); + sub_98197C(ebx, 16, 16, 1, 1, 0, height + ax + 3, get_current_rotation()); } } @@ -1544,7 +1608,7 @@ void viewport_track_paint_setup(uint8 direction, int height, rct_map_element *ma RCT2_GLOBAL(0x00F441A4, uint32) = 0x21600000; } if (mapElement->flags & MAP_ELEMENT_FLAG_GHOST) { - uint32 ghost_id = RCT2_ADDRESS(0x00993CC4, uint32)[RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CONSTRUCTION_MARKER, uint8)]; + uint32 ghost_id = RCT2_ADDRESS(0x00993CC4, uint32)[gConfigGeneral.construction_marker_colour]; RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8) = 0; RCT2_GLOBAL(0x00F44198, uint32) = ghost_id; RCT2_GLOBAL(0x00F4419C, uint32) = ghost_id; @@ -1554,10 +1618,11 @@ void viewport_track_paint_setup(uint8 direction, int height, rct_map_element *ma TRACK_PAINT_FUNCTION **trackTypeList = (TRACK_PAINT_FUNCTION**)RideTypeTrackPaintFunctionsOld[ride->type]; if (trackTypeList == NULL) { - trackTypeList = (TRACK_PAINT_FUNCTION**)RideTypeTrackPaintFunctions[ride->type]; - - if (trackTypeList[trackType] != NULL) - trackTypeList[trackType][direction](rideIndex, trackSequence, direction, height, mapElement); + TRACK_PAINT_FUNCTION_GETTER paintFunctionGetter = RideTypeTrackPaintFunctions[ride->type]; + TRACK_PAINT_FUNCTION paintFunction = paintFunctionGetter(trackType, direction); + if (paintFunction != NULL) { + paintFunction(rideIndex, trackSequence, direction, height, mapElement); + } } else { uint32 *trackDirectionList = (uint32*)trackTypeList[trackType]; @@ -1581,7 +1646,10 @@ void viewport_track_paint_setup(uint8 direction, int height, rct_map_element *ma } } -/* rct2: 0x00664FD4 */ +/** + * + * rct2: 0x00664FD4 + */ void viewport_entrance_paint_setup(uint8 direction, int height, rct_map_element* map_element){ RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8_t) = VIEWPORT_INTERACTION_ITEM_LABEL; @@ -1608,7 +1676,7 @@ void viewport_entrance_paint_setup(uint8 direction, int height, rct_map_element* RCT2_GLOBAL(0x009DEA56, sint16) = z; RCT2_GLOBAL(0x009DEA56, uint16) += 64; - sub_98197C(16, 0, image_id, 16, height, 1, 1, get_current_rotation()); + sub_98197C(image_id, 16, 16, 1, 1, 0, height, get_current_rotation()); } } @@ -1623,7 +1691,10 @@ void viewport_entrance_paint_setup(uint8 direction, int height, rct_map_element* } } -/* rct2: 0x006B9CC4 */ +/** + * + * rct2: 0x006B9CC4 + */ void viewport_banner_paint_setup(uint8 direction, int height, rct_map_element* map_element) { rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); @@ -1649,7 +1720,7 @@ void viewport_banner_paint_setup(uint8 direction, int height, rct_map_element* m if (map_element->flags & MAP_ELEMENT_FLAG_GHOST)//if being placed { RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8_t) = VIEWPORT_INTERACTION_ITEM_NONE; - image_id |= RCT2_ADDRESS(0x993CC4, uint32_t)[RCT2_GLOBAL(0x9AACBF, uint8)]; + image_id |= RCT2_ADDRESS(0x993CC4, uint32_t)[gConfigGeneral.construction_marker_colour]; } else{ image_id |= @@ -1657,11 +1728,11 @@ void viewport_banner_paint_setup(uint8 direction, int height, rct_map_element* m 0x20000000; } - sub_98197C(0, 0x15, image_id, 0, height, 1, 1, get_current_rotation()); + sub_98197C(image_id, 0, 0, 1, 1, 0x15, height, get_current_rotation()); RCT2_GLOBAL(0x9DEA52, uint32) = RCT2_ADDRESS(0x98D888, uint32)[direction * 2]; image_id++; - sub_98197C(0, 0x15, image_id, 0, height, 1, 1, get_current_rotation()); + sub_98197C(image_id, 0, 0, 1, 1, 0x15, height, get_current_rotation()); // Opposite direction direction ^= 2; @@ -1673,7 +1744,7 @@ void viewport_banner_paint_setup(uint8 direction, int height, rct_map_element* m scrollingMode += direction; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = 0; - RCT2_GLOBAL(0x13CE956, uint32_t) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32_t) = 0; rct_string_id string_id = STR_NO_ENTRY; if (!(gBanners[map_element->properties.banner.index].flags & BANNER_FLAG_NO_ENTRY)) @@ -1692,7 +1763,7 @@ void viewport_banner_paint_setup(uint8 direction, int height, rct_map_element* m uint16 string_width = gfx_get_string_width(RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char)); uint16 scroll = (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) / 2) % string_width; - sub_98199C(0, 0x15, scrolling_text_setup(string_id, scroll, scrollingMode), 0, height + 22, 1, 1, 0); + sub_98199C(scrolling_text_setup(string_id, scroll, scrollingMode), 0, 0, 1, 1, 0x15, height + 22, 0); } /** @@ -1713,9 +1784,10 @@ static void sub_68B3FB(int x, int y) RCT2_GLOBAL(0x9DE576, uint16_t) = y; rct_map_element* map_element = map_get_first_element_at(x >> 5, y >> 5); + uint8 rotation = get_current_rotation(); int dx = 0; - switch (get_current_rotation()) { + switch (rotation) { case 0: dx = x + y; break; @@ -1739,7 +1811,7 @@ static void sub_68B3FB(int x, int y) RCT2_GLOBAL(0x9DE56A, uint16) == RCT2_GLOBAL(RCT2_ADDRESS_MAP_ARROW_X, uint16) && RCT2_GLOBAL(0x9DE56E, uint16) == RCT2_GLOBAL(RCT2_ADDRESS_MAP_ARROW_Y, uint16)){ uint8 arrowRotation = - (get_current_rotation() + (rotation + (RCT2_GLOBAL(RCT2_ADDRESS_MAP_ARROW_DIRECTION, uint8) & 3)) & 3; uint32 imageId = @@ -1756,14 +1828,14 @@ static void sub_68B3FB(int x, int y) RCT2_GLOBAL(0x9DEA54, uint16) = 0; RCT2_GLOBAL(0x9DEA56, uint16) = arrowZ + 18; - sub_98197C(0, 0xFF, imageId, 0, arrowZ, 32, 32, get_current_rotation()); + sub_98197C(imageId, 0, 0, 32, 32, 0xFF, arrowZ, rotation); } int bx = dx + 52; if (bx <= dpi->y) return; - rct_map_element* element = map_element;//push map_element + const rct_map_element* element = map_element;//push map_element sint16 max_height = 0; do{ @@ -1790,7 +1862,7 @@ static void sub_68B3FB(int x, int y) RCT2_GLOBAL(0x9DE56C, sint16) = y; RCT2_GLOBAL(0x9DE57C, uint16) = 0; do { - int direction = (map_element->type + get_current_rotation()) & MAP_ELEMENT_DIRECTION_MASK; + int direction = (map_element->type + rotation) & MAP_ELEMENT_DIRECTION_MASK; int height = map_element->base_height * 8; uint32_t dword_9DE574 = RCT2_GLOBAL(0x9DE574, uint32_t); @@ -1822,13 +1894,15 @@ static void sub_68B3FB(int x, int y) case MAP_ELEMENT_TYPE_BANNER: viewport_banner_paint_setup(direction, height, map_element); break; - default: - // This is a little hack for taking care of undefined map_elements - // 8cars MOM used a dirty version of this to skip drawing certain elements + // A corrupt element inserted by OpenRCT2 itself, which skips the drawing of the next element only. + case MAP_ELEMENT_TYPE_CORRUPT: if (map_element_is_last_for_tile(map_element)) return; map_element++; break; + default: + // An undefined map element is most likely a corrupt element inserted by 8 cars' MOM feature to skip drawing of all elements after it. + return; } RCT2_GLOBAL(0x9DE574, uint32_t) = dword_9DE574; } while (!map_element_is_last_for_tile(map_element++)); @@ -1904,7 +1978,8 @@ void sub_68B2B7(int x, int y) RCT2_GLOBAL(0x0141E9CC, uint32) = 0xFFFF; RCT2_GLOBAL(0x0141E9D0, uint32) = 0xFFFF; RCT2_GLOBAL(0x0141E9D4, uint32) = 0xFFFF; - RCT2_GLOBAL(0x0141E9D8, uint32) = 0xFFFF; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = -1; + RCT2_GLOBAL(0x0141E9DA, uint16) = 0; RCT2_GLOBAL(0x0141E9DC, uint32) = 0xFFFF; RCT2_GLOBAL(0x0141E9DB, uint8) |= 2; @@ -1936,7 +2011,8 @@ void map_element_paint_setup(int x, int y) RCT2_GLOBAL(0x0141E9CC, uint32) = 0xFFFF; RCT2_GLOBAL(0x0141E9D0, uint32) = 0xFFFF; RCT2_GLOBAL(0x0141E9D4, uint32) = 0xFFFF; - RCT2_GLOBAL(0x0141E9D8, uint32) = 0xFFFF; + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = -1; + RCT2_GLOBAL(0x0141E9DA, sint16) = 0; RCT2_GLOBAL(0x0141E9DC, uint32) = 0xFFFF; sub_68B3FB(x, y); @@ -2058,7 +2134,7 @@ void viewport_paint_setup() void sub_688217_helper(uint16 ax, uint8 flag) { - paint_struct *ps; + paint_struct *ps, *ps_temp; paint_struct *ps_next = RCT2_GLOBAL(0x00EE7884, paint_struct*); do { @@ -2067,7 +2143,7 @@ void sub_688217_helper(uint16 ax, uint8 flag) if (ps_next == NULL) return; } while (ax > ps_next->var_18); - RCT2_GLOBAL(0x00F1AD14, paint_struct*) = ps; + ps_temp = ps; do { ps = ps->next_quadrant_ps; @@ -2082,8 +2158,9 @@ void sub_688217_helper(uint16 ax, uint8 flag) } } while (ps->var_18 <= ax + 1); - ps = RCT2_GLOBAL(0x00F1AD14, paint_struct*); + ps = ps_temp; + uint8 rotation = get_current_rotation(); while (true) { while (true) { ps_next = ps->next_quadrant_ps; @@ -2094,7 +2171,7 @@ void sub_688217_helper(uint16 ax, uint8 flag) } ps_next->var_1B &= ~(1 << 0); - RCT2_GLOBAL(0x00F1AD18, paint_struct*) = ps; + ps_temp = ps; uint16 my_attached_x = ps_next->attached_x; uint16 my_attached_y = ps_next->attached_y; @@ -2111,7 +2188,7 @@ void sub_688217_helper(uint16 ax, uint8 flag) if (!(ps_next->var_1B & (1 << 1))) continue; int yes = 0; - switch (get_current_rotation()) { + switch (rotation) { case 0: if (my_some_y >= ps_next->some_x && my_other_y >= ps_next->attached_y && my_other_x >= ps_next->attached_x && !(my_some_x < ps_next->some_y && my_attached_y < ps_next->other_y && my_attached_x < ps_next->other_x)) @@ -2136,14 +2213,14 @@ void sub_688217_helper(uint16 ax, uint8 flag) if (yes) { ps->next_quadrant_ps = ps_next->next_quadrant_ps; - paint_struct *ps_temp = RCT2_GLOBAL(0x00F1AD18, paint_struct*)->next_quadrant_ps; - RCT2_GLOBAL(0x00F1AD18, paint_struct*)->next_quadrant_ps = ps_next; - ps_next->next_quadrant_ps = ps_temp; + paint_struct *ps_temp2 = ps_temp->next_quadrant_ps; + ps_temp->next_quadrant_ps = ps_next; + ps_next->next_quadrant_ps = ps_temp2; ps_next = ps; } } - ps = RCT2_GLOBAL(0x00F1AD18, paint_struct*); + ps = ps_temp; } } @@ -2205,7 +2282,7 @@ static void draw_pixel_info_crop_by_zoom(rct_drawpixelinfo *dpi) /** * - * rct2:0x006860C3 + * rct2: 0x006860C3 */ static void viewport_draw_money_effects() { @@ -2234,7 +2311,7 @@ static void viewport_draw_money_effects() /** * - * rct2:0x00685CBF + * rct2: 0x00685CBF * eax: left * ebx: top * edx: right @@ -2520,7 +2597,7 @@ void hide_construction_rights() /** * - * rct2: 0x006CB70A + * rct2: 0x006CB70A */ void viewport_set_visibility(uint8 mode) { @@ -2567,7 +2644,7 @@ void viewport_set_visibility(uint8 mode) /** * Stores some info about the element pointed at, if requested for this particular type through the interaction mask. - * rct2: 0x00688697 + * rct2: 0x00688697 */ void store_interaction_info(paint_struct *ps) { @@ -2774,10 +2851,10 @@ rct_viewport *viewport_find_from_point(int screenX, int screenY) /** * * rct2: 0x00688972 - * In: + * In: * screen_x: eax * screen_y: ebx - * Out: + * Out: * x: ax * y: bx * map_element: edx ? @@ -2913,7 +2990,7 @@ uint8 get_current_rotation() uint32 rotation_masked = rotation & 3; #if DEBUG_LEVEL_1 if (rotation != rotation_masked) { - log_error("Found wrong rotation %d! Will return %d instead.", rotation, rotation_masked); + log_error("Found wrong rotation %d! Will return %d instead.", rotation, rotation_masked); } #endif // DEBUG_LEVEL_1 return (uint8)rotation_masked; diff --git a/src/interface/viewport.h b/src/interface/viewport.h index b8e4df70fa..55086127c3 100644 --- a/src/interface/viewport.h +++ b/src/interface/viewport.h @@ -131,9 +131,10 @@ void painter_setup(); void sub_688485(); void sub_688217(); -int sub_98197C(sint8 al, sint8 ah, int image_id, sint8 cl, int height, sint16 length_y, sint16 length_x, uint32 rotation); -int sub_98199C(sint8 al, sint8 ah, int image_id, sint8 cl, int height, sint16 length_y, sint16 length_x, uint32 rotation); -bool sub_6629BC(int height, uint16 ax, uint32 image_id, int edi); +int sub_98196C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation); +int sub_98197C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation); +int sub_98198C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation); +int sub_98199C(int image_id, sint8 x_offset, sint8 y_offset, sint16 length_x, sint16 length_y, sint8 z_offset, int height, uint32 rotation); void viewport_invalidate(rct_viewport *viewport, int left, int top, int right, int bottom); diff --git a/src/interface/viewport_interaction.c b/src/interface/viewport_interaction.c index b8ef2602e1..f391423be7 100644 --- a/src/interface/viewport_interaction.c +++ b/src/interface/viewport_interaction.c @@ -196,7 +196,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info return info->type = VIEWPORT_INTERACTION_ITEM_NONE; mapElement += 6; - ride = GET_RIDE(mapElement->type); + ride = get_ride(mapElement->type); if (ride->status == RIDE_STATUS_CLOSED) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 1163; RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = ride->name; @@ -210,7 +210,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; - ride = GET_RIDE(mapElement->properties.track.ride_index); + ride = get_ride(mapElement->properties.track.ride_index); if (ride->status != RIDE_STATUS_CLOSED) return info->type; @@ -222,7 +222,7 @@ int viewport_interaction_get_item_right(int x, int y, viewport_interaction_info } else if (mapElement->properties.track.type == 1 || mapElement->properties.track.type == 2 || mapElement->properties.track.type == 3) { RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = 1333; } else { - if (!map_is_location_owned(info->x, info->y, mapElement->base_height << 4)) + if (!gCheatsSandboxMode && !map_is_location_owned(info->x, info->y, mapElement->base_height << 4)) return info->type = VIEWPORT_INTERACTION_ITEM_NONE; RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = ride->name; @@ -272,9 +272,11 @@ 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 (window_find_by_class(WC_RIDE_CONSTRUCTION) == NULL && window_find_by_class(WC_FOOTPATH) == NULL) + 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; + } + } switch (info->type) { case VIEWPORT_INTERACTION_ITEM_SCENERY: @@ -291,7 +293,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; diff --git a/src/interface/widget.c b/src/interface/widget.c index 94557fa04e..091653a7f1 100644 --- a/src/interface/widget.c +++ b/src/interface/widget.c @@ -120,7 +120,7 @@ void widget_draw(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex) widget_button_draw(dpi, w, widgetIndex); break; case WWT_5: - case WWT_COLORBTN: + case WWT_COLOURBTN: case WWT_TRNBTN: case WWT_TAB: widget_tab_draw(dpi, w, widgetIndex); @@ -418,7 +418,7 @@ static void widget_text_unknown(rct_drawpixelinfo *dpi, rct_window *w, int widge // Get the colour colour = w->colours[widget->colour]; - // do not use widget color as this is already used as background for the text_button + // do not use widget colour as this is already used as background for the text_button // colour = 2; // Resolve the absolute ltrb @@ -440,7 +440,7 @@ static void widget_text_unknown(rct_drawpixelinfo *dpi, rct_window *w, int widge gfx_draw_string_left_clipped( dpi, stringId, - (void*)0x013CE952, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, colour, l + 1, t, @@ -453,7 +453,7 @@ static void widget_text_unknown(rct_drawpixelinfo *dpi, rct_window *w, int widge gfx_draw_string_centred_clipped( dpi, stringId, - (void*)0x013CE952, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, colour, (w->x + w->x + widget->left + widget->right + 1) / 2 - 1, t, @@ -489,7 +489,7 @@ static void widget_text(rct_drawpixelinfo *dpi, rct_window *w, int widgetIndex) if (widget_is_disabled(w, widgetIndex)) colour |= 0x40; - gfx_draw_string_left(dpi, widget->image, (void*)0x013CE952, colour, l + 1, t); + gfx_draw_string_left_clipped(dpi, widget->image, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, colour, l + 1, t, r - l); } /** @@ -576,7 +576,7 @@ static void widget_groupbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg colour = w->colours[widget->colour] & 0x7F; if (widget_is_disabled(w, widgetIndex)) colour |= 0x40; - gfx_draw_string_left(dpi, widget->image, (void*)0x013CE952, colour, l, t); + gfx_draw_string_left(dpi, widget->image, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, colour, l, t); textRight = l + gfx_get_string_width((char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER) + 1; } @@ -679,7 +679,7 @@ static void widget_caption_draw(rct_drawpixelinfo *dpi, rct_window *w, int widge width -= 10; } l += width / 2; - gfx_draw_string_centred_clipped(dpi, widget->image, (void*)0x013CE952, 34, l, t, width); + gfx_draw_string_centred_clipped(dpi, widget->image, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 34, l, t, width); } /** @@ -723,7 +723,7 @@ static void widget_closebox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg if (widget_is_disabled(w, widgetIndex)) colour |= 0x40; - gfx_draw_string_centred_clipped(dpi, widget->image, (void*)0x013CE952, colour, l, t, widget->right - widget->left - 2); + gfx_draw_string_centred_clipped(dpi, widget->image, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, colour, l, t, widget->right - widget->left - 2); } /** @@ -767,7 +767,7 @@ static void widget_checkbox_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg colour |= 0x40; } - gfx_draw_string_left_centred(dpi, (rct_string_id)widget->image, (void*)0x013CE952, colour, l + 14, yMid); + gfx_draw_string_left_centred(dpi, (rct_string_id)widget->image, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, colour, l + 14, yMid); } /** @@ -927,7 +927,7 @@ static void widget_draw_image(rct_drawpixelinfo *dpi, rct_window *w, int widgetI // Get the colour colour = w->colours[widget->colour] & 0x7F; - if (widget->type == WWT_4 || widget->type == WWT_COLORBTN || widget->type == WWT_TRNBTN || widget->type == WWT_TAB) + if (widget->type == WWT_4 || widget->type == WWT_COLOURBTN || widget->type == WWT_TRNBTN || widget->type == WWT_TAB) if (widget_is_pressed(w, widgetIndex) || widget_is_active_tool(w, widgetIndex)) image++; @@ -978,49 +978,43 @@ 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); - - if (w->pressed_widgets & (1LL << widgetIndex)) + if (w->pressed_widgets & (1LL << widgetIndex)) { + return 1; + } + if (gInputState == INPUT_STATE_WIDGET_PRESSED || gInputState == INPUT_STATE_DROPDOWN_ACTIVE) { + if (!(gInputFlags & INPUT_FLAG_WIDGET_PRESSED)) return 0; + if (gPressedWidget.window_classification != w->classification) return 0; + if (gPressedWidget.window_number != w->number) return 0; + if (gPressedWidget.widget_index != widgetIndex) return 0; return 1; - if (inputState == INPUT_STATE_WIDGET_PRESSED || inputState == INPUT_STATE_DROPDOWN_ACTIVE) { - if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WINDOWCLASS, rct_windowclass) != w->classification) - 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)) - return 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, sint32) == widgetIndex) - return 1; } return 0; } int widget_is_highlighted(rct_window *w, int widgetIndex) { - if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) != w->classification) - return 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWNUMBER, rct_windownumber) != w->number) - return 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, sint32) != widgetIndex) - return 0; + if (gHoverWidget.window_classification != w->classification) return 0; + if (gHoverWidget.window_number != w->number) return 0; + if (gHoverWidget.widget_index != widgetIndex) return 0; return 1; } 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; if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) != w->number) return 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, sint32) != widgetIndex) + if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != widgetIndex) return 0; return 1; } /** + * * rct2: 0x006E9F92 * eax: x / output_x * ebx: y / output_y @@ -1175,7 +1169,7 @@ static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg if (!active) { if (w->widgets[widgetIndex].image != 0) { - safe_strncpy(wrapped_string, (char*)w->widgets[widgetIndex].image, 512); + safe_strcpy(wrapped_string, (char*)w->widgets[widgetIndex].image, 512); gfx_wrap_string(wrapped_string, r - l - 5, &no_lines, &font_height); gfx_draw_string(dpi, wrapped_string, w->colours[1], l + 2, t); } @@ -1183,7 +1177,7 @@ static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg } - safe_strncpy(wrapped_string, gTextBoxInput, 512); + safe_strcpy(wrapped_string, gTextBoxInput, 512); // String length needs to add 12 either side of box // +13 for cursor when max length. @@ -1197,15 +1191,15 @@ static void widget_text_box_draw(rct_drawpixelinfo *dpi, rct_window *w, int widg // Make a copy of the string for measuring the width. char temp_string[512] = { 0 }; - memcpy(temp_string, wrapped_string, min(string_length, gTextInputCursorPosition)); + memcpy(temp_string, wrapped_string, min((size_t)string_length, gTextInput.selection_offset)); int cur_x = l + gfx_get_string_width(temp_string) + 3; int width = 6; - if ((uint32)gTextInputCursorPosition < strlen(gTextBoxInput)){ + if ((uint32)gTextInput.selection_offset < strlen(gTextBoxInput)){ // Make a new 1 character wide string for measuring the width // of the character that the cursor is under. temp_string[1] = '\0'; - temp_string[0] = gTextBoxInput[gTextInputCursorPosition]; + temp_string[0] = gTextBoxInput[gTextInput.selection_offset]; width = max(gfx_get_string_width(temp_string) - 2, 4); } diff --git a/src/interface/widget.h b/src/interface/widget.h index 8a8c5022c4..260216b7f6 100644 --- a/src/interface/widget.h +++ b/src/interface/widget.h @@ -30,7 +30,7 @@ typedef enum { WWT_IMGBTN = 3, WWT_4 = 4, WWT_5 = 5, - WWT_COLORBTN = 6, + WWT_COLOURBTN = 6, WWT_TRNBTN = 7, WWT_TAB = 8, WWT_FLATBTN = 9, diff --git a/src/interface/window.c b/src/interface/window.c index bada6d28e9..3900f8a752 100644 --- a/src/interface/window.c +++ b/src/interface/window.c @@ -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,11 +150,9 @@ 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); - - RCT2_CALLPROC_EBPSAFE(0x006EE411); // handle_text_input } void window_update_all_viewports() @@ -274,6 +272,39 @@ static void window_viewport_wheel_input(rct_window *w, int wheel) window_zoom_out(w); } +static bool window_other_wheel_input(rct_window *w, int widgetIndex, int wheel) +{ + // HACK: Until we have a new window system that allows us to add new events like mouse wheel easily, + // this selective approch will have to do. + + // Allow mouse wheel scrolling to increment or decrement the land tool size for various windows + int previewWidgetIndex; + switch (w->classification) { + case WC_WATER: + case WC_CLEAR_SCENERY: + case WC_LAND_RIGHTS: + previewWidgetIndex = 3; + break; + case WC_LAND: + previewWidgetIndex = 5; + break; + case WC_MAP: + previewWidgetIndex = 13; + break; + default: + return false; + } + + // Preview / Increment / Decrement + if (widgetIndex >= previewWidgetIndex && widgetIndex < previewWidgetIndex + 3) { + int buttonWidgetIndex = wheel < 0 ? previewWidgetIndex + 2 : previewWidgetIndex + 1; + window_event_mouse_up_call(w, buttonWidgetIndex); + return true; + } + + return false; +} + /** * * rct2: 0x006E7868 @@ -308,7 +339,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 @@ -327,6 +358,10 @@ static void window_all_wheel_input() window_scroll_wheel_input(w, window_get_scroll_index(w, widgetIndex), wheel); return; } + } else { + if (window_other_wheel_input(w, widgetIndex, wheel)) { + return; + } } // Check other scroll views on window @@ -753,7 +788,7 @@ rct_window *window_find_by_number(rct_windowclass cls, rct_windownumber number) } /** - * Closes the top-most window + * Closes the top-most window * * rct2: 0x006E403C */ @@ -776,7 +811,7 @@ void window_close_top() } /** - * Closes all open windows + * Closes all open windows * * rct2: 0x006EE927 */ @@ -922,8 +957,8 @@ void window_invalidate_by_number(rct_windowclass cls, rct_windownumber number) } /** - * Invalidates all windows. - */ + * Invalidates all windows. + */ void window_invalidate_all() { rct_window* w; @@ -1099,7 +1134,7 @@ rct_window *window_bring_to_front(rct_window *w) if (!(v->flags & WF_STICK_TO_FRONT)) break; - if (v >= g_window_list && w != v) { + if (v >= g_window_list && w != v) { do { t = *w; *w = *(w + 1); @@ -1157,7 +1192,7 @@ rct_window *window_bring_to_front_by_number(rct_windowclass cls, rct_windownumbe /** * - * rct2: 0x006EE65A + * rct2: 0x006EE65A */ void window_push_others_right(rct_window* window) { @@ -1247,8 +1282,7 @@ rct_window *window_get_main() /** * Based on - * rct2: 0x696ee9 & 0x66842F & 0x006AF3B3 - * + * rct2: 0x696ee9, 0x66842F, 0x006AF3B3 */ void window_scroll_to_viewport(rct_window *w) { @@ -1364,7 +1398,7 @@ void sub_688956() /** * * rct2: 0x0068881A - * direction can be used to alter the camera rotation: + * direction can be used to alter the camera rotation: * 1: clockwise * -1: anti-clockwise */ @@ -1460,16 +1494,6 @@ void window_zoom_out(rct_window *w) window_zoom_set(w, w->viewport->zoom + 1); } -/** - * - * rct2: 0x006EE308 - * DEPRECIATED please use the new text_input window. - */ -void window_show_textinput(rct_window *w, int widgetIndex, uint16 title, uint16 text, int value) -{ - RCT2_CALLPROC_X(0x006EE308, title, text, value, widgetIndex, (int)w, 0, 0); -} - /** * Draws a window that is in the specified region. * rct2: 0x006E756C @@ -1740,7 +1764,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) && @@ -1753,8 +1777,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; @@ -1770,8 +1794,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(); @@ -1779,7 +1803,7 @@ void tool_cancel() // Reset map selection RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, sint16) >= 0) { + if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != 0xFFFF) { // Invalidate tool widget widget_invalidate_by_number( RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass), @@ -2001,9 +2025,9 @@ void window_event_scroll_paint_call(rct_window *w, rct_drawpixelinfo *dpi, int s } /** + * Bubbles an item one position up in the window list. This is done by swapping + * the two locations. * rct2: New function not from rct2 - * Bubbles an item one position up in the window list. - * This is done by swapping the two locations. */ void window_bubble_list_item(rct_window* w, int item_position){ char swap = w->list_item_positions[item_position]; @@ -2011,7 +2035,9 @@ void window_bubble_list_item(rct_window* w, int item_position){ w->list_item_positions[item_position + 1] = swap; } -/* rct2: 0x006ED710 +/** + * + * rct2: 0x006ED710 * Called after a window resize to move windows if they * are going to be out of sight. */ @@ -2423,15 +2449,7 @@ void textinput_cancel() // Close the new text input window window_close_by_class(WC_TEXTINPUT); - // The following code is only necessary for the old Windows text input dialog. In theory this isn't used anymore, but can - // still be triggered via original code paths. -#ifdef _WIN32 - RCT2_CALLPROC_EBPSAFE(0x0040701D); -#else - log_warning("there should be something called here (0x0040701D)"); -#endif // _WIN32 if (RCT2_GLOBAL(RCT2_ADDRESS_TEXTINPUT_WINDOWCLASS, uint8) != 255) { - RCT2_CALLPROC_EBPSAFE(0x006EE4E2); w = window_find_by_number( RCT2_GLOBAL(RCT2_ADDRESS_TEXTINPUT_WINDOWCLASS, rct_windowclass), RCT2_GLOBAL(RCT2_ADDRESS_TEXTINPUT_WINDOWNUMBER, rct_windownumber) @@ -2462,7 +2480,7 @@ void window_start_textbox(rct_window *call_w, int call_widget, rct_string_id exi // Enter in the the text input buffer any existing // text. - if (existing_text != (rct_string_id)STR_NONE) + if (existing_text != STR_NONE) format_string(gTextBoxInput, existing_text, &existing_args); // In order to prevent strings that exceed the maxLength diff --git a/src/interface/window.h b/src/interface/window.h index 28862b35c9..a101157dc9 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -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; @@ -41,6 +43,7 @@ typedef void wndproc(struct rct_window*, union rct_window_event*); typedef uint8 rct_windowclass; typedef uint16 rct_windownumber; +typedef sint16 rct_widgetindex; typedef struct { rct_windowclass classification; @@ -260,11 +263,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 var_494; + 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 +387,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, @@ -434,6 +436,7 @@ enum { WC_TRACK_DELETE_PROMPT = 48, WC_INSTALL_TRACK = 49, WC_CLEAR_SCENERY = 50, + WC_NOTIFICATION_OPTIONS = 109, WC_CHEATS = 110, WC_RESEARCH = 111, WC_VIEWPORT = 112, @@ -448,8 +451,8 @@ enum { WC_CHANGELOG = 121, WC_TITLE_EDITOR = 122, WC_TITLE_COMMAND_EDITOR = 123, - WC_CHAT_HOST = 124, - WC_PLAYER_LIST = 125, + WC_MULTIPLAYER = 124, + WC_PLAYER = 125, WC_NETWORK_STATUS = 126, WC_SERVER_LIST = 127, WC_SERVER_START = 128, @@ -458,7 +461,7 @@ enum { WC_STAFF = 220, WC_EDITOR_TRACK_BOTTOM_TOOLBAR = 221, WC_EDITOR_SCENARIO_BOTTOM_TOOLBAR = 222, -} WINDOW_CLASS; +}; enum PROMPT_MODE { PM_SAVE_BEFORE_LOAD = 0, @@ -484,8 +487,6 @@ enum { LOADSAVETYPE_LANDSCAPE = 1 << 1, LOADSAVETYPE_SCENARIO = 2 << 1, LOADSAVETYPE_TRACK = 3 << 1, - - LOADSAVETYPE_NETWORK = 1 << 4, }; enum { @@ -495,10 +496,13 @@ enum { }; typedef void (*modal_callback)(int result); +typedef void (*scenarioselect_callback)(const utf8 *path); extern bool gLoadSaveTitleSequenceSave; extern modal_callback gLoadSaveCallback; +typedef void (*close_callback)(); + // rct2: 0x01420078 extern rct_window* g_window_list; @@ -582,7 +586,7 @@ void window_title_exit_open(); void window_title_options_open(); void window_title_logo_open(); void window_news_open(); -void window_scenarioselect_open(); +void window_scenarioselect_open(scenarioselect_callback callback); void window_track_list_open(ride_list_item item); void window_clear_scenery_open(); void window_land_open(); @@ -627,9 +631,11 @@ void window_install_track_open(const char* path); void window_banner_open(rct_windownumber number); void window_sign_open(rct_windownumber number); void window_sign_small_open(rct_windownumber number); +void window_news_options_open(); void window_cheats_open(); -void window_player_list_open(); -void window_network_status_open(const char* text); +void window_multiplayer_open(); +void window_player_open(uint8 id); +void window_network_status_open(const char* text, close_callback onClose); void window_network_status_close(); void window_network_status_open_password(); void window_server_list_open(); diff --git a/src/localisation/LanguagePack.cpp b/src/localisation/LanguagePack.cpp index 5e7d3dd64b..cccce403db 100644 --- a/src/localisation/LanguagePack.cpp +++ b/src/localisation/LanguagePack.cpp @@ -1,201 +1,245 @@ -extern "C" { - #include "../common.h" - #include "../util/util.h" - #include "localisation.h" - #include "../platform/platform.h" +extern "C" +{ + #include "../common.h" + #include "../platform/platform.h" + #include "../util/util.h" + #include "localisation.h" } #include "../core/FileStream.hpp" +#include "../core/Math.hpp" #include "../core/Memory.hpp" #include "../core/StringBuilder.hpp" #include "LanguagePack.h" #include -constexpr rct_string_id ObjectOverrideBase = 0x6000; -constexpr int ObjectOverrideMaxStringCount = 4; +// Don't try to load more than language files that exceed 64 MiB +constexpr uint64 MAX_LANGUAGE_SIZE = 64 * 1024 * 1024; -constexpr rct_string_id ScenarioOverrideBase = 0x7000; -constexpr int ScenarioOverrideMaxStringCount = 3; +constexpr rct_string_id ObjectOverrideBase = 0x6000; +constexpr int ObjectOverrideMaxStringCount = 4; -LanguagePack *LanguagePack::FromFile(int id, const utf8 *path) +constexpr rct_string_id ScenarioOverrideBase = 0x7000; +constexpr int ScenarioOverrideMaxStringCount = 3; + +LanguagePack * LanguagePack::FromFile(uint16 id, const utf8 * path) { - assert(path != nullptr); + assert(path != nullptr); - uint32 fileLength; - utf8 *fileData = nullptr; + // Load file directly into memory + utf8 * fileData = nullptr; + try + { + FileStream fs = FileStream(path, FILE_MODE_OPEN); + + size_t fileLength = (size_t)fs.GetLength(); + if (fileLength > MAX_LANGUAGE_SIZE) + { + throw IOException("Language file too large."); + } - // Load file directly into memory - try { - FileStream fs = FileStream(path, FILE_MODE_OPEN); + fileData = Memory::Allocate(fileLength + 1); + fs.Read(fileData, fileLength); + fileData[fileLength] = '\0'; + } + catch (Exception ex) + { + Memory::Free(fileData); + log_error("Unable to open %s: %s", path, ex.GetMessage()); + return nullptr; + } - fileLength = (uint32)fs.GetLength(); - fileData = Memory::Allocate(fileLength + 1); - fs.Read(fileData, fileLength); - fileData[fileLength] = '\0'; + // Parse the memory as text + LanguagePack * result = FromText(id, fileData); - fs.Dispose(); - } catch (Exception ex) { - Memory::Free(fileData); - log_error("Unable to open %s: %s", path, ex.GetMessage()); - return nullptr; - } - - // Parse the memory as text - LanguagePack *result = FromText(id, fileData); - - Memory::Free(fileData); - return result; + Memory::Free(fileData); + return result; } -LanguagePack *LanguagePack::FromText(int id, const utf8 *text) +LanguagePack * LanguagePack::FromText(uint16 id, const utf8 * text) { - return new LanguagePack(id, text); + return new LanguagePack(id, text); } -LanguagePack::LanguagePack(int id, const utf8 *text) +LanguagePack::LanguagePack(uint16 id, const utf8 * text) { - assert(text != nullptr); + assert(text != nullptr); - _id = id; - _stringData = nullptr; - _currentGroup = nullptr; - _currentObjectOverride = nullptr; - _currentScenarioOverride = nullptr; + _id = id; + _stringData = nullptr; + _currentGroup = nullptr; + _currentObjectOverride = nullptr; + _currentScenarioOverride = nullptr; - auto reader = UTF8StringReader(text); - while (reader.CanRead()) { - ParseLine(&reader); - } + auto reader = UTF8StringReader(text); + while (reader.CanRead()) + { + ParseLine(&reader); + } - _stringData = _stringDataSB.GetString(); + _stringData = _stringDataSB.GetString(); - size_t stringDataBaseAddress = (size_t)_stringData; - for (size_t i = 0; i < _strings.size(); i++) { - if (_strings[i] != nullptr) - _strings[i] = (utf8*)(stringDataBaseAddress + (size_t)_strings[i]); - } - for (size_t i = 0; i < _objectOverrides.size(); i++) { - for (int j = 0; j < ObjectOverrideMaxStringCount; j++) { - const utf8 **strPtr = &(_objectOverrides[i].strings[j]); - if (*strPtr != nullptr) { - *strPtr = (utf8*)(stringDataBaseAddress + (size_t)*strPtr); - } - } - } - for (size_t i = 0; i < _scenarioOverrides.size(); i++) { - for (int j = 0; j < ScenarioOverrideMaxStringCount; j++) { - const utf8 **strPtr = &(_scenarioOverrides[i].strings[j]); - if (*strPtr != nullptr) { - *strPtr = (utf8*)(stringDataBaseAddress + (size_t)*strPtr); - } - } - } + size_t stringDataBaseAddress = (size_t)_stringData; + for (size_t i = 0; i < _strings.size(); i++) + { + if (_strings[i] != nullptr) + { + _strings[i] = (utf8*)(stringDataBaseAddress + (size_t)_strings[i]); + } + } + for (size_t i = 0; i < _objectOverrides.size(); i++) + { + for (int j = 0; j < ObjectOverrideMaxStringCount; j++) + { + const utf8 * * strPtr = &(_objectOverrides[i].strings[j]); + if (*strPtr != nullptr) + { + *strPtr = (utf8*)(stringDataBaseAddress + (size_t)*strPtr); + } + } + } + for (size_t i = 0; i < _scenarioOverrides.size(); i++) + { + for (int j = 0; j < ScenarioOverrideMaxStringCount; j++) + { + const utf8 **strPtr = &(_scenarioOverrides[i].strings[j]); + if (*strPtr != nullptr) + { + *strPtr = (utf8*)(stringDataBaseAddress + (size_t)*strPtr); + } + } + } - // Destruct the string builder to free memory - _stringDataSB = StringBuilder(); + // Destruct the string builder to free memory + _stringDataSB = StringBuilder(); } LanguagePack::~LanguagePack() { - SafeFree(_stringData); - SafeFree(_currentGroup); + Memory::Free(_stringData); + Memory::Free(_currentGroup); } -const utf8 *LanguagePack::GetString(int stringId) const { - if (stringId >= ScenarioOverrideBase) { - int offset = stringId - ScenarioOverrideBase; - int ooIndex = offset / ScenarioOverrideMaxStringCount; - int ooStringIndex = offset % ScenarioOverrideMaxStringCount; - - if (_scenarioOverrides.size() > (size_t)ooIndex) { - return _scenarioOverrides[ooIndex].strings[ooStringIndex]; - } else { - return nullptr; - } - }else if (stringId >= ObjectOverrideBase) { - int offset = stringId - ObjectOverrideBase; - int ooIndex = offset / ObjectOverrideMaxStringCount; - int ooStringIndex = offset % ObjectOverrideMaxStringCount; - - if (_objectOverrides.size() > (size_t)ooIndex) { - return _objectOverrides[ooIndex].strings[ooStringIndex]; - } else { - return nullptr; - } - } else { - if (_strings.size() > (size_t)stringId) { - return _strings[stringId]; - } else { - return nullptr; - } - } -} - -rct_string_id LanguagePack::GetObjectOverrideStringId(const char *objectIdentifier, int index) +const utf8 * LanguagePack::GetString(rct_string_id stringId) const { - assert(objectIdentifier != nullptr); - assert(index < ObjectOverrideMaxStringCount); + if (stringId >= ScenarioOverrideBase) + { + int offset = stringId - ScenarioOverrideBase; + int ooIndex = offset / ScenarioOverrideMaxStringCount; + int ooStringIndex = offset % ScenarioOverrideMaxStringCount; - int ooIndex = 0; - for (const ObjectOverride &objectOverride : _objectOverrides) { - if (strncmp(objectOverride.name, objectIdentifier, 8) == 0) { - if (objectOverride.strings[index] == nullptr) { - return STR_NONE; - } - return ObjectOverrideBase + (ooIndex * ObjectOverrideMaxStringCount) + index; - } - ooIndex++; - } + if (_scenarioOverrides.size() > (size_t)ooIndex) + { + return _scenarioOverrides[ooIndex].strings[ooStringIndex]; + } + else + { + return nullptr; + } + } + else if (stringId >= ObjectOverrideBase) + { + int offset = stringId - ObjectOverrideBase; + int ooIndex = offset / ObjectOverrideMaxStringCount; + int ooStringIndex = offset % ObjectOverrideMaxStringCount; - return STR_NONE; + if (_objectOverrides.size() > (size_t)ooIndex) + { + return _objectOverrides[ooIndex].strings[ooStringIndex]; + } + else + { + return nullptr; + } + } + else + { + if (_strings.size() > (size_t)stringId) + { + return _strings[stringId]; + } + else + { + return nullptr; + } + } } -rct_string_id LanguagePack::GetScenarioOverrideStringId(const utf8 *scenarioFilename, int index) +rct_string_id LanguagePack::GetObjectOverrideStringId(const char * objectIdentifier, uint8 index) { - assert(scenarioFilename != nullptr); - assert(index < ScenarioOverrideMaxStringCount); + assert(objectIdentifier != nullptr); + assert(index < ObjectOverrideMaxStringCount); - int ooIndex = 0; - for (const ScenarioOverride &scenarioOverride : _scenarioOverrides) { - if (_stricmp(scenarioOverride.filename, scenarioFilename) == 0) { - if (scenarioOverride.strings[index] == nullptr) { - return STR_NONE; - } - return ScenarioOverrideBase + (ooIndex * ScenarioOverrideMaxStringCount) + index; - } - ooIndex++; - } + int ooIndex = 0; + for (const ObjectOverride &objectOverride : _objectOverrides) + { + if (strncmp(objectOverride.name, objectIdentifier, 8) == 0) + { + if (objectOverride.strings[index] == nullptr) + { + return STR_NONE; + } + return ObjectOverrideBase + (ooIndex * ObjectOverrideMaxStringCount) + index; + } + ooIndex++; + } - return STR_NONE; + return STR_NONE; } -LanguagePack::ObjectOverride *LanguagePack::GetObjectOverride(const char *objectIdentifier) +rct_string_id LanguagePack::GetScenarioOverrideStringId(const utf8 * scenarioFilename, uint8 index) { - assert(objectIdentifier != nullptr); + assert(scenarioFilename != nullptr); + assert(index < ScenarioOverrideMaxStringCount); - for (size_t i = 0; i < _objectOverrides.size(); i++) { - ObjectOverride *oo = &_objectOverrides[i]; - if (strncmp(oo->name, objectIdentifier, 8) == 0) { - return oo; - } - } - return nullptr; + int ooIndex = 0; + for (const ScenarioOverride &scenarioOverride : _scenarioOverrides) + { + if (_stricmp(scenarioOverride.filename, scenarioFilename) == 0) + { + if (scenarioOverride.strings[index] == nullptr) + { + return STR_NONE; + } + return ScenarioOverrideBase + (ooIndex * ScenarioOverrideMaxStringCount) + index; + } + ooIndex++; + } + + return STR_NONE; } -LanguagePack::ScenarioOverride *LanguagePack::GetScenarioOverride(const utf8 *scenarioIdentifier) +LanguagePack::ObjectOverride * LanguagePack::GetObjectOverride(const char * objectIdentifier) { - assert(scenarioIdentifier != nullptr); + assert(objectIdentifier != nullptr); - for (size_t i = 0; i < _scenarioOverrides.size(); i++) { - ScenarioOverride *so = &_scenarioOverrides[i]; - // At this point ScenarioOverrides were not yet rewritten to point at - // strings, but rather still hold offsets from base. - const utf8 *name = _stringDataSB.GetBuffer() + (size_t)so->name; - if (_stricmp(name, scenarioIdentifier) == 0) { - return so; - } - } - return nullptr; + for (size_t i = 0; i < _objectOverrides.size(); i++) + { + ObjectOverride *oo = &_objectOverrides[i]; + if (strncmp(oo->name, objectIdentifier, 8) == 0) + { + return oo; + } + } + return nullptr; +} + +LanguagePack::ScenarioOverride * LanguagePack::GetScenarioOverride(const utf8 * scenarioIdentifier) +{ + assert(scenarioIdentifier != nullptr); + + for (size_t i = 0; i < _scenarioOverrides.size(); i++) + { + ScenarioOverride *so = &_scenarioOverrides[i]; + // At this point ScenarioOverrides were not yet rewritten to point at + // strings, but rather still hold offsets from base. + const utf8 *name = _stringDataSB.GetBuffer() + (size_t)so->name; + if (_stricmp(name, scenarioIdentifier) == 0) + { + return so; + } + } + return nullptr; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -213,284 +257,337 @@ LanguagePack::ScenarioOverride *LanguagePack::GetScenarioOverride(const utf8 *sc // Use # at the beginning of a line to leave a comment. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -static bool IsWhitespace(int codepoint) +static bool IsWhitespace(codepoint_t codepoint) { - return codepoint == '\t' || codepoint == ' ' || codepoint == '\r' || codepoint == '\n'; + return codepoint == '\t' || codepoint == ' ' || codepoint == '\r' || codepoint == '\n'; } -static bool IsNewLine(int codepoint) +static bool IsNewLine(codepoint_t codepoint) { - return codepoint == '\r' || codepoint == '\n'; + return codepoint == '\r' || codepoint == '\n'; } -static void SkipWhitespace(IStringReader *reader) +static void SkipWhitespace(IStringReader * reader) { - int codepoint; - while (reader->TryPeek(&codepoint)) { - if (IsWhitespace(codepoint)) { - reader->Skip(); - } else { - break; - } - } + codepoint_t codepoint; + while (reader->TryPeek(&codepoint)) + { + if (IsWhitespace(codepoint)) + { + reader->Skip(); + } + else + { + break; + } + } } -static void SkipNewLine(IStringReader *reader) +static void SkipNewLine(IStringReader * reader) { - int codepoint; - while (reader->TryPeek(&codepoint)) { - if (IsNewLine(codepoint)) { - reader->Skip(); - } else { - break; - } - } + codepoint_t codepoint; + while (reader->TryPeek(&codepoint)) + { + if (IsNewLine(codepoint)) + { + reader->Skip(); + } + else + { + break; + } + } } -static void SkipToEndOfLine(IStringReader *reader) +static void SkipToEndOfLine(IStringReader * reader) { - int codepoint; - while (reader->TryPeek(&codepoint)) { - if (codepoint != '\r' && codepoint != '\n') { - reader->Skip(); - } else { - break; - } - } + codepoint_t codepoint; + while (reader->TryPeek(&codepoint)) { + if (codepoint != '\r' && codepoint != '\n') + { + reader->Skip(); + } + else + { + break; + } + } } void LanguagePack::ParseLine(IStringReader *reader) { - SkipWhitespace(reader); + SkipWhitespace(reader); - int codepoint; - if (reader->TryPeek(&codepoint)) { - switch (codepoint) { - case '#': - SkipToEndOfLine(reader); - break; - case '[': - ParseGroupObject(reader); - break; - case '<': - ParseGroupScenario(reader); - break; - case '\r': - case '\n': - break; - default: - ParseString(reader); - break; - } - SkipToEndOfLine(reader); - SkipNewLine(reader); - } + codepoint_t codepoint; + if (reader->TryPeek(&codepoint)) + { + switch (codepoint) { + case '#': + SkipToEndOfLine(reader); + break; + case '[': + ParseGroupObject(reader); + break; + case '<': + ParseGroupScenario(reader); + break; + case '\r': + case '\n': + break; + default: + ParseString(reader); + break; + } + SkipToEndOfLine(reader); + SkipNewLine(reader); + } } -void LanguagePack::ParseGroupObject(IStringReader *reader) +void LanguagePack::ParseGroupObject(IStringReader * reader) { - auto sb = StringBuilder(); - int codepoint; + auto sb = StringBuilder(); + codepoint_t codepoint; - // Should have already deduced that the next codepoint is a [ - reader->Skip(); + // Should have already deduced that the next codepoint is a [ + reader->Skip(); - // Read string up to ] or line end - bool closedCorrectly = false; - while (reader->TryPeek(&codepoint)) { - if (IsNewLine(codepoint)) break; + // Read string up to ] or line end + bool closedCorrectly = false; + while (reader->TryPeek(&codepoint)) + { + if (IsNewLine(codepoint)) break; - reader->Skip(); - if (codepoint == ']') { - closedCorrectly = true; - break; - } - sb.Append(codepoint); - } + reader->Skip(); + if (codepoint == ']') + { + closedCorrectly = true; + break; + } + sb.Append(codepoint); + } - if (closedCorrectly) { - SafeFree(_currentGroup); + if (closedCorrectly) + { + SafeFree(_currentGroup); - while (sb.GetLength() < 8) { - sb.Append(' '); - } - if (sb.GetLength() == 8) { - _currentGroup = sb.GetString(); - _currentObjectOverride = GetObjectOverride(_currentGroup); - _currentScenarioOverride = nullptr; - if (_currentObjectOverride == nullptr) { - _objectOverrides.push_back(ObjectOverride()); - _currentObjectOverride = &_objectOverrides[_objectOverrides.size() - 1]; - memset(_currentObjectOverride, 0, sizeof(ObjectOverride)); - memcpy(_currentObjectOverride->name, _currentGroup, 8); - } - } - } + while (sb.GetLength() < 8) + { + sb.Append(' '); + } + if (sb.GetLength() == 8) + { + _currentGroup = sb.GetString(); + _currentObjectOverride = GetObjectOverride(_currentGroup); + _currentScenarioOverride = nullptr; + if (_currentObjectOverride == nullptr) + { + _objectOverrides.push_back(ObjectOverride()); + _currentObjectOverride = &_objectOverrides[_objectOverrides.size() - 1]; + memset(_currentObjectOverride, 0, sizeof(ObjectOverride)); + memcpy(_currentObjectOverride->name, _currentGroup, 8); + } + } + } } -void LanguagePack::ParseGroupScenario(IStringReader *reader) +void LanguagePack::ParseGroupScenario(IStringReader * reader) { - auto sb = StringBuilder(); - int codepoint; + auto sb = StringBuilder(); + codepoint_t codepoint; - // Should have already deduced that the next codepoint is a < - reader->Skip(); + // Should have already deduced that the next codepoint is a < + reader->Skip(); - // Read string up to > or line end - bool closedCorrectly = false; - while (reader->TryPeek(&codepoint)) { - if (IsNewLine(codepoint)) break; + // Read string up to > or line end + bool closedCorrectly = false; + while (reader->TryPeek(&codepoint)) + { + if (IsNewLine(codepoint)) break; - reader->Skip(); - if (codepoint == '>') { - closedCorrectly = true; - break; - } - sb.Append(codepoint); - } + reader->Skip(); + if (codepoint == '>') + { + closedCorrectly = true; + break; + } + sb.Append(codepoint); + } - if (closedCorrectly) { - SafeFree(_currentGroup); + if (closedCorrectly) + { + SafeFree(_currentGroup); - _currentGroup = sb.GetString(); - _currentObjectOverride = nullptr; - _currentScenarioOverride = GetScenarioOverride(_currentGroup); - if (_currentScenarioOverride == nullptr) { - _scenarioOverrides.push_back(ScenarioOverride()); - _currentScenarioOverride = &_scenarioOverrides[_scenarioOverrides.size() - 1]; - memset(_currentScenarioOverride, 0, sizeof(ScenarioOverride)); - _currentScenarioOverride->filename = sb.GetString(); - } - } + _currentGroup = sb.GetString(); + _currentObjectOverride = nullptr; + _currentScenarioOverride = GetScenarioOverride(_currentGroup); + if (_currentScenarioOverride == nullptr) + { + _scenarioOverrides.push_back(ScenarioOverride()); + _currentScenarioOverride = &_scenarioOverrides[_scenarioOverrides.size() - 1]; + Memory::Set(_currentScenarioOverride, 0, sizeof(ScenarioOverride)); + _currentScenarioOverride->filename = sb.GetString(); + } + } } void LanguagePack::ParseString(IStringReader *reader) { - auto sb = StringBuilder(); - int codepoint; + auto sb = StringBuilder(); + codepoint_t codepoint; - // Parse string identifier - while (reader->TryPeek(&codepoint)) { - if (IsNewLine(codepoint)) { - // Unexpected new line, ignore line entirely - return; - } else if (!IsWhitespace(codepoint) && codepoint != ':') { - reader->Skip(); - sb.Append(codepoint); - } else { - break; - } - } + // Parse string identifier + while (reader->TryPeek(&codepoint)) + { + if (IsNewLine(codepoint)) + { + // Unexpected new line, ignore line entirely + return; + } + else if (!IsWhitespace(codepoint) && codepoint != ':') + { + reader->Skip(); + sb.Append(codepoint); + } + else + { + break; + } + } - SkipWhitespace(reader); + SkipWhitespace(reader); - // Parse a colon - if (!reader->TryPeek(&codepoint) || codepoint != ':') { - // Expected a colon, ignore line entirely - return; - } - reader->Skip(); + // Parse a colon + if (!reader->TryPeek(&codepoint) || codepoint != ':') + { + // Expected a colon, ignore line entirely + return; + } + reader->Skip(); - // Validate identifier - const utf8 *identifier = sb.GetBuffer(); + // Validate identifier + const utf8 *identifier = sb.GetBuffer(); - int stringId; - if (_currentGroup == nullptr) { - if (sscanf(identifier, "STR_%4d", &stringId) != 1) { - // Ignore line entirely - return; - } - } else { - if (strcmp(identifier, "STR_NAME") == 0) { stringId = 0; } - else if (strcmp(identifier, "STR_DESC") == 0) { stringId = 1; } - else if (strcmp(identifier, "STR_CPTY") == 0) { stringId = 2; } + int stringId; + if (_currentGroup == nullptr) + { + if (sscanf(identifier, "STR_%4d", &stringId) != 1) + { + // Ignore line entirely + return; + } + } + else + { + if (strcmp(identifier, "STR_NAME") == 0) { stringId = 0; } + else if (strcmp(identifier, "STR_DESC") == 0) { stringId = 1; } + else if (strcmp(identifier, "STR_CPTY") == 0) { stringId = 2; } - else if (strcmp(identifier, "STR_SCNR") == 0) { stringId = 0; } - else if (strcmp(identifier, "STR_PARK") == 0) { stringId = 1; } - else if (strcmp(identifier, "STR_DTLS") == 0) { stringId = 2; } - else { - // Ignore line entirely - return; - } - } + else if (strcmp(identifier, "STR_SCNR") == 0) { stringId = 0; } + else if (strcmp(identifier, "STR_PARK") == 0) { stringId = 1; } + else if (strcmp(identifier, "STR_DTLS") == 0) { stringId = 2; } + else { + // Ignore line entirely + return; + } + } - // Rest of the line is the actual string - sb.Clear(); - while (reader->TryPeek(&codepoint) && !IsNewLine(codepoint)) { - if (codepoint == '{') { - uint32 token; - bool isByte; - if (ParseToken(reader, &token, &isByte)) { - if (isByte) { - sb.Append((const utf8*)&token, 1); - } else { - sb.Append((int)token); - } - } else { - // Syntax error or unknown token, ignore line entirely - return; - } - } else { - reader->Skip(); - sb.Append(codepoint); - } - } + // Rest of the line is the actual string + sb.Clear(); + while (reader->TryPeek(&codepoint) && !IsNewLine(codepoint)) + { + if (codepoint == '{') + { + uint32 token; + bool isByte; + if (ParseToken(reader, &token, &isByte)) + { + if (isByte) + { + sb.Append((const utf8*)&token, 1); + } + else + { + sb.Append((int)token); + } + } + else + { + // Syntax error or unknown token, ignore line entirely + return; + } + } + else + { + reader->Skip(); + sb.Append(codepoint); + } + } - // Append a null terminator for the benefit of the last string - _stringDataSB.Append(0); + // Append a null terminator for the benefit of the last string + _stringDataSB.Append('\0'); - // Get the relative offset to the string (add the base offset when we extract the string properly) - utf8 *relativeOffset = (utf8*)_stringDataSB.GetLength(); + // Get the relative offset to the string (add the base offset when we extract the string properly) + utf8 * relativeOffset = (utf8*)_stringDataSB.GetLength(); - if (_currentGroup == nullptr) { - // Make sure the list is big enough to contain this string id - while (_strings.size() <= (size_t)stringId) { - _strings.push_back(nullptr); - } + if (_currentGroup == nullptr) + { + // Make sure the list is big enough to contain this string id + while (_strings.size() <= (size_t)stringId) + { + _strings.push_back(nullptr); + } - _strings[stringId] = relativeOffset; - } else { - if (_currentObjectOverride != nullptr) { - _currentObjectOverride->strings[stringId] = relativeOffset; - } else { - _currentScenarioOverride->strings[stringId] = relativeOffset; - } - } + _strings[stringId] = relativeOffset; + } + else + { + if (_currentObjectOverride != nullptr) + { + _currentObjectOverride->strings[stringId] = relativeOffset; + } + else + { + _currentScenarioOverride->strings[stringId] = relativeOffset; + } + } - _stringDataSB.Append(&sb); + _stringDataSB.Append(&sb); } -bool LanguagePack::ParseToken(IStringReader *reader, uint32 *token, bool *isByte) +bool LanguagePack::ParseToken(IStringReader * reader, uint32 * token, bool * isByte) { - auto sb = StringBuilder(); - int codepoint; + auto sb = StringBuilder(); + codepoint_t codepoint; - // Skip open brace - reader->Skip(); + // Skip open brace + reader->Skip(); - while (reader->TryPeek(&codepoint)) { - if (IsNewLine(codepoint)) return false; - if (IsWhitespace(codepoint)) return false; + while (reader->TryPeek(&codepoint)) + { + if (IsNewLine(codepoint)) return false; + if (IsWhitespace(codepoint)) return false; - reader->Skip(); + reader->Skip(); - if (codepoint == '}') break; + if (codepoint == '}') break; - sb.Append(codepoint); - } + sb.Append(codepoint); + } - const utf8 *tokenName = sb.GetBuffer(); - *token = format_get_code(tokenName); - *isByte = false; + const utf8 * tokenName = sb.GetBuffer(); + *token = format_get_code(tokenName); + *isByte = false; - // Handle explicit byte values - if (*token == 0) { - int number; - if (sscanf(tokenName, "%d", &number) == 1) { - *token = Math::Clamp(0, number, 255); - *isByte = true; - } - } + // Handle explicit byte values + if (*token == 0) + { + int number; + if (sscanf(tokenName, "%d", &number) == 1) + { + *token = Math::Clamp(0, number, 255); + *isByte = true; + } + } - return true; + return true; } diff --git a/src/localisation/LanguagePack.h b/src/localisation/LanguagePack.h index 871b689401..db5f6a5fbb 100644 --- a/src/localisation/LanguagePack.h +++ b/src/localisation/LanguagePack.h @@ -2,10 +2,11 @@ #include -extern "C" { - #include "../common.h" - #include "../util/util.h" - #include "localisation.h" +extern "C" +{ + #include "../common.h" + #include "../util/util.h" + #include "localisation.h" } #include "../core/StringBuilder.hpp" @@ -13,65 +14,71 @@ extern "C" { class LanguagePack final { public: - static LanguagePack *FromFile(int id, const utf8 *path); - static LanguagePack *FromText(int id, const utf8 *text); + static LanguagePack * FromFile(uint16 id, const utf8 * path); + static LanguagePack * FromText(uint16 id, const utf8 * text); - ~LanguagePack(); + ~LanguagePack(); - int GetId() const { return _id; } - int GetCount() const { return _strings.size(); } + uint16 GetId() const { return _id; } + uint32 GetCount() const { return _strings.size(); } - const utf8 *GetString(int stringId) const; + const utf8 * GetString(rct_string_id stringId) const; - void SetString(int stringId, const utf8 *str) { - if (_strings.size() >= (size_t)stringId) { - _strings[stringId] = str; - } - } + void SetString(rct_string_id stringId, const utf8 * str) + { + if (_strings.size() >= (size_t)stringId) + { + _strings[stringId] = str; + } + } - rct_string_id GetObjectOverrideStringId(const char *objectIdentifier, int index); - rct_string_id GetScenarioOverrideStringId(const utf8 *scenarioFilename, int index); + rct_string_id GetObjectOverrideStringId(const char * objectIdentifier, uint8 index); + rct_string_id GetScenarioOverrideStringId(const utf8 * scenarioFilename, uint8 index); private: - struct ObjectOverride { - char name[8]; - const utf8 *strings[4]; - }; + struct ObjectOverride + { + char name[8]; + const utf8 * strings[4]; + }; - struct ScenarioOverride { - const utf8 *filename; - union { - const utf8 *strings[3]; - struct { - const utf8 *name; - const utf8 *park; - const utf8 *details; - }; - }; - }; + struct ScenarioOverride + { + const utf8 * filename; + union { + const utf8 * strings[3]; + struct { + const utf8 * name; + const utf8 * park; + const utf8 * details; + }; + }; + }; - int _id; - utf8 *_stringData; - std::vector _strings; - std::vector _objectOverrides; - std::vector _scenarioOverrides; + uint16 _id; + utf8 * _stringData; - LanguagePack(int id, const utf8 *text); - ObjectOverride *GetObjectOverride(const char *objectIdentifier); - ScenarioOverride *GetScenarioOverride(const utf8 *scenarioFilename); + std::vector _strings; + std::vector _objectOverrides; + std::vector _scenarioOverrides; - /////////////////////////////////////////////////////////////////////////// - // Parsing - /////////////////////////////////////////////////////////////////////////// - StringBuilder _stringDataSB; - utf8 *_currentGroup; - ObjectOverride *_currentObjectOverride; - ScenarioOverride *_currentScenarioOverride; + LanguagePack(uint16 id, const utf8 * text); - void ParseLine(IStringReader *reader); - void ParseGroupObject(IStringReader *reader); - void ParseGroupScenario(IStringReader *reader); - void ParseString(IStringReader *reader); + ObjectOverride * GetObjectOverride(const char * objectIdentifier); + ScenarioOverride * GetScenarioOverride(const utf8 * scenarioFilename); - bool ParseToken(IStringReader *reader, uint32 *token, bool *isByte); + /////////////////////////////////////////////////////////////////////////// + // Parsing + /////////////////////////////////////////////////////////////////////////// + StringBuilder _stringDataSB; + utf8 * _currentGroup; + ObjectOverride * _currentObjectOverride; + ScenarioOverride * _currentScenarioOverride; + + void ParseLine(IStringReader * reader); + void ParseGroupObject(IStringReader * reader); + void ParseGroupScenario(IStringReader * reader); + void ParseString(IStringReader * reader); + + bool ParseToken(IStringReader * reader, uint32 * token, bool * isByte); }; diff --git a/src/localisation/currency.c b/src/localisation/currency.c index 1dbd267e8b..001ad23158 100644 --- a/src/localisation/currency.c +++ b/src/localisation/currency.c @@ -22,17 +22,20 @@ #include "string_ids.h" const currency_descriptor CurrencyDescriptors[CURRENCY_END] = { - { 10 , CURRENCY_PREFIX, "\xC2\xA3" , CURRENCY_SUFFIX, "GBP" , STR_POUNDS }, // British Pound - { 10 , CURRENCY_PREFIX, "$" , CURRENCY_PREFIX, "$" , STR_DOLLARS }, // US Dollar - { 10 , CURRENCY_SUFFIX, "F" , CURRENCY_SUFFIX, "F" , STR_FRANC }, // French Franc - { 10 , CURRENCY_PREFIX, "DM" , CURRENCY_PREFIX, "DM" , STR_DEUTSCHMARK }, // Deutschmark - { 1000 , CURRENCY_PREFIX, "\xC2\xA5" , CURRENCY_SUFFIX, "YEN" , STR_YEN }, // Japanese Yen - { 10 , CURRENCY_SUFFIX, "Pts" , CURRENCY_SUFFIX, "Pts" , STR_PESETA }, // Spanish Peseta - { 1000 , CURRENCY_PREFIX, "L" , CURRENCY_PREFIX, "L" , STR_LIRA }, // Italian Lira - { 10 , CURRENCY_PREFIX, "\xC6\x92" , CURRENCY_PREFIX, "fl." , STR_GUILDERS }, // Dutch Guilder - { 10 , CURRENCY_SUFFIX, "kr." , CURRENCY_SUFFIX, "kr." , STR_KRONA }, // Swedish Krona - { 10 , CURRENCY_PREFIX, "\xE2\x82\xAC" , CURRENCY_SUFFIX, "EUR" , STR_EUROS }, // Euro - { 10000 , CURRENCY_PREFIX, "\xE2\x82\xA9" , CURRENCY_PREFIX, "W" , STR_WON }, // South Korean Won - { 1000 , CURRENCY_PREFIX, "R " , CURRENCY_PREFIX, "R " , STR_ROUBLE }, // Russian Rouble - { 100 , CURRENCY_SUFFIX, " K\xC4\x8D" , CURRENCY_SUFFIX, " Kc" , STR_CZECH_KORUNA }, // Czech koruna + { "GBP", 10, CURRENCY_PREFIX, "\xC2\xA3", CURRENCY_SUFFIX, "GBP", STR_POUNDS }, // British Pound + { "USD", 10, CURRENCY_PREFIX, "$", CURRENCY_PREFIX, "$", STR_DOLLARS }, // US Dollar + { "FRF", 10, CURRENCY_SUFFIX, "F", CURRENCY_SUFFIX, "F", STR_FRANC }, // French Franc + { "DEM", 10, CURRENCY_PREFIX, "DM", CURRENCY_PREFIX, "DM", STR_DEUTSCHMARK }, // Deutschmark + { "JPY", 1000, CURRENCY_PREFIX, "\xC2\xA5", CURRENCY_SUFFIX, "YEN", STR_YEN }, // Japanese Yen + { "ESP", 10, CURRENCY_SUFFIX, "Pts", CURRENCY_SUFFIX, "Pts", STR_PESETA }, // Spanish Peseta + { "ITL", 1000, CURRENCY_PREFIX, "L", CURRENCY_PREFIX, "L", STR_LIRA }, // Italian Lira + { "NLG", 10, CURRENCY_PREFIX, "\xC6\x92", CURRENCY_PREFIX, "fl.", STR_GUILDERS }, // Dutch Guilder + { "SEK", 10, CURRENCY_SUFFIX, "kr.", CURRENCY_SUFFIX, "kr.", STR_KRONA }, // Swedish Krona + { "EUR", 10, CURRENCY_PREFIX, "\xE2\x82\xAC", CURRENCY_SUFFIX, "EUR", STR_EUROS }, // Euro + { "KRW", 10000, CURRENCY_PREFIX, "\xE2\x82\xA9", CURRENCY_PREFIX, "W", STR_WON }, // South Korean Won + { "RUB", 1000, CURRENCY_PREFIX, "R ", CURRENCY_PREFIX, "R ", STR_ROUBLE }, // Russian Rouble + { "CZK", 100, CURRENCY_SUFFIX, " K\xC4\x8D", CURRENCY_SUFFIX, " Kc", STR_CZECH_KORUNA }, // Czech koruna + { "HKD", 100, CURRENCY_SUFFIX, "$", CURRENCY_SUFFIX, "HKD", STR_HONG_KONG_DOLLAR}, // Hong Kong Dollar + { "TWD", 1000, CURRENCY_SUFFIX, "NT$", CURRENCY_SUFFIX, "NT$", STR_NEW_TAIWAN_DOLLAR}, // New Taiwan Dollar + { "HKD", 100, CURRENCY_SUFFIX, "CN\xC2\xA5", CURRENCY_SUFFIX, "CNY", STR_CHINESE_YUAN }, // Chinese Yuan }; diff --git a/src/localisation/currency.h b/src/localisation/currency.h index ffa400828b..9333baca5e 100644 --- a/src/localisation/currency.h +++ b/src/localisation/currency.h @@ -38,6 +38,9 @@ typedef enum { CURRENCY_WON, // South Korean Won CURRENCY_ROUBLE, // Russian Rouble CURRENCY_CZECH_KORUNA, // Czech koruna + CURRENCY_HKD, // Hong Kong Dollar + CURRENCY_TWD, // New Taiwan Dollar + CURRENCY_YUAN, // Chinese Yuan CURRENCY_END // Last item } CURRENCY_TYPE; @@ -51,6 +54,7 @@ typedef enum { // Currency format specification - inspired by OpenTTD typedef struct { + char isoCode[4]; // Rate is relative to 0.10 GBP int rate; uint8 affix_unicode; diff --git a/src/localisation/format_codes.h b/src/localisation/format_codes.h index 4f312be760..52b3033ed6 100644 --- a/src/localisation/format_codes.h +++ b/src/localisation/format_codes.h @@ -57,7 +57,7 @@ enum { FORMAT_INLINE_SPRITE = 23, // Argument format codes - FORMAT_ARGUMENT_CODE_START = 123, + FORMAT_ARGUMENT_CODE_START = 123, // 'z' == 122 or 0x7A FORMAT_COMMA32 = 123, FORMAT_INT32, FORMAT_COMMA2DP32, @@ -134,6 +134,7 @@ enum { FORMAT_SYMBOL_RAILWAY = 20001, FORMAT_SYMBOL_ROAD = 20002, FORMAT_SYMBOL_FLAG = 20003, + FORMAT_COMMA1DP16 = 20004 }; #endif diff --git a/src/localisation/language.cpp b/src/localisation/language.cpp index 7e22900aa5..5de1f473c9 100644 --- a/src/localisation/language.cpp +++ b/src/localisation/language.cpp @@ -47,32 +47,39 @@ enum { RCT2_LANGUAGE_ID_END = 255 }; +static TTFFontSetDescriptor TTFFontMSGothic = {{ + { "msgothic.ttc", "MS PGothic", 9, 1, 0, 15, nullptr }, + { "msgothic.ttc", "MS PGothic", 12, 1, 0, 17, nullptr }, + { "msgothic.ttc", "MS PGothic", 12, 1, 0, 17, nullptr }, + { "msgothic.ttc", "MS PGothic", 13, 1, 0, 20, nullptr }, +}}; + static TTFFontSetDescriptor TTFFontMingLiu = {{ - { "msjh.ttc", 9, -1, -3, 6, nullptr }, - { "mingliu.ttc", 11, 1, 1, 12, nullptr }, - { "mingliu.ttc", 12, 1, 0, 12, nullptr }, - { "mingliu.ttc", 13, 1, 0, 20, nullptr }, + { "msjh.ttc", "JhengHei", 9, -1, -3, 6, nullptr }, + { "mingliu.ttc", "MingLiU", 11, 1, 1, 12, nullptr }, + { "mingliu.ttc", "MingLiU", 12, 1, 0, 12, nullptr }, + { "mingliu.ttc", "MingLiU", 13, 1, 0, 20, nullptr }, }}; static TTFFontSetDescriptor TTFFontSimSun = {{ - { "msyh.ttc", 9, -1, -3, 6, nullptr }, - { "simsun.ttc", 11, 1, -1, 14, nullptr }, - { "simsun.ttc", 12, 1, -2, 14, nullptr }, - { "simsun.ttc", 13, 1, 0, 20, nullptr }, + { "msyh.ttc", "YaHei", 9, -1, -3, 6, nullptr }, + { "simsun.ttc", "SimSun", 11, 1, -1, 14, nullptr }, + { "simsun.ttc", "SimSun", 12, 1, -2, 14, nullptr }, + { "simsun.ttc", "SimSun", 13, 1, 0, 20, nullptr }, }}; static TTFFontSetDescriptor TTFFontGulim = {{ - { "gulim.ttc", 11, 1, 0, 15, nullptr }, - { "gulim.ttc", 12, 1, 0, 17, nullptr }, - { "gulim.ttc", 12, 1, 0, 17, nullptr }, - { "gulim.ttc", 13, 1, 0, 20, nullptr }, + { "gulim.ttc", "Gulim", 11, 1, 0, 15, nullptr }, + { "gulim.ttc", "Gulim", 12, 1, 0, 17, nullptr }, + { "gulim.ttc", "Gulim", 12, 1, 0, 17, nullptr }, + { "gulim.ttc", "Gulim", 13, 1, 0, 20, nullptr }, }}; static TTFFontSetDescriptor TTFFontArial = {{ - { "arial.ttf", 8, 0, -1, 6, nullptr }, - { "arial.ttf", 10, 0, -1, 12, nullptr }, - { "arial.ttf", 11, 0, -1, 12, nullptr }, - { "arial.ttf", 12, 0, -1, 20, nullptr }, + { "arial.ttf", "Arial", 8, 0, -1, 6, nullptr }, + { "arial.ttf", "Arial", 10, 0, -1, 12, nullptr }, + { "arial.ttf", "Arial", 11, 0, -1, 12, nullptr }, + { "arial.ttf", "Arial", 12, 0, -1, 20, nullptr }, }}; const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = { @@ -83,7 +90,7 @@ const language_descriptor LanguagesDescriptors[LANGUAGE_COUNT] = { { "nl-NL", "Dutch", "Nederlands", "dutch", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_DUTCH }, // LANGUAGE_DUTCH { "fr-FR", "French", "Fran\xC3\xA7" "ais", "french", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_FRENCH }, // LANGUAGE_FRENCH { "hu-HU", "Hungarian", "Magyar", "hungarian", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_HUNGARIAN - { "pl-PL", "Polish", "Polski", "polish", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_POLISH + { "pl-PL", "Polish", "Polski", "polish", &TTFFontArial, RCT2_LANGUAGE_ID_ENGLISH_UK }, // LANGUAGE_POLISH { "es-ES", "Spanish", "Espa\xC3\xB1ol", "spanish_sp", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_SPANISH }, // LANGUAGE_SPANISH { "sv-SE", "Swedish", "Svenska", "swedish", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_SWEDISH }, // LANGUAGE_SWEDISH { "it-IT", "Italian", "Italiano", "italian", FONT_OPENRCT2_SPRITE, RCT2_LANGUAGE_ID_ITALIAN }, // LANGUAGE_ITALIAN @@ -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; @@ -110,13 +118,13 @@ const utf8 BlackLeftArrowString[] = { (utf8)0xC2, (utf8)0x8E, (utf8)0xE2, (utf8 const utf8 BlackRightArrowString[] = { (utf8)0xC2, (utf8)0x8E, (utf8)0xE2, (utf8)0x96, (utf8)0xB6, (utf8)0x00 }; const utf8 CheckBoxMarkString[] = { (utf8)0xE2, (utf8)0x9C, (utf8)0x93, (utf8)0x00 }; -void utf8_remove_format_codes(utf8 *text) +void utf8_remove_format_codes(utf8 *text, bool allowcolours) { utf8 *dstCh = text; utf8 *ch = text; int codepoint; while ((codepoint = utf8_get_next(ch, (const utf8**)&ch)) != 0) { - if (!utf8_is_format_code(codepoint)) { + if (!utf8_is_format_code(codepoint) || (allowcolours && utf8_is_colour_code(codepoint))) { dstCh = utf8_write_codepoint(dstCh, codepoint); } } @@ -127,7 +135,7 @@ const char *language_get_string(rct_string_id id) { const char *openrctString = nullptr; - if (id == (rct_string_id)STR_NONE) + if (id == STR_NONE) return nullptr; if (_languageCurrent != nullptr) @@ -146,19 +154,21 @@ const char *language_get_string(rct_string_id id) int language_open(int id) { - static const char *languagePath = "%s/data/language/%s.txt"; + static const char *languagePath = "%s/language/%s.txt"; char filename[MAX_PATH]; + char dataPath[MAX_PATH]; language_close_all(); if (id == LANGUAGE_UNDEFINED) return 1; + platform_get_openrct_data_path(dataPath); if (id != LANGUAGE_ENGLISH_UK) { - sprintf(filename, languagePath, gExePath, LanguagesDescriptors[LANGUAGE_ENGLISH_UK].path); + sprintf(filename, languagePath, dataPath, LanguagesDescriptors[LANGUAGE_ENGLISH_UK].path); _languageFallback = LanguagePack::FromFile(LANGUAGE_ENGLISH_UK, filename); } - sprintf(filename, languagePath, gExePath, LanguagesDescriptors[id].path); + sprintf(filename, languagePath, dataPath, LanguagesDescriptors[id].path); _languageCurrent = LanguagePack::FromFile(id, filename); if (_languageCurrent != nullptr) { gCurrentLanguage = id; @@ -171,16 +181,27 @@ int language_open(int id) ttf_dispose(); gUseTrueTypeFont = true; gCurrentTTFFontSet = LanguagesDescriptors[id].font; - if (!ttf_initialise()) { - log_warning("Unable to initialise TrueType fonts."); + bool font_initialised = ttf_initialise(); - // Fall back to sprite font + // Have we tried Arial yet? + if (!font_initialised && gCurrentTTFFontSet != &TTFFontArial) { + log_warning("Unable to initialise prefered TrueType font -- falling back to Arial."); + gCurrentTTFFontSet = &TTFFontArial; + font_initialised = ttf_initialise(); + } + + // Fall back to sprite font. + if (!font_initialised) { + log_warning("Falling back to sprite font."); gUseTrueTypeFont = false; gCurrentTTFFontSet = nullptr; return 0; } } + // Objects and their localized strings need to be refreshed + reset_loaded_objects(); + return 1; } @@ -328,6 +349,11 @@ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/ // Skip over the actual string entry to get to the next entry while (*(*pStringTable)++ != 0); } + // Fall back in case language does not get set. + if (pString == NULL) + { + pString = (char*)(*pStringTable); + } char name[9]; if (RCT2_GLOBAL(0x009ADAFC, uint8) == 0) { @@ -338,7 +364,7 @@ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/ name[8] = 0; rct_string_id stringId = _languageCurrent->GetObjectOverrideStringId(name, tableindex); - if (stringId != (rct_string_id)STR_NONE) { + if (stringId != STR_NONE) { return stringId; } @@ -405,9 +431,9 @@ bool language_get_localised_scenario_strings(const utf8 *scenarioFilename, rct_s outStringIds[1] = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename, 1); outStringIds[2] = _languageCurrent->GetScenarioOverrideStringId(scenarioFilename, 2); return - outStringIds[0] != (rct_string_id)STR_NONE || - outStringIds[1] != (rct_string_id)STR_NONE || - outStringIds[2] != (rct_string_id)STR_NONE; + outStringIds[0] != STR_NONE || + outStringIds[1] != STR_NONE || + outStringIds[2] != STR_NONE; } } diff --git a/src/localisation/language.h b/src/localisation/language.h index 3adf76de0f..5f12220d8f 100644 --- a/src/localisation/language.h +++ b/src/localisation/language.h @@ -43,6 +43,7 @@ enum { LANGUAGE_KOREAN, LANGUAGE_RUSSIAN, LANGUAGE_CZECH, + LANGUAGE_JAPANESE, LANGUAGE_COUNT }; @@ -77,8 +78,8 @@ rct_string_id object_get_localised_text(uint8_t** pStringTable/*ebp*/, int type/ uint32 utf8_get_next(const utf8 *char_ptr, const utf8 **nextchar_ptr); utf8 *utf8_write_codepoint(utf8 *dst, uint32 codepoint); int utf8_insert_codepoint(utf8 *dst, uint32 codepoint); -bool utf8_is_codepoint_start(utf8 *text); -void utf8_remove_format_codes(utf8 *text); +bool utf8_is_codepoint_start(const utf8 *text); +void utf8_remove_format_codes(utf8 *text, bool allowcolours); int utf8_get_codepoint_length(int codepoint); int utf8_length(const utf8 *text); wchar_t *utf8_to_widechar(const utf8 *src); diff --git a/src/localisation/localisation.c b/src/localisation/localisation.c index 237f22f36c..c9868efd46 100644 --- a/src/localisation/localisation.c +++ b/src/localisation/localisation.c @@ -18,12 +18,15 @@ * along with this program. If not, see . *****************************************************************************/ -#ifdef _WIN32 +#include "../common.h" + +#ifdef __WINDOWS__ #include #else #include #include -#endif // _WIN32 +#endif // __WINDOWS__ + #include "../addresses.h" #include "../config.h" #include "../game.h" @@ -109,7 +112,8 @@ format_code_token format_code_tokens[] = { { FORMAT_SMALLUP, "SMALLUP" }, { FORMAT_SMALLDOWN, "SMALLDOWN" }, { FORMAT_LEFT, "LEFT" }, - { FORMAT_INVERTEDQUESTION, "INVERTEDQUESTION" } + { FORMAT_INVERTEDQUESTION, "INVERTEDQUESTION" }, + { FORMAT_COMMA1DP16, "COMMA1DP16" } }; uint32 format_get_code(const char *token) @@ -134,6 +138,13 @@ bool utf8_is_format_code(int codepoint) { if (codepoint < 32) return true; if (codepoint >= FORMAT_ARGUMENT_CODE_START && codepoint <= FORMAT_ARGUMENT_CODE_END) return true; + if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END) return true; + if (codepoint == FORMAT_COMMA1DP16) return true; + return false; +} + +bool utf8_is_colour_code(int codepoint) +{ if (codepoint >= FORMAT_COLOUR_CODE_START && codepoint <= FORMAT_COLOUR_CODE_END) return true; return false; } @@ -275,6 +286,71 @@ void format_comma_separated_integer(char **dest, long long value) *dest = finish; } +void format_comma_separated_fixed_1dp(char **dest, long long value) +{ + int digit, groupIndex; + char *dst = *dest; + char *finish; + char tmp; + const char *commaMark = language_get_string(5151); + const char *decimalMark = language_get_string(5152); + const char *ch; + + // Negative sign + if (value < 0) { + *dst++ = '-'; + value = -value; + } + + *dest = dst; + + // One decimal place + digit = value % 10; + value /= 10; + *dst++ = '0' + digit; + + ch = decimalMark; + while (*ch != 0) { + *dst++ = *ch++; + } + + if (value == 0) { + *dst++ = '0'; + } else { + // Groups of three digits, right to left + groupIndex = 0; + while (value > 0) { + // Append group separator + if (groupIndex == 3) { + groupIndex = 0; + + ch = commaMark; + while (*ch != 0) { + *dst++ = *ch++; + } + } + + digit = value % 10; + value /= 10; + + *dst++ = '0' + digit; + groupIndex++; + } + } + finish = dst; + + // Reverse string + dst--; + while (*dest < dst) { + tmp = **dest; + **dest = *dst; + *dst = tmp; + (*dest)++; + dst--; + } + *dest = finish; +} + void format_comma_separated_fixed_2dp(char **dest, long long value) { int digit, groupIndex; @@ -372,7 +448,7 @@ void format_currency(char **dest, long long value) // Prefix if (affix == CURRENCY_PREFIX) { - safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); + safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } @@ -380,7 +456,7 @@ void format_currency(char **dest, long long value) // Currency symbol suffix if (affix == CURRENCY_SUFFIX) { - safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); + safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } } @@ -408,7 +484,7 @@ void format_currency_2dp(char **dest, long long value) // Prefix if (affix == CURRENCY_PREFIX) { - safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); + safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } @@ -421,7 +497,7 @@ void format_currency_2dp(char **dest, long long value) // Currency symbol suffix if (affix == CURRENCY_SUFFIX) { - safe_strncpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); + safe_strcpy(*dest, symbol, CURRENCY_SYMBOL_MAX_SIZE); *dest += strlen(*dest); } } @@ -450,11 +526,20 @@ void format_length(char **dest, sint16 value) void format_velocity(char **dest, uint16 value) { - rct_string_id stringId = 2734; + rct_string_id stringId; - if (gConfigGeneral.measurement_format == MEASUREMENT_FORMAT_METRIC) { + switch (gConfigGeneral.measurement_format) { + default: + stringId = STR_UNIT_SUFFIX_MILES_PER_HOUR; + break; + case MEASUREMENT_FORMAT_METRIC: value = mph_to_kmph(value); - stringId++; + stringId = STR_UNIT_SUFFIX_KILOMETRES_PER_HOUR; + break; + case MEASUREMENT_FORMAT_SI: + value = mph_to_dmps(value); + stringId = STR_UNIT_SUFFIX_METRES_PER_SECOND; + break; } uint16 *argRef = &value; @@ -508,7 +593,7 @@ void format_realtime(char **dest, uint16 value) (*dest)--; } -void format_string_code(unsigned char format_code, char **dest, char **args) +void format_string_code(unsigned int format_code, char **dest, char **args) { int value; @@ -534,6 +619,13 @@ void format_string_code(unsigned char format_code, char **dest, char **args) format_comma_separated_fixed_2dp(dest, value); break; + case FORMAT_COMMA1DP16: + // Pop argument + value = *((sint16*)*args); + *args += 2; + + format_comma_separated_fixed_1dp(dest, value); + break; case FORMAT_COMMA16: // Pop argument value = *((sint16*)*args); @@ -576,8 +668,10 @@ void format_string_code(unsigned char format_code, char **dest, char **args) value = *((uint32*)*args); *args += 4; - strcpy(*dest, (char*)value); - *dest += strlen(*dest); + if (value != 0) { + strcpy(*dest, (char*)value); + *dest += strlen(*dest); + } break; case FORMAT_MONTHYEAR: // Pop argument @@ -667,7 +761,7 @@ void format_string_part_from_raw(utf8 **dest, const utf8 *src, char **args) } } else if (code <= 'z') { *(*dest)++ = code; - } else if (code < 142) { + } else if (code < FORMAT_COLOUR_CODE_START || code == FORMAT_COMMA1DP16) { format_string_code(code, dest, args); } else { *dest = utf8_write_codepoint(*dest, code); @@ -677,7 +771,7 @@ void format_string_part_from_raw(utf8 **dest, const utf8 *src, char **args) void format_string_part(utf8 **dest, rct_string_id format, char **args) { - if (format == (rct_string_id)STR_NONE) { + if (format == STR_NONE) { **dest = 0; } else if (format < 0x8000) { // Language string @@ -704,6 +798,8 @@ void format_string_part(utf8 **dest, rct_string_id format, char **args) *args += 4; } else { // ? + log_error("Localisation CALLPROC reached. Please contact a dev"); + assert(false); RCT2_CALLPROC_EBPSAFE(RCT2_ADDRESS(0x0095AFB8, uint32)[format]); } } @@ -744,16 +840,18 @@ void format_string_to_upper(utf8 *dest, rct_string_id format, void *args) } /** + * * rct2: 0x006E37F7 * error (eax) * format (bx) */ -void error_string_quit(int error, rct_string_id format){ +void error_string_quit(int error, rct_string_id format) +{ RCT2_GLOBAL(0x14241A0, uint32) = error; RCT2_GLOBAL(0x9E2DA0, uint32) = 1; char* error_string = RCT2_ADDRESS(0x1424080, char); - void* args = RCT2_ADDRESS(0x13CE952, void); + void* args = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_FORMAT_ARGS, void); *error_string = 0; if (format != 0xFFFF){ @@ -761,7 +859,6 @@ void error_string_quit(int error, rct_string_id format){ } RCT2_GLOBAL(0x9E2D9C, uint32) = 1; rct2_exit(); - rct2_endupdate(); } void generate_string_file() @@ -799,7 +896,7 @@ void generate_string_file() } /** - * Returns a pointer to the null terminator of the given UTF-8 string. + * Returns a pointer to the null terminator of the given UTF-8 string. */ utf8 *get_string_end(const utf8 *text) { @@ -814,7 +911,7 @@ utf8 *get_string_end(const utf8 *text) } /** - * Return the number of bytes (including the null terminator) in the given UTF-8 string. + * Return the number of bytes (including the null terminator) in the given UTF-8 string. */ size_t get_string_size(const utf8 *text) { @@ -822,7 +919,7 @@ size_t get_string_size(const utf8 *text) } /** - * Return the number of visible characters (excludes format codes) in the given UTF-8 string. + * Return the number of visible characters (excludes format codes) in the given UTF-8 string. */ int get_string_length(const utf8 *text) { @@ -852,7 +949,7 @@ int win1252_to_utf8(utf8string dst, const char *src, size_t maxBufferLength) { size_t srcLength = strlen(src); -#ifdef _WIN32 +#ifdef __WINDOWS__ utf16 stackBuffer[256]; utf16 *heapBuffer = NULL; utf16 *intermediateBuffer = stackBuffer; @@ -861,15 +958,14 @@ int win1252_to_utf8(utf8string dst, const char *src, size_t maxBufferLength) if (srcLength > bufferCount) { bufferCount = srcLength + 4; heapBuffer = malloc(bufferCount * sizeof(utf16)); + assert(heapBuffer != NULL); intermediateBuffer = heapBuffer; } } MultiByteToWideChar(CP_ACP, 0, src, -1, intermediateBuffer, bufferCount); int result = WideCharToMultiByte(CP_UTF8, 0, intermediateBuffer, -1, dst, maxBufferLength, NULL, NULL); - if (heapBuffer != NULL) { - free(heapBuffer); - } + free(heapBuffer); #else //log_warning("converting %s of size %d", src, srcLength); char *buffer_conv = strndup(src, srcLength); @@ -921,7 +1017,7 @@ int win1252_to_utf8(utf8string dst, const char *src, size_t maxBufferLength) //log_warning("converted %s of size %d, %d", dst, byte_diff, strlen(dst)); int result = byte_diff; free(buffer_orig); -#endif // _WIN32 +#endif // __WINDOWS__ return result; } diff --git a/src/localisation/localisation.h b/src/localisation/localisation.h index ac255f5b91..a471a1eeee 100644 --- a/src/localisation/localisation.h +++ b/src/localisation/localisation.h @@ -27,6 +27,7 @@ #include "string_ids.h" bool utf8_is_format_code(int codepoint); +bool utf8_is_colour_code(int codepoint); bool utf8_should_use_sprite_for_codepoint(int codepoint); int font_sprite_get_codepoint_offset(int codepoint); int utf8_get_format_code_arg_length(int codepoint); diff --git a/src/localisation/string_ids.h b/src/localisation/string_ids.h index bc2bb1b397..c843a189cd 100644 --- a/src/localisation/string_ids.h +++ b/src/localisation/string_ids.h @@ -21,9 +21,11 @@ #ifndef _STRING_IDS_H_ #define _STRING_IDS_H_ -enum { - STR_NONE = -1, +#include "../common.h" +#define STR_NONE ((rct_string_id)-1) + +enum { STR_GUEST = 767, STR_DATE_DAY_1 = 779, @@ -228,6 +230,7 @@ enum { STR_COST_AMOUNT = 986, STR_TOO_MANY_RIDES = 987, + STR_CANT_CREATE_NEW_RIDE_ATTRACTION = 988, STR_CONSTRUCTION = 990, @@ -240,7 +243,7 @@ enum { STR_OVERALL_VIEW = 996, STR_VIEW_SELECTION = 997, - + STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE = 998, STR_REQUIRES_A_STATION_PLATFORM = 999, STR_TRACK_IS_NOT_A_COMPLETE_CIRCUIT = 1000, STR_TRACK_UNSUITABLE_FOR_TYPE_OF_TRAIN = 1001, @@ -266,6 +269,7 @@ enum { STR_RIDE_SET_VEHICLE_SET_NUM_CARS_PER_TRAIN_FAIL = 1019, STR_RIDE_SET_VEHICLE_SET_NUM_TRAINS_FAIL = 1020, + STR_STATION_PLATFORM_TOO_LONG = 1026, STR_LOCATE_SUBJECT_TIP = 1027, STR_OFF_EDGE_OF_MAP = 1028, @@ -276,18 +280,22 @@ enum { STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND = 1033, STR_CAN_ONLY_BUILD_THIS_ON_LAND = 1034, STR_LOCAL_AUTHORITY_WONT_ALLOW_CONSTRUCTION_ABOVE_TREE_HEIGHT = 1035, - STR_LOAD_GAME_DIALOG_TITLE = 1036, - STR_LOAD_LANDSCAPE_DIALOG_TITLE = 1037, - STR_CONVERT_SAVED_GAME_TO_SCENARIO_1038 = 1038, - - STR_SAVE_GAME_1040 = 1040, - STR_SAVE_SCENARIO = 1041, - - STR_RCT2_SAVED_GAME = 1043, - STR_RCT2_SCENARIO_FILE = 1044, - STR_RCT2_LANDSCAPE_FILE = 1045, + STR_FILE_DIALOG_TITLE_LOAD_GAME = 1036, + STR_FILE_DIALOG_TITLE_LOAD_LANDSCAPE = 1037, + STR_FILE_DIALOG_TITLE_CONVERT_SAVED_GAME_TO_SCENARIO = 1038, + STR_FILE_DIALOG_TITLE_INSTALL_NEW_TRACK_DESIGN = 1039, + STR_FILE_DIALOG_TITLE_SAVE_GAME = 1040, + STR_FILE_DIALOG_TITLE_SAVE_SCENARIO = 1041, + STR_FILE_DIALOG_TITLE_SAVE_LANDSCAPE = 1042, + STR_OPENRCT2_SAVED_GAME = 1043, + STR_OPENRCT2_SCENARIO_FILE = 1044, + STR_OPENRCT2_LANDSCAPE_FILE = 1045, + STR_OPENRCT2_TRACK_DESIGN_FILE = 1046, + STR_GAME_SAVE_FAILED = 1047, STR_SCENARIO_SAVE_FAILED = 1048, + STR_LANDSCAPE_SAVE_FAILED = 1049, + STR_FAILED_TO_LOAD_FILE_CONTAINS_INVALID_DATA = 1050, STR_INVISIBLE_SUPPORTS = 1051, STR_INVISIBLE_PEOPLE = 1052, @@ -382,6 +390,8 @@ enum { STR_SELECT_VEHICLE_COLOUR_SCHEME_TIP = 1140, STR_SELECT_VEHICLE_TO_MODIFY_TIP = 1141, + STR_DROPDOWN_MENU_LABEL = 1142, + STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION = 1144, STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION = 1145, STR_ENTRANCE_NOT_YET_BUILT = 1146, @@ -472,6 +482,10 @@ enum { STR_WATER_RIDES_TIP = 1227, STR_SHOPS_STALLS_TIP = 1228, + STR_PLAYER_DEFAULT_NAME = 1315, + STR_X_PLAYER = 1317, + STR_X_PLAYERS = 1318, + STR_ROTATE_OBJECTS_90 = 1327, STR_LEVEL_LAND_REQUIRED = 1328, STR_LAUNCH_SPEED = 1329, @@ -497,6 +511,7 @@ enum { STR_QUEUE_TIME_MINUTES = 1360, STR_TOO_HIGH_FOR_SUPPORTS = 1363, + STR_SUPPORTS_CANT_BE_EXTENDED = 1364, STR_IN_LINE_TWIST_LEFT = 1365, STR_IN_LINE_TWIST_RIGHT = 1366, @@ -718,7 +733,7 @@ enum { STR_OFF = 1775, STR_ON = 1776, - STR_MUSIC = 1777, + STR_RIDE_MUSIC = 1777, STR_UNIFORM_COLOUR_TIP = 1790, STR_UNIFORM_COLOUR = 1791, @@ -866,8 +881,16 @@ enum { STR_CONTINUE_SAVED_GAME_TIP = 1922, STR_SHOW_TUTORIAL_TIP = 1923, STR_EXIT = 1924, - STR_RIDE_HAS_CRASHED = 1928, + STR_RIDE_IS_BROKEN_DOWN = 1927, + STR_RIDE_HAS_CRASHED = 1928, + STR_RIDE_IS_STILL_NOT_FIXED = 1929, + + STR_PEEP_TRACKING_PEEP_JOINED_QUEUE_FOR_X = 1931, + STR_PEEP_TRACKING_PEEP_IS_ON_X = 1932, + STR_PEEP_TRACKING_PEEP_IS_IN_X = 1933, + STR_PEEP_TRACKING_LEFT_RIDE_X = 1934, + STR_PEEP_TRACKING_LEFT_PARK = 1935, STR_PEEP_TRACKING_NOTIFICATION_BOUGHT_X = 1936, STR_SHOW_SUBJECT_TIP = 1937, @@ -1099,6 +1122,7 @@ enum { STR_CELSIUS_VALUE = 2216, STR_FAHRENHEIT_VALUE = 2217, + STR_X_PEOPLE_DIED_ON_X = 2219, STR_PARK_RATING_LABEL = 2220, STR_PARK_RATING_TIP = 2221, @@ -1132,6 +1156,9 @@ enum { STR_CANT_DEMOLISH_RIDE = 2248, + STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE = 2249, + STR_NEWS_ITEM_RESEARCH_NEW_SCENERY_SET_AVAILABLE = 2250, + STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS = 2252, STR_RESEARCH_TRANSPORT_RIDES = 2253, @@ -1220,6 +1247,8 @@ enum { STR_METRIC = 2345, STR_DISPLAY = 2346, + STR_NEWS_ITEM_GUEST_DROWNED = 2347, + STR_STAFF_STATS_TIP = 2348, //STR_UNITS = 2358, @@ -1405,6 +1434,11 @@ enum { STR_SAVE_EVERY_HOUR = 2705, STR_SAVE_NEVER = 2706, + STR_UNIT_SUFFIX_FEET = 2732, + STR_UNIT_SUFFIX_METRES = 2733, + STR_UNIT_SUFFIX_MILES_PER_HOUR = 2734, + STR_UNIT_SUFFIX_KILOMETRES_PER_HOUR = 2735, + STR_DATE_FORMAT_DMY = 2737, STR_ROLLERCOASTER_TYCOON_1_DROPDOWN = 2740, @@ -1504,8 +1538,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, @@ -1526,8 +1558,8 @@ enum { STR_CHANGE_BANNER_TEXT_TIP = 2986, STR_SET_AS_NO_ENTRY_BANNER_TIP = 2987, STR_DEMOLISH_BANNER_TIP = 2988, - STR_SELECT_MAIN_COLOR_TIP = 2989, - STR_SELECT_TEXT_COLOR_TIP = 2990, + STR_SELECT_MAIN_SIGN_COLOUR_TIP = 2989, + STR_SELECT_TEXT_COLOUR_TIP = 2990, STR_SIGN = 2991, STR_CHANGE_SIGN_TEXT_TIP = 2994, @@ -1812,6 +1844,10 @@ enum { STR_OBJECTIVE = 3322, + STR_MISSING_OBJECT_DATA_ID = 3323, + STR_REQUIRES_THE_FOLLOWING_ADDON_PACK = 3324, + STR_REQUIRES_AN_ADDON_PACK = 3325, + STR_PEEP_SPAWNS_NOT_SET = 3327, STR_CANT_ADVANCE_TO_NEXT_EDITOR_STAGE = 3328, STR_NO_PARK_ENTRANCES = 3329, @@ -1823,6 +1859,10 @@ enum { STR_ROLLER_COASTER_DESIGNER_SELECT_RIDE_TYPES_VEHICLES = 3335, STR_TRACK_DESIGNS_MANAGER_SELECT_RIDE_TYPE = 3336, + STR_CUSTOM_DESIGNED_LAYOUT = 3338, + STR_1_DESIGN_AVAILABLE = 3339, + STR_X_DESIGNS_AVAILABLE = 3340, + STR_GAME_TOOLS = 3341, STR_SCENARIO_EDITOR = 3342, STR_CONVERT_SAVED_GAME_TO_SCENARIO = 3343, @@ -1855,10 +1895,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, @@ -1884,8 +1920,11 @@ enum { STR_CHEAT_RENEW_RIDES = 5123, STR_CHEAT_MAKE_DESTRUCTABLE = 5125, + STR_DISABLE_ELEVATION = 5127, + STR_SELECTION_SIZE = 5128, + STR_ENTER_SELECTION_SIZE = 5129, STR_CHEAT_FIX_ALL_RIDES = 5132, - STR_CHEAT_410_HILL_LIFT = 5137, + STR_CHEAT_UNLOCK_OPERATING_LIMITS = 5137, STR_CHEAT_DISABLE_BRAKES_FAILURE = 5140, STR_CHEAT_DISABLE_BREAKDOWNS = 5141, STR_CHEATS_BUTTON_ON_TOOLBAR = 5147, @@ -1981,9 +2020,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, @@ -2145,9 +2192,12 @@ enum { STR_CHEAT_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES = 5555, - STR_KICK_PLAYER = 5556, + STR_KICK_PLAYER_TIP = 5556, STR_STAY_CONNECTED_AFTER_DESYNC = 5557, + STR_AUTO_OPEN_SHOPS = 5586, + STR_AUTO_OPEN_SHOPS_TIP = 5587, + STR_RESTART_REQUIRED = 5558, STR_LANGUAGE_LOAD_FAILED = 5561, @@ -2163,8 +2213,8 @@ enum { STR_PASSWORD_REQUIRED_DESC = 5569, STR_FETCH_SERVERS = 5570, STR_JOIN_GAME = 5571, - STR_ADD_TO_FAVORITES = 5572, - STR_REMOVE_FROM_FAVORITES = 5573, + STR_ADD_TO_FAVOURITES = 5572, + STR_REMOVE_FROM_FAVOURITES = 5573, STR_SERVER_NAME = 5574, STR_MAX_PLAYERS = 5575, STR_PORT = 5576, @@ -2176,6 +2226,208 @@ enum { STR_CZECH_KORUNA = 5580, + STR_SHOW_FPS = 5581, + + STR_TRAP_MOUSE = 5582, + + STR_UNIT_SUFFIX_METRES_PER_SECOND = 5583, + STR_SI = 5584, + + STR_CHEAT_UNLOCK_OPERATING_LIMITS_TIP = 5585, + + STR_SHOW_MULTIPLAYER_TIP = 5588, + + STR_NOTIFICATION_SETTINGS = 5589, + STR_NOTIFICATION_PARK_AWARD = 5590, + STR_NOTIFICATION_PARK_MARKETING_CAMPAIGN_FINISHED = 5591, + STR_NOTIFICATION_PARK_WARNINGS = 5592, + STR_NOTIFICATION_PARK_RATING_WARNINGS = 5593, + STR_NOTIFICATION_RIDE_BROKEN_DOWN = 5594, + STR_NOTIFICATION_RIDE_CRASHED = 5595, + STR_NOTIFICATION_RIDE_WARNINGS = 5596, + STR_NOTIFICATION_RIDE_RESEARCHED = 5597, + STR_NOTIFICATION_GUEST_WARNINGS = 5598, + STR_NOTIFICATION_GUEST_LOST = 5599, + STR_NOTIFICATION_GUEST_LEFT_PARK = 5600, + STR_NOTIFICATION_GUEST_QUEUING_FOR_RIDE = 5601, + STR_NOTIFICATION_GUEST_ON_RIDE = 5602, + STR_NOTIFICATION_GUEST_LEFT_RIDE = 5603, + STR_NOTIFICATION_GUEST_BOUGHT_ITEM = 5604, + 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, + + STR_CMD_PLUS = 5633, + STR_OPTION_PLUS = 5634, + + STR_MONEY_SPENT = 5635, + STR_COMMANDS_RAN = 5636, + STR_CANT_DO_THIS = 5637, + STR_PERMISSION_DENIED = 5638, + STR_PLAYERS_TIP = 5639, + STR_GROUPS_TIP = 5640, + STR_DEFAULT_GROUP = 5641, + STR_GROUP = 5642, + STR_ADD_GROUP = 5643, + STR_REMOVE_GROUP = 5644, + + STR_ACTION_CHAT = 5645, + STR_ACTION_TERRAFORM = 5646, + STR_ACTION_TOGGLE_PAUSE = 5647, + STR_ACTION_SET_WATER_LEVEL = 5648, + STR_ACTION_CREATE_RIDE = 5649, + STR_ACTION_REMOVE_RIDE = 5650, + STR_ACTION_BUILD_RIDE = 5651, + STR_ACTION_RIDE_PROPERTIES = 5652, + STR_ACTION_SCENERY = 5653, + STR_ACTION_PATH = 5654, + STR_ACTION_GUEST = 5655, + STR_ACTION_STAFF = 5656, + STR_ACTION_PARK_PROPERTIES = 5657, + STR_ACTION_PARK_FUNDING = 5658, + STR_ACTION_KICK_PLAYER = 5659, + STR_ACTION_MODIFY_GROUPS = 5660, + STR_ACTION_SET_PLAYER_GROUP = 5661, + STR_ACTION_NA = 5662, + STR_ACTION_CLEAR_LANDSCAPE = 5663, + STR_ACTION_CHEAT = 5664, + STR_ACTION_TOGGLE_SCENERY_CLUSTER = 5665, + + STR_LAST_ACTION_RAN = 5701, + STR_LOCATE_PLAYER_TIP = 5702, + STR_CANT_KICK_THE_HOST = 5703, + STR_LAST_ACTION = 5704, + STR_CANT_SET_TO_THIS_GROUP = 5705, + STR_CANT_REMOVE_GROUP_THAT_PLAYERS_BELONG_TO = 5706, + STR_THIS_GROUP_CANNOT_BE_MODIFIED = 5707, + STR_CANT_CHANGE_GROUP_THAT_THE_HOST_BELONGS_TO = 5708, + STR_RENAME_GROUP = 5709, + STR_GROUP_NAME = 5710, + STR_ENTER_NEW_NAME_FOR_THIS_GROUP = 5711, + STR_CANT_MODIFY_PERMISSION_THAT_YOU_DO_NOT_HAVE_YOURSELF = 5712, + + STR_SHORTCUT_SHOW_OPTIONS = 5714, + + STR_NEW_GAME = 5715, + + STR_NOT_ALLOWED_IN_MULTIPLAYER = 5716, + + STR_NETWORK_VERSION = 5717, + STR_NETWORK_VERSION_TIP = 5718, + + STR_SUNNY = 5719, + STR_PARTIALLY_CLOUDY = STR_SUNNY + 1, + STR_CLOUDY = STR_SUNNY + 2, + STR_RAIN = STR_SUNNY + 3, + STR_HEAVY_RAIN = STR_SUNNY + 4, + STR_THUNDERSTORM = STR_SUNNY + 5, + STR_FORCE_WEATHER = 5725, + STR_FORCE_WEATHER_TOOLTIP = 5726, + + STR_SCALING_QUALITY = 5727, + STR_REQUIRES_HW_DISPLAY = 5728, + STR_REQUIRES_HW_DISPLAY_TIP = 5729, + STR_SCALING_QUALITY_NN = 5730, + STR_SCALING_QUALITY_LINEAR = 5731, + STR_SCALING_QUALITY_ANISOTROPIC = 5732, + STR_USE_NN_AT_INTEGER_SCALE = 5733, + STR_OPTIONS_RENDERING_TIP = 5734, + + STR_CLOSED_WITH_PERSON = 5737, + STR_CLOSED_WITH_PEOPLE = 5738, + + STR_CUSTOMERS_ON_RIDE = 5739, + + STR_CHEAT_NEVERENDING_MARKETING = 5740, + STR_CHEAT_TIP_NEVERENDING_MARKETING = 5741, + + STR_MULTIPLAYER_RESOLVING = 5742, + STR_MULTIPLAYER_CONNECTING = 5743, + STR_MULTIPLAYER_AUTHENTICATING = 5744, + STR_MULTIPLAYER_DESYNC = 5745, + STR_MULTIPLAYER_DISCONNECTED_NO_REASON = 5746, + STR_MULTIPLAYER_DISCONNECTED_WITH_REASON = 5747, + STR_MULTIPLAYER_KICKED = 5748, + STR_MULTIPLAYER_KICKED_REASON = 5749, + STR_MULTIPLAYER_CONNECTION_CLOSED = 5750, + STR_MULTIPLAYER_NO_DATA = 5751, + STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_NO_REASON = 5752, + STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_WITH_REASON = 5753, + STR_MULTIPLAYER_BAD_PLAYER_NAME = 5754, + STR_MULTIPLAYER_INCORRECT_SOFTWARE_VERSION = 5755, + STR_MULTIPLAYER_BAD_PASSWORD = 5756, + STR_MULTIPLAYER_SERVER_FULL = 5757, + STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME = 5758, + STR_MULTIPLAYER_DOWNLOADING_MAP = 5759, + + STR_HONG_KONG_DOLLAR = 5760, + STR_NEW_TAIWAN_DOLLAR = 5761, + STR_CHINESE_YUAN = 5762, + + STR_ALL_FILES = 5763, + + STR_INVALID_RIDE_TYPE = 5764, + STR_CANT_EDIT_INVALID_RIDE_TYPE = 5765, + + STR_RIDE_LIST_INCOME = 5767, + STR_RIDE_LIST_TOTAL_CUSTOMERS = 5768, + STR_RIDE_LIST_TOTAL_PROFIT = 5769, + STR_RIDE_LIST_CUSTOMERS_PER_HOUR = 5770, + STR_RIDE_LIST_RUNNING_COST = 5771, + STR_RIDE_LIST_AGE = 5772, + STR_RIDE_LIST_TOTAL_CUSTOMERS_LABEL = 5773, + STR_RIDE_LIST_TOTAL_PROFIT_LABEL = 5774, + STR_RIDE_LIST_CUSTOMERS_PER_HOUR_LABEL = 5775, + STR_RIDE_LIST_BUILT_THIS_YEAR_LABEL = 5776, + STR_RIDE_LIST_BUILT_LAST_YEAR_LABEL = 5777, + STR_RIDE_LIST_BUILT_X_YEARS_AGO_LABEL = 5778, + STR_RIDE_LIST_INCOME_LABEL = 5779, + STR_RIDE_LIST_RUNNING_COST_LABEL = 5780, + STR_RIDE_LIST_RUNNING_COST_UNKNOWN = 5781, + + + STR_MULTIPLAYER_CONNECTED_CHAT_HINT = 5782, + + STR_SCENARIO_LOCKED = 5783, + STR_SCENARIO_LOCKED_DESC = 5784, + + STR_CANT_RENAME_GROUP = 5785, + STR_INVALID_GROUP_NAME = 5786, + + STR_X_PLAYERS_ONLINE = 5787, + + STR_DEFAULT_INSPECTION_INTERVAL = 5788, + + STR_DISABLE_LIGHTNING_EFFECT = 5789, + + STR_CHEAT_TIP_UNLOCK_PRICES = 5790, + STR_CHEAT_TIP_RENEW_RIDES = 5791, + STR_CHEAT_TIP_FIX_ALL_RIDES = 5792, + STR_CHEAT_TIP_RESET_CRASH_STATUS = 5793, + STR_CHEAT_TIP_MAKE_DESTRUCTABLE = 5794, + STR_CHEAT_TIP_IGNORE_INTENSITY = 5795, + STR_CHEAT_TIP_OPEN_PARK = 5796, + STR_CHEAT_TIP_FREEZE_CLIMATE = 5797, + STR_CHEAT_TIP_BUILD_IN_PAUSE_MODE = 5798, + STR_CHEAT_TIP_DISABLE_BRAKES_FAILURE = 5799, + STR_CHEAT_TIP_DISABLE_BREAKDOWNS = 5800, + // Have to include resource strings (from scenarios and objects) for the time being now that language is partially working STR_COUNT = 32768 }; diff --git a/src/localisation/user.c b/src/localisation/user.c index e664715dd1..7e56d214a0 100644 --- a/src/localisation/user.c +++ b/src/localisation/user.c @@ -55,7 +55,7 @@ rct_string_id user_string_allocate(int base, const utf8 *text) if (userString[0] != 0) continue; - safe_strncpy(userString, text, USER_STRING_MAX_LENGTH - 1); + safe_strcpy(userString, text, USER_STRING_MAX_LENGTH); return 0x8000 + (i | highBits); } RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_MANY_NAMES_DEFINED; diff --git a/src/localisation/utf8.c b/src/localisation/utf8.c index e6403e1399..34963cb2d2 100644 --- a/src/localisation/utf8.c +++ b/src/localisation/utf8.c @@ -65,7 +65,7 @@ int utf8_insert_codepoint(utf8 *dst, uint32 codepoint) return shift; } -bool utf8_is_codepoint_start(utf8 *text) +bool utf8_is_codepoint_start(const utf8 *text) { if ((text[0] & 0x80) == 0) return true; if ((text[0] & 0xC0) == 0xC0) return true; diff --git a/src/management/award.c b/src/management/award.c index 6eac789f6b..9904033c31 100644 --- a/src/management/award.c +++ b/src/management/award.c @@ -19,6 +19,7 @@ *****************************************************************************/ #include "../addresses.h" +#include "../config.h" #include "../interface/window.h" #include "../localisation/localisation.h" #include "../peep/peep.h" @@ -134,11 +135,14 @@ static int award_is_deserved_best_rollercoasters(int awardType, int activeAwardT { int i, rollerCoasters; rct_ride *ride; - rct_ride_type *rideType; + rct_ride_entry *rideType; rollerCoasters = 0; FOR_ALL_RIDES(i, ride) { - rideType = gRideTypeList[ride->subtype]; + rideType = get_ride_entry(ride->subtype); + if (rideType == NULL) { + continue; + } if (rideType->category[0] != RIDE_GROUP_ROLLERCOASTER && rideType->category[1] != RIDE_GROUP_ROLLERCOASTER) continue; @@ -277,7 +281,7 @@ static int award_is_deserved_best_food(int awardType, int activeAwardTypes) int i, hungryPeeps, shops, uniqueShops; uint64 shopTypes; rct_ride *ride; - rct_ride_type *rideType; + rct_ride_entry *rideType; uint16 spriteIndex; rct_peep *peep; @@ -294,7 +298,10 @@ static int award_is_deserved_best_food(int awardType, int activeAwardTypes) continue; shops++; - rideType = gRideTypeList[ride->subtype]; + rideType = get_ride_entry(ride->subtype); + if (rideType == NULL) { + continue; + } if (!(shopTypes & (1ULL << rideType->shop_item))) { shopTypes |= (1ULL << rideType->shop_item); uniqueShops++; @@ -323,7 +330,7 @@ static int award_is_deserved_worst_food(int awardType, int activeAwardTypes) int i, hungryPeeps, shops, uniqueShops; uint64 shopTypes; rct_ride *ride; - rct_ride_type *rideType; + rct_ride_entry *rideType; uint16 spriteIndex; rct_peep *peep; @@ -340,7 +347,10 @@ static int award_is_deserved_worst_food(int awardType, int activeAwardTypes) continue; shops++; - rideType = gRideTypeList[ride->subtype]; + rideType = get_ride_entry(ride->subtype); + if (rideType == NULL) { + continue; + } if (!(shopTypes & (1ULL << rideType->shop_item))) { shopTypes |= (1ULL << rideType->shop_item); uniqueShops++; @@ -433,11 +443,14 @@ static int award_is_deserved_best_water_rides(int awardType, int activeAwardType { int i, waterRides; rct_ride *ride; - rct_ride_type *rideType; + rct_ride_entry *rideType; waterRides = 0; FOR_ALL_RIDES(i, ride) { - rideType = gRideTypeList[ride->subtype]; + rideType = get_ride_entry(ride->subtype); + if (rideType == NULL) { + continue; + } if (rideType->category[0] != RIDE_GROUP_WATER && rideType->category[1] != RIDE_GROUP_WATER) continue; @@ -533,11 +546,14 @@ static int award_is_deserved_best_gentle_rides(int awardType, int activeAwardTyp { int i, gentleRides; rct_ride *ride; - rct_ride_type *rideType; + rct_ride_entry *rideType; gentleRides = 0; FOR_ALL_RIDES(i, ride) { - rideType = gRideTypeList[ride->subtype]; + rideType = get_ride_entry(ride->subtype); + if (rideType == NULL) { + continue; + } if (rideType->category[0] != RIDE_GROUP_GENTLE && rideType->category[1] != RIDE_GROUP_GENTLE) continue; @@ -619,7 +635,9 @@ void award_update_all() // Add award gCurrentAwards[freeAwardEntryIndex].type = awardType; gCurrentAwards[freeAwardEntryIndex].time = 5; - news_item_add_to_queue(NEWS_ITEM_AWARD, STR_NEWS_ITEM_AWARD_MOST_UNTIDY + awardType, 0); + if (gConfigNotifications.park_award) { + news_item_add_to_queue(NEWS_ITEM_AWARD, STR_NEWS_ITEM_AWARD_MOST_UNTIDY + awardType, 0); + } window_invalidate_by_class(WC_PARK_INFORMATION); } } diff --git a/src/management/award.h b/src/management/award.h index 87e21fd6c3..971fa62d39 100644 --- a/src/management/award.h +++ b/src/management/award.h @@ -57,4 +57,4 @@ bool award_is_positive(int type); void award_reset(); void award_update_all(); -#endif \ No newline at end of file +#endif diff --git a/src/management/finance.c b/src/management/finance.c index d8231779d9..324fae0d1e 100644 --- a/src/management/finance.c +++ b/src/management/finance.c @@ -52,10 +52,10 @@ money32 *gParkValueHistory = RCT2_ADDRESS(RCT2_ADDRESS_PARK_VALUE_HISTORY, money /** * Pay an amount of money. - * rct2: 0x069C674 + * rct2: 0x069C674 * @param amount (eax) - * @param type passed via global var 0x0141F56C, our type is that var/4. - **/ + * @param type passed via global var 0x0141F56C (RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE), our type is that var/4. + */ void finance_payment(money32 amount, rct_expenditure_type type) { money32 cur_money = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32)); @@ -74,8 +74,8 @@ void finance_payment(money32 amount, rct_expenditure_type type) /** * Pays the wages of all active staff members in the park. - * rct2: 0x006C18A9 - **/ + * rct2: 0x006C18A9 + */ void finance_pay_wages() { rct_peep* peep; @@ -105,8 +105,8 @@ void finance_pay_research() /** * Pay interest on current loans. - * rct2: 0x0069E092 - **/ + * rct2: 0x0069E092 + */ void finance_pay_interest() { money32 current_loan = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, sint32); @@ -121,7 +121,7 @@ void finance_pay_interest() /** * - * rct2: 0x006AC885 + * rct2: 0x006AC885 */ void finance_pay_ride_upkeep() { @@ -132,8 +132,8 @@ void finance_pay_ride_upkeep() if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_EVER_BEEN_OPENED)) { ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); ride->reliability = RIDE_INITIAL_RELIABILITY; - } + if (ride->status != RIDE_STATUS_CLOSED && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { sint16 upkeep = ride->upkeep_cost; if (upkeep != -1) { @@ -142,6 +142,10 @@ void finance_pay_ride_upkeep() finance_payment(upkeep, RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS); } } + + if (ride->last_crash_type != RIDE_CRASH_TYPE_NONE) { + ride->last_crash_type--; + } } } diff --git a/src/management/marketing.c b/src/management/marketing.c index 5eee2c627e..1d4eddab54 100644 --- a/src/management/marketing.c +++ b/src/management/marketing.c @@ -19,12 +19,14 @@ *****************************************************************************/ #include "../addresses.h" +#include "../config.h" #include "../game.h" #include "../interface/window.h" #include "../localisation/localisation.h" #include "../management/finance.h" #include "../ride/ride.h" #include "../ride/ride_data.h" +#include "../cheats.h" #include "marketing.h" #include "news_item.h" @@ -58,7 +60,7 @@ int marketing_get_campaign_guest_generation_probability(int campaign) probability /= 8; break; case ADVERTISING_CAMPAIGN_RIDE_FREE: - ride = &g_ride_list[gMarketingCampaignRideIndex[campaign]]; + ride = get_ride(gMarketingCampaignRideIndex[campaign]); if (ride->price < 3) probability /= 8; break; @@ -67,13 +69,16 @@ int marketing_get_campaign_guest_generation_probability(int campaign) return probability; } -/* +/** * Update status of marketing campaigns and send produce a news item when they have finished. - * rct2: 0x0069E0C1 - **/ + * rct2: 0x0069E0C1 + */ void marketing_update() { for (int campaign = 0; campaign < ADVERTISING_CAMPAIGN_COUNT; campaign++) { + if (gCheatsNeverendingMarketing) + continue; + int active = (gMarketingCampaignDaysLeft[campaign] & CAMPAIGN_ACTIVE_FLAG) != 0; if (gMarketingCampaignDaysLeft[campaign] == 0) continue; @@ -93,14 +98,16 @@ void marketing_update() // This sets the string parameters for the marketing types that have an argument. if (campaign == ADVERTISING_CAMPAIGN_RIDE_FREE || campaign == ADVERTISING_CAMPAIGN_RIDE) { - rct_ride* ride = GET_RIDE(campaignItem); + rct_ride* ride = get_ride(campaignItem); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ride->name; - RCT2_GLOBAL(0x013CE954, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; } else if (campaign == ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ShopItemStringIds[campaignItem].plural; } - news_item_add_to_queue(NEWS_ITEM_MONEY, STR_MARKETING_FINISHED_BASE + campaign, 0); + if (gConfigNotifications.park_marketing_campaign_finished) { + news_item_add_to_queue(NEWS_ITEM_MONEY, STR_MARKETING_FINISHED_BASE + campaign, 0); + } } } @@ -144,7 +151,7 @@ void marketing_start_campaign(int type, int rideOrItem, int numWeeks) /** * - * rct2: 0x0069E73C + * rct2: 0x0069E73C */ void game_command_start_campaign(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { @@ -152,6 +159,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; @@ -173,7 +187,7 @@ bool marketing_is_campaign_type_applicable(int campaignType) { int i; rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; switch (campaignType) { case ADVERTISING_CAMPAIGN_PARK_ENTRY_FREE: @@ -199,7 +213,10 @@ bool marketing_is_campaign_type_applicable(int campaignType) case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE: // Check if any food or drink stalls exist FOR_ALL_RIDES(i, ride) { - rideEntry = GET_RIDE_ENTRY(ride->subtype); + rideEntry = get_ride_entry(ride->subtype); + if (rideEntry == NULL) { + continue; + } if ( shop_item_is_food_or_drink(rideEntry->shop_item) || shop_item_is_food_or_drink(rideEntry->shop_item_secondary) diff --git a/src/management/marketing.h b/src/management/marketing.h index 080289ad9d..0a7bc65fd2 100644 --- a/src/management/marketing.h +++ b/src/management/marketing.h @@ -22,6 +22,7 @@ #define _MARKETING_H_ #include "../common.h" +#include "../cheats.h" #include "../peep/peep.h" enum { @@ -54,4 +55,4 @@ void marketing_start_campaign(int type, int rideOrItem, int numWeeks); void game_command_start_campaign(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); bool marketing_is_campaign_type_applicable(int campaignType); -#endif \ No newline at end of file +#endif diff --git a/src/management/news_item.c b/src/management/news_item.c index 563703eeb7..17a588f174 100644 --- a/src/management/news_item.c +++ b/src/management/news_item.c @@ -110,39 +110,6 @@ static bool news_item_is_current_old() */ void news_item_update_current() { - short ax, bx; - - get_system_time(); - - ax = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16); - bx = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16); - - // Cheat detection - if (bx != RCT2_GLOBAL(0x009DEA6B, sint16)) { - bx--; - if (bx == 0) - bx = 12; - if (bx != RCT2_GLOBAL(0x009DEA6B, sint16) || ax != 1) { - // loc_66E2AE - RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32) -= 10000; - if (RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32) >= 0) - RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32) = -RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32); - } - } else { - if (ax != RCT2_GLOBAL(0x009DEA69, sint16)) { - ax--; - if (ax != RCT2_GLOBAL(0x009DEA69, sint16)) { - // loc_66E2AE - RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32) -= 10000; - if (RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32) >= 0) - RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32) = -RCT2_GLOBAL(RCT2_ADDRESS_INITIAL_CASH, sint32); - } - } - } - - RCT2_GLOBAL(0x009DEA69, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16); - RCT2_GLOBAL(0x009DEA6B, sint16) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16); - // Check if there is a current news item if (news_item_is_queue_empty()) return; @@ -234,7 +201,7 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int * switch (type) { case NEWS_ITEM_RIDE: - ride = &g_ride_list[subject]; + ride = get_ride(subject); if (ride->overall_view == 0xFFFF) { *x = SPRITE_LOCATION_NULL; break; @@ -257,7 +224,7 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int * } // Find which ride peep is on - ride = &g_ride_list[peep->current_ride]; + ride = get_ride(peep->current_ride); if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) { *x = SPRITE_LOCATION_NULL; break; @@ -291,16 +258,17 @@ void news_item_get_subject_location(int type, int subject, int *x, int *y, int * /** - * rct2: 0x0066DF55 + * + * rct2: 0x0066DF55 * * @param a (al) * @param string_id (ebx) * @param c (ecx) - **/ + */ void news_item_add_to_queue(uint8 type, rct_string_id string_id, uint32 assoc) { utf8 *buffer = (char*)0x0141EF68; - void *args = (void*)0x013CE952; + void *args = (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS; format_string(buffer, string_id, args); // overflows possible? news_item_add_to_queue_raw(type, buffer, assoc); @@ -326,7 +294,7 @@ void news_item_add_to_queue_raw(uint8 type, const utf8 *text, uint32 assoc) newsItem->ticks = 0; newsItem->month_year = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); newsItem->day = ((days_in_month[(newsItem->month_year & 7)] * RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16)) >> 16) + 1; - safe_strncpy(newsItem->text, text, 255); + safe_strcpy(newsItem->text, text, 255); newsItem->text[254] = 0; // blatant disregard for what happens on the last element. @@ -338,9 +306,9 @@ void news_item_add_to_queue_raw(uint8 type, const utf8 *text, uint32 assoc) /** * Opens the window/tab for the subject of the news item * - * rct2: 0x0066EBE6 + * rct2: 0x0066EBE6 * - **/ + */ void news_item_open_subject(int type, int subject) { rct_peep* peep; @@ -378,7 +346,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(); } } diff --git a/src/management/research.c b/src/management/research.c index 83df0fd6a1..fe9de1bd54 100644 --- a/src/management/research.c +++ b/src/management/research.c @@ -19,9 +19,11 @@ *****************************************************************************/ #include "../addresses.h" +#include "../config.h" #include "../game.h" #include "../interface/window.h" #include "../localisation/date.h" +#include "../localisation/string_ids.h" #include "../management/finance.h" #include "../scenario.h" #include "../rct1.h" @@ -166,7 +168,7 @@ static void research_next_design() void research_finish_item(sint32 entryIndex) { int i, ebx, base_ride_type, rideEntryIndex, subSceneryEntryIndex; - rct_ride_type *rideEntry, *rideEntry2; + rct_ride_entry *rideEntry, *rideEntry2; rct_scenery_set_entry *scenerySetEntry; RCT2_GLOBAL(RCT2_ADDRESS_LAST_RESEARCHED_ITEM_SUBJECT, sint32) = entryIndex; @@ -175,8 +177,8 @@ void research_finish_item(sint32 entryIndex) // Ride base_ride_type = (entryIndex >> 8) & 0xFF; rideEntryIndex = entryIndex & 0xFF; - rideEntry = GET_RIDE_ENTRY(rideEntryIndex); - RCT2_ADDRESS(0x01357404, uint32)[base_ride_type >> 5] |= (1 << (base_ride_type & 0x1F)); + rideEntry = get_ride_entry(rideEntryIndex); + RCT2_ADDRESS(0x01357404, uint32)[base_ride_type >> 5] |= (1u << (base_ride_type & 0x1F)); RCT2_ADDRESS(0x01357444, uint32)[base_ride_type] = RCT2_ADDRESS(0x0097C468, uint32)[base_ride_type]; RCT2_ADDRESS(0x01357644, uint32)[base_ride_type] = RCT2_ADDRESS(0x0097C5D4, uint32)[base_ride_type]; if (RideData4[base_ride_type].flags & RIDE_TYPE_FLAG4_3) { @@ -184,17 +186,17 @@ void research_finish_item(sint32 entryIndex) RCT2_ADDRESS(0x01357444, uint32)[ebx] = RCT2_ADDRESS(0x0097C468, uint32)[ebx]; RCT2_ADDRESS(0x01357644, uint32)[ebx] = RCT2_ADDRESS(0x0097C5D4, uint32)[ebx]; } - RCT2_ADDRESS(0x001357424, uint32)[rideEntryIndex >> 5] |= 1 << (rideEntryIndex & 0x1F); + RCT2_ADDRESS(0x001357424, uint32)[rideEntryIndex >> 5] |= 1u << (rideEntryIndex & 0x1F); if (!(rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE)) { for (i = 0; i < 128; i++) { - rideEntry2 = GET_RIDE_ENTRY(i); - if (rideEntry2 == (rct_ride_type*)-1) + rideEntry2 = get_ride_entry(i); + if (rideEntry2 == (rct_ride_entry*)-1) continue; if ((rideEntry2->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE)) continue; if (rideEntry2->ride_type[0] == base_ride_type || rideEntry2->ride_type[1] == base_ride_type || rideEntry2->ride_type[2] == base_ride_type) - RCT2_ADDRESS(0x001357424, uint32)[i >> 5] |= 1 << (i & 0x1F); + RCT2_ADDRESS(0x001357424, uint32)[i >> 5] |= 1u << (i & 0x1F); } } @@ -202,8 +204,11 @@ void research_finish_item(sint32 entryIndex) if (RCT2_GLOBAL(0x009AC06C, uint8) == 0) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = ((rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME)) ? rideEntry->name : base_ride_type + 2; - if (!gSilentResearch) - news_item_add_to_queue(NEWS_ITEM_RESEARCH, 2249, entryIndex); + if (!gSilentResearch) { + if (gConfigNotifications.ride_researched) { + news_item_add_to_queue(NEWS_ITEM_RESEARCH, STR_NEWS_ITEM_RESEARCH_NEW_RIDE_AVAILABLE, entryIndex); + } + } } research_invalidate_related_windows(); @@ -212,14 +217,17 @@ void research_finish_item(sint32 entryIndex) scenerySetEntry = g_scenerySetEntries[entryIndex & 0xFFFF]; for (i = 0; i < scenerySetEntry->entry_count; i++) { subSceneryEntryIndex = scenerySetEntry->scenery_entries[i]; - RCT2_ADDRESS(0x01357BD0, sint32)[subSceneryEntryIndex >> 5] |= 1 << (subSceneryEntryIndex & 0x1F); + RCT2_ADDRESS(0x01357BD0, sint32)[subSceneryEntryIndex >> 5] |= 1u << (subSceneryEntryIndex & 0x1F); } // I don't think 0x009AC06C is ever not 0, so probably redundant if (RCT2_GLOBAL(0x009AC06C, uint8) == 0) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = scenerySetEntry->name; - if (!gSilentResearch) - news_item_add_to_queue(NEWS_ITEM_RESEARCH, 2250, entryIndex); + if (!gSilentResearch) { + if (gConfigNotifications.ride_researched) { + news_item_add_to_queue(NEWS_ITEM_RESEARCH, STR_NEWS_ITEM_RESEARCH_NEW_SCENERY_SET_AVAILABLE, entryIndex); + } + } } research_invalidate_related_windows(); @@ -320,7 +328,7 @@ void sub_684AC3(){ for (int j = 0; j < scenery_set->entry_count; ++j){ uint8 value = scenery_set->scenery_entries[j] & 0x1F; - RCT2_ADDRESS(0x01357BD0, uint32)[scenery_set->scenery_entries[j] >> 5] &= ~(1 << value); + RCT2_ADDRESS(0x01357BD0, uint32)[scenery_set->scenery_entries[j] >> 5] &= ~(1u << value); } } @@ -355,7 +363,7 @@ void research_remove_non_separate_vehicle_types() researchItem->entryIndex != RESEARCHED_ITEMS_END && researchItem->entryIndex >= 0x10000 ) { - rct_ride_type *rideEntry = GET_RIDE_ENTRY(researchItem->entryIndex & 0xFF); + rct_ride_entry *rideEntry = get_ride_entry(researchItem->entryIndex & 0xFF); if (!(rideEntry->flags & (RIDE_ENTRY_FLAG_SEPARATE_RIDE | RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME))) { // Check if ride type already exists further up for a vehicle type that isn't displayed as a ride researchItem2 = researchItem - 1; @@ -364,7 +372,7 @@ void research_remove_non_separate_vehicle_types() researchItem2->entryIndex != RESEARCHED_ITEMS_SEPARATOR && researchItem2->entryIndex >= 0x10000 ) { - rideEntry = GET_RIDE_ENTRY(researchItem2->entryIndex & 0xFF); + rideEntry = get_ride_entry(researchItem2->entryIndex & 0xFF); if (!(rideEntry->flags & (RIDE_ENTRY_FLAG_SEPARATE_RIDE | RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME))) { if (((researchItem->entryIndex >> 8) & 0xFF) == ((researchItem2->entryIndex >> 8) & 0xFF)) { @@ -441,7 +449,10 @@ static void research_insert_researched(int entryIndex, int category) } while (entryIndex != (researchItem++)->entryIndex); } -/* rct2: 0x006857CF */ +/** + * + * rct2: 0x006857CF + */ void research_remove(sint32 entryIndex){ for (rct_research_item *researchItem = gResearchItems; researchItem->entryIndex != RESEARCHED_ITEMS_END; researchItem++){ if (researchItem->entryIndex == entryIndex){ @@ -467,14 +478,14 @@ void research_insert(int researched, int entryIndex, int category) */ void research_populate_list_random() { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_scenery_set_entry *scenerySetEntry; int rideType, researched; // Rides for (int i = 0; i < 128; i++) { - rideEntry = GET_RIDE_ENTRY(i); - if (rideEntry == (rct_ride_type*)-1) + rideEntry = get_ride_entry(i); + if (rideEntry == (rct_ride_entry*)-1) continue; researched = (scenario_rand() & 0xFF) > 128; @@ -498,14 +509,14 @@ void research_populate_list_random() void research_populate_list_researched() { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_scenery_set_entry *scenerySetEntry; int rideType; // Rides for (int i = 0; i < 128; i++) { - rideEntry = GET_RIDE_ENTRY(i); - if (rideEntry == (rct_ride_type*)-1) + rideEntry = get_ride_entry(i); + if (rideEntry == (rct_ride_entry*)-1) continue; for (int j = 0; j < 3; j++) { @@ -548,8 +559,14 @@ void game_command_set_research_funding(int* eax, int* ebx, int* ecx, int* edx, i RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RESEARCH * 4; if (*ebx & GAME_COMMAND_FLAG_APPLY) { - if (!setPriorities) + if (!setPriorities) { + if (fundingAmount < 0 || fundingAmount >= countof(_researchRate)) { + *ebx = MONEY32_UNDEFINED; + log_warning("Invalid research rate %d", fundingAmount); + return; + } RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RESEARCH_LEVEL, uint8) = fundingAmount; + } else RCT2_GLOBAL(RCT2_ADDRESS_ACTIVE_RESEARCH_TYPES, uint8) = activeCategories; diff --git a/src/network/http.cpp b/src/network/http.cpp index 29392b73d6..abc2461eb1 100644 --- a/src/network/http.cpp +++ b/src/network/http.cpp @@ -10,13 +10,18 @@ void http_dispose() { } #else -#include +#include "../core/Math.hpp" +#include "../core/Path.hpp" +#include "../core/String.hpp" -// cURL includes windows.h, but we don't need all of it. -#define WIN32_LEAN_AND_MEAN +#ifdef __WINDOWS__ + // cURL includes windows.h, but we don't need all of it. + #define WIN32_LEAN_AND_MEAN +#endif #include #define MIME_TYPE_APPLICATION_JSON "application/json" +#define DEFAULT_CA_BUNDLE_PATH "curl-ca-bundle.crt" typedef struct { char *ptr; @@ -30,9 +35,22 @@ typedef struct { int capacity; } write_buffer; +#ifdef __WINDOWS__ +static utf8 _caBundlePath[MAX_PATH]; +#endif + void http_init() { curl_global_init(CURL_GLOBAL_DEFAULT); + +#ifdef __WINDOWS__ + // Find SSL certificate bundle + platform_get_exe_path(_caBundlePath); + Path::Append(_caBundlePath, sizeof(_caBundlePath), DEFAULT_CA_BUNDLE_PATH); + if (!platform_file_exists(_caBundlePath)) { + String::Set(_caBundlePath, sizeof(_caBundlePath), DEFAULT_CA_BUNDLE_PATH); + } +#endif } void http_dispose() @@ -65,7 +83,7 @@ static size_t http_request_write_func(void *ptr, size_t size, size_t nmemb, void int newCapacity = writeBuffer->capacity; int newLength = writeBuffer->length + newBytesLength; while (newLength > newCapacity) { - newCapacity = max(4096, newCapacity * 2); + newCapacity = Math::Max(4096, newCapacity * 2); } if (newCapacity != writeBuffer->capacity) { writeBuffer->ptr = (char*)realloc(writeBuffer->ptr, newCapacity); @@ -116,9 +134,9 @@ http_json_response *http_request_json(const http_json_request *request) curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true); -#ifndef __linux__ - // On GNU/Linux, curl will use the system certs by default - curl_easy_setopt(curl, CURLOPT_CAINFO, "curl-ca-bundle.crt"); +#ifdef __WINDOWS__ + // On GNU/Linux (and OS X), curl will use the system certs by default + curl_easy_setopt(curl, CURLOPT_CAINFO, _caBundlePath); #endif curl_easy_setopt(curl, CURLOPT_URL, request->url); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &writeBuffer); diff --git a/src/network/network.cpp b/src/network/network.cpp index 265da30a25..2a2df3039d 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -36,22 +36,26 @@ extern "C" { #include #include #include +#include "../core/Util.hpp" extern "C" { #include "../config.h" #include "../game.h" #include "../interface/chat.h" #include "../interface/window.h" +#include "../interface/keyboard_shortcut.h" #include "../localisation/date.h" #include "../localisation/localisation.h" #include "../network/http.h" #include "../scenario.h" #include "../windows/error.h" #include "../util/util.h" +#include "../cheats.h" } #pragma comment(lib, "Ws2_32.lib") Network gNetwork; +NetworkActions gNetworkActions; enum { NETWORK_READPACKET_SUCCESS, @@ -71,21 +75,13 @@ enum { NETWORK_COMMAND_PINGLIST, NETWORK_COMMAND_SETDISCONNECTMSG, NETWORK_COMMAND_GAMEINFO, + NETWORK_COMMAND_SHOWERROR, + NETWORK_COMMAND_GROUPLIST, + NETWORK_COMMAND_EVENT, NETWORK_COMMAND_MAX, NETWORK_COMMAND_INVALID = -1 }; -const char *NetworkCommandNames[] = { - "NETWORK_COMMAND_AUTH", - "NETWORK_COMMAND_MAP", - "NETWORK_COMMAND_CHAT", - "NETWORK_COMMAND_GAMECMD", - "NETWORK_COMMAND_TICK", - "NETWORK_COMMAND_PLAYERLIST", - "NETWORK_COMMAND_PING", - "NETWORK_COMMAND_PINGLIST", -}; - enum { ADVERTISE_STATUS_DISABLED, ADVERTISE_STATUS_UNREGISTERED, @@ -99,9 +95,16 @@ enum { MASTER_SERVER_STATUS_INTERNAL_ERROR = 500 }; +enum { + SERVER_EVENT_PLAYER_JOINED, + SERVER_EVENT_PLAYER_DISCONNECTED, +}; + constexpr int MASTER_SERVER_REGISTER_TIME = 120 * 1000; // 2 minutes constexpr int MASTER_SERVER_HEARTBEAT_TIME = 60 * 1000; // 1 minute +void network_chat_show_connected_message(); + NetworkPacket::NetworkPacket() { transferred = 0; @@ -164,7 +167,7 @@ const char* NetworkPacket::ReadString() strend++; } if (*strend != 0) { - return 0; + return nullptr; } read++; return str; @@ -189,12 +192,132 @@ bool NetworkPacket::CommandRequiresAuth() } } -NetworkPlayer::NetworkPlayer(const char* name) +void NetworkPlayer::Read(NetworkPacket& packet) { - safe_strncpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name)); + const char* name = packet.ReadString(); + SetName(name); + packet >> id >> flags >> group; +} + +void NetworkPlayer::Write(NetworkPacket& packet) +{ + packet.WriteString((const char*)name); + packet << id << flags << group; +} + +void NetworkPlayer::SetName(const char* name) +{ + safe_strcpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name)); NetworkPlayer::name[sizeof(NetworkPlayer::name) - 1] = 0; - ping = 0; - flags = 0; + utf8_remove_format_codes((utf8*)NetworkPlayer::name, false); +} + +void NetworkPlayer::AddMoneySpent(money32 cost) +{ + money_spent += cost; + commands_ran++; + window_invalidate_by_number(WC_PLAYER, id); +} + +int NetworkActions::FindCommand(int command) +{ + auto it = std::find_if(actions.begin(), actions.end(), [&command](NetworkAction const& action) { + for (auto it = action.commands.begin(); it != action.commands.end(); it++) { + if ((*it) == command) { + return true; + } + } + return false; + }); + if (it != actions.end()) { + return it - actions.begin(); + } + return -1; +} + +NetworkGroup::NetworkGroup() +{ + name_string_id = STR_NONE; + actions_allowed = {0}; +} + +NetworkGroup::~NetworkGroup() +{ + FreeNameStringId(); +} + +void NetworkGroup::Read(NetworkPacket& packet) +{ + packet >> id; + SetName(packet.ReadString()); + for (size_t i = 0; i < actions_allowed.size(); i++) { + packet >> actions_allowed[i]; + } +} + +void NetworkGroup::Write(NetworkPacket& packet) +{ + packet << id; + packet.WriteString(GetName().c_str()); + for (size_t i = 0; i < actions_allowed.size(); i++) { + packet << actions_allowed[i]; + } +} + +void NetworkGroup::FreeNameStringId() +{ + if (name_string_id != STR_NONE) { + user_string_free(name_string_id); + name_string_id = STR_NONE; + } +} + +void NetworkGroup::ToggleActionPermission(size_t index) +{ + size_t byte = index / 8; + size_t bit = index % 8; + if (byte >= actions_allowed.size()) { + return; + } + actions_allowed[byte] ^= (1 << bit); +} + +bool NetworkGroup::CanPerformAction(size_t index) +{ + size_t byte = index / 8; + size_t bit = index % 8; + if (byte >= actions_allowed.size()) { + return false; + } + return (actions_allowed[byte] & (1 << bit)) ? true : false; +} + +bool NetworkGroup::CanPerformCommand(int command) +{ + int action = gNetworkActions.FindCommand(command); + if (action != -1) { + return CanPerformAction(action); + } + return false; +} + +std::string& NetworkGroup::GetName() +{ + return name; +} + +void NetworkGroup::SetName(std::string name) +{ + FreeNameStringId(); + NetworkGroup::name = name; +} + +rct_string_id NetworkGroup::GetNameStringId() +{ + if (name_string_id == STR_NONE) { + name_string_id = user_string_allocate(128, name.c_str()); + } + return name_string_id; } NetworkConnection::NetworkConnection() @@ -211,6 +334,10 @@ NetworkConnection::~NetworkConnection() if (socket != INVALID_SOCKET) { closesocket(socket); } + + if (last_disconnect_reason) { + delete[] last_disconnect_reason; + } } int NetworkConnection::ReadPacket() @@ -305,7 +432,7 @@ bool NetworkConnection::SetNonBlocking(bool on) bool NetworkConnection::SetNonBlocking(SOCKET socket, bool on) { -#ifdef _WIN32 +#ifdef __WINDOWS__ u_long nonblocking = on; return ioctlsocket(socket, FIONBIO, &nonblocking) == 0; #else @@ -321,12 +448,43 @@ void NetworkConnection::ResetLastPacketTime() bool NetworkConnection::ReceivedPacketRecently() { +#ifndef DEBUG if (SDL_TICKS_PASSED(SDL_GetTicks(), last_packet_time + 7000)) { return false; } +#endif return true; } +const char* NetworkConnection::getLastDisconnectReason() const +{ + return this->last_disconnect_reason; +} + +void NetworkConnection::setLastDisconnectReason(const char *src) +{ + if (src == nullptr) { + if (last_disconnect_reason) { + delete[] last_disconnect_reason; + last_disconnect_reason = NULL; + } + return; + } + + if (!last_disconnect_reason) { + last_disconnect_reason = new char[NETWORK_DISCONNECT_REASON_BUFFER_SIZE]; + } + + strncpy(last_disconnect_reason, src, NETWORK_DISCONNECT_REASON_BUFFER_SIZE - 1); +} + +void NetworkConnection::setLastDisconnectReason(const rct_string_id string_id) +{ + char buffer[NETWORK_DISCONNECT_REASON_BUFFER_SIZE]; + format_string(buffer, string_id, NULL); + setLastDisconnectReason(buffer); +} + NetworkAddress::NetworkAddress() { ss = std::make_shared(); @@ -413,6 +571,9 @@ Network::Network() client_command_handlers[NETWORK_COMMAND_PING] = &Network::Client_Handle_PING; client_command_handlers[NETWORK_COMMAND_PINGLIST] = &Network::Client_Handle_PINGLIST; client_command_handlers[NETWORK_COMMAND_SETDISCONNECTMSG] = &Network::Client_Handle_SETDISCONNECTMSG; + client_command_handlers[NETWORK_COMMAND_SHOWERROR] = &Network::Client_Handle_SHOWERROR; + client_command_handlers[NETWORK_COMMAND_GROUPLIST] = &Network::Client_Handle_GROUPLIST; + client_command_handlers[NETWORK_COMMAND_EVENT] = &Network::Client_Handle_EVENT; server_command_handlers.resize(NETWORK_COMMAND_MAX, 0); server_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Server_Handle_AUTH; server_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Server_Handle_CHAT; @@ -428,7 +589,7 @@ Network::~Network() bool Network::Init() { -#ifdef _WIN32 +#ifdef __WINDOWS__ if (!wsa_initialized) { log_verbose("Initialising WSA"); WSADATA wsa_data; @@ -439,6 +600,7 @@ bool Network::Init() wsa_initialized = true; } #endif + status = NETWORK_STATUS_READY; return true; } @@ -461,13 +623,15 @@ void Network::Close() mode = NETWORK_MODE_NONE; status = NETWORK_STATUS_NONE; server_connection.authstatus = NETWORK_AUTH_NONE; - server_connection.last_disconnect_reason = NULL; + + server_connection.setLastDisconnectReason(nullptr); client_connection_list.clear(); game_command_queue.clear(); player_list.clear(); + group_list.clear(); -#ifdef _WIN32 +#ifdef __WINDOWS__ if (wsa_initialized) { WSACleanup(); wsa_initialized = false; @@ -490,7 +654,11 @@ bool Network::BeginClient(const char* host, unsigned short port) server_address.Resolve(host, port); status = NETWORK_STATUS_RESOLVING; - window_network_status_open("Resolving..."); + char str_resolving[256]; + format_string(str_resolving, STR_MULTIPLAYER_RESOLVING, NULL); + window_network_status_open(str_resolving, []() -> void { + gNetwork.Close(); + }); mode = NETWORK_MODE_CLIENT; @@ -537,11 +705,17 @@ bool Network::BeginServer(unsigned short port, const char* address) return false; } - NetworkPlayer* player = AddPlayer(gConfigNetwork.player_name); + cheats_reset(); + LoadGroups(); + + NetworkPlayer* player = AddPlayer(); + player->SetName(gConfigNetwork.player_name); player->flags |= NETWORK_PLAYER_FLAG_ISSERVER; + player->group = 0; player_id = player->id; printf("Ready for clients...\n"); + network_chat_show_connected_message(); mode = NETWORK_MODE_SERVER; status = NETWORK_STATUS_CONNECTED; @@ -672,7 +846,11 @@ void Network::UpdateClient() } if (connect(server_connection.socket, (sockaddr *)&(*server_address.ss), (*server_address.ss_len)) == SOCKET_ERROR && (LAST_SOCKET_ERROR() == EINPROGRESS || LAST_SOCKET_ERROR() == EWOULDBLOCK)){ - window_network_status_open("Connecting..."); + char str_connecting[256]; + format_string(str_connecting, STR_MULTIPLAYER_CONNECTING, NULL); + window_network_status_open(str_connecting, []() -> void { + gNetwork.Close(); + }); server_connect_time = SDL_GetTicks(); status = NETWORK_STATUS_CONNECTING; } else { @@ -680,6 +858,8 @@ void Network::UpdateClient() connectfailed = true; break; } + } else if (server_address.GetResolveStatus() == NetworkAddress::RESOLVE_INPROGRESS) { + break; } else { log_error("Could not resolve address."); connectfailed = true; @@ -721,21 +901,29 @@ void Network::UpdateClient() status = NETWORK_STATUS_CONNECTED; server_connection.ResetLastPacketTime(); Client_Send_AUTH(gConfigNetwork.player_name, ""); - window_network_status_open("Authenticating..."); + char str_authenticating[256]; + format_string(str_authenticating, STR_MULTIPLAYER_AUTHENTICATING, NULL); + window_network_status_open(str_authenticating, []() -> void { + gNetwork.Close(); + }); } } }break; case NETWORK_STATUS_CONNECTED: if (!ProcessConnection(server_connection)) { - std::string errormsg = "Disconnected"; - if (server_connection.last_disconnect_reason) { - errormsg += ": "; - errormsg += server_connection.last_disconnect_reason; - } if (server_connection.authstatus == NETWORK_AUTH_REQUIREPASSWORD) { // Do not show disconnect message window when password window closed/canceled window_network_status_close(); } else { - window_network_status_open(errormsg.c_str()); + char str_disconnected[256]; + + if (server_connection.getLastDisconnectReason()) { + const char * disconnect_reason = server_connection.getLastDisconnectReason(); + format_string(str_disconnected, STR_MULTIPLAYER_DISCONNECTED_WITH_REASON, &disconnect_reason); + } else { + format_string(str_disconnected, STR_MULTIPLAYER_DISCONNECTED_NO_REASON, NULL); + } + + window_network_status_open(str_disconnected, NULL); } Close(); } @@ -744,7 +932,9 @@ void Network::UpdateClient() // Check synchronisation if (!_desynchronised && !CheckSRAND(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32), RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32))) { _desynchronised = true; - window_network_status_open("Network desync detected"); + char str_desync[256]; + format_string(str_desync, STR_MULTIPLAYER_DESYNC, NULL); + window_network_status_open(str_desync, NULL); if (!gConfigNetwork.stay_connected) { Close(); } @@ -759,12 +949,40 @@ void Network::UpdateClient() } } -NetworkPlayer* Network::GetPlayerByID(int id) { +std::vector>::iterator Network::GetPlayerIteratorByID(uint8 id) +{ auto it = std::find_if(player_list.begin(), player_list.end(), [&id](std::unique_ptr const& player) { return player->id == id; }); if (it != player_list.end()) { - return (*it).get(); + return it; } - return 0; + return player_list.end(); +} + +NetworkPlayer* Network::GetPlayerByID(uint8 id) +{ + auto it = GetPlayerIteratorByID(id); + if (it != player_list.end()) { + return it->get(); + } + return nullptr; +} + +std::vector>::iterator Network::GetGroupIteratorByID(uint8 id) +{ + auto it = std::find_if(group_list.begin(), group_list.end(), [&id](std::unique_ptr const& group) { return group->id == id; }); + if (it != group_list.end()) { + return it; + } + return group_list.end(); +} + +NetworkGroup* Network::GetGroupByID(uint8 id) +{ + auto it = GetGroupIteratorByID(id); + if (it != group_list.end()) { + return it->get(); + } + return nullptr; } const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text) @@ -775,13 +993,15 @@ const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text) if (fromplayer) { lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); - safe_strncpy(lineCh, (const char*)fromplayer->name, sizeof(fromplayer->name)); + safe_strcpy(lineCh, (const char*)fromplayer->name, sizeof(fromplayer->name)); strcat(lineCh, ": "); lineCh = strchr(lineCh, '\0'); } lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); lineCh = utf8_write_codepoint(lineCh, FORMAT_WHITE); - safe_strncpy(lineCh, text, 800); + char* ptrtext = lineCh; + safe_strcpy(lineCh, text, 800); + utf8_remove_format_codes((utf8*)ptrtext, true); return formatted; } @@ -817,8 +1037,10 @@ void Network::KickPlayer(int playerId) for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) { if ((*it)->player->id == playerId) { // Disconnect the client gracefully - (*it)->last_disconnect_reason = "Kicked"; - Server_Send_SETDISCONNECTMSG(*(*it), "Get out of the server!"); + (*it)->setLastDisconnectReason(STR_MULTIPLAYER_KICKED); + char str_disconnect_msg[256]; + format_string(str_disconnect_msg, STR_MULTIPLAYER_KICKED_REASON, NULL); + Server_Send_SETDISCONNECTMSG(*(*it), str_disconnect_msg); shutdown((*it)->socket, SHUT_RD); (*it)->SendQueuedPackets(); break; @@ -844,10 +1066,10 @@ std::string Network::GenerateAdvertiseKey() static char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; char key[17]; for (int i = 0; i < 16; i++) { - int hexCharIndex = util_rand() % countof(hexChars); + int hexCharIndex = util_rand() % Util::CountOf(hexChars); key[i] = hexChars[hexCharIndex]; } - key[countof(key) - 1] = 0; + key[Util::CountOf(key) - 1] = 0; return key; } @@ -920,7 +1142,7 @@ void Network::AdvertiseHeartbeat() json_object_set_new(body, "players", json_integer(network_get_num_players())); json_t *gameInfo = json_object(); - json_object_set_new(gameInfo, "mapSize", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint8) - 2)); + json_object_set_new(gameInfo, "mapSize", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_MINUS_2, sint16))); json_object_set_new(gameInfo, "day", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16))); json_object_set_new(gameInfo, "month", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16))); json_object_set_new(gameInfo, "guests", json_integer(RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16))); @@ -957,11 +1179,141 @@ void Network::AdvertiseHeartbeat() #endif } +NetworkGroup* Network::AddGroup() +{ + NetworkGroup* addedgroup = nullptr; + int newid = -1; + // Find first unused group id + for (int id = 0; id < 255; id++) { + if (std::find_if(group_list.begin(), group_list.end(), [&id](std::unique_ptr const& group) { return group->id == id; }) == group_list.end()) { + newid = id; + break; + } + } + if (newid != -1) { + std::unique_ptr group(new NetworkGroup); // change to make_unique in c++14 + group->id = newid; + group->SetName("Group #" + std::to_string(newid)); + addedgroup = group.get(); + group_list.push_back(std::move(group)); + } + return addedgroup; +} + +void Network::RemoveGroup(uint8 id) +{ + auto group = GetGroupIteratorByID(id); + if (group != group_list.end()) { + group_list.erase(group); + } +} + +uint8 Network::GetDefaultGroup() +{ + return default_group; +} + +void Network::SetDefaultGroup(uint8 id) +{ + if (GetGroupByID(id)) { + default_group = id; + } +} + +void Network::SaveGroups() +{ + if (GetMode() == NETWORK_MODE_SERVER) { + utf8 path[MAX_PATH]; + SDL_RWops *file; + + platform_get_user_directory(path, NULL); + strcat(path, "groups.cfg"); + + file = SDL_RWFromFile(path, "wb"); + if (file == NULL) { + return; + } + + std::unique_ptr stream = std::move(NetworkPacket::Allocate()); + *stream << (uint8)group_list.size(); + *stream << default_group; + for (auto it = group_list.begin(); it != group_list.end(); it++) { + (*it)->Write(*stream); + } + + SDL_RWwrite(file, stream->GetData(), stream->data->size(), 1); + + SDL_RWclose(file); + } +} + +void Network::LoadGroups() +{ + group_list.clear(); + + utf8 path[MAX_PATH]; + SDL_RWops *file; + + platform_get_user_directory(path, NULL); + strcat(path, "groups.cfg"); + + file = SDL_RWFromFile(path, "rb"); + if (file == NULL) { + // Hardcoded permission groups + std::unique_ptr admin(new NetworkGroup()); // change to make_unique in c++14 + admin->SetName("Admin"); + admin->actions_allowed.fill(0xFF); + admin->id = 0; + group_list.push_back(std::move(admin)); + std::unique_ptr spectator(new NetworkGroup()); // change to make_unique in c++14 + spectator->SetName("Spectator"); + spectator->ToggleActionPermission(0); // Chat + spectator->id = 1; + group_list.push_back(std::move(spectator)); + std::unique_ptr user(new NetworkGroup()); // change to make_unique in c++14 + user->SetName("User"); + user->actions_allowed.fill(0xFF); + user->ToggleActionPermission(15); // Kick Player + user->ToggleActionPermission(16); // Modify Groups + user->ToggleActionPermission(17); // Set Player Group + user->ToggleActionPermission(18); // Cheat + user->id = 2; + group_list.push_back(std::move(user)); + SetDefaultGroup(1); + return; + } + + std::unique_ptr stream = std::move(NetworkPacket::Allocate()); + uint8 byte; + while(SDL_RWread(file, &byte, sizeof(byte), 1)){ + *stream << byte; + } + stream->size = (uint16)stream->data->size(); + + uint8 num; + *stream >> num >> default_group; + for (unsigned int i = 0; i < num; i++) { + NetworkGroup group; + group.Read(*stream); + std::unique_ptr newgroup(new NetworkGroup(group)); // change to make_unique in c++14 + group_list.push_back(std::move(newgroup)); + } + + SDL_RWclose(file); +} + +void Network::FreeStringIds() +{ + for (auto it = group_list.begin(); it != group_list.end(); it++) { + (*it)->FreeNameStringId(); + } +} + void Network::Client_Send_AUTH(const char* name, const char* password) { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); *packet << (uint32)NETWORK_COMMAND_AUTH; - packet->WriteString(OPENRCT2_VERSION); + packet->WriteString(NETWORK_STREAM_ID); packet->WriteString(name); packet->WriteString(password); server_connection.authstatus = NETWORK_AUTH_REQUESTED; @@ -985,23 +1337,55 @@ void Network::Server_Send_AUTH(NetworkConnection& connection) void Network::Server_Send_MAP(NetworkConnection* connection) { - int buffersize = 0x600000; - std::vector buffer(buffersize); - SDL_RWops* rw = SDL_RWFromMem(&buffer[0], buffersize); + bool RLEState = gUseRLE; + gUseRLE = false; + FILE* temp = tmpfile(); + if (!temp) { + log_warning("Failed to create temporary file to save map."); + return; + } + SDL_RWops* rw = SDL_RWFromFP(temp, SDL_TRUE); scenario_save_network(rw); + gUseRLE = RLEState; int size = (int)SDL_RWtell(rw); - int chunksize = 1000; - for (int i = 0; i < size; i += chunksize) { - int datasize = (std::min)(chunksize, size - i); + std::vector buffer(size); + SDL_RWseek(rw, 0, RW_SEEK_SET); + if (SDL_RWread(rw, &buffer[0], size, 1) == 0) { + log_warning("Failed to read temporary map file into memory."); + SDL_RWclose(rw); + return; + } + size_t chunksize = 1000; + size_t out_size = size; + unsigned char *compressed = util_zlib_deflate(&buffer[0], size, &out_size); + unsigned char *header; + if (compressed != NULL) + { + header = (unsigned char *)_strdup("open2_sv6_zlib"); + size_t header_len = strlen((char *)header) + 1; // account for null terminator + header = (unsigned char *)realloc(header, header_len + out_size); + memcpy(&header[header_len], compressed, out_size); + out_size += header_len; + free(compressed); + log_verbose("Sending map of size %u bytes, compressed to %u bytes", size, out_size); + } else { + log_warning("Failed to compress the data, falling back to non-compressed sv6."); + header = (unsigned char *)malloc(size); + out_size = size; + memcpy(header, &buffer[0], size); + } + for (size_t i = 0; i < out_size; i += chunksize) { + int datasize = (std::min)(chunksize, out_size - i); std::unique_ptr packet = std::move(NetworkPacket::Allocate()); - *packet << (uint32)NETWORK_COMMAND_MAP << (uint32)size << (uint32)i; - packet->Write(&buffer[i], datasize); + *packet << (uint32)NETWORK_COMMAND_MAP << (uint32)out_size << (uint32)i; + packet->Write(&header[i], datasize); if (connection) { connection->QueuePacket(std::move(packet)); } else { SendPacketToClients(*packet); } } + free(header); SDL_RWclose(rw); } @@ -1046,10 +1430,9 @@ void Network::Server_Send_TICK() void Network::Server_Send_PLAYERLIST() { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); - *packet << (uint32)NETWORK_COMMAND_PLAYERLIST << (uint32)player_list.size(); + *packet << (uint32)NETWORK_COMMAND_PLAYERLIST << (uint8)player_list.size(); for (unsigned int i = 0; i < player_list.size(); i++) { - packet->WriteString((const char*)player_list[i]->name); - *packet << player_list[i]->id << player_list[i]->flags; + player_list[i]->Write(*packet); } SendPacketToClients(*packet); } @@ -1075,7 +1458,7 @@ void Network::Server_Send_PING() void Network::Server_Send_PINGLIST() { std::unique_ptr packet = std::move(NetworkPacket::Allocate()); - *packet << (uint32)NETWORK_COMMAND_PINGLIST << (uint32)player_list.size(); + *packet << (uint32)NETWORK_COMMAND_PINGLIST << (uint8)player_list.size(); for (unsigned int i = 0; i < player_list.size(); i++) { *packet << player_list[i]->id << player_list[i]->ping; } @@ -1098,7 +1481,7 @@ void Network::Server_Send_GAMEINFO(NetworkConnection& connection) json_t* obj = json_object(); json_object_set_new(obj, "name", json_string(gConfigNetwork.server_name)); json_object_set_new(obj, "requiresPassword", json_boolean(password.size() > 0)); - json_object_set_new(obj, "version", json_string(OPENRCT2_VERSION)); + json_object_set_new(obj, "version", json_string(NETWORK_STREAM_ID)); json_object_set_new(obj, "players", json_integer(player_list.size())); json_object_set_new(obj, "maxPlayers", json_integer(gConfigNetwork.maxplayers)); json_object_set_new(obj, "description", json_string(gConfigNetwork.server_description)); @@ -1117,6 +1500,42 @@ void Network::Server_Send_GAMEINFO(NetworkConnection& connection) connection.QueuePacket(std::move(packet)); } +void Network::Server_Send_SHOWERROR(NetworkConnection& connection, rct_string_id title, rct_string_id message) +{ + std::unique_ptr packet = std::move(NetworkPacket::Allocate()); + *packet << (uint32)NETWORK_COMMAND_SHOWERROR << title << message; + connection.QueuePacket(std::move(packet)); +} + +void Network::Server_Send_GROUPLIST(NetworkConnection& connection) +{ + std::unique_ptr packet = std::move(NetworkPacket::Allocate()); + *packet << (uint32)NETWORK_COMMAND_GROUPLIST << (uint8)group_list.size() << default_group; + for (unsigned int i = 0; i < group_list.size(); i++) { + group_list[i]->Write(*packet); + } + connection.QueuePacket(std::move(packet)); +} + +void Network::Server_Send_EVENT_PLAYER_JOINED(const char *playerName) +{ + std::unique_ptr packet = std::move(NetworkPacket::Allocate()); + *packet << (uint32)NETWORK_COMMAND_EVENT; + *packet << (uint16)SERVER_EVENT_PLAYER_JOINED; + packet->WriteString(playerName); + SendPacketToClients(*packet); +} + +void Network::Server_Send_EVENT_PLAYER_DISCONNECTED(const char *playerName, const char *reason) +{ + std::unique_ptr packet = std::move(NetworkPacket::Allocate()); + *packet << (uint32)NETWORK_COMMAND_EVENT; + *packet << (uint16)SERVER_EVENT_PLAYER_DISCONNECTED; + packet->WriteString(playerName); + packet->WriteString(reason); + SendPacketToClients(*packet); +} + bool Network::ProcessConnection(NetworkConnection& connection) { int packetStatus; @@ -1125,8 +1544,8 @@ bool Network::ProcessConnection(NetworkConnection& connection) switch(packetStatus) { case NETWORK_READPACKET_DISCONNECTED: // closed connection or network error - if (!connection.last_disconnect_reason) { - connection.last_disconnect_reason = "Connection Closed"; + if (!connection.getLastDisconnectReason()) { + connection.setLastDisconnectReason(STR_MULTIPLAYER_CONNECTION_CLOSED); } return false; break; @@ -1144,8 +1563,8 @@ bool Network::ProcessConnection(NetworkConnection& connection) } while (packetStatus == NETWORK_READPACKET_MORE_DATA || packetStatus == NETWORK_READPACKET_SUCCESS); connection.SendQueuedPackets(); if (!connection.ReceivedPacketRecently()) { - if (!connection.last_disconnect_reason) { - connection.last_disconnect_reason = "No Data"; + if (!connection.getLastDisconnectReason()) { + connection.setLastDisconnectReason(STR_MULTIPLAYER_NO_DATA); } return false; } @@ -1157,7 +1576,6 @@ void Network::ProcessPacket(NetworkConnection& connection, NetworkPacket& packet uint32 command; packet >> command; if (command < NETWORK_COMMAND_MAX) { - // printf("RECV %s\n", NetworkCommandNames[command]); switch (gNetwork.GetMode()) { case NETWORK_MODE_SERVER: if (server_command_handlers[command]) { @@ -1184,7 +1602,17 @@ void Network::ProcessGameCommandQueue() if (GetPlayerID() == gc.playerid) { game_command_callback = game_command_callback_get_callback(gc.callback); } - game_do_command_p(gc.esi, (int*)&gc.eax, (int*)&gc.ebx, (int*)&gc.ecx, (int*)&gc.edx, (int*)&gc.esi, (int*)&gc.edi, (int*)&gc.ebp); + game_command_playerid = gc.playerid; + int command = gc.esi; + money32 cost = game_do_command_p(command, (int*)&gc.eax, (int*)&gc.ebx, (int*)&gc.ecx, (int*)&gc.edx, (int*)&gc.esi, (int*)&gc.edi, (int*)&gc.ebp); + if (cost != MONEY32_UNDEFINED) { + NetworkPlayer* player = GetPlayerByID(gc.playerid); + if (player) { + player->last_action = gNetworkActions.FindCommand(command); + player->last_action_time = SDL_GetTicks(); + player->AddMoneySpent(cost); + } + } game_command_queue.erase(game_command_queue.begin()); } } @@ -1202,26 +1630,27 @@ void Network::RemoveClient(std::unique_ptr& connection) NetworkPlayer* connection_player = connection->player; if (connection_player) { char text[256]; - char* lineCh = text; - lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); - lineCh = utf8_write_codepoint(lineCh, FORMAT_RED); - char reasonstr[100]; - reasonstr[0] = 0; - if (connection->last_disconnect_reason && strlen(connection->last_disconnect_reason) < sizeof(reasonstr)) { - sprintf(reasonstr, " (%s)", connection->last_disconnect_reason); + const char * has_disconnected_args[2] = { + (char *) connection_player->name, + connection->getLastDisconnectReason() + }; + if (has_disconnected_args[1]) { + format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_WITH_REASON, has_disconnected_args); + } else { + format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_NO_REASON, &(has_disconnected_args[0])); } - sprintf(lineCh, "%s has disconnected%s", connection_player->name, reasonstr); + chat_history_add(text); - gNetwork.Server_Send_CHAT(text); + gNetwork.Server_Send_EVENT_PLAYER_DISCONNECTED((char*)connection_player->name, connection->getLastDisconnectReason()); } player_list.erase(std::remove_if(player_list.begin(), player_list.end(), [connection_player](std::unique_ptr& player){ return player.get() == connection_player; }), player_list.end()); client_connection_list.remove(connection); Server_Send_PLAYERLIST(); } -NetworkPlayer* Network::AddPlayer(const char* name) +NetworkPlayer* Network::AddPlayer() { - NetworkPlayer* addedplayer = 0; + NetworkPlayer* addedplayer = nullptr; int newid = -1; if (GetMode() == NETWORK_MODE_SERVER) { // Find first unused player id @@ -1235,20 +1664,18 @@ NetworkPlayer* Network::AddPlayer(const char* name) newid = 0; } if (newid != -1) { - std::unique_ptr player(new NetworkPlayer(name)); // change to make_unique in c++14 + std::unique_ptr player(new NetworkPlayer); // change to make_unique in c++14 player->id = newid; + player->group = GetDefaultGroup(); addedplayer = player.get(); player_list.push_back(std::move(player)); - if (GetMode() == NETWORK_MODE_SERVER) { - Server_Send_PLAYERLIST(); - } } return addedplayer; } void Network::PrintError() { -#ifdef _WIN32 +#ifdef __WINDOWS__ wchar_t *s = NULL; FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, LAST_SOCKET_ERROR(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&s, 0, NULL); fprintf(stderr, "%S\n", s); @@ -1260,40 +1687,39 @@ void Network::PrintError() } -int Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) { packet >> (uint32&)connection.authstatus >> (uint8&)player_id; switch(connection.authstatus) { case NETWORK_AUTH_BADNAME: - connection.last_disconnect_reason = "Bad Player Name"; + connection.setLastDisconnectReason(STR_MULTIPLAYER_BAD_PLAYER_NAME); shutdown(connection.socket, SHUT_RDWR); break; case NETWORK_AUTH_BADVERSION: - connection.last_disconnect_reason = "Incorrect Software Version"; + connection.setLastDisconnectReason(STR_MULTIPLAYER_INCORRECT_SOFTWARE_VERSION); shutdown(connection.socket, SHUT_RDWR); break; case NETWORK_AUTH_BADPASSWORD: - connection.last_disconnect_reason = "Bad Password"; + connection.setLastDisconnectReason(STR_MULTIPLAYER_BAD_PASSWORD); shutdown(connection.socket, SHUT_RDWR); break; case NETWORK_AUTH_FULL: - connection.last_disconnect_reason = "Server Full"; + connection.setLastDisconnectReason(STR_MULTIPLAYER_SERVER_FULL); shutdown(connection.socket, SHUT_RDWR); break; case NETWORK_AUTH_REQUIREPASSWORD: window_network_status_open_password(); break; } - return 1; } -int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet) { if (connection.authstatus != NETWORK_AUTH_OK) { const char* gameversion = packet.ReadString(); const char* name = packet.ReadString(); const char* password = packet.ReadString(); - if (!gameversion || strcmp(gameversion, OPENRCT2_VERSION) != 0) { + if (!gameversion || strcmp(gameversion, NETWORK_STREAM_ID) != 0) { connection.authstatus = NETWORK_AUTH_BADVERSION; } else if (!name) { @@ -1309,82 +1735,112 @@ int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa connection.authstatus = NETWORK_AUTH_FULL; } else { connection.authstatus = NETWORK_AUTH_OK; - NetworkPlayer* player = AddPlayer(name); + NetworkPlayer* player = AddPlayer(); connection.player = player; if (player) { + player->SetName(name); char text[256]; - char* lineCh = text; - lineCh = utf8_write_codepoint(lineCh, FORMAT_OUTLINE); - lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); - sprintf(lineCh, "%s has joined the game", player->name); + const char * player_name = (const char *) player->name; + format_string(text, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &player_name); chat_history_add(text); - gNetwork.Server_Send_CHAT(text); Server_Send_MAP(&connection); + gNetwork.Server_Send_EVENT_PLAYER_JOINED(player_name); + Server_Send_GROUPLIST(connection); + Server_Send_PLAYERLIST(); } } Server_Send_AUTH(connection); } - return 1; } -int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet) { uint32 size, offset; packet >> size >> offset; - if (offset > 0x600000) { - // too big - return 0; - } else { - int chunksize = packet.size - packet.read; - if (chunksize <= 0) { - return 0; - } - if (offset + chunksize > chunk_buffer.size()) { - chunk_buffer.resize(offset + chunksize); - } - char status[256]; - sprintf(status, "Downloading map ... (%lu / %lu)", (offset + chunksize) / 1000, size / 1000); - window_network_status_open(status); - memcpy(&chunk_buffer[offset], (void*)packet.Read(chunksize), chunksize); - if (offset + chunksize == size) { - window_network_status_close(); - - SDL_RWops* rw = SDL_RWFromMem(&chunk_buffer[0], size); - if (game_load_network(rw)) { - game_load_init(); - game_command_queue.clear(); - server_tick = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32); - server_srand0_tick = 0; - // window_network_status_open("Loaded new map from network"); - _desynchronised = false; + int chunksize = packet.size - packet.read; + if (chunksize <= 0) { + return; + } + if (offset + chunksize > chunk_buffer.size()) { + chunk_buffer.resize(offset + chunksize); + } + char str_downloading_map[256]; + unsigned int downloading_map_args[2] = {(offset + chunksize) / 1000, size / 1000}; + format_string(str_downloading_map, STR_MULTIPLAYER_DOWNLOADING_MAP, downloading_map_args); + window_network_status_open(str_downloading_map, []() -> void { + gNetwork.Close(); + }); + memcpy(&chunk_buffer[offset], (void*)packet.Read(chunksize), chunksize); + if (offset + chunksize == size) { + window_network_status_close(); + bool has_to_free = false; + unsigned char *data = &chunk_buffer[0]; + size_t data_size = size; + // zlib-compressed + if (strcmp("open2_sv6_zlib", (char *)&chunk_buffer[0]) == 0) + { + log_verbose("Received zlib-compressed sv6 map"); + has_to_free = true; + size_t header_len = strlen("open2_sv6_zlib") + 1; + data = util_zlib_inflate(&chunk_buffer[header_len], size - header_len, &data_size); + if (data == NULL) + { + log_warning("Failed to decompress data sent from server."); + return; } - SDL_RWclose(rw); + } else { + log_verbose("Assuming received map is in plain sv6 format"); + } + SDL_RWops* rw = SDL_RWFromMem(data, data_size); + if (game_load_network(rw)) { + game_load_init(); + game_command_queue.clear(); + server_tick = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32); + server_srand0_tick = 0; + // window_network_status_open("Loaded new map from network"); + _desynchronised = false; + + // Notify user he is now online and which shortcut key enables chat + network_chat_show_connected_message(); + } + else + { + //Something went wrong, game is not loaded. Return to main screen. + game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 1, 0); + } + SDL_RWclose(rw); + if (has_to_free) + { + free(data); } } - return 1; } -int Network::Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) { const char* text = packet.ReadString(); if (text) { chat_history_add(text); } - return 1; } -int Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet) { + if (connection.player) { + NetworkGroup* group = GetGroupByID(connection.player->group); + if (!group || (group && !group->CanPerformCommand(-1))) { + return; + } + } const char* text = packet.ReadString(); if (text) { const char* formatted = FormatChat(connection.player, text); chat_history_add(formatted); Server_Send_CHAT(formatted); } - return 1; } -int Network::Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) { uint32 tick; uint32 args[7]; @@ -1394,34 +1850,66 @@ int Network::Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& GameCommand gc = GameCommand(tick, args, playerid, callback); game_command_queue.insert(gc); - return 1; } -int Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet) { uint32 tick; uint32 args[7]; uint8 playerid; uint8 callback; - if (connection.player) { - playerid = connection.player->id; + + if (!connection.player) { + return; } + + playerid = connection.player->id; + packet >> tick >> args[0] >> args[1] >> args[2] >> args[3] >> args[4] >> args[5] >> args[6] >> callback; int commandCommand = args[4]; + int ticks = SDL_GetTicks(); //tick count is different by time last_action_time is set, keep same value. + + // Check if player's group permission allows command to run + NetworkGroup* group = GetGroupByID(connection.player->group); + if (!group || (group && !group->CanPerformCommand(commandCommand))) { + Server_Send_SHOWERROR(connection, STR_CANT_DO_THIS, STR_PERMISSION_DENIED); + return; + } + // Incase someone modifies the code / memory to enable cluster build, + // require a small delay in between placing scenery to provide some security, as + // cluster mode is a for loop that runs the place_scenery code multiple times. + if (commandCommand == GAME_COMMAND_PLACE_SCENERY) { + if ((ticks - connection.player->last_action_time) < 20) { + if (!(group->CanPerformCommand(-2))) { + Server_Send_SHOWERROR(connection, STR_CANT_DO_THIS, STR_CANT_DO_THIS); + return; + } + } + } // Don't let clients send pause or quit - if (commandCommand != GAME_COMMAND_TOGGLE_PAUSE && - commandCommand != GAME_COMMAND_LOAD_OR_QUIT + if (commandCommand == GAME_COMMAND_TOGGLE_PAUSE || + commandCommand == GAME_COMMAND_LOAD_OR_QUIT ) { - Server_Send_GAMECMD(args[0], args[1], args[2], args[3], args[4], args[5], args[6], playerid, callback); - game_do_command(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); + return; } - return 1; + // Set this to reference inside of game command functions + game_command_playerid = playerid; + // Run game command, and if it is successful send to clients + money32 cost = game_do_command(args[0], args[1] | GAME_COMMAND_FLAG_NETWORKED, args[2], args[3], args[4], args[5], args[6]); + if (cost == MONEY32_UNDEFINED) { + return; + } + + connection.player->last_action = gNetworkActions.FindCommand(commandCommand); + connection.player->last_action_time = SDL_GetTicks(); + connection.player->AddMoneySpent(cost); + Server_Send_GAMECMD(args[0], args[1], args[2], args[3], args[4], args[5], args[6], playerid, callback); } -int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet) { uint32 srand0; packet >> server_tick >> srand0; @@ -1429,34 +1917,44 @@ int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& pa server_srand0 = srand0; server_srand0_tick = server_tick; } - return 1; } -int Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet) { - player_list.clear(); - uint32 size; + uint8 size; packet >> size; + std::vector ids; for (unsigned int i = 0; i < size; i++) { - const char* name = packet.ReadString(); - NetworkPlayer* player = AddPlayer(name); - if (player) { - packet >> player->id >> player->flags; - if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { - server_connection.player = player; + NetworkPlayer tempplayer; + tempplayer.Read(packet); + ids.push_back(tempplayer.id); + if (!GetPlayerByID(tempplayer.id)) { + NetworkPlayer* player = AddPlayer(); + if (player) { + *player = tempplayer; + if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { + server_connection.player = player; + } } } } - return 1; + // Remove any players that are not in newly received list + auto it = player_list.begin(); + while (it != player_list.end()) { + if (std::find(ids.begin(), ids.end(), (*it)->id) == ids.end()) { + it = player_list.erase(it); + } else { + it++; + } + } } -int Network::Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) { Client_Send_PING(); - return 1; } -int Network::Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet) { int ping = SDL_GetTicks() - connection.ping_time; if (ping < 0) { @@ -1464,13 +1962,13 @@ int Network::Server_Handle_PING(NetworkConnection& connection, NetworkPacket& pa } if (connection.player) { connection.player->ping = ping; + window_invalidate_by_number(WC_PLAYER, connection.player->id); } - return 1; } -int Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet) { - uint32 size; + uint8 size; packet >> size; for (unsigned int i = 0; i < size; i++) { uint8 id; @@ -1481,24 +1979,72 @@ int Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket player->ping = ping; } } - return 1; + window_invalidate_by_class(WC_PLAYER); } -int Network::Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet) +void Network::Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet) { static std::string msg; const char* disconnectmsg = packet.ReadString(); if (disconnectmsg) { msg = disconnectmsg; - connection.last_disconnect_reason = msg.c_str(); + connection.setLastDisconnectReason(msg.c_str()); } - return 1; } -int Network::Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet) +void Network::Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet) { Server_Send_GAMEINFO(connection); - return 1; +} + +void Network::Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet) +{ + rct_string_id title, message; + packet >> title >> message; + window_error_open(title, message); +} + +void Network::Client_Handle_GROUPLIST(NetworkConnection& connection, NetworkPacket& packet) +{ + group_list.clear(); + uint8 size; + packet >> size >> default_group; + for (unsigned int i = 0; i < size; i++) { + NetworkGroup group; + group.Read(packet); + std::unique_ptr newgroup(new NetworkGroup(group)); // change to make_unique in c++14 + group_list.push_back(std::move(newgroup)); + } +} + +void Network::Client_Handle_EVENT(NetworkConnection& connection, NetworkPacket& packet) +{ + uint16 eventType; + packet >> eventType; + switch (eventType) { + case SERVER_EVENT_PLAYER_JOINED: + { + char text[256]; + const char *playerName = packet.ReadString(); + format_string(text, STR_MULTIPLAYER_PLAYER_HAS_JOINED_THE_GAME, &playerName); + chat_history_add(text); + break; + } + case SERVER_EVENT_PLAYER_DISCONNECTED: + { + char text[256]; + const char *playerName = packet.ReadString(); + const char *reason = packet.ReadString(); + const char *args[] = { playerName, reason }; + if (str_is_null_or_empty(reason)) { + format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_NO_REASON, args); + } else { + format_string(text, STR_MULTIPLAYER_PLAYER_HAS_DISCONNECTED_WITH_REASON, args); + } + chat_history_add(text); + break; + } + } } int network_init() @@ -1581,6 +2127,314 @@ int network_get_player_id(unsigned int index) return gNetwork.player_list[index]->id; } +money32 network_get_player_money_spent(unsigned int index) +{ + return gNetwork.player_list[index]->money_spent; +} + +void network_add_player_money_spent(unsigned int index, money32 cost) +{ + gNetwork.player_list[index]->AddMoneySpent(cost); +} + +int network_get_player_last_action(unsigned int index, int time) +{ + if (time && SDL_TICKS_PASSED(SDL_GetTicks(), gNetwork.player_list[index]->last_action_time + time)) { + return -999; + } + return gNetwork.player_list[index]->last_action; +} + +void network_set_player_last_action(unsigned int index, int command) +{ + gNetwork.player_list[index]->last_action = gNetworkActions.FindCommand(command); + gNetwork.player_list[index]->last_action_time = SDL_GetTicks(); +} + +rct_xyz16 network_get_player_last_action_coord(unsigned int index) +{ + return gNetwork.player_list[index]->last_action_coord; +} + +void network_set_player_last_action_coord(unsigned int index, rct_xyz16 coord) +{ + if (index < gNetwork.player_list.size()) { + gNetwork.player_list[index]->last_action_coord = coord; + } +} + +unsigned int network_get_player_commands_ran(unsigned int index) +{ + return gNetwork.player_list[index]->commands_ran; +} + +int network_get_player_index(uint8 id) +{ + auto it = gNetwork.GetPlayerIteratorByID(id); + if(it == gNetwork.player_list.end()){ + return -1; + } + return gNetwork.GetPlayerIteratorByID(id) - gNetwork.player_list.begin(); +} + +uint8 network_get_player_group(unsigned int index) +{ + return gNetwork.player_list[index]->group; +} + +void network_set_player_group(unsigned int index, unsigned int groupindex) +{ + gNetwork.player_list[index]->group = gNetwork.group_list[groupindex]->id; +} + +int network_get_group_index(uint8 id) +{ + auto it = gNetwork.GetGroupIteratorByID(id); + if(it == gNetwork.group_list.end()){ + return -1; + } + return gNetwork.GetGroupIteratorByID(id) - gNetwork.group_list.begin(); +} + +uint8 network_get_group_id(unsigned int index) +{ + return gNetwork.group_list[index]->id; +} + +int network_get_num_groups() +{ + return gNetwork.group_list.size(); +} + +const char* network_get_group_name(unsigned int index) +{ + return gNetwork.group_list[index]->GetName().c_str(); +} + +rct_string_id network_get_group_name_string_id(unsigned int index) +{ + return gNetwork.group_list[index]->GetNameStringId(); +} + +void network_chat_show_connected_message() +{ + char *templateString = (char*)language_get_string(STR_INDIVIDUAL_KEYS_BASE); + keyboard_shortcut_format_string(templateString, gShortcutKeys[SHORTCUT_OPEN_CHAT_WINDOW]); + utf8 buffer[256]; + NetworkPlayer server; + safe_strcpy((char*)&server.name, "Server", sizeof(server.name)); + format_string(buffer, STR_MULTIPLAYER_CONNECTED_CHAT_HINT, &templateString); + const char *formatted = Network::FormatChat(&server, buffer); + chat_history_add(formatted); +} + +void game_command_set_player_group(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + uint8 playerid = (uint8)*ecx; + uint8 groupid = (uint8)*edx; + NetworkPlayer* player = gNetwork.GetPlayerByID(playerid); + NetworkGroup* fromgroup = gNetwork.GetGroupByID(game_command_playerid); + if (!player) { + *ebx = MONEY32_UNDEFINED; + return; + } + if (!gNetwork.GetGroupByID(groupid)) { + *ebx = MONEY32_UNDEFINED; + return; + } + if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_GROUP_THAT_THE_HOST_BELONGS_TO; + *ebx = MONEY32_UNDEFINED; + return; + } + if (groupid == 0 && fromgroup && fromgroup->id != 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_SET_TO_THIS_GROUP; + *ebx = MONEY32_UNDEFINED; + return; + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + player->group = groupid; + window_invalidate_by_number(WC_PLAYER, playerid); + } + *ebx = 0; +} + +void game_command_modify_groups(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + uint8 action = (uint8)*eax; + uint8 groupid = (uint8)(*eax >> 8); + uint8 nameChunkIndex = (uint8)(*eax >> 16); + + char oldName[128]; + static char newName[128]; + + switch (action) + { + case 0:{ // add group + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + NetworkGroup* newgroup = gNetwork.AddGroup(); + if (!newgroup) { + *ebx = MONEY32_UNDEFINED; + return; + } + } + }break; + case 1:{ // remove group + if (groupid == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_THIS_GROUP_CANNOT_BE_MODIFIED; + *ebx = MONEY32_UNDEFINED; + return; + } + for (auto it = gNetwork.player_list.begin(); it != gNetwork.player_list.end(); it++) { + if((*it)->group == groupid) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_REMOVE_GROUP_THAT_PLAYERS_BELONG_TO; + *ebx = MONEY32_UNDEFINED; + return; + } + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + gNetwork.RemoveGroup(groupid); + } + }break; + case 2:{ // set permissions + int index = *ecx; + bool all = *edx & 1; + bool allvalue = (*edx >> 1) & 1; + if (groupid == 0) { // cant change admin group permissions + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_THIS_GROUP_CANNOT_BE_MODIFIED; + *ebx = MONEY32_UNDEFINED; + return; + } + NetworkGroup* mygroup = nullptr; + NetworkPlayer* player = gNetwork.GetPlayerByID(game_command_playerid); + if (player && !all) { + mygroup = gNetwork.GetGroupByID(player->group); + if (!mygroup || (mygroup && !mygroup->CanPerformAction(index))) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_MODIFY_PERMISSION_THAT_YOU_DO_NOT_HAVE_YOURSELF; + *ebx = MONEY32_UNDEFINED; + return; + } + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + NetworkGroup* group = gNetwork.GetGroupByID(groupid); + if (group) { + if (all) { + if (mygroup) { + if (allvalue) { + group->actions_allowed = mygroup->actions_allowed; + } else { + group->actions_allowed.fill(0x00); + } + } + } else { + group->ToggleActionPermission(index); + } + } + } + }break; + case 3:{ // set group name + size_t nameChunkOffset = nameChunkIndex - 1; + if (nameChunkIndex == 0) + nameChunkOffset = 2; + nameChunkOffset *= 12; + nameChunkOffset = (std::min)(nameChunkOffset, Util::CountOf(newName) - 12); + RCT2_GLOBAL(newName + nameChunkOffset + 0, uint32) = *edx; + RCT2_GLOBAL(newName + nameChunkOffset + 4, uint32) = *ebp; + RCT2_GLOBAL(newName + nameChunkOffset + 8, uint32) = *edi; + + if (nameChunkIndex != 0) { + *ebx = 0; + return; + } + + if (strcmp(oldName, newName) == 0) { + *ebx = 0; + return; + } + + if (newName[0] == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_RENAME_GROUP; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_GROUP_NAME; + *ebx = MONEY32_UNDEFINED; + return; + } + + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + NetworkGroup* group = gNetwork.GetGroupByID(groupid); + if (group) { + group->SetName(newName); + } + } + }break; + case 4:{ // set default group + if (groupid == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_SET_TO_THIS_GROUP; + *ebx = MONEY32_UNDEFINED; + return; + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + gNetwork.SetDefaultGroup(groupid); + } + }break; + } + + gNetwork.SaveGroups(); + + *ebx = 0; +} + +void game_command_kick_player(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + uint8 playerid = (uint8)*eax; + NetworkPlayer* player = gNetwork.GetPlayerByID(playerid); + if (player && player->flags & NETWORK_PLAYER_FLAG_ISSERVER) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_KICK_THE_HOST; + *ebx = MONEY32_UNDEFINED; + return; + } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + if (gNetwork.GetMode() == NETWORK_MODE_SERVER) { + gNetwork.KickPlayer(playerid); + } + } + *ebx = 0; +} + +uint8 network_get_default_group() +{ + return gNetwork.GetDefaultGroup(); +} + +int network_get_num_actions() +{ + return gNetworkActions.actions.size(); +} + +rct_string_id network_get_action_name_string_id(unsigned int index) +{ + return gNetworkActions.actions[index].name; +} + +int network_can_perform_action(unsigned int groupindex, unsigned int index) +{ + return gNetwork.group_list[groupindex]->CanPerformAction(index); +} + +int network_can_perform_command(unsigned int groupindex, unsigned int index) +{ + return gNetwork.group_list[groupindex]->CanPerformCommand(index); +} + +int network_get_current_player_group_index() +{ + return network_get_group_index(gNetwork.GetPlayerByID(gNetwork.GetPlayerID())->group); +} + +void network_free_string_ids() +{ + gNetwork.FreeStringIds(); +} + void network_send_map() { gNetwork.Server_Send_MAP(); @@ -1616,11 +2470,6 @@ void network_send_password(const char* password) gNetwork.Client_Send_AUTH(gConfigNetwork.player_name, password); } -void network_kick_player(int playerId) -{ - gNetwork.KickPlayer(playerId); -} - void network_set_password(const char* password) { gNetwork.SetPassword(password); @@ -1641,11 +2490,35 @@ const char* network_get_player_name(unsigned int index) { return "local (OpenRCT uint32 network_get_player_flags(unsigned int index) { return 0; } int network_get_player_ping(unsigned int index) { return 0; } int network_get_player_id(unsigned int index) { return 0; } +money32 network_get_player_money_spent(unsigned int index) { return MONEY(0, 0); } +void network_add_player_money_spent(unsigned int index, money32 cost) { } +int network_get_player_last_action(unsigned int index, int time) { return -999; } +void network_set_player_last_action(unsigned int index, int command) { } +rct_xyz16 network_get_player_last_action_coord(unsigned int index) { return {0, 0, 0}; } +void network_set_player_last_action_coord(unsigned int index, rct_xyz16 coord) { } +unsigned int network_get_player_commands_ran(unsigned int index) { return 0; } +int network_get_player_index(uint8 id) { return -1; } +uint8 network_get_player_group(unsigned int index) { return 0; } +void network_set_player_group(unsigned int index, unsigned int groupindex) { } +int network_get_group_index(uint8 id) { return -1; } +uint8 network_get_group_id(unsigned int index) { return 0; } +int network_get_num_groups() { return 0; } +const char* network_get_group_name(unsigned int index) { return ""; }; +rct_string_id network_get_group_name_string_id(unsigned int index) { return -1; } +void game_command_set_player_group(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { } +void game_command_modify_groups(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { } +void game_command_kick_player(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { } +uint8 network_get_default_group() { return 0; } +int network_get_num_actions() { return 0; } +rct_string_id network_get_action_name_string_id(unsigned int index) { return -1; } +int network_can_perform_action(unsigned int groupindex, unsigned int index) { return 0; } +int network_can_perform_command(unsigned int groupindex, unsigned int index) { return 0; } +void network_free_string_ids() {} void network_send_chat(const char* text) {} void network_send_password(const char* password) {} void network_close() {} void network_shutdown_client() {} -void network_kick_player(int playerId) {} void network_set_password(const char* password) {} uint8 network_get_current_player_id() { return 0; } +int network_get_current_player_group_index() { return 0; } #endif /* DISABLE_NETWORK */ diff --git a/src/network/network.h b/src/network/network.h index 56260ce5f2..305b5813e0 100644 --- a/src/network/network.h +++ b/src/network/network.h @@ -56,14 +56,24 @@ enum { extern "C" { #endif // __cplusplus #include "../common.h" +#include "../game.h" #include "../platform/platform.h" +#include "../localisation/string_ids.h" #ifdef __cplusplus } #endif // __cplusplus #ifndef DISABLE_NETWORK -#ifdef _WIN32 +// This define specifies which version of network stream current build uses. +// It is used for making sure only compatible builds get connected, even within +// single OpenRCT2 version. +#define NETWORK_STREAM_VERSION "5" +#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION + +#define NETWORK_DISCONNECT_REASON_BUFFER_SIZE 256 + +#ifdef __WINDOWS__ #include #include #define LAST_SOCKET_ERROR() WSAGetLastError() @@ -88,10 +98,17 @@ extern "C" { #define LAST_SOCKET_ERROR() errno #define closesocket close #define ioctlsocket ioctl -#endif // _WIN32 +#endif // __WINDOWS__ + +// Fixes issues on OS X +#if defined(_RCT2_H_) && !defined(_MSC_VER) +// use similar struct packing as MSVC for our structs +#pragma pack(1) +#endif #ifdef __cplusplus +#include #include #include #include @@ -131,18 +148,85 @@ public: uint16 size; std::shared_ptr> data; - int transferred; + unsigned int transferred; int read; }; class NetworkPlayer { public: - NetworkPlayer(const char* name); - uint8 id; - uint8 name[32 + 1]; - uint16 ping; - uint32 flags; + NetworkPlayer() = default; + void Read(NetworkPacket& packet); + void Write(NetworkPacket& packet); + void SetName(const char* name); + void AddMoneySpent(money32 cost); + uint8 id = 0; + uint8 name[32 + 1] = { 0 }; + uint16 ping = 0; + uint8 flags = 0; + uint8 group = 0; + money32 money_spent = MONEY(0, 0); + unsigned int commands_ran = 0; + int last_action = -999; + uint32 last_action_time = 0; + rct_xyz16 last_action_coord = { 0 }; +}; + +class NetworkAction +{ +public: + rct_string_id name; + std::vector commands; +}; + +class NetworkActions +{ +public: + int FindCommand(int command); + const std::vector actions = { + {STR_ACTION_CHAT, {-1}}, + {STR_ACTION_TERRAFORM, {GAME_COMMAND_SET_LAND_HEIGHT, GAME_COMMAND_RAISE_LAND, GAME_COMMAND_LOWER_LAND, GAME_COMMAND_EDIT_LAND_SMOOTH, GAME_COMMAND_CHANGE_SURFACE_STYLE}}, + {STR_ACTION_SET_WATER_LEVEL, {GAME_COMMAND_SET_WATER_HEIGHT, GAME_COMMAND_RAISE_WATER, GAME_COMMAND_LOWER_WATER}}, + {STR_ACTION_TOGGLE_PAUSE, {GAME_COMMAND_TOGGLE_PAUSE}}, + {STR_ACTION_CREATE_RIDE, {GAME_COMMAND_CREATE_RIDE}}, + {STR_ACTION_REMOVE_RIDE, {GAME_COMMAND_DEMOLISH_RIDE}}, + {STR_ACTION_BUILD_RIDE, {GAME_COMMAND_PLACE_TRACK, GAME_COMMAND_REMOVE_TRACK, GAME_COMMAND_SET_MAZE_TRACK, GAME_COMMAND_PLACE_TRACK_DESIGN, GAME_COMMAND_PLACE_MAZE_DESIGN, GAME_COMMAND_PLACE_RIDE_ENTRANCE_OR_EXIT, GAME_COMMAND_REMOVE_RIDE_ENTRANCE_OR_EXIT}}, + {STR_ACTION_RIDE_PROPERTIES, {GAME_COMMAND_SET_RIDE_NAME, GAME_COMMAND_SET_RIDE_APPEARANCE, GAME_COMMAND_SET_RIDE_STATUS, GAME_COMMAND_SET_RIDE_VEHICLES, GAME_COMMAND_SET_RIDE_SETTING, GAME_COMMAND_SET_RIDE_PRICE, GAME_COMMAND_SET_BRAKES_SPEED}}, + {STR_ACTION_SCENERY, {GAME_COMMAND_REMOVE_SCENERY, GAME_COMMAND_PLACE_SCENERY, GAME_COMMAND_SET_BRAKES_SPEED, GAME_COMMAND_REMOVE_FENCE, GAME_COMMAND_PLACE_FENCE, GAME_COMMAND_REMOVE_LARGE_SCENERY, GAME_COMMAND_PLACE_LARGE_SCENERY, GAME_COMMAND_PLACE_BANNER, GAME_COMMAND_REMOVE_BANNER, GAME_COMMAND_SET_SCENERY_COLOUR, GAME_COMMAND_SET_FENCE_COLOUR, GAME_COMMAND_SET_LARGE_SCENERY_COLOUR, GAME_COMMAND_SET_BANNER_COLOUR, GAME_COMMAND_SET_BANNER_NAME, GAME_COMMAND_SET_SIGN_NAME, GAME_COMMAND_SET_BANNER_STYLE, GAME_COMMAND_SET_SIGN_STYLE}}, + {STR_ACTION_PATH, {GAME_COMMAND_PLACE_PATH, GAME_COMMAND_PLACE_PATH_FROM_TRACK, GAME_COMMAND_REMOVE_PATH}}, + {STR_ACTION_CLEAR_LANDSCAPE, {GAME_COMMAND_CLEAR_SCENERY}}, + {STR_ACTION_GUEST, {GAME_COMMAND_SET_PEEP_NAME}}, + {STR_ACTION_STAFF, {GAME_COMMAND_HIRE_NEW_STAFF_MEMBER, GAME_COMMAND_SET_STAFF_PATROL, GAME_COMMAND_FIRE_STAFF_MEMBER, GAME_COMMAND_SET_STAFF_ORDER, GAME_COMMAND_SET_STAFF_COLOUR}}, + {STR_ACTION_PARK_PROPERTIES, {GAME_COMMAND_SET_PARK_NAME, GAME_COMMAND_SET_PARK_OPEN, GAME_COMMAND_SET_PARK_ENTRANCE_FEE, GAME_COMMAND_SET_LAND_OWNERSHIP, GAME_COMMAND_BUY_LAND_RIGHTS, GAME_COMMAND_PLACE_PARK_ENTRANCE, GAME_COMMAND_REMOVE_PARK_ENTRANCE}}, + {STR_ACTION_PARK_FUNDING, {GAME_COMMAND_SET_CURRENT_LOAN, GAME_COMMAND_SET_RESEARCH_FUNDING, GAME_COMMAND_START_MARKETING_CAMPAIGN}}, + {STR_ACTION_KICK_PLAYER, {GAME_COMMAND_KICK_PLAYER}}, + {STR_ACTION_MODIFY_GROUPS, {GAME_COMMAND_MODIFY_GROUPS}}, + {STR_ACTION_SET_PLAYER_GROUP, {GAME_COMMAND_SET_PLAYER_GROUP}}, + {STR_ACTION_CHEAT, {GAME_COMMAND_CHEAT}}, + {STR_ACTION_TOGGLE_SCENERY_CLUSTER, {-2}} + }; +}; + +class NetworkGroup +{ +public: + NetworkGroup(); + ~NetworkGroup(); + void Read(NetworkPacket& packet); + void Write(NetworkPacket& packet); + void FreeNameStringId(); + void ToggleActionPermission(size_t index); + bool CanPerformAction(size_t index); + bool CanPerformCommand(int command); + std::string& GetName(); + void SetName(std::string name); + rct_string_id GetNameStringId(); + std::array actions_allowed; + uint8 id = 0; + +private: + std::string name; + rct_string_id name_string_id; }; class NetworkConnection @@ -159,14 +243,18 @@ public: void ResetLastPacketTime(); bool ReceivedPacketRecently(); - SOCKET socket; + const char *getLastDisconnectReason() const; + void setLastDisconnectReason(const char *src); + void setLastDisconnectReason(const rct_string_id string_id); + + SOCKET socket = INVALID_SOCKET; NetworkPacket inboundpacket; - int authstatus; + int authstatus = NETWORK_AUTH_NONE; NetworkPlayer* player; - uint32 ping_time; - const char* last_disconnect_reason; + uint32 ping_time = 0; private: + char* last_disconnect_reason; bool SendPacket(NetworkPacket& packet); std::list> outboundpackets; uint32 last_packet_time; @@ -192,10 +280,10 @@ public: private: static int ResolveFunc(void* pointer); - const char* host; - unsigned short port; - SDL_mutex* mutex; - SDL_cond* cond; + const char* host = nullptr; + unsigned short port = 0; + SDL_mutex* mutex = nullptr; + SDL_cond* cond = nullptr; std::shared_ptr status; }; @@ -214,8 +302,11 @@ public: uint32 GetServerTick(); uint8 GetPlayerID(); void Update(); - NetworkPlayer* GetPlayerByID(int id); - const char* FormatChat(NetworkPlayer* fromplayer, const char* text); + std::vector>::iterator GetPlayerIteratorByID(uint8 id); + NetworkPlayer* GetPlayerByID(uint8 id); + std::vector>::iterator GetGroupIteratorByID(uint8 id); + NetworkGroup* GetGroupByID(uint8 id); + static const char* FormatChat(NetworkPlayer* fromplayer, const char* text); void SendPacketToClients(NetworkPacket& packet, bool front = false); bool CheckSRAND(uint32 tick, uint32 srand0); void KickPlayer(int playerId); @@ -223,6 +314,13 @@ public: void ShutdownClient(); void AdvertiseRegister(); void AdvertiseHeartbeat(); + NetworkGroup* AddGroup(); + void RemoveGroup(uint8 id); + uint8 GetDefaultGroup(); + void SetDefaultGroup(uint8 id); + void SaveGroups(); + void LoadGroups(); + void FreeStringIds(); void Client_Send_AUTH(const char* name, const char* password); void Server_Send_AUTH(NetworkConnection& connection); @@ -238,8 +336,13 @@ public: void Server_Send_PINGLIST(); void Server_Send_SETDISCONNECTMSG(NetworkConnection& connection, const char* msg); void Server_Send_GAMEINFO(NetworkConnection& connection); + void Server_Send_SHOWERROR(NetworkConnection& connection, rct_string_id title, rct_string_id message); + void Server_Send_GROUPLIST(NetworkConnection& connection); + void Server_Send_EVENT_PLAYER_JOINED(const char *playerName); + void Server_Send_EVENT_PLAYER_DISCONNECTED(const char *playerName, const char *reason); std::vector> player_list; + std::vector> group_list; private: bool ProcessConnection(NetworkConnection& connection); @@ -247,9 +350,9 @@ private: void ProcessGameCommandQueue(); void AddClient(SOCKET socket); void RemoveClient(std::unique_ptr& connection); - NetworkPlayer* AddPlayer(const char* name); + NetworkPlayer* AddPlayer(); void PrintError(); - const char *GetMasterServerUrl(); + const char* GetMasterServerUrl(); std::string GenerateAdvertiseKey(); struct GameCommand @@ -264,54 +367,60 @@ private: } }; - int mode; - int status; + int mode = NETWORK_MODE_NONE; + int status = NETWORK_STATUS_NONE; NetworkAddress server_address; - bool wsa_initialized; - SOCKET listening_socket; - unsigned short listening_port; + bool wsa_initialized = false; + SOCKET listening_socket = INVALID_SOCKET; + unsigned short listening_port = 0; NetworkConnection server_connection; - uint32 last_tick_sent_time; - uint32 last_ping_sent_time; - uint32 server_tick; - uint32 server_srand0; - uint32 server_srand0_tick; - uint8 player_id; + uint32 last_tick_sent_time = 0; + uint32 last_ping_sent_time = 0; + uint32 server_tick = 0; + uint32 server_srand0 = 0; + uint32 server_srand0_tick = 0; + uint8 player_id = 0; std::list> client_connection_list; std::multiset game_command_queue; std::vector chunk_buffer; std::string password; - bool _desynchronised; - uint32 server_connect_time; - uint32 last_advertise_time; + bool _desynchronised = false; + uint32 server_connect_time = 0; + uint32 last_advertise_time = 0; std::string advertise_token; std::string advertise_key; - int advertise_status; - uint32 last_heartbeat_time; + int advertise_status = 0; + uint32 last_heartbeat_time = 0; + uint8 default_group = 0; void UpdateServer(); void UpdateClient(); private: - std::vector client_command_handlers; - std::vector server_command_handlers; - int Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet); - int Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet); - int Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet); + std::vector client_command_handlers; + std::vector server_command_handlers; + void Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_CHAT(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet); + void Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_SHOWERROR(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_GROUPLIST(NetworkConnection& connection, NetworkPacket& packet); + void Client_Handle_EVENT(NetworkConnection& connection, NetworkPacket& packet); }; #endif // __cplusplus +#else /* DISABLE_NETWORK */ +#define NETWORK_STREAM_ID "Multiplayer disabled" #endif /* DISABLE_NETWORK */ #ifdef __cplusplus @@ -334,13 +443,37 @@ const char* network_get_player_name(unsigned int index); uint32 network_get_player_flags(unsigned int index); int network_get_player_ping(unsigned int index); int network_get_player_id(unsigned int index); +money32 network_get_player_money_spent(unsigned int index); +void network_add_player_money_spent(unsigned int index, money32 cost); +int network_get_player_last_action(unsigned int index, int time); +void network_set_player_last_action(unsigned int index, int command); +rct_xyz16 network_get_player_last_action_coord(unsigned int index); +void network_set_player_last_action_coord(unsigned int index, rct_xyz16 coord); +unsigned int network_get_player_commands_ran(unsigned int index); +int network_get_player_index(uint8 id); +uint8 network_get_player_group(unsigned int index); +void network_set_player_group(unsigned int index, unsigned int groupindex); +int network_get_group_index(uint8 id); +int network_get_current_player_group_index(); +uint8 network_get_group_id(unsigned int index); +int network_get_num_groups(); +const char* network_get_group_name(unsigned int index); +rct_string_id network_get_group_name_string_id(unsigned int index); +void game_command_set_player_group(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp); +void game_command_modify_groups(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void game_command_kick_player(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +uint8 network_get_default_group(); +int network_get_num_actions(); +rct_string_id network_get_action_name_string_id(unsigned int index); +int network_can_perform_action(unsigned int groupindex, unsigned int index); +int network_can_perform_command(unsigned int groupindex, unsigned int index); +void network_free_string_ids(); void network_send_map(); void network_send_chat(const char* text); void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp, uint8 callback); void network_send_password(const char* password); -void network_kick_player(int playerId); void network_set_password(const char* password); void network_print_error(); diff --git a/src/network/twitch.cpp b/src/network/twitch.cpp index fbc47434e9..738df2791d 100644 --- a/src/network/twitch.cpp +++ b/src/network/twitch.cpp @@ -304,23 +304,23 @@ static void twitch_parse_followers() } } - if (peep->flags & PEEP_FLAGS_TWITCH) { + if (peep->peep_flags & PEEP_FLAGS_TWITCH) { if (member == NULL) { // Member no longer peep name worthy - peep->flags &= ~(PEEP_FLAGS_TRACKING | PEEP_FLAGS_TWITCH); + peep->peep_flags &= ~(PEEP_FLAGS_TRACKING | PEEP_FLAGS_TWITCH); // TODO set peep name back to number / real name } else { if (member->shouldTrack) - peep->flags |= (PEEP_FLAGS_TRACKING); + peep->peep_flags |= (PEEP_FLAGS_TRACKING); else if (!member->shouldTrack) - peep->flags &= ~(PEEP_FLAGS_TRACKING); + peep->peep_flags &= ~(PEEP_FLAGS_TRACKING); } - } else if (member != NULL && !(peep->flags & PEEP_FLAGS_LEAVING_PARK)) { + } else if (member != NULL && !(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)) { // Peep with same name already exists but not twitch - peep->flags |= PEEP_FLAGS_TWITCH; + peep->peep_flags |= PEEP_FLAGS_TWITCH; if (member->shouldTrack) - peep->flags |= PEEP_FLAGS_TRACKING; + peep->peep_flags |= PEEP_FLAGS_TRACKING; } } } @@ -340,14 +340,14 @@ static void twitch_parse_followers() break; AudienceMember *member = &members[memberIndex]; - if (!is_user_string_id(peep->name_string_idx) && !(peep->flags & PEEP_FLAGS_LEAVING_PARK)) { + if (!is_user_string_id(peep->name_string_idx) && !(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)) { // Rename peep and add flags rct_string_id newStringId = user_string_allocate(4, member->name); if (newStringId != 0) { peep->name_string_idx = newStringId; - peep->flags |= PEEP_FLAGS_TWITCH; + peep->peep_flags |= PEEP_FLAGS_TWITCH; if (member->shouldTrack) - peep->flags |= PEEP_FLAGS_TRACKING; + peep->peep_flags |= PEEP_FLAGS_TRACKING; } } else { // Peep still yet to be found for member @@ -422,15 +422,13 @@ static void twitch_parse_chat_message(const char *message) message++; ch = strchrm(message, " \t"); - safe_strncpy(buffer, message, ch - message); - buffer[ch - message] = 0; + safe_strcpy(buffer, message, ch - message + 1); if (_strcmpi(buffer, "news") == 0) { if (gConfigTwitch.enable_news) { ch = strskipwhitespace(ch); buffer[0] = (char)FORMAT_TOPAZ; - safe_strncpy(buffer + 1, ch, sizeof(buffer) - 2); - buffer[sizeof(buffer) - 2] = 0; + safe_strcpy(buffer + 1, ch, sizeof(buffer) - 2); // Remove unsupport characters // TODO allow when OpenRCT2 gains unicode support diff --git a/src/network/twitch.h b/src/network/twitch.h index 247c721281..20deb0b454 100644 --- a/src/network/twitch.h +++ b/src/network/twitch.h @@ -7,4 +7,4 @@ extern bool gTwitchEnable; void twitch_update(); -#endif \ No newline at end of file +#endif diff --git a/src/object.c b/src/object.c index 96badbb090..ea4ea68421 100644 --- a/src/object.c +++ b/src/object.c @@ -59,7 +59,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi char path[MAX_PATH]; SDL_RWops* rw; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), (char*)installedObject + 16); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), (char*)installedObject + 16); log_verbose("loading object, %s", path); @@ -83,39 +83,42 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi uint8 *chunk; if (*chunkSize == 0xFFFFFFFF) { - chunk = rct2_malloc(0x600000); + chunk = (uint8*)malloc(0x600000); *chunkSize = sawyercoding_read_chunk(rw, chunk); - chunk = rct2_realloc(chunk, *chunkSize); + chunk = realloc(chunk, *chunkSize); } else { - chunk = rct2_malloc(*chunkSize); + chunk = (uint8*)malloc(*chunkSize); *chunkSize = sawyercoding_read_chunk(rw, chunk); } SDL_RWclose(rw); - + int calculatedChecksum = object_calculate_checksum(&openedEntry, chunk, *chunkSize); // Calculate and check checksum - if (object_calculate_checksum(&openedEntry, chunk, *chunkSize) != openedEntry.checksum) { - log_error("Object Load failed due to checksum failure."); + if (calculatedChecksum != openedEntry.checksum && !gConfigGeneral.allow_loading_with_incorrect_checksum) { + char buffer[100]; + sprintf(buffer, "Object Load failed due to checksum failure: calculated checksum %d, object says %d.", calculatedChecksum, (int)openedEntry.checksum); + log_error(buffer); RCT2_GLOBAL(0x00F42BD9, uint8) = 2; - rct2_free(chunk); + free(chunk); return 0; + } objectType = openedEntry.flags & 0x0F; - if (object_paint(objectType, 2, 0, objectType, 0, (int)chunk, 0, 0)) { + if (!object_test(objectType, chunk)) { log_error("Object Load failed due to paint failure."); RCT2_GLOBAL(0x00F42BD9, uint8) = 3; - rct2_free(chunk); + free(chunk); return 0; } if (RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) >= 0x4726E){ log_error("Object Load failed due to too many images loaded."); RCT2_GLOBAL(0x00F42BD9, uint8) = 4; - rct2_free(chunk); + free(chunk); return 0; } @@ -125,7 +128,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi if (groupIndex + 1 >= object_entry_group_counts[objectType]) { log_error("Object Load failed due to too many objects of a certain type."); RCT2_GLOBAL(0x00F42BD9, uint8) = 5; - rct2_free(chunk); + free(chunk); return 0; } } @@ -137,10 +140,11 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi memcpy(extended_entry, &openedEntry, sizeof(rct_object_entry)); extended_entry->chunk_size = *chunkSize; - RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*) = chunk; + gLastLoadedObjectChunkData = chunk; - if (RCT2_GLOBAL(0x9ADAFD, uint8) != 0) - object_paint(objectType, 0, groupIndex, objectType, 0, (int)chunk, 0, 0); + if (RCT2_GLOBAL(0x9ADAFD, uint8) != 0) { + object_load(objectType, chunk, groupIndex); + } return 1; } @@ -148,7 +152,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi * * rct2: 0x006A985D */ -int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize) +int object_load_chunk(int groupIndex, rct_object_entry *entry, int* chunkSize) { // Alow chunkSize to be null int tempChunkSize; @@ -157,7 +161,7 @@ int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize) RCT2_GLOBAL(0xF42B64, uint32) = groupIndex; - if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) == 0) { + if (gInstalledObjectsCount == 0) { RCT2_GLOBAL(0xF42BD9, uint8) = 0; log_error("Object Load failed due to no items installed check."); return 1; @@ -175,11 +179,14 @@ int object_load(int groupIndex, rct_object_entry *entry, int* chunkSize) return 0; } -/** rct2: 0x006a9f42 - * ebx : file - * ebp : entry +/** + * + * rct2: 0x006a9f42 + * ebx: file + * ebp: entry */ -int write_object_file(SDL_RWops *rw, rct_object_entry* entry){ +int write_object_file(SDL_RWops *rw, rct_object_entry* entry) +{ uint8 entryGroupIndex = 0, type = 0; uint8* chunk = 0; @@ -187,10 +194,10 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry){ chunk = object_entry_groups[type].chunks[entryGroupIndex]; - object_paint(type, 1, entryGroupIndex, type, 0, (int)chunk, 0, 0); + object_unload(type, chunk); rct_object_entry_extended* installed_entry = &object_entry_groups[type].entries[entryGroupIndex]; - uint8* dst_buffer = malloc(0x600000); + uint8* dst_buffer = (uint8*)malloc(0x600000); memcpy(dst_buffer, installed_entry, sizeof(rct_object_entry)); uint32 size_dst = sizeof(rct_object_entry); @@ -202,9 +209,50 @@ int write_object_file(SDL_RWops *rw, rct_object_entry* entry){ chunkHeader.encoding = object_entry_group_encoding[type]; chunkHeader.length = installed_entry->chunk_size; - size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), chunk, chunkHeader); - SDL_RWwrite(rw, dst_buffer, 1, size_dst); + //Check if content of object file matches the stored checksum. If it does not, then fix it. + int calculated_checksum = object_calculate_checksum(entry, chunk, installed_entry->chunk_size); + if(entry->checksum != calculated_checksum) { + //Store the current length of the header - it's the offset at which we will write the extra bytes + int salt_offset = chunkHeader.length; + /*Allocate a new chunk 11 bytes longer. + I would just realloc the old one, but realloc can move the data, leaving dangling pointers + into the old buffer. If the chunk is only referenced in one place it would be safe to realloc + it and update that reference, but I don't know the codebase well enough to know if that's the + case, so to be on the safe side I copy it*/ + uint8* new_chunk = malloc(chunkHeader.length + 11); + memcpy(new_chunk,chunk, chunkHeader.length); + //It should be safe to update these in-place because they are local + chunkHeader.length += 11; + + /*Next work out which bits need to be flipped to make the current checksum match the one in the file + The bitwise rotation compensates for the rotation performed during the checksum calculation*/ + int bits_to_flip = entry->checksum ^ ((calculated_checksum << 25) | (calculated_checksum >> 7)); + /*Each set bit encountered during encoding flips one bit of the resulting checksum (so each bit of the checksum is an XOR + of bits from the file). Here, we take each bit that should be flipped in the checksum and set one of the bits in the data + that maps to it. 11 bytes is the minimum needed to touch every bit of the checksum - with less than that, you wouldn't + always be able to make the checksum come out to the desired target*/ + new_chunk[salt_offset] = (bits_to_flip & 0x00000001) << 7; + new_chunk[salt_offset + 1] = ((bits_to_flip & 0x00200000) >> 14); + new_chunk[salt_offset + 2] = ((bits_to_flip & 0x000007F8) >> 3); + new_chunk[salt_offset + 3] = ((bits_to_flip & 0xFF000000) >> 24); + new_chunk[salt_offset + 4] = ((bits_to_flip & 0x00100000) >> 13); + new_chunk[salt_offset + 5] = (bits_to_flip & 0x00000004) >> 2; + new_chunk[salt_offset + 6] = 0; + new_chunk[salt_offset + 7] = ((bits_to_flip & 0x000FF000) >> 12); + new_chunk[salt_offset + 8] = (bits_to_flip & 0x00000002) >> 1; + new_chunk[salt_offset + 9] = (bits_to_flip & 0x00C00000) >> 22; + new_chunk[salt_offset + 10] = (bits_to_flip & 0x00000800) >> 11; + + //Write modified chunk data + size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry),new_chunk,chunkHeader); + free(new_chunk); + } else { + //If the checksum matches, write chunk data + size_dst += sawyercoding_write_chunk_buffer(dst_buffer + sizeof(rct_object_entry), chunk, chunkHeader); + } + + SDL_RWwrite(rw, dst_buffer, 1, size_dst); free(dst_buffer); return 1; } @@ -221,9 +269,9 @@ int object_load_packed(SDL_RWops* rw) SDL_RWread(rw, &entry, 16, 1); - uint8* chunk = rct2_malloc(0x600000); + uint8* chunk = (uint8*)malloc(0x600000); uint32 chunkSize = sawyercoding_read_chunk(rw, chunk); - chunk = rct2_realloc(chunk, chunkSize); + chunk = realloc(chunk, chunkSize); if (chunk == NULL){ log_error("Failed to allocate memory for packed object."); @@ -231,25 +279,31 @@ int object_load_packed(SDL_RWops* rw) } if (object_calculate_checksum(&entry, chunk, chunkSize) != entry.checksum){ - log_error("Checksum missmatch from packed object: %.8s", entry.name); - rct2_free(chunk); - return 0; + + if(gConfigGeneral.allow_loading_with_incorrect_checksum) { + log_warning("Checksum mismatch from packed object: %.8s", entry.name); + } else { + log_error("Checksum mismatch from packed object: %.8s", entry.name); + free(chunk); + return 0; + } } int type = entry.flags & 0x0F; - if (object_paint(type, 2, 0, type, 0, (int)chunk, 0, 0)) { + if (!object_test(type, chunk)) { log_error("Packed object failed paint test."); - rct2_free(chunk); + free(chunk); return 0; } if (RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) >= 0x4726E){ log_error("Packed object has too many images."); - rct2_free(chunk); + free(chunk); return 0; } + int entryGroupIndex = 0; for (; entryGroupIndex < object_entry_group_counts[type]; entryGroupIndex++){ @@ -262,7 +316,7 @@ int object_load_packed(SDL_RWops* rw) // This should never occur. Objects are not loaded before installing a // packed object. So there is only one object loaded at this point. log_error("Too many objects of the same type loaded."); - rct2_free(chunk); + free(chunk); return 0; } @@ -273,9 +327,9 @@ int object_load_packed(SDL_RWops* rw) extended_entry->chunk_size = chunkSize; // Ensure the entry does not already exist. - rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); - if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)){ - for (uint32 i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); ++i){ + rct_object_entry *installedObject = gInstalledObjects; + if (gInstalledObjectsCount){ + for (uint32 i = 0; i < gInstalledObjectsCount; ++i){ if (object_entry_compare(&entry, installedObject)){ object_unload_all(); return 0; @@ -294,7 +348,7 @@ int object_load_packed(SDL_RWops* rw) objectPath[i] = '\0'; } - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); // Require pointer to start of filename char* last_char = path + strlen(path); strcat(path, ".DAT"); @@ -304,7 +358,7 @@ int object_load_packed(SDL_RWops* rw) for (; platform_file_exists(path);){ for (char* curr_char = last_char - 1;; --curr_char){ if (*curr_char == '\\'){ - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), "00000000.DAT"); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), "00000000.DAT"); char* last_char = path + strlen(path); break; } @@ -335,7 +389,7 @@ int object_load_packed(SDL_RWops* rw) * * rct2: 0x006A9CAF */ -void object_unload(rct_object_entry *entry) +void object_unload_chunk(rct_object_entry *entry) { uint8 object_type, object_index; if (!find_object_in_entry_group(entry, &object_type, &object_index)){ @@ -344,29 +398,27 @@ void object_unload(rct_object_entry *entry) uint8* chunk = object_entry_groups[object_type].chunks[object_index]; - object_paint(object_type, 1, 0, 0, 0, (int)chunk, 0, 0); + object_unload(object_type, chunk); - rct2_free(chunk); + free(chunk); object_entry_groups[object_type].chunks[object_index] = (uint8*)-1; } int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b) { // If an official object don't bother checking checksum - if (a->flags & 0xF0) { + if ((a->flags & 0xF0) || (b->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; @@ -377,26 +429,26 @@ int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b) int object_calculate_checksum(const rct_object_entry *entry, const uint8 *data, int dataLength) { - int i; - const char *eee = (char*)entry; - int checksum = 0xF369A75B; - char *ccc = (char*)&checksum; + const uint8 *entryBytePtr = (uint8*)entry; - *ccc ^= eee[0]; + uint32 checksum = 0xF369A75B; + checksum ^= entryBytePtr[0]; checksum = rol32(checksum, 11); - for (i = 4; i < 12; i++) { - *ccc ^= eee[i]; + for (int i = 4; i < 12; i++) { + checksum ^= entryBytePtr[i]; checksum = rol32(checksum, 11); } - for (i = 0; i < dataLength; i++) { - *ccc ^= data[i]; + for (int i = 0; i < dataLength; i++) { + checksum ^= data[i]; checksum = rol32(checksum, 11); } - - return checksum; + return (int)checksum; } -/* rct2: 0x006A9ED1 */ +/** + * + * rct2: 0x006A9ED1 + */ int object_chunk_load_image_directory(uint8_t** chunk) { int image_start_no = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32_t); @@ -428,1068 +480,1185 @@ int object_chunk_load_image_directory(uint8_t** chunk) return image_start_no; } -/* rct2: 0x006DE83E */ -int paint_ride_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) +typedef bool (*object_load_func)(void *objectEntry, uint32 entryIndex); +typedef void (*object_unload_func)(void *objectEntry); +typedef bool (*object_test_func)(void *objectEntry); +typedef void (*object_paint_func)(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y); +typedef rct_string_id (*object_desc_func)(void *objectEntry); + +/** + * Represents addresses for virtual object functions. + */ +typedef struct { + object_load_func load; + object_unload_func unload; + object_test_func test; + object_paint_func paint; + object_desc_func desc; +} object_type_vtable; + +/////////////////////////////////////////////////////////////////////////////// +// Ride (rct2: 0x006E6E2A) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_ride_load(void *objectEntry, uint32 entryIndex) { - if ((flags & 0xFF) == 0){ - // esi - rct_ride_type* ride_type = (rct_ride_type*)esi; + rct_ride_entry *rideEntry = (rct_ride_entry*)objectEntry; - // After ride_type is 3 string tables - uint8_t* chunk = (uint8*)(ride_type + 1); - ride_type->name = object_get_localised_text(&chunk, ecx, ebx, 0); - ride_type->description = object_get_localised_text(&chunk, ecx, ebx, 1); + // After rideEntry is 3 string tables + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + sizeof(rct_ride_entry)); + rideEntry->name = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_RIDE, entryIndex, 0); + rideEntry->description = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_RIDE, entryIndex, 1); - //TODO: Move to its own function when ride construction window is merged. - if(gConfigInterface.select_by_track_type) { - ride_type->enabledTrackPieces = 0xFFFFFFFFFFFFFFFF; + //TODO: Move to its own function when ride construction window is merged. + if (gConfigInterface.select_by_track_type) { + rideEntry->enabledTrackPieces = 0xFFFFFFFFFFFFFFFF; + } + + object_get_localised_text(&extendedEntryData, OBJECT_TYPE_RIDE, entryIndex, 2); + rideEntry->vehicle_preset_list = (vehicle_colour_preset_list*)extendedEntryData; + + // If Unknown struct size is 0xFF then there are 32 3 byte structures + uint8 unknown_size = *extendedEntryData++; + if (unknown_size != 0xFF) { + extendedEntryData += unknown_size * 3; + } else { + extendedEntryData += 0x60; + } + + sint8 *peep_loading_positions = (sint8*)extendedEntryData; + // Peep loading positions variable size + // 4 different vehicle subtypes are available + for (int i = 0; i < 4; i++){ + uint16 no_peep_positions = *extendedEntryData++; + // If no_peep_positions is 0xFF then no_peep_positions is a word + if (no_peep_positions == 0xFF) { + no_peep_positions = *((uint16*)extendedEntryData); + extendedEntryData += 2; } + extendedEntryData += no_peep_positions; + } - object_get_localised_text(&chunk, ecx, ebx, 2); - ride_type->vehicle_preset_list = (vehicle_colour_preset_list*)chunk; + int images_offset = object_chunk_load_image_directory(&extendedEntryData); + rideEntry->images_offset = images_offset; - // If Unknown struct size is 0xFF then there are 32 3 byte structures - uint8 unknown_size = *chunk++; - if (unknown_size != 0xFF) - { - chunk += unknown_size * 3; - } - else { - chunk += 0x60; - } + int cur_vehicle_images_offset = images_offset + 3; - sint8* peep_loading_positions = (sint8 *)chunk; - // Peep loading positions variable size - // 4 different vehicle subtypes are available - for (int i = 0; i < 4; ++i){ - uint16 no_peep_positions = *chunk++; - // If no_peep_positions is 0xFF then no_peep_positions is a word - if (no_peep_positions == 0xFF) - { - no_peep_positions = *((uint16_t*)chunk); - chunk += 2; - } - chunk += no_peep_positions; - } + for (int i = 0; i < 4; i++) { + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[i]; - int images_offset = object_chunk_load_image_directory(&chunk); - ride_type->images_offset = images_offset; - - int cur_vehicle_images_offset = images_offset + 3; - - for (int i = 0; i < 4; ++i){ - rct_ride_type_vehicle* rideVehicleEntry = &ride_type->vehicles[i]; - - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT) { - int al = 1; - if (rideVehicleEntry->var_14 & 2) { - al = 13; - if ((rideVehicleEntry->var_14 & 0x820) != 0x820) { - al = 7; - if (!(rideVehicleEntry->var_14 & 0x20)) { - if (!(rideVehicleEntry->var_14 & 0x800)) { - al = 5; - if (rideVehicleEntry->var_14 & 0x200) { - al = 3; - } + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT) { + int al = 1; + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SWINGING) { + al = 13; + if ((vehicleEntry->flags_b & (VEHICLE_ENTRY_FLAG_B_5 | VEHICLE_ENTRY_FLAG_B_11)) != (VEHICLE_ENTRY_FLAG_B_5 | VEHICLE_ENTRY_FLAG_B_11)) { + al = 7; + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_5)) { + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_11)) { + al = 5; + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_9) { + al = 3; } } } } - rideVehicleEntry->var_03 = al; - // 0x6DE90B + } + vehicleEntry->var_03 = al; + // 0x6DE90B - al = 0x20; - if (!(rideVehicleEntry->var_12 & 0x4000)) - { - al = 1; - if (rideVehicleEntry->var_14 & 0x80) - { - if (rideVehicleEntry->var_11 != 6) - { - al = 2; - if (!(rideVehicleEntry->var_12 & 0x80)) al = 4; + al = 0x20; + if (!(vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_14)) { + al = 1; + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_7) { + if (vehicleEntry->var_11 != 6) { + al = 2; + if (!(vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_7)) { + al = 4; } } } - if (rideVehicleEntry->var_12 & 0x1000) al = rideVehicleEntry->special_frames; - rideVehicleEntry->var_02 = al; - // 0x6DE946 + } + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_12) { + al = vehicleEntry->special_frames; + } + vehicleEntry->var_02 = al; + // 0x6DE946 - rideVehicleEntry->var_16 = rideVehicleEntry->var_02 * rideVehicleEntry->var_03; - rideVehicleEntry->base_image_id = cur_vehicle_images_offset; - int image_index = rideVehicleEntry->base_image_id; + vehicleEntry->var_16 = vehicleEntry->var_02 * vehicleEntry->var_03; + vehicleEntry->base_image_id = cur_vehicle_images_offset; + int image_index = vehicleEntry->base_image_id; - if (rideVehicleEntry->car_visual != VEHICLE_VISUAL_RIVER_RAPIDS) { - int b = rideVehicleEntry->var_16 * 32; + if (vehicleEntry->car_visual != VEHICLE_VISUAL_RIVER_RAPIDS) { + int b = vehicleEntry->var_16 * 32; - if (rideVehicleEntry->var_12 & 0x800) b /= 2; - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_15) b /= 8; + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_11) b /= 2; + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_15) b /= 8; + + image_index += b; + + // Incline 25 + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_GENTLE_SLOPES) { + vehicleEntry->var_20 = image_index; + b = vehicleEntry->var_16 * 72; + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_14) + b = vehicleEntry->var_16 * 16; image_index += b; - - // Incline 25 - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_GENTLE_SLOPES) { - rideVehicleEntry->var_20 = image_index; - b = rideVehicleEntry->var_16 * 72; - if (rideVehicleEntry->var_12 & 0x4000) - b = rideVehicleEntry->var_16 * 16; - - image_index += b; - } - - // Incline 60 - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_STEEP_SLOPES) { - rideVehicleEntry->var_24 = image_index; - b = rideVehicleEntry->var_16 * 80; - image_index += b; - } - // Verticle - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_VERTICAL_SLOPES) { - rideVehicleEntry->var_28 = image_index; - b = rideVehicleEntry->var_16 * 116; - image_index += b; - } - // Unknown - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_DIAGONAL_SLOPES) { - rideVehicleEntry->var_2C = image_index; - b = rideVehicleEntry->var_16 * 24; - image_index += b; - } - - // Bank - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT_BANKED) { - rideVehicleEntry->var_30 = image_index; - b = rideVehicleEntry->var_16 * 80; - image_index += b; - } - - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_INLINE_TWISTS) { - rideVehicleEntry->var_34 = image_index; - b = rideVehicleEntry->var_16 * 40; - image_index += b; - } - - // Track half? Up/Down - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_BANKED_TRANSITIONS) { - rideVehicleEntry->var_38 = image_index; - b = rideVehicleEntry->var_16 * 128; - image_index += b; - } - // Unknown - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_DIAGONAL_GENTLE_SLOPE_BANKED_TRANSITIONS) { - rideVehicleEntry->var_3C = image_index; - b = rideVehicleEntry->var_16 * 16; - image_index += b; - } - // Unknown - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TRANSITIONS) { - rideVehicleEntry->var_40 = image_index; - b = rideVehicleEntry->var_16 * 16; - image_index += b; - } - - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TURNS) { - rideVehicleEntry->var_44 = image_index; - b = rideVehicleEntry->var_16 * 128; - image_index += b; - } - - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS) { - rideVehicleEntry->var_48 = image_index; - b = rideVehicleEntry->var_16 * 16; - image_index += b; - } - - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_CORKSCREWS) { - rideVehicleEntry->var_4C = image_index; - b = rideVehicleEntry->var_16 * 80; - image_index += b; - } - // Unknown - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION) { - rideVehicleEntry->var_1C = image_index; - b = rideVehicleEntry->var_16 * 12; - image_index += b; - } - - if (rideVehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_14) { - // Same offset as above??? - rideVehicleEntry->var_4C = image_index; - b = rideVehicleEntry->var_16 * 32; - image_index += b; - } - - } - else{ - image_index += rideVehicleEntry->var_16 * 36; - } - // No vehicle images - rideVehicleEntry->no_vehicle_images = image_index - cur_vehicle_images_offset; - - // Move the offset over this vehicles images. Including peeps - cur_vehicle_images_offset = image_index + rideVehicleEntry->no_seating_rows * rideVehicleEntry->no_vehicle_images; - // 0x6DEB0D - - if (!(rideVehicleEntry->var_12 & 0x400)){ - int num_images = cur_vehicle_images_offset - rideVehicleEntry->base_image_id; - if (rideVehicleEntry->var_12 & 0x2000){ - num_images *= 2; - } - - set_vehicle_type_image_max_sizes(rideVehicleEntry, num_images); } - sint8 no_positions = *peep_loading_positions++; - if (no_positions == -1) - { - // The no_positions is 16 bit skip over - peep_loading_positions += 2; - } - rideVehicleEntry->peep_loading_positions = peep_loading_positions; - } - } - - // 0x6DEB71 - if (RCT2_GLOBAL(0x9ADAFD, uint8_t) == 0) - { - for (int i = 0; i < 3; ++i){ - int dl = ride_type->ride_type[i]; - - if (dl == 0xFF)continue; - - uint8 *typeToRideEntryIndexMap = RCT2_ADDRESS(0x009E32F8, uint8); - - while (dl >= 0){ - if (*typeToRideEntryIndexMap++ == 0xFF)dl--; + // Incline 60 + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_STEEP_SLOPES) { + vehicleEntry->var_24 = image_index; + b = vehicleEntry->var_16 * 80; + image_index += b; } - typeToRideEntryIndexMap--; - uint8 previous_entry = ebx; - while (typeToRideEntryIndexMap < RCT2_ADDRESS(0x9E34E4, uint8)){ - uint8 backup_entry = *typeToRideEntryIndexMap; - *typeToRideEntryIndexMap++ = previous_entry; - previous_entry = backup_entry; + // Verticle + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_VERTICAL_SLOPES) { + vehicleEntry->var_28 = image_index; + b = vehicleEntry->var_16 * 116; + image_index += b; } - } - } - // 0x6DEBAA - if (RCT2_GLOBAL(0x9ADAF4, sint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - - int di = ride_type->ride_type[0] | (ride_type->ride_type[1] << 8) | (ride_type->ride_type[2] << 16); - - if ((ride_type->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) && !rideTypeShouldLoseSeparateFlag(ride_type)) di |= 0x1000000; - - RCT2_GLOBAL(0xF433DD, uint32) = di; - return 0;// flags; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_ride_type* ride_type = (rct_ride_type*)esi; - ride_type->name = 0; - ride_type->description = 0; - ride_type->images_offset = 0; - - for (int i = 0; i < 4; ++i){ - rct_ride_type_vehicle* rideVehicleEntry = &ride_type->vehicles[i]; - - rideVehicleEntry->base_image_id = 0; - rideVehicleEntry->var_1C = 0; - rideVehicleEntry->var_20 = 0; - rideVehicleEntry->var_24 = 0; - rideVehicleEntry->var_28 = 0; - rideVehicleEntry->var_2C = 0; - rideVehicleEntry->var_30 = 0; - rideVehicleEntry->var_34 = 0; - rideVehicleEntry->var_38 = 0; - rideVehicleEntry->var_3C = 0; - rideVehicleEntry->var_40 = 0; - rideVehicleEntry->var_44 = 0; - rideVehicleEntry->var_48 = 0; - rideVehicleEntry->var_4C = 0; - rideVehicleEntry->no_vehicle_images = 0; - rideVehicleEntry->var_16 = 0; - - if (!(rideVehicleEntry->var_12 & 0x400)){ - rideVehicleEntry->sprite_width = 0; - rideVehicleEntry->sprite_height_negative = 0; - rideVehicleEntry->sprite_height_positive = 0; - } - rideVehicleEntry->var_02 = 0; - rideVehicleEntry->var_03 = 0; - rideVehicleEntry->peep_loading_positions = 0; - } - - ride_type->vehicle_preset_list = NULL; - return flags; - } - else if ((flags & 0xFF) == 2){ - - rct_ride_type* ride_type = (rct_ride_type*)esi; - - if (ride_type->excitement_multipler > 75) return 1; - if (ride_type->intensity_multipler > 75) return 1; - if (ride_type->nausea_multipler > 75) return 1; - return 0; - } - else if ((flags & 0xFF) == 3){ - // Paint object picture and description - - rct_ride_type* ride_type = (rct_ride_type*)ebp; - int x = ecx, y = edx; - - if (!((flags >> 8) & 0xFF)) - { - int image_id = ride_type->images_offset; - if (ride_type->ride_type[0] == 0xFF) - { - image_id++; - if (ride_type->ride_type[1] == 0xFF) image_id++; - } - gfx_draw_sprite(dpi, image_id, x - 56, y - 56, ebp); - return flags; - } - else - { - rct_window* w = (rct_window*)esi; - int width = w->x + w->width - x - 4; - - int format_args = ride_type->description; - if (!(ride_type->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) || rideTypeShouldLoseSeparateFlag(ride_type)) - { - format_args = ride_type->ride_type[0]; - if ((format_args & 0xFF) == 0xFF) - { - format_args = ride_type->ride_type[1]; - if ((format_args & 0xFF) == 0xFF) format_args = ride_type->ride_type[2]; + // Unknown + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_DIAGONAL_SLOPES) { + vehicleEntry->var_2C = image_index; + b = vehicleEntry->var_16 * 24; + image_index += b; } - format_args += 0x200; - } - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = format_args; - gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y + 5, width, 1191, 0); - return flags; - } - } - return flags; -} - -/* rct2: 0x006E3466 */ -int paint_small_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) -{ - if ((flags & 0xFF) == 0){ - // Object Load - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - uint8* chunk = (uint8*)(esi + 0x1C); - - scenery_type->name = object_get_localised_text(&chunk, ecx, ebx, 0); - - scenery_type->small_scenery.scenery_tab_id = 0xFF; - - if (*chunk != 0xFF){ - uint8 entry_type, entry_index; - if (find_object_in_entry_group((rct_object_entry*)chunk, &entry_type, &entry_index)){ - scenery_type->small_scenery.scenery_tab_id = entry_index; - } - } - - chunk += sizeof(rct_object_entry); - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG16){ - scenery_type->small_scenery.var_10 = (uint32)chunk; - while (*++chunk != 0xFF); - chunk++; - } - - scenery_type->image = object_chunk_load_image_directory(&chunk); - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - scenery_type->name = 0; - scenery_type->image = 0; - scenery_type->small_scenery.var_10 = 0; - scenery_type->small_scenery.scenery_tab_id = 0; - } - else if ((flags & 0xFF) == 2){ - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - - if (scenery_type->small_scenery.price <= 0)return 1; - - if (scenery_type->small_scenery.removal_price > 0) return 0; - - // Make sure you don't make a profit when placing then removing. - if (-scenery_type->small_scenery.removal_price > scenery_type->small_scenery.price)return 1; - - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - if (!((flags >> 8) & 0xFF)) - { - rct_scenery_entry* scenery_type = (rct_scenery_entry*)ebp; - - dpi = clip_drawpixelinfo(dpi, x - 56, 112, y - 56, 112); - if (dpi == NULL) return flags; - - int image_id = scenery_type->image; - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR){ - image_id |= 0x20D00000; - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) - image_id |= 0x92000000; - } - - x = 56; - y = scenery_type->small_scenery.height / 4 + 78; - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE){ - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE){ - y -= 12; + // Bank + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT_BANKED) { + vehicleEntry->var_30 = image_index; + b = vehicleEntry->var_16 * 80; + image_index += b; } + + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_INLINE_TWISTS) { + vehicleEntry->var_34 = image_index; + b = vehicleEntry->var_16 * 40; + image_index += b; + } + + // Track half? Up/Down + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_BANKED_TRANSITIONS) { + vehicleEntry->var_38 = image_index; + b = vehicleEntry->var_16 * 128; + image_index += b; + } + + // Unknown + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_DIAGONAL_GENTLE_SLOPE_BANKED_TRANSITIONS) { + vehicleEntry->var_3C = image_index; + b = vehicleEntry->var_16 * 16; + image_index += b; + } + + // Unknown + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TRANSITIONS) { + vehicleEntry->var_40 = image_index; + b = vehicleEntry->var_16 * 16; + image_index += b; + } + + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_GENTLE_SLOPE_BANKED_TURNS) { + vehicleEntry->var_44 = image_index; + b = vehicleEntry->var_16 * 128; + image_index += b; + } + + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_FLAT_TO_GENTLE_SLOPE_WHILE_BANKED_TRANSITIONS) { + vehicleEntry->var_48 = image_index; + b = vehicleEntry->var_16 * 16; + image_index += b; + } + + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_CORKSCREWS) { + vehicleEntry->var_4C = image_index; + b = vehicleEntry->var_16 * 80; + image_index += b; + } + + // Unknown + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_RESTRAINT_ANIMATION) { + vehicleEntry->var_1C = image_index; + b = vehicleEntry->var_16 * 12; + image_index += b; + } + + if (vehicleEntry->sprite_flags & VEHICLE_SPRITE_FLAG_14) { + // Same offset as above??? + vehicleEntry->var_4C = image_index; + b = vehicleEntry->var_16 * 32; + image_index += b; + } + } else { + image_index += vehicleEntry->var_16 * 36; + } + // No vehicle images + vehicleEntry->no_vehicle_images = image_index - cur_vehicle_images_offset; + + // Move the offset over this vehicles images. Including peeps + cur_vehicle_images_offset = image_index + vehicleEntry->no_seating_rows * vehicleEntry->no_vehicle_images; + // 0x6DEB0D + + if (!(vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_10)) { + int num_images = cur_vehicle_images_offset - vehicleEntry->base_image_id; + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_13) { + num_images *= 2; + } + + set_vehicle_type_image_max_sizes(vehicleEntry, num_images); } - gfx_draw_sprite(dpi, image_id, x, y, 0); - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG10){ - image_id = scenery_type->image + 0x44500004; - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) - image_id |= 0x92000000; - - gfx_draw_sprite(dpi, image_id, x, y, 0); + sint8 no_positions = *peep_loading_positions++; + if (no_positions == -1) { + // The no_positions is 16 bit skip over + peep_loading_positions += 2; } - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG8){ - image_id = scenery_type->image + 4; - - if (scenery_type->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) - image_id |= 0x92000000; - - gfx_draw_sprite(dpi, image_id, x, y, 0); - } - - rct2_free(dpi); + vehicleEntry->peep_loading_positions = peep_loading_positions; } } - return flags; -} -/* rct2: 0x006B92A7 */ -int paint_large_scenery(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) -{ - if ((flags & 0xFF) == 0){ - // Object Load - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - uint8* chunk = (uint8*)(esi + 0x1A); - - scenery_type->name = object_get_localised_text(&chunk, ecx, ebx, 0); - - scenery_type->large_scenery.scenery_tab_id = 0xFF; - - if (*chunk != 0xFF){ - uint8 entry_type, entry_index; - if (find_object_in_entry_group((rct_object_entry*)chunk, &entry_type, &entry_index)){ - scenery_type->large_scenery.scenery_tab_id = entry_index; - } - } - - chunk += sizeof(rct_object_entry); - - if (scenery_type->large_scenery.flags & (1<<2)){ - scenery_type->large_scenery.var_12 = (uint32)chunk; - chunk += 1038; - } - - scenery_type->large_scenery.tiles = (rct_large_scenery_tile*)chunk; - - // skip over large scenery tiles - while (*((uint16*)chunk) != 0xFFFF){ - chunk += sizeof(rct_large_scenery_tile); - } - - chunk += 2; - - int image_id = object_chunk_load_image_directory(&chunk); - if (scenery_type->large_scenery.flags & (1 << 2)){ - scenery_type->large_scenery.var_16 = image_id; - - uint8* edx = (uint8*)scenery_type->large_scenery.var_12; - if (!(edx[0xC] & 1)){ - image_id += edx[0xD] * 4; - } - else{ - image_id += edx[0xD] * 2; - } - } - scenery_type->image = image_id; - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - scenery_type->name = 0; - scenery_type->image = 0; - scenery_type->large_scenery.tiles = 0; - scenery_type->large_scenery.scenery_tab_id = 0; - scenery_type->large_scenery.var_12 = 0; - scenery_type->large_scenery.var_16 = 0; - } - else if ((flags & 0xFF) == 2){ - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - - if (scenery_type->large_scenery.price <= 0)return 1; - - if (scenery_type->large_scenery.removal_price > 0) return 0; - - // Make sure you don't make a profit when placing then removing. - if (-scenery_type->large_scenery.removal_price > scenery_type->large_scenery.price)return 1; - - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - if (!((flags >> 8) & 0xFF)) - { - rct_scenery_entry* scenery_type = (rct_scenery_entry*)ebp; - - int image_id = scenery_type->image | 0xB2D00000; - - gfx_draw_sprite(dpi, image_id, x, y - 39, 0); - } - } - return flags; -} - -/* rct2: 0x006E5A25 */ -int paint_wall(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) -{ - if ((flags & 0xFF) == 0){ - // Object Load - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - uint8* chunk = (uint8*)(esi + 0xE); - - scenery_type->name = object_get_localised_text(&chunk, ecx, ebx, 0); - - scenery_type->wall.scenery_tab_id = 0xFF; - - if (*chunk != 0xFF){ - uint8 entry_type, entry_index; - if (find_object_in_entry_group((rct_object_entry*)chunk, &entry_type, &entry_index)){ - scenery_type->wall.scenery_tab_id = entry_index; - } - } - - chunk += sizeof(rct_object_entry); - - scenery_type->image = object_chunk_load_image_directory(&chunk); - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - scenery_type->name = 0; - scenery_type->image = 0; - scenery_type->wall.scenery_tab_id = 0; - } - else if ((flags & 0xFF) == 2){ - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - - if (scenery_type->wall.price <= 0)return 1; - - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - - if (!((flags >> 8) & 0xFF)) - { - rct_scenery_entry* scenery_type = (rct_scenery_entry*)ebp; - - dpi = clip_drawpixelinfo(dpi, x - 56, 112, y - 56, 112); - if (dpi == NULL) return flags; - - int image_id = scenery_type->image; - - - image_id |= 0x20D00000; - - if (scenery_type->wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) - image_id |= 0x92000000; - - - x = 70; - y = scenery_type->wall.height * 2 + 72; - - gfx_draw_sprite(dpi, image_id, x, y, 0); - - if (scenery_type->wall.flags & WALL_SCENERY_FLAG2){ - image_id = scenery_type->image + 0x44500006; - - gfx_draw_sprite(dpi, image_id, x, y, 0); - } - else if (scenery_type->wall.flags & WALL_SCENERY_FLAG5){ - image_id++; - - gfx_draw_sprite(dpi, image_id, x, y, 0); - } - rct2_free(dpi); - } - } - return flags; -} - -/* rct2: 0x006BA84E */ -int paint_banner(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) -{ - if ((flags & 0xFF) == 0){ - // Object Load - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - uint8* chunk = (uint8*)(esi + 0xC); - - scenery_type->name = object_get_localised_text(&chunk, ecx, ebx, 0); - - scenery_type->banner.scenery_tab_id = 0xFF; - - if (*chunk != 0xFF){ - uint8 entry_type, entry_index; - if (find_object_in_entry_group((rct_object_entry*)chunk, &entry_type, &entry_index)){ - scenery_type->banner.scenery_tab_id = entry_index; - } - } - - chunk += sizeof(rct_object_entry); - - scenery_type->image = object_chunk_load_image_directory(&chunk); - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - scenery_type->name = 0; - scenery_type->image = 0; - scenery_type->banner.scenery_tab_id = 0; - } - else if ((flags & 0xFF) == 2){ - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - if (scenery_type->banner.price <= 0)return 1; - - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - - if (!((flags >> 8) & 0xFF)) - { - rct_scenery_entry* scenery_type = (rct_scenery_entry*)ebp; - - int image_id = scenery_type->image; - - image_id |= 0x20D00000; - - - gfx_draw_sprite(dpi, image_id, x, y, 0); - - gfx_draw_sprite(dpi, image_id + 1, x, y, 0); - } - } - return flags; -} - -//rct2: 0x006A8621 -int paint_path_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) -{ - if ((flags & 0xFF) == 0){ - // Object Load - - rct_path_type* path_type = (rct_path_type*)esi; - // String table starts after path entry - // Note there are 2 spare bytes after - // the path entry. - uint8* chunk = (uint8*)(esi + 0xE); - - // Only 1 string table for paths - path_type->string_idx = object_get_localised_text(&chunk, ecx, ebx, 0); - - int image_id = object_chunk_load_image_directory(&chunk); - path_type->image = image_id; - path_type->bridge_image = image_id + 109; - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - - RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = 0; - // Set the default path for when opening footpath window - for (int i = 0; i < object_entry_group_counts[OBJECT_TYPE_PATHS]; ++i){ - rct_path_type* path_type_entry = (rct_path_type*)object_entry_groups[OBJECT_TYPE_PATHS].chunks[i]; - if ((uint32)path_type_entry == 0xFFFFFFFF) continue; - if (!(path_type_entry->flags & 4)) - { - RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = i; - break; - } - RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = i; - - } - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_path_type* path_type = (rct_path_type*)esi; - path_type->string_idx = 0; - path_type->image = 0; - path_type->bridge_image = 0; - } - else if ((flags & 0xFF) == 2){ - - rct_path_type* path_type = (rct_path_type*)esi; - if (path_type->var_0A >= 2) return 1;//actually the carry bit should be set (stc) - else return 0; - } - else if ((flags & 0xFF) == 3){ - rct_path_type* path_type = (rct_path_type*)ebp; - if (!((flags >> 8) & 0xFF)) - { - //Draws preview for scenario editor! - gfx_draw_sprite(dpi, path_type->image + 71, ecx - 49, edx - 17, ebp); - gfx_draw_sprite(dpi, path_type->image + 72, ecx + 4, edx - 17, ebp); - } - - } - return flags; -} - -/* rct2: 0x006A86E2 */ -int paint_path_bit(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) -{ - if ((flags & 0xFF) == 0){ - // Object Load - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - uint8* chunk = (uint8*)(esi + 0xE); - - scenery_type->name = object_get_localised_text(&chunk, ecx, ebx, 0); - - scenery_type->path_bit.scenery_tab_id = 0xFF; - - if (*chunk != 0xFF){ - uint8 entry_type, entry_index; - if (find_object_in_entry_group((rct_object_entry*)chunk, &entry_type, &entry_index)){ - scenery_type->path_bit.scenery_tab_id = entry_index; - } - } - - chunk += sizeof(rct_object_entry); - - scenery_type->image = object_chunk_load_image_directory(&chunk); - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - scenery_type->name = 0; - scenery_type->image = 0; - scenery_type->path_bit.scenery_tab_id = 0; - } - else if ((flags & 0xFF) == 2){ - rct_scenery_entry* scenery_type = (rct_scenery_entry*)esi; - - if (scenery_type->path_bit.price <= 0)return 1; - - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - - if (!((flags >> 8) & 0xFF)) - { - rct_scenery_entry* scenery_type = (rct_scenery_entry*)ebp; - - int image_id = scenery_type->image; - - x -= 22; - y -= 24; - - gfx_draw_sprite(dpi, image_id, x, y, 0); - } - } - return flags; -} - -/* rct2: 0x006B93AA */ -int paint_scenery_set(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) -{ - if ((flags & 0xFF) == 0){ - // Object Load - - rct_scenery_set_entry* scenery_set = (rct_scenery_set_entry*)esi; - uint8* chunk = (uint8*)(esi + sizeof(rct_scenery_set_entry)); - - scenery_set->name = object_get_localised_text(&chunk, ecx, ebx, 0); - - rct_object_entry* entry_objects = NULL; - uint8* eax = RCT2_GLOBAL(0x9ADAF4, uint8*); - if ((uint32)eax != 0xFFFFFFFF){ - *((uint16*)eax) = 0; - entry_objects = (rct_object_entry*)(eax + 2); - } - - scenery_set->entry_count = 0; - scenery_set->var_107 = 0; - - for (; *chunk != 0xFF; chunk += sizeof(rct_object_entry)){ - scenery_set->var_107++; - - if (entry_objects != NULL){ - memcpy(entry_objects, chunk, sizeof(rct_object_entry)); - entry_objects++; - (*(eax + 1))++; - } - uint8 entry_type; - uint8 entry_index = 0; - if (!find_object_in_entry_group((rct_object_entry*)chunk, &entry_type, &entry_index)) + // 0x6DEB71 + if (RCT2_GLOBAL(0x9ADAFD, uint8) == 0) { + for (int i = 0; i < 3; i++) { + int dl = rideEntry->ride_type[i]; + if (dl == 0xFF) { continue; - - uint16 scenery_entry = entry_index; - - switch (entry_type){ - case OBJECT_TYPE_SMALL_SCENERY: - break; - case OBJECT_TYPE_LARGE_SCENERY: - scenery_entry |= 0x300; - break; - case OBJECT_TYPE_WALLS: - scenery_entry |= 0x200; - break; - case OBJECT_TYPE_PATH_BITS: - scenery_entry |= 0x100; - break; - default: - scenery_entry |= 0x400; - break; } - scenery_set->scenery_entries[scenery_set->entry_count++] = scenery_entry; - } + uint8 *typeToRideEntryIndexMap = RCT2_ADDRESS(0x009E32F8, uint8); + while (dl >= 0) { + if (*typeToRideEntryIndexMap++ == 0xFF) { + dl--; + } + } - chunk++; - - scenery_set->image = object_chunk_load_image_directory(&chunk); - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_scenery_set_entry* scenery_set = (rct_scenery_set_entry*)esi; - scenery_set->name = 0; - scenery_set->image = 0; - scenery_set->entry_count = 0; - scenery_set->var_107 = 0; - - memset(scenery_set->scenery_entries, 0, 256); - } - else if ((flags & 0xFF) == 2){ - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - - rct_scenery_set_entry* scenery_set = (rct_scenery_set_entry*)ebp; - - if (!((flags >> 8) & 0xFF)) - { - int image_id = scenery_set->image; - - image_id += 0x20600001; - - gfx_draw_sprite(dpi, image_id, x - 15, y - 14, 0); - } - else{ - RCT2_GLOBAL(0x13CE952, uint16) = scenery_set->var_107; - - gfx_draw_string_left(dpi, 3167, RCT2_ADDRESS(0x13CE952, void), 0, x, y); + typeToRideEntryIndexMap--; + uint8 previous_entry = entryIndex; + while (typeToRideEntryIndexMap < RCT2_ADDRESS(0x9E34E4, uint8)){ + uint8 backup_entry = *typeToRideEntryIndexMap; + *typeToRideEntryIndexMap++ = previous_entry; + previous_entry = backup_entry; + } } } - return flags; + + // 0x6DEBAA + if (RCT2_GLOBAL(0x9ADAF4, sint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + int di = rideEntry->ride_type[0] | (rideEntry->ride_type[1] << 8) | (rideEntry->ride_type[2] << 16); + + if ((rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) && !rideTypeShouldLoseSeparateFlag(rideEntry)) { + di |= 0x1000000; + } + + RCT2_GLOBAL(0xF433DD, uint32) = di; + return true; } - -//rct2: 0x00666E42 -int paint_park_entrance_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) +static void object_type_ride_unload(void *objectEntry) { - if ((flags & 0xFF) == 0){ - // Object Load + rct_ride_entry *rideEntry = (rct_ride_entry*)objectEntry; + rideEntry->name = 0; + rideEntry->description = 0; + rideEntry->images_offset = 0; - rct_entrance_type* entrance_type = (rct_entrance_type*)esi; - uint8* pStringTable = (uint8*)(esi + sizeof(rct_entrance_type)); + for (int i = 0; i < 4; i++) { + rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[i]; - entrance_type->string_idx = object_get_localised_text(&pStringTable, ecx, ebx, 0); + rideVehicleEntry->base_image_id = 0; + rideVehicleEntry->var_1C = 0; + rideVehicleEntry->var_20 = 0; + rideVehicleEntry->var_24 = 0; + rideVehicleEntry->var_28 = 0; + rideVehicleEntry->var_2C = 0; + rideVehicleEntry->var_30 = 0; + rideVehicleEntry->var_34 = 0; + rideVehicleEntry->var_38 = 0; + rideVehicleEntry->var_3C = 0; + rideVehicleEntry->var_40 = 0; + rideVehicleEntry->var_44 = 0; + rideVehicleEntry->var_48 = 0; + rideVehicleEntry->var_4C = 0; + rideVehicleEntry->no_vehicle_images = 0; + rideVehicleEntry->var_16 = 0; - entrance_type->image_id = object_chunk_load_image_directory(&pStringTable); - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_entrance_type* entrance_type = (rct_entrance_type*)esi; - entrance_type->string_idx = 0; - entrance_type->image_id = 0; - } - else if ((flags & 0xFF) == 2){ - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - if (!((flags >> 8) & 0xFF)) - { - rct_entrance_type* entrance_type = (rct_entrance_type*)ebp; - - dpi = clip_drawpixelinfo(dpi, x - 56, 112, y - 56, 112); - if (dpi == NULL) return flags; - - int image_id = entrance_type->image_id; - - gfx_draw_sprite(dpi, image_id + 1, 24, 68, ebp); - gfx_draw_sprite(dpi, image_id, 56, 84, ebp); - gfx_draw_sprite(dpi, image_id + 2, 88, 100, ebp); - - rct2_free(dpi); + if (!(rideVehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_10)) { + rideVehicleEntry->sprite_width = 0; + rideVehicleEntry->sprite_height_negative = 0; + rideVehicleEntry->sprite_height_positive = 0; } + rideVehicleEntry->var_02 = 0; + rideVehicleEntry->var_03 = 0; + rideVehicleEntry->peep_loading_positions = 0; } - return flags; + + rideEntry->vehicle_preset_list = NULL; } -//rct2: 0x006E6E2A -int paint_water_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) +static bool object_type_ride_test(void *objectEntry) { - if ((flags & 0xFF) == 0){ - // Object Load - - rct_water_type* water_type = (rct_water_type*)esi; - - uint8_t* pStringTable = (uint8_t*)(esi + sizeof(rct_water_type)); - water_type->string_idx = object_get_localised_text(&pStringTable, ecx, ebx, 0); - - int image_id = object_chunk_load_image_directory(&pStringTable); - water_type->image_id = image_id; - water_type->var_06 = image_id + 1; - water_type->var_0A = image_id + 4; - - if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; - - if (RCT2_GLOBAL(0x9ADAFD, uint8_t) == 0) - { - load_palette(); - gfx_invalidate_screen(); - } - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_water_type* water_type = (rct_water_type*)esi; - water_type->string_idx = 0; - water_type->image_id = 0; - water_type->var_06 = 0; - water_type->var_0A = 0; - } - else if ((flags & 0xFF) == 2){ - return 0; - } - else if ((flags & 0xFF) == 3){ - if (!((flags >> 8) & 0xFF)) - gfx_draw_string_centred(dpi, 3326, ecx, edx, 0, (void*)esi); - } - return flags; + rct_ride_entry* rideEntry = (rct_ride_entry*)objectEntry; + if (rideEntry->excitement_multipler > 75) return false; + if (rideEntry->intensity_multipler > 75) return false; + if (rideEntry->nausea_multipler > 75) return false; + return true; } -//rct2: 0x0066B355 -int paint_stex_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dpi, int esi, int ebp) +static void object_type_ride_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) { - if ((flags & 0xFF) == 0){ - // Object Load - - rct_stex_entry* stex_entry = (rct_stex_entry*)esi; - uint8_t* pStringTable = (uint8_t*)(esi + 8); - stex_entry->scenario_name = object_get_localised_text(&pStringTable, ecx, ebx, 0); - stex_entry->park_name = object_get_localised_text(&pStringTable, ecx, ebx, 1); - stex_entry->details = object_get_localised_text(&pStringTable, ecx, ebx, 2); - if (RCT2_GLOBAL(0x9ADAF4, int) != -1) RCT2_GLOBAL(0x9ADAF4, uint16_t*)[0] = 0; - } - else if ((flags & 0xFF) == 1){ - // Object Unload - - rct_stex_entry* stex_entry = (rct_stex_entry*)esi; - stex_entry->scenario_name = 0; - stex_entry->park_name = 0; - stex_entry->details = 0; - } - else if ((flags & 0xFF) == 2){ - return 0; - } - else if ((flags & 0xFF) == 3){ - int x = ecx, y = edx; - rct_stex_entry* stex_entry = (rct_stex_entry*)ebp; - rct_window* w = (rct_window*)esi; - - if (!((flags >> 8) & 0xFF)) { - gfx_draw_string_centred(dpi, 0xCFE, x, y, 0, NULL); - } - else{ - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = stex_entry->details; - int width = w->x + w->width - 4 - x; - gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, width, 3168, 0); + rct_ride_entry *rideEntry = (rct_ride_entry*)objectEntry; + int imageId = rideEntry->images_offset; + if (rideEntry->ride_type[0] == 0xFF) { + imageId++; + if (rideEntry->ride_type[1] == 0xFF) { + imageId++; } } - return flags; + gfx_draw_sprite(dpi, imageId, x - 56, y - 56, 0); } -int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp) +static rct_string_id object_type_ride_desc(void *objectEntry) { - switch (type) - { - case OBJECT_TYPE_RIDE: - return paint_ride_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_SMALL_SCENERY: - return paint_small_scenery(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_LARGE_SCENERY: - return paint_large_scenery(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_WALLS: - return paint_wall(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_BANNERS: - return paint_banner(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_PATHS: - return paint_path_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_PATH_BITS: - return paint_path_bit(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_SCENERY_SETS: - return paint_scenery_set(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_PARK_ENTRANCE: - return paint_park_entrance_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_WATER: - return paint_water_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - case OBJECT_TYPE_SCENARIO_TEXT: - return paint_stex_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp); - default: - assert(false); - return 0; + rct_ride_entry *rideEntry = (rct_ride_entry*)objectEntry; + + // Get description + rct_string_id stringId = rideEntry->description; + if (!(rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) || rideTypeShouldLoseSeparateFlag(rideEntry)) { + uint8 rideType = rideEntry->ride_type[0]; + if (rideType == 0xFF) { + rideType = rideEntry->ride_type[1]; + if (rideType == 0xFF) { + rideType = rideEntry->ride_type[2]; + } + } + stringId = 512 + rideType; } + return stringId; +} + +static const object_type_vtable object_type_ride_vtable[] = { + object_type_ride_load, + object_type_ride_unload, + object_type_ride_test, + object_type_ride_paint, + object_type_ride_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Small Scenery (rct2: 0x006E3466) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_small_scenery_load(void *objectEntry, uint32 entryIndex) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + (size_t)0x1C); + + sceneryEntry->name = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_SMALL_SCENERY, entryIndex, 0); + sceneryEntry->small_scenery.scenery_tab_id = 0xFF; + if (*extendedEntryData != 0xFF) { + uint8 entry_type, entry_index; + if (find_object_in_entry_group((rct_object_entry*)extendedEntryData, &entry_type, &entry_index)) { + sceneryEntry->small_scenery.scenery_tab_id = entry_index; + } + } + + extendedEntryData += sizeof(rct_object_entry); + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG16){ + sceneryEntry->small_scenery.var_10 = (uint32)extendedEntryData; + while (*++extendedEntryData != 0xFF); + extendedEntryData++; + } + + sceneryEntry->image = object_chunk_load_image_directory(&extendedEntryData); + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + return true; +} + +static void object_type_small_scenery_unload(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + sceneryEntry->name = 0; + sceneryEntry->image = 0; + sceneryEntry->small_scenery.var_10 = 0; + sceneryEntry->small_scenery.scenery_tab_id = 0; +} + +static bool object_type_small_scenery_test(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + + if (sceneryEntry->small_scenery.price <= 0) return false; + if (sceneryEntry->small_scenery.removal_price > 0) return true; + + // Make sure you don't make a profit when placing then removing. + if (-sceneryEntry->small_scenery.removal_price > sceneryEntry->small_scenery.price) return false; + + return true; +} + +static void object_type_small_scenery_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + rct_drawpixelinfo clipDPI; + if (!clip_drawpixelinfo(&clipDPI, dpi, x - 56, y - 56, 112, 112)) { + return; + } + + int imageId = sceneryEntry->image; + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR) { + imageId |= 0x20D00000; + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) { + imageId |= 0x92000000; + } + } + + x = 56; + y = sceneryEntry->small_scenery.height / 4 + 78; + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE) { + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_VOFFSET_CENTRE) { + y -= 12; + } + } + + gfx_draw_sprite(&clipDPI, imageId, x, y, 0); + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG10) { + imageId = sceneryEntry->image + 0x44500004; + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) { + imageId |= 0x92000000; + } + + gfx_draw_sprite(&clipDPI, imageId, x, y, 0); + } + + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG8) { + imageId = sceneryEntry->image + 4; + if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) { + imageId |= 0x92000000; + } + + gfx_draw_sprite(&clipDPI, imageId, x, y, 0); + } +} + +static rct_string_id object_type_small_scenery_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_small_scenery_vtable[] = { + object_type_small_scenery_load, + object_type_small_scenery_unload, + object_type_small_scenery_test, + object_type_small_scenery_paint, + object_type_small_scenery_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Large Scenery (rct2: 0x006B92A7) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_large_scenery_load(void *objectEntry, uint32 entryIndex) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + (size_t)0x1A); + + sceneryEntry->name = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_LARGE_SCENERY, entryIndex, 0); + sceneryEntry->large_scenery.scenery_tab_id = 0xFF; + if (*extendedEntryData != 0xFF) { + uint8 entry_type, entry_index; + if (find_object_in_entry_group((rct_object_entry*)extendedEntryData, &entry_type, &entry_index)) { + sceneryEntry->large_scenery.scenery_tab_id = entry_index; + } + } + + extendedEntryData += sizeof(rct_object_entry); + if (sceneryEntry->large_scenery.flags & (1 << 2)) { + sceneryEntry->large_scenery.var_12 = (uint32)extendedEntryData; + extendedEntryData += 1038; + } + + sceneryEntry->large_scenery.tiles = (rct_large_scenery_tile*)extendedEntryData; + + // skip over large scenery tiles + while (*((uint16*)extendedEntryData) != 0xFFFF){ + extendedEntryData += sizeof(rct_large_scenery_tile); + } + + extendedEntryData += 2; + + int imageId = object_chunk_load_image_directory(&extendedEntryData); + if (sceneryEntry->large_scenery.flags & (1 << 2)){ + sceneryEntry->large_scenery.var_16 = imageId; + + uint8* edx = (uint8*)sceneryEntry->large_scenery.var_12; + if (!(edx[0xC] & 1)) { + imageId += edx[0xD] * 4; + } else{ + imageId += edx[0xD] * 2; + } + } + sceneryEntry->image = imageId; + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + return true; +} + +static void object_type_large_scenery_unload(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + sceneryEntry->name = 0; + sceneryEntry->image = 0; + sceneryEntry->large_scenery.tiles = 0; + sceneryEntry->large_scenery.scenery_tab_id = 0; + sceneryEntry->large_scenery.var_12 = 0; + sceneryEntry->large_scenery.var_16 = 0; +} + +static bool object_type_large_scenery_test(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + + if (sceneryEntry->large_scenery.price <= 0) return false; + if (sceneryEntry->large_scenery.removal_price > 0) return true; + + // Make sure you don't make a profit when placing then removing. + if (-sceneryEntry->large_scenery.removal_price > sceneryEntry->large_scenery.price) return false; + + return true; +} + +static void object_type_large_scenery_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + + int imageId = sceneryEntry->image | 0xB2D00000; + gfx_draw_sprite(dpi, imageId, x, y - 39, 0); +} + +static rct_string_id object_type_large_scenery_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_large_scenery_vtable[] = { + object_type_large_scenery_load, + object_type_large_scenery_unload, + object_type_large_scenery_test, + object_type_large_scenery_paint, + object_type_large_scenery_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Wall (rct2: 0x006E5A25) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_wall_load(void *objectEntry, uint32 entryIndex) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + (size_t)0x0E); + + sceneryEntry->name = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_WALLS, entryIndex, 0); + sceneryEntry->wall.scenery_tab_id = 0xFF; + if (*extendedEntryData != 0xFF){ + uint8 entry_type, entry_index; + if (find_object_in_entry_group((rct_object_entry*)extendedEntryData, &entry_type, &entry_index)) { + sceneryEntry->wall.scenery_tab_id = entry_index; + } + } + + extendedEntryData += sizeof(rct_object_entry); + sceneryEntry->image = object_chunk_load_image_directory(&extendedEntryData); + + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + return true; + +} + +static void object_type_wall_unload(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + sceneryEntry->name = 0; + sceneryEntry->image = 0; + sceneryEntry->wall.scenery_tab_id = 0; +} + +static bool object_type_wall_test(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + if (sceneryEntry->wall.price <= 0) return false; + return true; +} + +static void object_type_wall_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + rct_drawpixelinfo clipDPI; + if (!clip_drawpixelinfo(&clipDPI, dpi, x - 56, y - 56, 112, 112)) { + return; + } + + int imageId = sceneryEntry->image; + imageId |= 0x20D00000; + if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) { + imageId |= 0x92000000; + } + + x = 70; + y = sceneryEntry->wall.height * 2 + 72; + gfx_draw_sprite(&clipDPI, imageId, x, y, 0); + + if (sceneryEntry->wall.flags & WALL_SCENERY_FLAG2){ + imageId = sceneryEntry->image + 0x44500006; + gfx_draw_sprite(&clipDPI, imageId, x, y, 0); + } else if (sceneryEntry->wall.flags & WALL_SCENERY_FLAG5){ + imageId++; + gfx_draw_sprite(&clipDPI, imageId, x, y, 0); + } +} + +static rct_string_id object_type_wall_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_wall_vtable[] = { + object_type_wall_load, + object_type_wall_unload, + object_type_wall_test, + object_type_wall_paint, + object_type_wall_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Banner (rct2: 0x006BA84E) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_banner_load(void *objectEntry, uint32 entryIndex) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + (size_t)0x0C); + + sceneryEntry->name = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_BANNERS, entryIndex, 0); + sceneryEntry->banner.scenery_tab_id = 0xFF; + if (*extendedEntryData != 0xFF){ + uint8 entry_type, entry_index; + if (find_object_in_entry_group((rct_object_entry*)extendedEntryData, &entry_type, &entry_index)){ + sceneryEntry->banner.scenery_tab_id = entry_index; + } + } + + extendedEntryData += sizeof(rct_object_entry); + sceneryEntry->image = object_chunk_load_image_directory(&extendedEntryData); + + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + return true; +} + +static void object_type_banner_unload(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + sceneryEntry->name = 0; + sceneryEntry->image = 0; + sceneryEntry->banner.scenery_tab_id = 0; +} + +static bool object_type_banner_test(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + if (sceneryEntry->banner.price <= 0) return false; + return true; +} + +static void object_type_banner_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + + int imageId = sceneryEntry->image | 0x20D00000; + gfx_draw_sprite(dpi, imageId, x, y, 0); + gfx_draw_sprite(dpi, imageId + 1, x, y, 0); +} + +static rct_string_id object_type_banner_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_banner_vtable[] = { + object_type_banner_load, + object_type_banner_unload, + object_type_banner_test, + object_type_banner_paint, + object_type_banner_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Path (rct2: 0x006A8621) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_path_load(void *objectEntry, uint32 entryIndex) +{ + rct_path_type *pathEntry = (rct_path_type*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + (size_t)0x0E); + + pathEntry->string_idx = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_PATHS, entryIndex, 0); + + int imageId = object_chunk_load_image_directory(&extendedEntryData); + pathEntry->image = imageId; + pathEntry->bridge_image = imageId + 109; + + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = 0; + // Set the default path for when opening footpath window + for (int i = 0; i < object_entry_group_counts[OBJECT_TYPE_PATHS]; i++) { + rct_path_type *pathEntry2 = (rct_path_type*)object_entry_groups[OBJECT_TYPE_PATHS].chunks[i]; + if (pathEntry2 == (rct_path_type*)-1) { + continue; + } + if (!(pathEntry2->flags & 4)) { + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = i; + break; + } + RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_PATH_ID, sint16) = i; + } + + return true; +} + +static void object_type_path_unload(void *objectEntry) +{ + rct_path_type *pathEntry = (rct_path_type*)objectEntry; + pathEntry->string_idx = 0; + pathEntry->image = 0; + pathEntry->bridge_image = 0; +} + +static bool object_type_path_test(void *objectEntry) +{ + rct_path_type *pathEntry = (rct_path_type*)objectEntry; + if (pathEntry->var_0A >= 2) return false; + return true; +} + +static void object_type_path_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_path_type *pathEntry = (rct_path_type*)objectEntry; + gfx_draw_sprite(dpi, pathEntry->image + 71, x - 49, y - 17, 0); + gfx_draw_sprite(dpi, pathEntry->image + 72, x + 4, y - 17, 0); +} + +static rct_string_id object_type_path_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_path_vtable[] = { + object_type_path_load, + object_type_path_unload, + object_type_path_test, + object_type_path_paint, + object_type_path_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Path Item (rct2: 0x006A86E2) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_path_bit_load(void *objectEntry, uint32 entryIndex) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + (size_t)0x0E); + + sceneryEntry->name = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_PATH_BITS, entryIndex, 0); + sceneryEntry->path_bit.scenery_tab_id = 0xFF; + if (*extendedEntryData != 0xFF) { + uint8 entry_type, entry_index; + if (find_object_in_entry_group((rct_object_entry*)extendedEntryData, &entry_type, &entry_index)){ + sceneryEntry->path_bit.scenery_tab_id = entry_index; + } + } + + extendedEntryData += sizeof(rct_object_entry); + sceneryEntry->image = object_chunk_load_image_directory(&extendedEntryData); + + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + return true; +} + +static void object_type_path_bit_unload(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + sceneryEntry->name = 0; + sceneryEntry->image = 0; + sceneryEntry->path_bit.scenery_tab_id = 0; +} + +static bool object_type_path_bit_test(void *objectEntry) +{ + rct_scenery_entry *sceneryEntry = (rct_scenery_entry*)objectEntry; + if (sceneryEntry->path_bit.price <= 0) return false; + return true; +} + +static void object_type_path_bit_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_scenery_entry* sceneryEntry = (rct_scenery_entry*)objectEntry; + gfx_draw_sprite(dpi, sceneryEntry->image, x - 22, y - 24, 0); +} + +static rct_string_id object_type_path_bit_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_path_bit_vtable[] = { + object_type_path_bit_load, + object_type_path_bit_unload, + object_type_path_bit_test, + object_type_path_bit_paint, + object_type_path_bit_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Scenery Set (rct2: 0x006B93AA) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_scenery_set_load(void *objectEntry, uint32 entryIndex) +{ + rct_scenery_set_entry *scenerySetEntry = (rct_scenery_set_entry*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + sizeof(rct_scenery_set_entry)); + + scenerySetEntry->name = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_SCENERY_SETS, entryIndex, 0); + + rct_object_entry *entryObjects = NULL; + uint8 *eax = RCT2_GLOBAL(0x9ADAF4, uint8*); + if ((uint32)eax != 0xFFFFFFFF){ + *((uint16*)eax) = 0; + entryObjects = (rct_object_entry*)(eax + 2); + } + + scenerySetEntry->entry_count = 0; + scenerySetEntry->var_107 = 0; + + for (; *extendedEntryData != 0xFF; extendedEntryData += sizeof(rct_object_entry)) { + scenerySetEntry->var_107++; + + if (entryObjects != NULL){ + memcpy(entryObjects, extendedEntryData, sizeof(rct_object_entry)); + entryObjects++; + (*(eax + 1))++; + } + uint8 entry_type; + uint8 entry_index = 0; + if (!find_object_in_entry_group((rct_object_entry*)extendedEntryData, &entry_type, &entry_index)) + continue; + + uint16 scenery_entry = entry_index; + + switch (entry_type){ + case OBJECT_TYPE_SMALL_SCENERY: + break; + case OBJECT_TYPE_LARGE_SCENERY: + scenery_entry |= 0x300; + break; + case OBJECT_TYPE_WALLS: + scenery_entry |= 0x200; + break; + case OBJECT_TYPE_PATH_BITS: + scenery_entry |= 0x100; + break; + default: + scenery_entry |= 0x400; + break; + } + + scenerySetEntry->scenery_entries[scenerySetEntry->entry_count++] = scenery_entry; + } + + extendedEntryData++; + scenerySetEntry->image = object_chunk_load_image_directory(&extendedEntryData); + + return true; +} + +static void object_type_scenery_set_unload(void *objectEntry) +{ + rct_scenery_set_entry *scenerySetEntry = (rct_scenery_set_entry*)objectEntry; + scenerySetEntry->name = 0; + scenerySetEntry->image = 0; + scenerySetEntry->entry_count = 0; + scenerySetEntry->var_107 = 0; + memset(scenerySetEntry->scenery_entries, 0, 256); +} + +static bool object_type_scenery_set_test(void *objectEntry) +{ + return true; +} + +static void object_type_scenery_set_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_scenery_set_entry *scenerySetEntry = (rct_scenery_set_entry*)objectEntry; + int imageId = scenerySetEntry->image + 0x20600001; + gfx_draw_sprite(dpi, imageId, x - 15, y - 14, 0); +} + +static rct_string_id object_type_scenery_set_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_scenery_set_vtable[] = { + object_type_scenery_set_load, + object_type_scenery_set_unload, + object_type_scenery_set_test, + object_type_scenery_set_paint, + object_type_scenery_set_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Park Entrance (rct2: 0x00666E42) +/////////////////////////////////////////////////////////////////////////////// + +bool object_type_park_entrance_load(void *objectEntry, uint32 entryIndex) +{ + rct_entrance_type *entranceType = (rct_entrance_type*)objectEntry; + uint8 *extendedEntryData = (uint8*)((size_t)objectEntry + sizeof(rct_entrance_type)); + + entranceType->string_idx = object_get_localised_text(&extendedEntryData, OBJECT_TYPE_PARK_ENTRANCE, entryIndex, 0); + entranceType->image_id = object_chunk_load_image_directory(&extendedEntryData); + + if (RCT2_GLOBAL(0x9ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x9ADAF4, uint16*) = 0; + } + + return true; +} + +static void object_type_park_entrance_unload(void *objectEntry) +{ + rct_entrance_type *entranceType = (rct_entrance_type*)objectEntry; + entranceType->string_idx = 0; + entranceType->image_id = 0; +} + +static bool object_type_park_entrance_test(void *objectEntry) +{ + return true; +} + +static void object_type_park_entrance_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + rct_entrance_type *entranceType = (rct_entrance_type*)objectEntry; + + rct_drawpixelinfo clipDPI; + if (!clip_drawpixelinfo(&clipDPI, dpi, x - 56, y - 56, 112, 112)) { + return; + } + + int imageId = entranceType->image_id; + gfx_draw_sprite(&clipDPI, imageId + 1, 24, 68, 0); + gfx_draw_sprite(&clipDPI, imageId, 56, 84, 0); + gfx_draw_sprite(&clipDPI, imageId + 2, 88, 100, 0); +} + +static rct_string_id object_type_park_entrance_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_park_entrance_vtable[] = { + object_type_park_entrance_load, + object_type_park_entrance_unload, + object_type_park_entrance_test, + object_type_park_entrance_paint, + object_type_park_entrance_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Water (rct2: 0x006E6E2A) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_water_load(void *objectEntry, uint32 entryIndex) +{ + rct_water_type *waterEntry = (rct_water_type*)objectEntry; + + uint8 *pStringTable = (uint8*)((size_t)objectEntry + sizeof(rct_water_type)); + waterEntry->string_idx = object_get_localised_text(&pStringTable, OBJECT_TYPE_WATER, entryIndex, 0); + + int imageId = object_chunk_load_image_directory(&pStringTable); + waterEntry->image_id = imageId; + waterEntry->var_06 = imageId + 1; + waterEntry->var_0A = imageId + 4; + + if (RCT2_GLOBAL(0x009ADAF4, uint32) != 0xFFFFFFFF) { + *RCT2_GLOBAL(0x009ADAF4, uint16*) = 0; + } + + if (RCT2_GLOBAL(0x009ADAFD, uint8) == 0) { + load_palette(); + gfx_invalidate_screen(); + } + + return true; +} + +static void object_type_water_unload(void *objectEntry) +{ + rct_water_type *waterEntry = (rct_water_type*)objectEntry; + waterEntry->string_idx = 0; + waterEntry->image_id = 0; + waterEntry->var_06 = 0; + waterEntry->var_0A = 0; +} + +static bool object_type_water_test(void *objectEntry) +{ + return true; +} + +static void object_type_water_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + // Write (no image) + gfx_draw_string_centred(dpi, 3326, x, y, 0, NULL); +} + +static rct_string_id object_type_water_desc(void *objectEntry) +{ + return STR_NONE; +} + +static const object_type_vtable object_type_water_vtable[] = { + object_type_water_load, + object_type_water_unload, + object_type_water_test, + object_type_water_paint, + object_type_water_desc +}; + +/////////////////////////////////////////////////////////////////////////////// +// Stex (rct2: 0x0066B355) +/////////////////////////////////////////////////////////////////////////////// + +static bool object_type_stex_load(void *objectEntry, uint32 entryIndex) +{ + rct_stex_entry *stexEntry = (rct_stex_entry*)objectEntry; + uint8 *stringTable = (uint8*)((size_t)objectEntry + (size_t)0x08); + + stexEntry->scenario_name = object_get_localised_text(&stringTable, OBJECT_TYPE_SCENARIO_TEXT, entryIndex, 0); + stexEntry->park_name = object_get_localised_text(&stringTable, OBJECT_TYPE_SCENARIO_TEXT, entryIndex, 1); + stexEntry->details = object_get_localised_text(&stringTable, OBJECT_TYPE_SCENARIO_TEXT, entryIndex, 2); + + if (RCT2_GLOBAL(0x9ADAF4, int) != -1) { + RCT2_GLOBAL(0x9ADAF4, uint16*)[0] = 0; + } + + return true; +} + +static void object_type_stex_unload(void *objectEntry) +{ + rct_stex_entry *stexEntry = (rct_stex_entry*)objectEntry; + stexEntry->scenario_name = 0; + stexEntry->park_name = 0; + stexEntry->details = 0; +} + +static bool object_type_stex_test(void *objectEntry) +{ + return true; +} + +static void object_type_stex_paint(void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + // Write (no image) + gfx_draw_string_centred(dpi, 3326, x, y, 0, NULL); +} + +static rct_string_id object_type_stex_desc(void *objectEntry) +{ + rct_stex_entry *stexEntry = (rct_stex_entry*)objectEntry; + return stexEntry->details; +} + +static const object_type_vtable object_type_stex_vtable[] = { + object_type_stex_load, + object_type_stex_unload, + object_type_stex_test, + object_type_stex_paint, + object_type_stex_desc +}; + +/////////////////////////////////////////////////////////////////////////////// + +static const object_type_vtable * const object_type_vtables[] = { + object_type_ride_vtable, + object_type_small_scenery_vtable, + object_type_large_scenery_vtable, + object_type_wall_vtable, + object_type_banner_vtable, + object_type_path_vtable, + object_type_path_bit_vtable, + object_type_scenery_set_vtable, + object_type_park_entrance_vtable, + object_type_water_vtable, + object_type_stex_vtable +}; + +bool object_load(int type, void *objectEntry, uint32 entryIndex) +{ + assert(type >= OBJECT_TYPE_RIDE && type <= OBJECT_TYPE_SCENARIO_TEXT); + const object_type_vtable *vtable = object_type_vtables[type]; + return vtable->load(objectEntry, entryIndex) ? 0 : 1; +} + +void object_unload(int type, void *objectEntry) +{ + assert(type >= OBJECT_TYPE_RIDE && type <= OBJECT_TYPE_SCENARIO_TEXT); + const object_type_vtable *vtable = object_type_vtables[type]; + vtable->unload(objectEntry); +} + +bool object_test(int type, void *objectEntry) +{ + assert(type >= OBJECT_TYPE_RIDE && type <= OBJECT_TYPE_SCENARIO_TEXT); + const object_type_vtable *vtable = object_type_vtables[type]; + return vtable->test(objectEntry); +} + +void object_paint(int type, void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y) +{ + assert(type >= OBJECT_TYPE_RIDE && type <= OBJECT_TYPE_SCENARIO_TEXT); + const object_type_vtable *vtable = object_type_vtables[type]; + vtable->paint(objectEntry, dpi, x, y); +} + +rct_string_id object_desc(int type, void *objectEntry) +{ + assert(type >= OBJECT_TYPE_RIDE && type <= OBJECT_TYPE_SCENARIO_TEXT); + const object_type_vtable *vtable = object_type_vtables[type]; + return vtable->desc(objectEntry); } /** @@ -1498,7 +1667,7 @@ int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, */ int object_get_scenario_text(rct_object_entry *entry) { - rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry *installedObject = gInstalledObjects; installedObject = object_list_find(entry); @@ -1510,7 +1679,7 @@ int object_get_scenario_text(rct_object_entry *entry) char path[MAX_PATH]; char *objectPath = (char*)installedObject + 16; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath); rct_object_entry openedEntry; SDL_RWops* rw = SDL_RWFromFile(path, "rb"); @@ -1528,12 +1697,12 @@ int object_get_scenario_text(rct_object_entry *entry) uint8 *chunk; if (chunkSize == 0xFFFFFFFF) { - chunk = malloc(0x600000); + chunk = (uint8*)malloc(0x600000); chunkSize = sawyercoding_read_chunk(rw, chunk); chunk = realloc(chunk, chunkSize); } else { - chunk = malloc(chunkSize); + chunk = (uint8*)malloc(chunkSize); sawyercoding_read_chunk(rw, chunk); } SDL_RWclose(rw); @@ -1546,9 +1715,9 @@ int object_get_scenario_text(rct_object_entry *entry) return 0; } - if (object_paint(openedEntry.flags & 0x0F, 2, 0, 0, 0, (int)chunk, 0, 0)) { + if (!object_test(openedEntry.flags & 0x0F, chunk)) { // This is impossible for STEX entries to fail. - log_error("Opened object failed paitn test."); + log_error("Opened object failed paint test."); RCT2_GLOBAL(0x00F42BD9, uint8) = 3; free(chunk); return 0; @@ -1569,7 +1738,7 @@ int object_get_scenario_text(rct_object_entry *entry) memcpy(gTempObjectLoadName, openedEntry.name, 8); // Not used?? RCT2_GLOBAL(0x009ADAFD, uint8) = 1; - object_paint(openedEntry.flags & 0x0F, 0, 0, 0, 0, (int)chunk, 0, 0); + object_load(openedEntry.flags & 0x0F, chunk, 0); // Tell text to be loaded into normal address RCT2_GLOBAL(0x009ADAFC, uint8) = 0; // Not used?? diff --git a/src/object.h b/src/object.h index dfbfc30901..7d0dc72b0e 100644 --- a/src/object.h +++ b/src/object.h @@ -22,6 +22,7 @@ #define _OBJECT_H_ #include "common.h" +#include "drawing/drawing.h" #include "platform/platform.h" // First 0xF of rct_object_entry->flags @@ -50,6 +51,9 @@ typedef enum{ OBJECT_SELECTION_FLAG_8 = (1 << 7), }OBJECT_SELECTION_FLAGS; +#define OBJECT_ENTRY_GROUP_COUNT 11 +#define OBJECT_ENTRY_COUNT 721 + /** * Object entry structure. * size: 0x10 @@ -91,8 +95,16 @@ typedef struct { } rct_object_filters; extern rct_object_entry_group object_entry_groups[]; +extern void** gObjectList; extern char gTempObjectLoadName[9]; +extern uint32 gInstalledObjectsCount; +extern rct_object_entry *gInstalledObjects; +extern uint32 gNumInstalledRCT2Objects; +extern uint32 gNumInstalledCustomObjects; + +extern void *gLastLoadedObjectChunkData; + int object_load_entry(const utf8 *path, rct_object_entry *outEntry); void object_list_load(); void set_load_objects_fail_reason(); @@ -101,15 +113,14 @@ int object_load_packed(SDL_RWops* rw); void object_unload_all(); int check_object_entry(rct_object_entry *entry); -int object_load(int groupIndex, rct_object_entry *entry, int* chunk_size); int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSize, const rct_object_entry *installedObject); -void object_unload(rct_object_entry *entry); +int object_load_chunk(int groupIndex, rct_object_entry *entry, int* chunk_size); +void object_unload_chunk(rct_object_entry *entry); int object_get_scenario_text(rct_object_entry *entry); void object_free_scenario_text(); int object_get_length(rct_object_entry *entry); int object_entry_compare(const rct_object_entry *a, const rct_object_entry *b); int object_calculate_checksum(const rct_object_entry *entry, const uint8 *data, int dataLength); -int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp); rct_object_entry *object_get_next(rct_object_entry *entry); int write_object_file(SDL_RWops* rw, rct_object_entry* entry); void reset_loaded_objects(); @@ -122,4 +133,10 @@ char *object_get_name(rct_object_entry *entry); rct_object_filters *get_object_filter(int index); +bool object_load(int type, void *objectEntry, uint32 entryIndex); +void object_unload(int type, void *objectEntry); +bool object_test(int type, void *objectEntry); +void object_paint(int type, void *objectEntry, rct_drawpixelinfo *dpi, sint32 x, sint32 y); +rct_string_id object_desc(int type, void *objectEntry); + #endif diff --git a/src/object_list.c b/src/object_list.c index 12410c6580..082764e7cb 100644 --- a/src/object_list.c +++ b/src/object_list.c @@ -32,8 +32,6 @@ #include "world/scenery.h" #include "world/water.h" -#define OBJECT_ENTRY_GROUP_COUNT 11 -#define OBJECT_ENTRY_COUNT 721 #define FILTER_VERSION 1 typedef struct { @@ -76,19 +74,21 @@ int object_entry_group_encoding[] = { // 0x98D97C chunk address', 0x98D980 object_entries rct_object_entry_group object_entry_groups[] = { - (uint8**)(0x009ACFA4 ), (rct_object_entry_extended*)(0x00F3F03C ), // rides - (uint8**)(0x009ACFA4 + (128 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery 0x009AD1A4, 0xF2FA3C - (uint8**)(0x009ACFA4 + (380 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery 0x009AD594, 0xF40DEC - (uint8**)(0x009ACFA4 + (508 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls 0x009AD794, 0xF417EC - (uint8**)(0x009ACFA4 + (636 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners 0x009AD994, 0xF421EC - (uint8**)(0x009ACFA4 + (668 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths 0x009ADA14, 0xF4246C - (uint8**)(0x009ACFA4 + (684 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits 0x009ADA54, 0xF425AC - (uint8**)(0x009ACFA4 + (699 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets 0x009ADA90, 0xF426D8 - (uint8**)(0x009ACFA4 + (718 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance 0x009ADADC, 0xF42854 - (uint8**)(0x009ACFA4 + (719 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water 0x009ADAE0, 0xF42868 - (uint8**)(0x009ACFA4 + (720 * 4)), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text 0x009ADAE4, 0xF4287C + (uint8**)(RCT2_ADDRESS_RIDE_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C ), // rides + (uint8**)(RCT2_ADDRESS_SMALL_SCENERY_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (128 * 20)), // small scenery 0x009AD1A4, 0xF2FA3C + (uint8**)(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (380 * 20)), // large scenery 0x009AD594, 0xF40DEC + (uint8**)(RCT2_ADDRESS_WALL_SCENERY_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (508 * 20)), // walls 0x009AD794, 0xF417EC + (uint8**)(RCT2_ADDRESS_BANNER_SCENERY_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (636 * 20)), // banners 0x009AD994, 0xF421EC + (uint8**)(RCT2_ADDRESS_PATH_TYPES ), (rct_object_entry_extended*)(0x00F3F03C + (668 * 20)), // paths 0x009ADA14, 0xF4246C + (uint8**)(RCT2_ADDRESS_PATH_BIT_SCENERY_ENTRIES), (rct_object_entry_extended*)(0x00F3F03C + (684 * 20)), // path bits 0x009ADA54, 0xF425AC + (uint8**)(RCT2_ADDRESS_SCENERY_SET_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (699 * 20)), // scenery sets 0x009ADA90, 0xF426D8 + (uint8**)(RCT2_ADDRESS_PARK_ENTRANCE_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (718 * 20)), // park entrance 0x009ADADC, 0xF42854 + (uint8**)(RCT2_ADDRESS_WATER_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (719 * 20)), // water 0x009ADAE0, 0xF42868 + (uint8**)(RCT2_ADDRESS_SCENARIO_TEXT_ENTRIES ), (rct_object_entry_extended*)(0x00F3F03C + (720 * 20)) // scenario text 0x009ADAE4, 0xF4287C }; +void **gObjectList = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, void*); + static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int fileDateModifiedChecksum); static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileDateModifiedChecksum, int currentItemOffset); @@ -98,6 +98,13 @@ static void load_object_filter(rct_object_entry* entry, uint8* chunk, rct_object static rct_object_filters *_installedObjectFilters = NULL; +uint32 gInstalledObjectsCount; +rct_object_entry *gInstalledObjects; +uint32 gNumInstalledRCT2Objects; +uint32 gNumInstalledCustomObjects; + +void *gLastLoadedObjectChunkData; + static void get_plugin_path(utf8 *outPath) { platform_get_user_directory(outPath, NULL); @@ -108,12 +115,12 @@ static void object_list_sort() { rct_object_entry **objectBuffer, *newBuffer, *entry, *destEntry, *lowestEntry = NULL; rct_object_filters *newFilters = NULL, *destFilter = NULL; - int numObjects, i, j, bufferSize, entrySize, lowestIndex; + int numObjects, i, j, bufferSize, entrySize, lowestIndex = 0; char *objectName, *lowestString; uint8 *copied; - objectBuffer = &RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); - numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32); + objectBuffer = &gInstalledObjects; + numObjects = gInstalledObjectsCount; copied = calloc(numObjects, sizeof(uint8)); // Get buffer size @@ -123,7 +130,7 @@ static void object_list_sort() bufferSize = (int)entry - (int)*objectBuffer; // Create new buffer - newBuffer = rct2_malloc(bufferSize); + newBuffer = (rct_object_entry*)malloc(bufferSize); destEntry = newBuffer; if (_installedObjectFilters) { newFilters = malloc(numObjects * sizeof(rct_object_filters)); @@ -155,7 +162,7 @@ static void object_list_sort() } // Replace old buffer - rct2_free(*objectBuffer); + free(*objectBuffer); *objectBuffer = newBuffer; if (_installedObjectFilters) { free(_installedObjectFilters); @@ -165,31 +172,36 @@ static void object_list_sort() free(copied); } +static uint32 object_list_count_custom_objects() +{ + uint32 numCustomObjects = 0; + rct_object_entry *object = gInstalledObjects; + for (uint32 i = 0; i < gInstalledObjectsCount; i++) { + if ((object->flags & 0xF0) == 0) { + numCustomObjects++; + } + object = object_get_next(object); + } + + gNumInstalledCustomObjects = numCustomObjects; + return numCustomObjects; +} + /** * * rct2: 0x006A93CD */ static void object_list_examine() { - int i; - rct_object_entry *object; - - RCT2_GLOBAL(RCT2_ADDRESS_CUSTOM_OBJECTS_INSTALLED, uint8) = 0; - - object = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); - for (i = 0; i < RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32); i++) { - if (!(object->flags & 0xF0)) - RCT2_GLOBAL(RCT2_ADDRESS_CUSTOM_OBJECTS_INSTALLED, uint8) |= 1; - - object = object_get_next(object); - } + object_list_count_custom_objects(); object_list_sort(); - - // Create a search index object_list_create_hash_table(); } -/* rct2: 0x006A9FC0 */ +/** + * + * rct2: 0x006A9FC0 + */ void reset_loaded_objects() { reset_type_to_ride_entry_index_map(); @@ -200,7 +212,7 @@ void reset_loaded_objects() for (int j = 0; j < object_entry_group_counts[type]; j++){ uint8* chunk = object_entry_groups[type].chunks[j]; if (chunk != (uint8*)-1) - object_paint(type, 0, j, type, 0, (int)chunk, 0, 0); + object_load(type, chunk, j); } } } @@ -246,34 +258,27 @@ void object_list_load() uint64 totalFileSize; file_info enumFileInfo; - object_list_query_directory(&totalFiles, &totalFileSize, &fileDateModifiedChecksum); + int ok = object_list_query_directory(&totalFiles, &totalFileSize, &fileDateModifiedChecksum); + if (ok != 1) { + return; + } // Would move this into cache load, but its used further on totalFiles = ror32(totalFiles, 24); totalFiles = (totalFiles & ~0xFF) | 1; totalFiles = rol32(totalFiles, 24); - if (object_list_cache_load(totalFiles, totalFileSize, fileDateModifiedChecksum)) + if (object_list_cache_load(totalFiles, totalFileSize, fileDateModifiedChecksum)) { return; - - // Reload object list - - // RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS used to control if this was the first time loading objects - // and display the starting RCT2 for the first time message. - //if (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, uint8) != 0) - // RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FIRST_TIME_LOAD_OBJECTS, uint8) = 0; - - reset_loaded_objects(); - - // Dispose installed object list - if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { - rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; } - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(4096); - if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){ + // Dispose installed object list + reset_loaded_objects(); + SafeFree(gInstalledObjects); + + gInstalledObjectsCount = 0; + gInstalledObjects = (rct_object_entry*)malloc(4096); + if (gInstalledObjects == NULL) { log_error("Failed to allocate memory for object list"); rct2_exit_reason(835, 3162); return; @@ -281,9 +286,8 @@ void object_list_load() uint32 fileCount = 0; uint32 objectCount = 0; - uint32 current_item_offset = 0; - uint32 next_offset = 0; - RCT2_GLOBAL(RCT2_ADDRESS_ORIGINAL_RCT2_OBJECT_COUNT, uint32) = 0; + size_t currentEntryOffset = 0; + gNumInstalledRCT2Objects = 0; log_verbose("building cache of available objects..."); @@ -294,15 +298,14 @@ void object_list_load() enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char)); if (enumFileHandle != INVALID_HANDLE) { - uint32 installed_buffer_size = 0x1000; - + size_t installedObjectsCapacity = 4096; while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) { fileCount++; - if ((installed_buffer_size - current_item_offset) <= 2842){ - installed_buffer_size += 0x1000; - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size); - if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){ + if ((installedObjectsCapacity - currentEntryOffset) <= 2842){ + installedObjectsCapacity += 4096; + gInstalledObjects = (rct_object_entry*)realloc(gInstalledObjects, installedObjectsCapacity); + if (gInstalledObjects == NULL) { log_error("Failed to allocate memory for object list"); rct2_exit_reason(835, 3162); return; @@ -310,26 +313,20 @@ void object_list_load() } char path[MAX_PATH]; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), enumFileInfo.path); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), enumFileInfo.path); rct_object_entry entry; - if (!object_load_entry(path, &entry)) - continue; - - if (_installedObjectFilters) + if (object_load_entry(path, &entry)) { _installedObjectFilters = realloc(_installedObjectFilters, sizeof(rct_object_filters) * (objectCount + 1)); - else - _installedObjectFilters = malloc(sizeof(rct_object_filters) * (objectCount + 1)); - rct_object_entry* installed_entry = (rct_object_entry*)(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*) + current_item_offset); - rct_object_filters filter; - - next_offset = install_object_entry(&entry, installed_entry, enumFileInfo.path, &filter); - if (next_offset) { - current_item_offset += next_offset; - - _installedObjectFilters[objectCount] = filter; - objectCount++; + rct_object_entry *installedEntry = (rct_object_entry*)((size_t)gInstalledObjects + currentEntryOffset); + rct_object_filters filter; + size_t newEntrySize = install_object_entry(&entry, installedEntry, enumFileInfo.path, &filter); + if (newEntrySize != 0) { + _installedObjectFilters[objectCount] = filter; + objectCount++; + currentEntryOffset += newEntrySize; + } } } platform_enumerate_files_end(enumFileHandle); @@ -337,7 +334,7 @@ void object_list_load() reset_loaded_objects(); - object_list_cache_save(fileCount, totalFileSize, fileDateModifiedChecksum, current_item_offset); + object_list_cache_save(fileCount, totalFileSize, fileDateModifiedChecksum, currentEntryOffset); // Reload track list ride_list_item ride_list; @@ -372,26 +369,23 @@ static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int file pluginHeader.date_modified_checksum == fileDateModifiedChecksum ) { // Dispose installed object list - if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) != -1) { - rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*)); - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, sint32) = -1; - } + SafeFree(gInstalledObjects); // Read installed object list - RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_malloc(pluginHeader.object_list_size); - if (SDL_RWread(file, RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), pluginHeader.object_list_size, 1) == 1) { - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) = pluginHeader.object_list_no_items; + gInstalledObjects = (rct_object_entry*)malloc(pluginHeader.object_list_size); + if (SDL_RWread(file, gInstalledObjects, pluginHeader.object_list_size, 1) == 1) { + gInstalledObjectsCount = pluginHeader.object_list_no_items; if (pluginHeader.object_list_no_items != (pluginHeader.total_files & 0xFFFFFF)) log_error("Potential mismatch in file numbers. Possible corrupt file. Consider deleting plugin.dat."); if (SDL_RWread(file, &filterVersion, sizeof(filterVersion), 1) == 1) { if (filterVersion == FILTER_VERSION) { - if (_installedObjectFilters) + if (_installedObjectFilters != NULL) { free(_installedObjectFilters); + } _installedObjectFilters = malloc(sizeof(rct_object_filters) * pluginHeader.object_list_no_items); if (SDL_RWread(file, _installedObjectFilters, sizeof(rct_object_filters) * pluginHeader.object_list_no_items, 1) == 1) { - SDL_RWclose(file); reset_loaded_objects(); object_list_examine(); @@ -438,7 +432,7 @@ static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileD pluginHeader.total_file_size = (uint32)totalFileSize; pluginHeader.date_modified_checksum = fileDateModifiedChecksum; pluginHeader.object_list_size = currentItemOffset; - pluginHeader.object_list_no_items = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); + pluginHeader.object_list_no_items = gInstalledObjectsCount; get_plugin_path(path); file = SDL_RWFromFile(path,"wb"); @@ -448,9 +442,9 @@ static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileD } SDL_RWwrite(file, &pluginHeader, sizeof(rct_plugin_header), 1); - SDL_RWwrite(file, RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, uint8*), pluginHeader.object_list_size, 1); + SDL_RWwrite(file, gInstalledObjects, pluginHeader.object_list_size, 1); SDL_RWwrite(file, &filterVersion, sizeof(filterVersion), 1); - SDL_RWwrite(file, _installedObjectFilters, sizeof(rct_object_filters) * RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32), 1); + SDL_RWwrite(file, _installedObjectFilters, sizeof(rct_object_filters) * gInstalledObjectsCount, 1); SDL_RWclose(file); return 1; } @@ -461,8 +455,12 @@ int check_object_entry(rct_object_entry *entry) return (0xFFFFFFFF & dwords[0] & dwords[1] & dwords[2] & dwords[3]) + 1 != 0; } -/* rct2: 0x006AB344 */ -void object_create_identifier_name(char* string_buffer, const rct_object_entry* object){ +/** + * + * rct2: 0x006AB344 + */ +void object_create_identifier_name(char* string_buffer, const rct_object_entry* object) +{ for (uint8 i = 0; i < 8; ++i){ if (object->name[i] != ' '){ *string_buffer++ = object->name[i]; @@ -485,17 +483,24 @@ void object_create_identifier_name(char* string_buffer, const rct_object_entry* *string_buffer++ = '\0'; } -/* rct2: 0x675827 */ -void set_load_objects_fail_reason(){ - rct_object_entry* object = RCT2_ADDRESS(0x13CE952, rct_object_entry); +/** + * + * rct2: 0x675827 + */ +void set_load_objects_fail_reason() +{ + rct_string_id expansionNameId; + + rct_object_entry* object = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_object_entry); int expansion = (object->flags & 0xFF) >> 4; + if (expansion == 0 || expansion == 8 - || RCT2_GLOBAL(0x9AB4C0, uint16) & (1 << expansion)){ + || RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16) & (1 << expansion)){ char* string_buffer = RCT2_ADDRESS(0x9BC677, char); - format_string(string_buffer, 3323, 0); //Missing object data, ID: + format_string(string_buffer, STR_MISSING_OBJECT_DATA_ID, 0); object_create_identifier_name(string_buffer, object); RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0xFF; @@ -503,17 +508,23 @@ void set_load_objects_fail_reason(){ return; } - char* exapansion_name = &RCT2_ADDRESS(RCT2_ADDRESS_EXPANSION_NAMES, char)[128 * expansion]; - if (*exapansion_name == '\0'){ - RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0xFF; - RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3325; - return; + switch(expansion) { + case 1: // Wacky Worlds + expansionNameId = STR_OBJECT_FILTER_WW; + break; + case 2: // Time Twister + expansionNameId = STR_OBJECT_FILTER_TT; + break; + default: + RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0xFF; + RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = STR_REQUIRES_AN_ADDON_PACK; + return; } char* string_buffer = RCT2_ADDRESS(0x9BC677, char); - format_string(string_buffer, 3324, 0); // Requires expansion pack - strcat(string_buffer, exapansion_name); + format_string(string_buffer, STR_REQUIRES_THE_FOLLOWING_ADDON_PACK, &expansionNameId); + RCT2_GLOBAL(RCT2_ADDRESS_ERROR_TYPE, uint8) = 0xFF; RCT2_GLOBAL(RCT2_ADDRESS_ERROR_STRING_ID, uint16) = 3165; } @@ -550,9 +561,9 @@ int object_read_and_load_entries(SDL_RWops* rw) } // Load the obect - if (!object_load(entryGroupIndex, &entries[i], NULL)) { + if (!object_load_chunk(entryGroupIndex, &entries[i], NULL)) { log_error("failed to load entry: %.8s", entries[i].name); - memcpy((char*)0x13CE952, &entries[i], sizeof(rct_object_entry)); + memcpy((char*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, &entries[i], sizeof(rct_object_entry)); load_fail = 1; } } @@ -560,7 +571,6 @@ int object_read_and_load_entries(SDL_RWops* rw) free(entries); if (load_fail){ object_unload_all(); - RCT2_GLOBAL(0x14241BC, uint32) = 0; return 0; } @@ -581,7 +591,7 @@ void object_unload_all() for (i = 0; i < OBJECT_ENTRY_GROUP_COUNT; i++) for (j = 0; j < object_entry_group_counts[i]; j++) if (object_entry_groups[i].chunks[j] != (uint8*)0xFFFFFFFF) - object_unload((rct_object_entry*)&object_entry_groups[i].entries[j]); + object_unload_chunk((rct_object_entry*)&object_entry_groups[i].entries[j]); reset_loaded_objects(); } @@ -600,15 +610,15 @@ uint32 object_get_hash_code(rct_object_entry *object) int i; for (i = 0; i < 8; i++) - hash = ((hash << 5) + hash) + object->name[i]; + hash = ((hash << 5) + hash) + object->name[i]; - return hash; + return hash; } void object_list_create_hash_table() { rct_object_entry *installedObject; - int numInstalledObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32); + int numInstalledObjects = gInstalledObjectsCount; if (_installedObjectHashTable != NULL) free(_installedObjectHashTable); @@ -617,7 +627,7 @@ void object_list_create_hash_table() _installedObjectHashTable = calloc(_installedObjectHashTableSize, sizeof(rct_object_entry*)); _installedObjectHashTableCollisions = 0; - installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + installedObject = gInstalledObjects; for (int i = 0; i < numInstalledObjects; i++) { uint32 hash = object_get_hash_code(installedObject); uint32 index = hash % _installedObjectHashTableSize; @@ -637,7 +647,9 @@ void object_list_create_hash_table() } } -/* 0x006A9DA2 +/** + * + * rct2: 0x006A9DA2 * bl = entry_index * ecx = entry_type */ @@ -682,7 +694,7 @@ rct_string_id object_get_name_string_id(rct_object_entry *entry, const void *chu int objectType = entry->flags & 0x0F; switch (objectType) { case OBJECT_TYPE_RIDE: - return ((rct_ride_type*)chunk)->name; + return ((rct_ride_entry*)chunk)->name; case OBJECT_TYPE_SMALL_SCENERY: case OBJECT_TYPE_LARGE_SCENERY: case OBJECT_TYPE_WALLS: @@ -704,7 +716,8 @@ rct_string_id object_get_name_string_id(rct_object_entry *entry, const void *chu } } -/* Installs an object_entry at the desired installed_entry address +/** + * Installs an object_entry at the desired installed_entry address * Returns the size of the new entry. Will return 0 on failure. */ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* installed_entry, const char* path, rct_object_filters* filter){ @@ -728,7 +741,7 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32) = 0xF26E; - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)++; + gInstalledObjectsCount++; // This is a variable used by object_load to decide if it should // use object_paint on the entry. @@ -743,7 +756,7 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in log_error("Object Load File failed. Potentially corrupt file: %.8s", entry->name); RCT2_GLOBAL(0x009ADAF4, sint32) = -1; RCT2_GLOBAL(0x009ADAFD, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; + gInstalledObjectsCount--; return 0; } @@ -754,25 +767,25 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in RCT2_GLOBAL(0x009ADAFD, uint8) = 0; if ((entry->flags & 0xF0) == 0x80) { - RCT2_GLOBAL(RCT2_ADDRESS_ORIGINAL_RCT2_OBJECT_COUNT, uint32)++; - if (RCT2_GLOBAL(RCT2_ADDRESS_ORIGINAL_RCT2_OBJECT_COUNT, uint32) > 772){ + gNumInstalledRCT2Objects++; + if (gNumInstalledRCT2Objects > 772){ log_error("Incorrect number of vanilla RCT2 objects."); - RCT2_GLOBAL(RCT2_ADDRESS_ORIGINAL_RCT2_OBJECT_COUNT, uint32)--; - RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32)--; - object_unload(entry); + gNumInstalledRCT2Objects--; + gInstalledObjectsCount--; + object_unload_chunk(entry); return 0; } } *((sint32*)installed_entry_pointer) = chunk_size; installed_entry_pointer += 4; - uint8* chunk = RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_CHUNK_POINTER, uint8*); // Loaded in object_load + uint8* chunk = (uint8*)gLastLoadedObjectChunkData; // Loaded in object_load load_object_filter(entry, chunk, filter); // Always extract only the vehicle type, since the track type is always displayed in the left column, to prevent duplicate track names. rct_string_id nameStringId = object_get_name_string_id(entry, chunk); - if (nameStringId == (rct_string_id)STR_NONE) { + if (nameStringId == STR_NONE) { nameStringId = (rct_string_id)RCT2_GLOBAL(RCT2_ADDRESS_CURR_OBJECT_BASE_STRING_ID, uint32); } @@ -805,19 +818,19 @@ static uint32 install_object_entry(rct_object_entry* entry, rct_object_entry* in uint32 size_of_object = installed_entry_pointer - (uint8*)installed_entry; - object_unload(entry); + object_unload_chunk(entry); return size_of_object; } static void load_object_filter(rct_object_entry* entry, uint8* chunk, rct_object_filters* filter) { - rct_ride_type *rideType; + rct_ride_entry *rideType; rct_ride_filters *rideFilter; switch (entry->flags & 0xF) { case OBJECT_TYPE_RIDE: - rideType = ((rct_ride_type*)chunk); + rideType = ((rct_ride_entry*)chunk); rideFilter = &(filter->ride); rideFilter->category[0] = rideType->category[0]; diff --git a/src/openrct2.c b/src/openrct2.c index 6a6692d8d9..6f919e89d3 100644 --- a/src/openrct2.c +++ b/src/openrct2.c @@ -21,18 +21,19 @@ #include "addresses.h" #include "audio/audio.h" #include "audio/mixer.h" -#include "cmdline.h" #include "config.h" #include "editor.h" #include "game.h" #include "hook.h" #include "interface/chat.h" +#include "interface/themes.h" #include "interface/window.h" #include "interface/viewport.h" #include "localisation/localisation.h" #include "network/http.h" #include "network/network.h" #include "openrct2.h" +#include "platform/crash.h" #include "platform/platform.h" #include "ride/ride.h" #include "title.h" @@ -40,31 +41,29 @@ #include "util/util.h" #include "world/mapgen.h" -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) #include #include #include #include #include #include -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#endif // defined(__unix__) + +int gExitCode; int gOpenRCT2StartupAction = STARTUP_ACTION_TITLE; utf8 gOpenRCT2StartupActionPath[512] = { 0 }; utf8 gExePath[MAX_PATH]; utf8 gCustomUserDataPath[MAX_PATH] = { 0 }; +utf8 gCustomOpenrctDataPath[MAX_PATH] = { 0 }; +utf8 gCustomPassword[MAX_PATH] = { 0 }; // This should probably be changed later and allow a custom selection of things to initialise like SDL_INIT bool gOpenRCT2Headless = false; bool gOpenRCT2ShowChangelog; -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -void *gDataSegment; -void *gTextSegment; -int gExeFd; -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - /** If set, will end the OpenRCT2 game loop. Intentially private to this module so that the flag can not be set back to 0. */ int _finished; @@ -72,8 +71,6 @@ int _finished; static struct { sint16 x, y, z; } _spritelocations1[MAX_SPRITES], _spritelocations2[MAX_SPRITES]; static void openrct2_loop(); -static bool openrct2_setup_rct2_segment(); -static bool openrct2_release_rct2_segment(); static void openrct2_setup_rct2_hooks(); void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize) @@ -89,15 +86,16 @@ void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize) if (!str_is_null_or_empty(OPENRCT2_BRANCH)) { sprintf(strchr(buffer, 0), "-%s", OPENRCT2_BRANCH); } - if (!str_is_null_or_empty(OPENRCT2_BUILD_NUMBER)) { - sprintf(strchr(buffer, 0), " build %s", OPENRCT2_BUILD_NUMBER); - } if (!str_is_null_or_empty(OPENRCT2_COMMIT_SHA1_SHORT)) { - sprintf(strchr(buffer, 0), " (%s)", OPENRCT2_COMMIT_SHA1_SHORT); + sprintf(strchr(buffer, 0), " build %s", OPENRCT2_COMMIT_SHA1_SHORT); } if (!str_is_null_or_empty(OPENRCT2_BUILD_SERVER)) { sprintf(strchr(buffer, 0), " provided by %s", OPENRCT2_BUILD_SERVER); } + +#if DEBUG + sprintf(strchr(buffer, 0), " (DEBUG)"); +#endif } static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 *newDirectory, const utf8 *extension) @@ -112,7 +110,7 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 * } // Create filter path - safe_strncpy(filter, originalDirectory, MAX_PATH); + safe_strcpy(filter, originalDirectory, MAX_PATH); ch = strchr(filter, '*'); if (ch != NULL) *ch = 0; @@ -121,10 +119,10 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 * fileEnumHandle = platform_enumerate_files_begin(filter); while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { - safe_strncpy(newPath, newDirectory, MAX_PATH); + safe_strcpy(newPath, newDirectory, MAX_PATH); strcat(newPath, fileInfo.path); - safe_strncpy(oldPath, originalDirectory, MAX_PATH); + safe_strcpy(oldPath, originalDirectory, MAX_PATH); ch = strchr(oldPath, '*'); if (ch != NULL) *ch = 0; @@ -137,10 +135,10 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 * fileEnumHandle = platform_enumerate_directories_begin(originalDirectory); while (platform_enumerate_directories_next(fileEnumHandle, filter)) { - safe_strncpy(newPath, newDirectory, MAX_PATH); + safe_strcpy(newPath, newDirectory, MAX_PATH); strcat(newPath, filter); - safe_strncpy(oldPath, originalDirectory, MAX_PATH); + safe_strcpy(oldPath, originalDirectory, MAX_PATH); ch = strchr(oldPath, '*'); if (ch != NULL) *ch = 0; @@ -155,43 +153,10 @@ static void openrct2_copy_files_over(const utf8 *originalDirectory, const utf8 * platform_enumerate_directories_end(fileEnumHandle); } -// TODO move to platform static void openrct2_set_exe_path() { -#ifdef _WIN32 - wchar_t exePath[MAX_PATH]; - wchar_t tempPath[MAX_PATH]; - wchar_t *exeDelimiter; - int exeDelimiterIndex; - - GetModuleFileNameW(NULL, exePath, MAX_PATH); - exeDelimiter = wcsrchr(exePath, platform_get_path_separator()); - exeDelimiterIndex = (int)(exeDelimiter - exePath); - lstrcpynW(tempPath, exePath, exeDelimiterIndex + 1); - tempPath[exeDelimiterIndex] = L'\0'; - _wfullpath(exePath, tempPath, MAX_PATH); - WideCharToMultiByte(CP_UTF8, 0, exePath, countof(exePath), gExePath, countof(gExePath), NULL, NULL); -#else - char exePath[MAX_PATH]; - ssize_t bytesRead; - bytesRead = readlink("/proc/self/exe", exePath, MAX_PATH); - if (bytesRead == -1) { - log_fatal("failed to read /proc/self/exe"); - } - exePath[bytesRead - 1] = '\0'; - log_verbose("######################################## Setting exe path to %s", exePath); - char *exeDelimiter = strrchr(exePath, platform_get_path_separator()); - if (exeDelimiter == NULL) - { - log_error("should never happen here"); - gExePath[0] = '\0'; - return; - } - int exeDelimiterIndex = (int)(exeDelimiter - exePath); - - safe_strncpy(gExePath, exePath, exeDelimiterIndex + 1); - gExePath[exeDelimiterIndex] = '\0'; -#endif // _WIN32 + platform_get_exe_path(gExePath); + log_verbose("Setting exe path to %s", gExePath); } /** @@ -212,6 +177,7 @@ bool openrct2_initialise() { utf8 userPath[MAX_PATH]; + platform_resolve_openrct_data_path(); platform_resolve_user_data_path(); platform_get_user_directory(userPath, NULL); if (!platform_ensure_directory_exists(userPath)) { @@ -219,6 +185,8 @@ bool openrct2_initialise() return false; } + crash_init(); + if (!openrct2_setup_rct2_segment()) { log_fatal("Unable to load RCT2 data sector"); return false; @@ -229,7 +197,11 @@ bool openrct2_initialise() config_set_defaults(); if (!config_open_default()) { if (!config_find_or_browse_install_directory()) { - log_fatal("An RCT2 install directory must be specified!"); + gConfigGeneral.last_run_version = strndup(OPENRCT2_VERSION, strlen(OPENRCT2_VERSION)); + config_save_default(); + utf8 path[MAX_PATH]; + config_get_default_path(path); + log_fatal("An RCT2 install directory must be specified! Please edit \"game_path\" in %s.", path); return false; } } @@ -237,7 +209,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 @@ -246,7 +218,6 @@ bool openrct2_initialise() // return false; // } - get_system_info(); if (!gOpenRCT2Headless) { audio_init(); audio_populate_devices(); @@ -261,8 +232,7 @@ bool openrct2_initialise() } http_init(); - themes_set_default(); - themes_load_presets(); + theme_manager_initialise(); title_sequences_set_default(); title_sequences_load_presets(); @@ -310,13 +280,24 @@ void openrct2_launch() break; case STARTUP_ACTION_OPEN: assert(gOpenRCT2StartupActionPath != NULL); - if (rct2_open_file(gOpenRCT2StartupActionPath) == 0) + if (!rct2_open_file(gOpenRCT2StartupActionPath)) { break; + } RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) = SCREEN_FLAGS_PLAYING; #ifndef DISABLE_NETWORK if (gNetworkStart == NETWORK_MODE_SERVER) { + if (gNetworkStartPort == 0) { + gNetworkStartPort = gConfigNetwork.default_port; + } + + if (str_is_null_or_empty(gCustomPassword)) { + network_set_password(gConfigNetwork.default_password); + } + else { + network_set_password(gCustomPassword); + } network_begin_server(gNetworkStartPort); } #endif // DISABLE_NETWORK @@ -332,6 +313,10 @@ void openrct2_launch() #ifndef DISABLE_NETWORK if (gNetworkStart == NETWORK_MODE_CLIENT) { + if (gNetworkStartPort == 0) { + gNetworkStartPort = gConfigNetwork.default_port; + } + network_begin_client(gNetworkStartHost, gNetworkStartPort); } #endif // DISABLE_NETWORK @@ -349,7 +334,8 @@ void openrct2_dispose() network_close(); http_dispose(); language_close_all(); - openrct2_release_rct2_segment(); + rct2_dispose(); + config_release(); platform_free(); } @@ -382,7 +368,7 @@ static void openrct2_loop() _finished = 0; do { - if (gConfigGeneral.uncap_fps && gGameSpeed <= 4) { + if (gConfigGeneral.uncap_fps && gGameSpeed <= 4 && !gOpenRCT2Headless) { currentTick = SDL_GetTicks(); if (uncapTick == 0) { // Reset sprite locations @@ -499,21 +485,14 @@ void openrct2_reset_object_tween_locations() * Loads RCT2's data model and remaps the addresses. * @returns true if the data integrity check succeeded, otherwise false. */ -static bool openrct2_setup_rct2_segment() +bool openrct2_setup_rct2_segment() { - // POSIX OSes will run OpenRCT2 as a native application and then load in the Windows PE, mapping the appropriate addresses as + // OpenRCT2 on Linux and OS X is wired to have the original Windows PE sections loaded // necessary. Windows does not need to do this as OpenRCT2 runs as a DLL loaded from the Windows PE. -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#if defined(__unix__) #define RDATA_OFFSET 0x004A4000 #define DATASEG_OFFSET 0x005E2000 - const char *exepath = "openrct2.exe"; - gExeFd = open(exepath, O_RDONLY); - if (gExeFd < 0) { - log_fatal("failed to open %s, errno = %d", exepath, errno); - exit(1); - } - // Using PE-bear I was able to figure out all the needed addresses to be filled. // There are three sections to be loaded: .rdata, .data and .text, plus another // one to be mapped: DATASEG. @@ -536,51 +515,63 @@ static bool openrct2_setup_rct2_segment() // 0x9a6000 + 0xA81C3C = 0x1427C3C, which after alignment to page size becomes // 0x1428000, which can be seen as next section, DATASEG // - // Since mmap does not provide a way to create a mapping with virtual size, - // I resorted to creating a one large map for data and memcpy'ing data where - // required. - // Another section is needed for .text, as it requires PROT_EXEC flag. + // The data is now loaded into memory with a linker script, which proves to + // be more reliable, as mallocs that happen before we reach segment setup + // could have already taken the space we need. // TODO: UGLY, UGLY HACK! off_t file_size = 6750208; int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB - // section: rw data - gDataSegment = mmap((void *)0x8a4000, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_SHARED, 0, 0); - if (gDataSegment != (void *)0x8a4000) { - log_fatal("mmap failed to get required offset for data segment! got %p, expected %p, errno = %d", gDataSegment, (void *)(0x8a4000), errno); - exit(1); - } - - len = 0x004A3000; - // section: text - gTextSegment = mmap((void *)(0x401000), len, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_FIXED | MAP_PRIVATE, gExeFd, 0x1000); - if (gTextSegment != (void *)(0x401000)) - { - log_fatal("mmap failed to get required offset for text segment! got %p, expected %p, errno = %d", gTextSegment, (void *)(0x401000), errno); - exit(1); - } - - void *fbase = mmap(NULL, file_size, PROT_READ, MAP_PRIVATE, gExeFd, 0); - int err = errno; - log_warning("mmapped file to %p", fbase); - if (fbase == MAP_FAILED) - { - log_fatal("mmap failed to get required offset! got %p, errno = %d", fbase, err); - exit(1); - } - // .rdata and real part of .data - // 0x9e2000 - 0x8a4000 = 0x13e000 - memcpy(gDataSegment, fbase + RDATA_OFFSET, 0x13e000); - // 0x8a4000 + 0xb84000 = 0x1428000 aka DATASEG - memcpy(gDataSegment + 0xB84000, fbase + DATASEG_OFFSET, 0x1000); - err = munmap(fbase, file_size); + int pageSize = getpagesize(); + int numPages = (len + pageSize - 1) / pageSize; + unsigned char *dummy = malloc(numPages); + int err = mincore((void *)0x8a4000, len, dummy); + bool pagesMissing = false; if (err != 0) { err = errno; - log_error("Failed to unmap file! errno = %d", err); +#ifdef __LINUX__ + // On Linux ENOMEM means all requested range is unmapped + if (err != ENOMEM) + { + pagesMissing = true; + perror("mincore"); + } +#else + pagesMissing = true; + perror("mincore"); +#endif // __LINUX__ + } else { + for (int i = 0; i < numPages; i++) + { + if (dummy[i] != 1) + { + pagesMissing = true; + void *start = (void *)0x8a4000 + i * pageSize; + void *end = (void *)0x8a4000 + (i + 1) * pageSize - 1; + log_warning("required page %p - %p is not in memory!", start, end); + } + } } -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + free(dummy); + if (pagesMissing) + { + log_error("At least one of required pages was not found in memory. This can cause segfaults later on."); + } + // section: text + err = mprotect((void *)0x401000, 0x8a4000 - 0x401000, PROT_READ | PROT_EXEC); + if (err != 0) + { + perror("mprotect"); + } + // section: rw data + err = mprotect((void *)0x8a4000, 0x01429000 - 0x8a4000, PROT_READ | PROT_WRITE); + if (err != 0) + { + perror("mprotect"); + } +#endif // defined(__unix__) // Check that the expected data is at various addresses. // Start at 0x9a6000, which is start of .data, to skip the region containing addresses to DLL @@ -598,41 +589,6 @@ static bool openrct2_setup_rct2_segment() return true; } -/** - * Releases segments created with @ref openrct2_setup_rct2_segment, if any. - */ -static bool openrct2_release_rct2_segment() -{ - bool result = true; -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - int len = 0x01429000 - 0x8a4000; // 0xB85000, 12079104 bytes or around 11.5MB - int err; - err = munmap(gDataSegment, len); - if (err != 0) - { - err = errno; - log_error("Failed to unmap data segment! errno = %d", err); - result = false; - } - len = 0x004A3000; - err = munmap(gTextSegment, len); - if (err != 0) - { - err = errno; - log_error("Failed to unmap text segment! errno = %d", err); - result = false; - } - err = close(gExeFd); - if (err != 0) - { - err = errno; - log_error("Failed to close file! errno = %d", err); - result = false; - } -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - return result; -} - /** * Setup hooks to allow RCT2 to call OpenRCT2 functions instead. */ @@ -642,7 +598,7 @@ static void openrct2_setup_rct2_hooks() addhook(0x006E7499, (int)gfx_redraw_screen_rect, 0, (int[]){ EAX, EBX, EDX, EBP, END }, 0, 0); // remove when 0x6E7FF3 is decompiled addhook(0x006B752C, (int)ride_crash, 0, (int[]){ EDX, EBX, END }, 0, 0); // remove when all callers are decompiled addhook(0x0069A42F, (int)peep_window_state_update, 0, (int[]){ ESI, END }, 0, 0); // remove when all callers are decompiled - addhook(0x006BB76E, (int)audio_play_sound_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, EAX, 0); // remove when all callers are decompiled + addhook(0x006BB76E, (int)audio_play_sound_panned, 0, (int[]){EAX, EBX, ECX, EDX, EBP, END}, 0, EAX); // remove when all callers are decompiled addhook(0x006C42D9, (int)scrolling_text_setup, 0, (int[]){EAX, ECX, EBP, END}, 0, EBX); // remove when all callers are decompiled addhook(0x006C2321, (int)gfx_get_string_width, 0, (int[]){ESI, END}, 0, ECX); // remove when all callers are decompiled addhook(0x006C2555, (int)format_string, 0, (int[]){EDI, EAX, ECX, END}, 0, 0); // remove when all callers are decompiled diff --git a/src/openrct2.h b/src/openrct2.h index 4642985872..4be5d7fcb3 100644 --- a/src/openrct2.h +++ b/src/openrct2.h @@ -22,6 +22,7 @@ #define _OPENRCT2_H_ #include "common.h" +#include "platform/platform.h" enum { STARTUP_ACTION_INTRO, @@ -30,18 +31,32 @@ enum { STARTUP_ACTION_EDIT }; +/** The exit code for OpenRCT2 when it exits. */ +extern int gExitCode; + extern int gOpenRCT2StartupAction; extern utf8 gOpenRCT2StartupActionPath[512]; extern utf8 gExePath[MAX_PATH]; extern utf8 gCustomUserDataPath[MAX_PATH]; +extern utf8 gCustomOpenrctDataPath[MAX_PATH]; +extern utf8 gCustomPassword[MAX_PATH]; extern bool gOpenRCT2Headless; extern bool gOpenRCT2ShowChangelog; +#ifndef DISABLE_NETWORK +extern int gNetworkStart; +extern char gNetworkStartHost[128]; +extern int gNetworkStartPort; +#endif + void openrct2_write_full_version_info(utf8 *buffer, size_t bufferSize); bool openrct2_initialise(); void openrct2_launch(); void openrct2_dispose(); void openrct2_finish(); void openrct2_reset_object_tween_locations(); +bool openrct2_setup_rct2_segment(); -#endif \ No newline at end of file +int cmdline_run(const char **argv, int argc); + +#endif diff --git a/src/peep/peep.c b/src/peep/peep.c index 7961c49e17..620d710c43 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -37,8 +37,11 @@ #include "../world/footpath.h" #include "../management/marketing.h" #include "../game.h" +#include "../ride/track.h" +#include "../cheats.h" #include "peep.h" #include "staff.h" +#include "../world/map.h" enum { PATH_SEARCH_DEAD_END, @@ -78,9 +81,9 @@ static void peep_ride_is_too_intense(rct_peep *peep, int rideIndex, bool peepAtR static void peep_chose_not_to_go_on_ride(rct_peep *peep, int rideIndex, bool peepAtRide, bool updateLastRide); static void peep_tried_to_enter_full_queue(rct_peep *peep, int rideIndex); static bool peep_should_go_to_shop(rct_peep *peep, int rideIndex, bool peepAtShop); -static void sub_69A98C(rct_peep *peep); -static void sub_68FD3A(rct_peep *peep); -static bool sub_690B99(rct_peep *peep, int edge, uint8 *rideToView, uint8 *rideSeatToView); +static void peep_reset_pathfind_goal(rct_peep *peep); +static bool peep_find_ride_to_look_at(rct_peep *peep, uint8 edge, uint8 *rideToView, uint8 *rideSeatToView); +static void peep_easter_egg_peep_interactions(rct_peep *peep); static int peep_get_height_on_slope(rct_peep *peep, int x, int y); static void peep_pick_ride_to_go_on(rct_peep *peep); static void peep_head_for_nearest_ride_type(rct_peep *peep, int rideType); @@ -89,6 +92,21 @@ static void peep_give_real_name(rct_peep *peep); static int guest_surface_path_finding(rct_peep* peep); static void peep_read_map(rct_peep *peep); static bool peep_heading_for_ride_or_park_exit(rct_peep *peep); +static bool peep_update_fixing_sub_state_0(rct_ride *ride); +static bool peep_update_fixing_sub_state_1(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_2345(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_6(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_7(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_8(bool firstRun, rct_peep *peep); +static bool peep_update_fixing_sub_state_9(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_10(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_11(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_12(bool firstRun, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_13(bool firstRun, int steps, rct_peep *peep, rct_ride *ride); +static bool peep_update_fixing_sub_state_14(bool firstRun, rct_peep *peep, rct_ride *ride); +static void sub_6B7588(int rideIndex); + +bool loc_690FD0(rct_peep *peep, uint8 *rideToView, uint8 *rideSeatToView, rct_map_element *esi); const char *gPeepEasterEggNames[] = { "MICHAEL SCHUMACHER", @@ -171,7 +189,10 @@ void peep_update_all() } } -/* rct2: 0x0069BC9A */ +/** + * + * rct2: 0x0069BC9A + */ static uint8 peep_assess_surroundings(sint16 center_x, sint16 center_y, sint16 center_z){ if ((map_element_height(center_x, center_y) & 0xFFFF) > center_z) return 0; @@ -196,11 +217,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 & @@ -218,7 +239,7 @@ static uint8 peep_assess_surroundings(sint16 center_x, sint16 center_y, sint16 c num_scenery++; break; case MAP_ELEMENT_TYPE_TRACK: - ride = GET_RIDE(mapElement->properties.track.ride_index); + ride = get_ride(mapElement->properties.track.ride_index); if (ride->type == RIDE_TYPE_MERRY_GO_ROUND && ride->music_tune_id != 0xFF){ nearby_music |= 1; @@ -277,7 +298,10 @@ static uint8 peep_assess_surroundings(sint16 center_x, sint16 center_y, sint16 c return 0; } -/* rct2: 0x0068F9A9*/ +/** + * + * rct2: 0x0068F9A9 + */ static void peep_update_hunger(rct_peep *peep){ if (peep->hunger >= 3){ peep->hunger -= 2; @@ -286,18 +310,21 @@ static void peep_update_hunger(rct_peep *peep){ } } -/* rct2: 0x0068F93E */ +/** + * + * rct2: 0x0068F93E + */ static void peep_leave_park(rct_peep* peep){ peep->guest_heading_to_ride_id = 0xFF; - if (peep->flags & PEEP_FLAGS_LEAVING_PARK){ + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK){ if (peep->peep_is_lost_countdown < 60){ return; } } else{ peep->peep_is_lost_countdown = 254; - peep->flags |= PEEP_FLAGS_LEAVING_PARK; - peep->flags &= ~PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; + peep->peep_flags |= PEEP_FLAGS_LEAVING_PARK; + peep->peep_flags &= ~PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; } peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_GO_HOME, 0xFF); @@ -325,7 +352,7 @@ static void sub_68F8CD(rct_peep *peep) return; } - if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK)){ + if (!(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)){ if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) { if (peep->energy >= 70 && peep->happiness >= 60) { return; @@ -371,9 +398,9 @@ static void sub_68F41A(rct_peep *peep, int index) if (peep->action < PEEP_ACTION_NONE_1) peep->action = PEEP_ACTION_NONE_2; - peep->flags &= ~PEEP_FLAGS_SLOW_WALK; + peep->peep_flags &= ~PEEP_FLAGS_SLOW_WALK; if (RCT2_ADDRESS(0x00982134, uint8)[sprite_type] & 1){ - peep->flags |= PEEP_FLAGS_SLOW_WALK; + peep->peep_flags |= PEEP_FLAGS_SLOW_WALK; } peep->action_sprite_type = 0xFF; @@ -384,14 +411,14 @@ static void sub_68F41A(rct_peep *peep, int index) if ((index & 0x1FF) == (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x1FF)){ //RCT2_GLOBAL(0x00F1EDFE, uint32) = index; not needed all cases accounted for - if (peep->flags & PEEP_FLAGS_CROWDED){ + if (peep->peep_flags & PEEP_FLAGS_CROWDED){ uint8 thought_type = RCT2_ADDRESS(0x009823AC, uint8)[scenario_rand() & 0xF]; if (thought_type != PEEP_THOUGHT_TYPE_NONE){ peep_insert_new_thought(peep, thought_type, 0xFF); } } - if (peep->flags & PEEP_FLAGS_EXPLODE && peep->x != (sint16)0x8000){ + if (peep->peep_flags & PEEP_FLAGS_EXPLODE && peep->x != (sint16)0x8000){ audio_play_sound_at_location(SOUND_CRASH, peep->x, peep->y, peep->z); sprite_misc_3_create(peep->x, peep->y, peep->z + 16); @@ -401,19 +428,19 @@ static void sub_68F41A(rct_peep *peep, int index) return; } - if (peep->flags & PEEP_FLAGS_HUNGER){ + if (peep->peep_flags & PEEP_FLAGS_HUNGER){ if (peep->hunger >= 15)peep->hunger -= 15; } - if (peep->flags & PEEP_FLAGS_BATHROOM){ + if (peep->peep_flags & PEEP_FLAGS_BATHROOM){ if (peep->bathroom <= 180)peep->bathroom += 50; } - if (peep->flags & PEEP_FLAGS_HAPPINESS){ + if (peep->peep_flags & PEEP_FLAGS_HAPPINESS){ peep->happiness_growth_rate = 5; } - if (peep->flags & PEEP_FLAGS_NAUSEA){ + if (peep->peep_flags & PEEP_FLAGS_NAUSEA){ peep->nausea_growth_rate = 200; if (peep->nausea <= 130)peep->nausea = 130; } @@ -456,7 +483,7 @@ static void sub_68F41A(rct_peep *peep, int index) if (peep->state == PEEP_STATE_ON_RIDE || peep->state == PEEP_STATE_ENTERING_RIDE){ peep->time_on_ride = min(255, peep->time_on_ride + 1); - if (peep->flags & PEEP_FLAGS_WOW){ + if (peep->peep_flags & PEEP_FLAGS_WOW){ peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_WOW2, 0xFF); } @@ -464,7 +491,7 @@ static void sub_68F41A(rct_peep *peep, int index) peep->happiness_growth_rate = min(0, peep->happiness_growth_rate - 5); if (peep->time_on_ride > 22){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); uint8 thought_type = ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IN_RIDE) ? PEEP_THOUGHT_TYPE_GET_OUT : @@ -477,7 +504,7 @@ static void sub_68F41A(rct_peep *peep, int index) if (peep->state == PEEP_STATE_WALKING && peep->outside_of_park == 0 && - !(peep->flags & PEEP_FLAGS_LEAVING_PARK) && + !(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) && peep->no_of_rides == 0 && peep->guest_heading_to_ride_id == 0xFF){ @@ -508,7 +535,7 @@ static void sub_68F41A(rct_peep *peep, int index) uint8 num_thoughts = 0; uint8 possible_thoughts[5] = { 0 }; - if (peep->flags & PEEP_FLAGS_LEAVING_PARK){ + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK){ possible_thoughts[num_thoughts++] = PEEP_THOUGHT_TYPE_GO_HOME; } else{ @@ -547,13 +574,13 @@ static void sub_68F41A(rct_peep *peep, int index) switch (chosen_thought){ case PEEP_THOUGHT_TYPE_HUNGRY: - peep_head_for_nearest_ride_with_flags(peep, 0x00800000); + peep_head_for_nearest_ride_with_flags(peep, RIDE_TYPE_FLAG_SELLS_FOOD); break; case PEEP_THOUGHT_TYPE_THIRSTY: - peep_head_for_nearest_ride_with_flags(peep, 0x01000000); + peep_head_for_nearest_ride_with_flags(peep, RIDE_TYPE_FLAG_SELLS_DRINKS); break; case PEEP_THOUGHT_TYPE_BATHROOM: - peep_head_for_nearest_ride_with_flags(peep, 0x00200000); + peep_head_for_nearest_ride_with_flags(peep, RIDE_TYPE_FLAG_IS_BATHROOM); break; case PEEP_THOUGHT_RUNNING_OUT: peep_head_for_nearest_ride_type(peep, RIDE_TYPE_CASH_MACHINE); @@ -610,9 +637,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; } @@ -793,10 +821,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); @@ -809,10 +844,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); @@ -820,31 +859,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){ @@ -876,15 +915,17 @@ static void peep_state_reset(rct_peep* peep){ sub_693BE5(peep, 0); } -/* rct2: 0x69C308 +/** + * + * rct2: 0x69C308 * Check if lost. */ void peep_check_if_lost(rct_peep* peep){ - if (!(peep->flags & PEEP_FLAGS_LOST)){ + if (!(peep->peep_flags & PEEP_FLAGS_LOST)){ if (RCT2_GLOBAL(RCT2_ADDRESS_RIDE_COUNT, uint16) < 2)return; - peep->flags ^= PEEP_FLAGS_21; + peep->peep_flags ^= PEEP_FLAGS_21; - if (!(peep->flags & PEEP_FLAGS_21)) return; + if (!(peep->peep_flags & PEEP_FLAGS_21)) return; peep->var_F4++; if (peep->var_F4 != 254)return; @@ -895,7 +936,9 @@ void peep_check_if_lost(rct_peep* peep){ peep->happiness_growth_rate = max(peep->happiness_growth_rate - 30, 0); } -/* rct2: 0x69C26B +/** + * + * rct2: 0x69C26B * Check if cant find ride. */ void peep_check_cant_find_ride(rct_peep* peep){ @@ -922,11 +965,13 @@ void peep_check_cant_find_ride(rct_peep* peep){ widget_invalidate_by_number(WC_PEEP, peep->sprite_index, 12); } -/* rct2: 0x69C2D0 +/** + * + * rct2: 0x69C2D0 * Check if cant find exit. */ void peep_check_cant_find_exit(rct_peep* peep){ - if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK)) + if (!(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)) return; // Peeps who can't find the park exit will continue to get less happy until they find it. @@ -939,11 +984,18 @@ void peep_check_cant_find_exit(rct_peep* peep){ peep->peep_is_lost_countdown = 90; } -/* rct2: 0x6939EB +/** + * + * rct2: 0x6939EB * Also used to move peeps to the correct position to * start an action. Returns 1 if the correct destination * has not yet been reached. xy_distance is how close the * peep is to the target. + * + * @param x (ax) + * @param y (cx) + * @param distance (bp) + * @param peep (esi) */ int peep_update_action(sint16* x, sint16* y, sint16* xy_distance, rct_peep* peep){ RCT2_GLOBAL(0xF1AEF0, uint8) = peep->action_sprite_image_offset; @@ -977,11 +1029,11 @@ int peep_update_action(sint16* x, sint16* y, sint16* xy_distance, rct_peep* peep } } peep->sprite_direction = direction; - *x = peep->x + RCT2_ADDRESS(0x981D7C, uint16)[direction / 4]; - *y = peep->y + RCT2_ADDRESS(0x981D7E, uint16)[direction / 4]; + *x = peep->x + RCT2_ADDRESS(0x981D7C, sint16)[direction / 4]; + *y = peep->y + RCT2_ADDRESS(0x981D7E, sint16)[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; } @@ -989,8 +1041,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]; @@ -1045,13 +1097,13 @@ void peep_decrement_num_riders(rct_peep* peep){ if (peep->state == PEEP_STATE_ON_RIDE || peep->state == PEEP_STATE_ENTERING_RIDE){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); ride->num_riders--; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; } } -/* Part of 0x0069B8CC rct2:0x0069BC31 */ +/* Part of 0x0069B8CC rct2: 0x0069BC31 */ void set_sprite_type(rct_peep* peep, uint8 type){ if (peep->sprite_type == type)return; @@ -1062,9 +1114,9 @@ void set_sprite_type(rct_peep* peep, uint8 type){ if (peep->action >= PEEP_ACTION_NONE_1) peep->action = PEEP_ACTION_NONE_2; - peep->flags &= ~PEEP_FLAGS_SLOW_WALK; + peep->peep_flags &= ~PEEP_FLAGS_SLOW_WALK; if (RCT2_ADDRESS(0x00982134, uint8)[type] & 1){ - peep->flags |= PEEP_FLAGS_SLOW_WALK; + peep->peep_flags |= PEEP_FLAGS_SLOW_WALK; } peep->action_sprite_type = 0xFF; @@ -1072,12 +1124,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); } } @@ -1223,10 +1275,9 @@ void peep_update_sprite_type(rct_peep* peep) } /** + * Call after changing a peeps state to insure that all relevant windows update. + * Note also increase ride count if on/entering a ride. * rct2: 0x0069A42F - * Call after changing a peeps state to insure that - * all relevant windows update. Note also increase ride - * count if on/entering a ride. */ void peep_window_state_update(rct_peep* peep){ @@ -1239,7 +1290,7 @@ void peep_window_state_update(rct_peep* peep){ widget_invalidate_by_number(WC_PEEP, peep->sprite_index, 12); if (peep->state == PEEP_STATE_ON_RIDE || peep->state == PEEP_STATE_ENTERING_RIDE){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); ride->num_riders++; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; } @@ -1253,7 +1304,10 @@ void peep_window_state_update(rct_peep* peep){ } } -/* rct2: 0x0069A535*/ +/** + * + * rct2: 0x0069A535 + */ void peep_sprite_remove(rct_peep* peep){ remove_peep_from_ride(peep); invalidate_sprite_2((rct_sprite*)peep); @@ -1280,8 +1334,8 @@ void peep_sprite_remove(rct_peep* peep){ sprite_remove((rct_sprite*)peep); } -/** New function removes peep from - * park existance. Works with staff. +/** + * New function removes peep from park existance. Works with staff. */ void peep_remove(rct_peep* peep){ if (peep->type == PEEP_TYPE_GUEST){ @@ -1297,8 +1351,8 @@ void peep_remove(rct_peep* peep){ } /** - * rct2: 0x690028 * Falling and its subset drowning + * rct2: 0x690028 */ void peep_update_falling(rct_peep* peep){ if (peep->action == PEEP_ACTION_DROWNING){ @@ -1307,11 +1361,13 @@ void peep_update_falling(rct_peep* peep){ peep_update_action(&x, &y, &xy_distance, peep); if (peep->action == PEEP_ACTION_DROWNING) return; - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & 0x80000)){ - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; - news_item_add_to_queue(NEWS_ITEM_BLANK, 2347, peep->x | (peep->y << 16)); + + if (gConfigNotifications.guest_died) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + news_item_add_to_queue(NEWS_ITEM_BLANK, STR_NEWS_ITEM_GUEST_DROWNED, peep->x | (peep->y << 16)); } + RCT2_GLOBAL(0x135882E, uint16) += 25; if (RCT2_GLOBAL(0x135882E, uint16) > 1000){ RCT2_GLOBAL(0x135882E, uint16) = 1000; @@ -1409,7 +1465,8 @@ void peep_update_falling(rct_peep* peep){ } /** - * rct2: 0x00691677 + * + * rct2: 0x00691677 */ void peep_try_get_up_from_sitting(rct_peep* peep){ // Eats all food first @@ -1430,11 +1487,12 @@ void peep_try_get_up_from_sitting(rct_peep* peep){ } /** - * rct2: 0x0069152B + * + * rct2: 0x0069152B */ 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); @@ -1451,7 +1509,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++; @@ -1470,7 +1528,7 @@ void peep_update_sitting(rct_peep* peep){ return; } - if ((peep->flags & PEEP_FLAGS_LEAVING_PARK)){ + if ((peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)){ peep_decrement_num_riders(peep); peep->state = PEEP_STATE_WALKING; peep_window_state_update(peep); @@ -1529,11 +1587,11 @@ void peep_update_sitting(rct_peep* peep){ /** * - * rct2: 0x006966A9 + * rct2: 0x006966A9 */ void remove_peep_from_queue(rct_peep* peep) { - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); uint8 cur_station = peep->current_ride_station; ride->queue_length[cur_station]--; @@ -1552,10 +1610,13 @@ void remove_peep_from_queue(rct_peep* peep) } } -/* rct2: 0x00691C6E */ +/** + * + * rct2: 0x00691C6E + */ static rct_vehicle* peep_choose_car_from_ride(rct_peep* peep, rct_ride* ride, uint8* car_array, uint8 car_array_size){ uint8 chosen_car = scenario_rand(); - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & RIDE_TYPE_FLAG_HAS_G_FORCES + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES) && ((chosen_car & 0xC) != 0xC)){ chosen_car = (scenario_rand() & 1) ? 0 : car_array_size - 1; } @@ -1574,14 +1635,17 @@ static rct_vehicle* peep_choose_car_from_ride(rct_peep* peep, rct_ride* ride, ui return vehicle; } -/* rct2: 0x00691CD1 */ +/** + * + * rct2: 0x00691CD1 + */ static void peep_choose_seat_from_car(rct_peep* peep, rct_ride* ride, rct_vehicle* vehicle){ uint8 chosen_seat = vehicle->next_free_seat; if (ride->mode == RIDE_MODE_FORWARD_ROTATION || ride->mode == RIDE_MODE_BACKWARD_ROTATION){ - chosen_seat = (((~vehicle->var_1F + 1) >> 3) & 0xF) * 2; + chosen_seat = (((~vehicle->vehicle_sprite_type + 1) >> 3) & 0xF) * 2; if (vehicle->next_free_seat & 1){ chosen_seat++; } @@ -1593,7 +1657,10 @@ static void peep_choose_seat_from_car(rct_peep* peep, rct_ride* ride, rct_vehicl vehicle->peep_tshirt_colours[peep->current_seat] = peep->tshirt_colour; } -/* rct2: 0x00691D27 */ +/** + * + * rct2: 0x00691D27 + */ static void peep_go_to_ride_entrance(rct_peep* peep, rct_ride* ride){ int x = ride->entrances[peep->current_ride_station] & 0xFF; int y = ride->entrances[peep->current_ride_station] >> 8; @@ -1601,7 +1668,7 @@ static void peep_go_to_ride_entrance(rct_peep* peep, rct_ride* ride){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 direction = !map_element ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); x *= 32; y *= 32; @@ -1612,9 +1679,9 @@ static void peep_go_to_ride_entrance(rct_peep* peep, rct_ride* ride){ sint16 y_shift = RCT2_ADDRESS(0x00981D6E, sint16)[direction * 2]; uint8 shift_multiplier = 21; - rct_ride_type* ride_type = GET_RIDE_ENTRY(ride->subtype); - if (ride_type->vehicles[ride_type->default_vehicle].var_12 & (1 << 3) || - ride_type->vehicles[ride_type->default_vehicle].var_14 & 0x5000){ + rct_ride_entry* ride_type = get_ride_entry(ride->subtype); + if (ride_type->vehicles[ride_type->default_vehicle].flags_a & VEHICLE_ENTRY_FLAG_A_MINI_GOLF || + ride_type->vehicles[ride_type->default_vehicle].flags_b & (VEHICLE_ENTRY_FLAG_B_12 | VEHICLE_ENTRY_FLAG_B_14)){ shift_multiplier = 32; } @@ -1639,9 +1706,12 @@ static void peep_go_to_ride_entrance(rct_peep* peep, rct_ride* ride){ remove_peep_from_queue(peep); } -/* rct2: 0x00691A3B */ +/** + * + * rct2: 0x00691A3B + */ static void peep_update_ride_sub_state_0(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (peep->destination_tolerence != 0){ invalidate_sprite_2((rct_sprite*)peep); @@ -1665,7 +1735,7 @@ static void peep_update_ride_sub_state_0(rct_peep* peep){ uint8 car_array_size = 0xFF; uint8* car_array = RCT2_ADDRESS(0xF1AD78, uint8); - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & RIDE_TYPE_FLAG_13){ + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13)){ if (ride->num_riders >= ride->operation_option) return; } @@ -1689,7 +1759,7 @@ static void peep_update_ride_sub_state_0(rct_peep* peep){ } } else{ - chosen_train = ride->var_066[peep->current_ride_station]; + chosen_train = ride->train_at_station[peep->current_ride_station]; } if (chosen_train == 0xFF){ return; @@ -1724,7 +1794,7 @@ static void peep_update_ride_sub_state_0(rct_peep* peep){ if (ride->mode == RIDE_MODE_FORWARD_ROTATION || ride->mode == RIDE_MODE_BACKWARD_ROTATION) { - uint8 position = (((~vehicle->var_1F + 1) >> 3) & 0xF) * 2; + uint8 position = (((~vehicle->vehicle_sprite_type + 1) >> 3) & 0xF) * 2; if (vehicle->peep[position] != 0xFFFF) continue; } @@ -1738,7 +1808,7 @@ static void peep_update_ride_sub_state_0(rct_peep* peep){ } if (ride->status != RIDE_STATUS_OPEN || - ride->var_1CA != 0){ + ride->vehicle_change_timeout != 0){ if (peep->destination_tolerence == 0){ remove_peep_from_queue(peep); peep_decrement_num_riders(peep); @@ -1794,26 +1864,29 @@ static void peep_update_ride_sub_state_0(rct_peep* peep){ } } - if (!(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & RIDE_TYPE_FLAG_13)){ + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13)){ rct_vehicle* vehicle = peep_choose_car_from_ride(peep, ride, car_array, car_array_size); peep_choose_seat_from_car(peep, ride, vehicle); } peep_go_to_ride_entrance(peep, ride); } -/* rct2: 0x006921D3 */ +/** + * + * rct2: 0x006921D3 + */ void peep_update_ride_sub_state_1(rct_peep* peep){ sint16 x, y, xy_distance; - rct_ride* ride = GET_RIDE(peep->current_ride); - rct_ride_type* ride_entry = gRideTypeList[ride->subtype]; + rct_ride* ride = get_ride(peep->current_ride); + rct_ride_entry* ride_entry = get_ride_entry(ride->subtype); if (peep_update_action(&x, &y, &xy_distance, peep)) { uint8 vehicle = ride_entry->default_vehicle; - if (ride_entry->vehicles[vehicle].var_12 & (1 << 3) || - ride_entry->vehicles[vehicle].var_14 & ((1 << 14) | (1<<12))) + if (ride_entry->vehicles[vehicle].flags_a & VEHICLE_ENTRY_FLAG_A_MINI_GOLF || + ride_entry->vehicles[vehicle].flags_b & (VEHICLE_ENTRY_FLAG_B_12 | VEHICLE_ENTRY_FLAG_B_14)) RCT2_GLOBAL(0xF1AECA, uint16) = 0x1C; else RCT2_GLOBAL(0xF1AECA, uint16) = 0x10; @@ -1837,7 +1910,7 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ return; } - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] &RIDE_TYPE_FLAG_13) + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13)) { sint16 x, y, z; x = ride->entrances[peep->current_ride_station] & 0xFF; @@ -1846,7 +1919,7 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 direction_entrance = (map_element->type & MAP_ELEMENT_DIRECTION_MASK); + uint8 direction_entrance = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); if (ride->type == RIDE_TYPE_MAZE){ peep->maze_last_edge = direction_entrance + 1; @@ -1873,7 +1946,7 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ peep->destination_y = y; peep->destination_tolerence = 3; - ride->var_120++; + ride->cur_num_customers++; peep_on_enter_or_exit_ride(peep, peep->current_ride, 0); peep->sub_state = 17; return; @@ -1884,7 +1957,7 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ map_element = ride_get_station_start_track_element(ride, peep->current_ride_station); - uint8 direction_track = (!map_element ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); + uint8 direction_track = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); peep->var_37 = (direction_entrance << 2) | (direction_track << 4); @@ -1900,7 +1973,7 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ peep->destination_y = y; peep->current_car = 0; - ride->var_120++; + ride->cur_num_customers++; peep_on_enter_or_exit_ride(peep, peep->current_ride, 0); peep->sub_state = 14; return; @@ -1911,10 +1984,10 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ vehicle = GET_VEHICLE(vehicle->next_vehicle_on_train); } - ride_entry = GET_RIDE_ENTRY(vehicle->ride_subtype); - rct_ride_type_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; + ride_entry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; - if (vehicle_type->var_14 & (1 << 10)){ + if (vehicle_type->flags_b & VEHICLE_ENTRY_FLAG_B_10){ sint16 x, y, z; x = ride->entrances[peep->current_ride_station] & 0xFF; y = ride->entrances[peep->current_ride_station] >> 8; @@ -1922,17 +1995,17 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 direction_entrance = !map_element ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 direction_entrance = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); x = ride->station_starts[peep->current_ride_station] & 0xFF; y = ride->station_starts[peep->current_ride_station] >> 8; map_element = ride_get_station_start_track_element(ride, peep->current_ride_station); - uint8 direction_track = (!map_element ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); + uint8 direction_track = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); vehicle = GET_VEHICLE(ride->vehicles[peep->current_train]); - ride_entry = GET_RIDE_ENTRY(vehicle->ride_subtype); + ride_entry = get_ride_entry(vehicle->ride_subtype); vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; uint8 cl = peep->current_seat; @@ -1971,7 +2044,7 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ return; } - if (vehicle_type->var_14 & (1 << 15)){ + if (vehicle_type->flags_b & VEHICLE_ENTRY_FLAG_B_15){ peep->destination_x = vehicle->x; peep->destination_y = vehicle->y; peep->destination_tolerence = 15; @@ -2000,7 +2073,10 @@ void peep_update_ride_sub_state_1(rct_peep* peep){ return; } -/* rct2: 0x0069321D */ +/** + * + * rct2: 0x0069321D + */ static void peep_go_to_ride_exit(rct_peep* peep, rct_ride* ride, sint16 x, sint16 y, sint16 z, uint8 exit_direction){ z += RCT2_ADDRESS(0x0097D21C, uint8)[ride->type * 8]; @@ -2019,10 +2095,10 @@ static void peep_go_to_ride_exit(rct_peep* peep, rct_ride* ride, sint16 x, sint1 sint16 shift_multiplier = 20; - rct_ride_type* ride_type = GET_RIDE_ENTRY(ride->subtype); - rct_ride_type_vehicle* vehicle_entry = &ride_type->vehicles[ride_type->default_vehicle]; - if (vehicle_entry->var_12 & (1 << 3) || - vehicle_entry->var_14 & 0x5000){ + rct_ride_entry* ride_type = get_ride_entry(ride->subtype); + rct_ride_entry_vehicle* vehicle_entry = &ride_type->vehicles[ride_type->default_vehicle]; + if (vehicle_entry->flags_a & VEHICLE_ENTRY_FLAG_A_MINI_GOLF || + vehicle_entry->flags_b & (VEHICLE_ENTRY_FLAG_B_12 | VEHICLE_ENTRY_FLAG_B_14)){ shift_multiplier = 32; } @@ -2041,7 +2117,10 @@ static void peep_go_to_ride_exit(rct_peep* peep, rct_ride* ride, sint16 x, sint1 return; } -/* rct2: 0x006920B4 */ +/** + * + * rct2: 0x006920B4 + */ static void peep_update_ride_sub_state_2_enter_ride(rct_peep* peep, rct_ride* ride){ if (ride->price != 0){ if ((peep->item_standard_flags & PEEP_ITEM_VOUCHER) && @@ -2069,19 +2148,21 @@ static void peep_update_ride_sub_state_2_enter_ride(rct_peep* peep, rct_ride* ri window_invalidate_by_number(WC_RIDE, peep->current_ride); } - if (peep->flags & PEEP_FLAGS_TRACKING){ - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; - RCT2_GLOBAL(0x13CE958, uint16) = ride->name; - RCT2_GLOBAL(0x13CE95A, uint32) = ride->name_arguments; + if (peep->peep_flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; rct_string_id msg_string; - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & RIDE_TYPE_FLAG_IN_RIDE) - msg_string = 1932; + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IN_RIDE)) + msg_string = STR_PEEP_TRACKING_PEEP_IS_IN_X; else - msg_string = 1933; + msg_string = STR_PEEP_TRACKING_PEEP_IS_ON_X; - news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, msg_string, peep->sprite_index); + if (gConfigNotifications.guest_on_ride) { + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, msg_string, peep->sprite_index); + } } if (ride->type == RIDE_TYPE_SPIRAL_SLIDE){ @@ -2091,7 +2172,10 @@ static void peep_update_ride_sub_state_2_enter_ride(rct_peep* peep, rct_ride* ri peep_update_ride_sub_state_1(peep); } -/* rct2: 0x00691FD4 */ +/** + * + * rct2: 0x00691FD4 + */ static void peep_update_ride_sub_state_2_rejoin_queue(rct_peep* peep, rct_ride* ride){ sint16 x, y, z; x = ride->entrances[peep->current_ride_station] & 0xFF; @@ -2100,7 +2184,7 @@ static void peep_update_ride_sub_state_2_rejoin_queue(rct_peep* peep, rct_ride* rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 direction_entrance = !map_element ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 direction_entrance = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); x *= 32; y *= 32; @@ -2133,7 +2217,9 @@ static void peep_update_ride_sub_state_2_rejoin_queue(rct_peep* peep, rct_ride* queue_peep->next_in_queue = peep->sprite_index; } -/* rct2: 0x00691E42 +/** + * + * rct2: 0x00691E42 * Note: Before this was the entry * point for sub state 1 and 3. The * check has been removed that would @@ -2141,11 +2227,11 @@ static void peep_update_ride_sub_state_2_rejoin_queue(rct_peep* peep, rct_ride* * separate functions. */ static void peep_update_ride_sub_state_2(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & RIDE_TYPE_FLAG_13){ + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13)){ if (ride->status != RIDE_STATUS_OPEN || - ride->var_1CA != 0 || + ride->vehicle_change_timeout != 0 || (++peep->var_AC) == 0){ peep_update_ride_sub_state_2_rejoin_queue(peep, ride); @@ -2161,10 +2247,10 @@ static void peep_update_ride_sub_state_2(rct_peep* peep){ vehicle = GET_VEHICLE(vehicle->next_vehicle_on_train); } - rct_ride_type* ride_entry = GET_RIDE_ENTRY(vehicle->ride_subtype); + rct_ride_entry* ride_entry = get_ride_entry(vehicle->ride_subtype); - if (ride_entry->vehicles[0].var_12 & (1 << 3)){ - vehicle->var_D5 &= ~(1 << 5); + if (ride_entry->vehicles[0].flags_a & VEHICLE_ENTRY_FLAG_A_MINI_GOLF){ + vehicle->mini_golf_flags &= ~(1 << 5); for (int i = 0; i < ride->num_vehicles; ++i){ @@ -2177,7 +2263,7 @@ static void peep_update_ride_sub_state_2(rct_peep* peep){ if (second_vehicle->num_peeps == 0) continue; - if (second_vehicle->var_D5 & (1 << 5)) + if (second_vehicle->mini_golf_flags & (1 << 5)) continue; return; @@ -2209,8 +2295,7 @@ static void peep_update_ride_sub_state_2(rct_peep* peep){ rct_vehicle *currentTrain = GET_VEHICLE(ride->vehicles[peep->current_train]); if (ride->status == RIDE_STATUS_OPEN && ++peep->var_AC != 0 && - !(vehicle->update_flags & VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART) - ) { + !(currentTrain->update_flags & VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART)){ return; } @@ -2227,7 +2312,7 @@ static void peep_update_ride_sub_state_2(rct_peep* peep){ } static void peep_update_ride_sub_state_5(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); rct_vehicle* vehicle = GET_VEHICLE(ride->vehicles[peep->current_train]); for (int i = peep->current_car; i != 0; --i){ @@ -2246,7 +2331,7 @@ static void peep_update_ride_sub_state_5(rct_peep* peep){ return; vehicle->num_peeps++; - ride->var_120++; + ride->cur_num_customers++; vehicle->friction += seated_peep->var_41; invalidate_sprite_2((rct_sprite*)seated_peep); @@ -2261,7 +2346,7 @@ static void peep_update_ride_sub_state_5(rct_peep* peep){ } vehicle->num_peeps++; - ride->var_120++; + ride->cur_num_customers++; vehicle->friction += peep->var_41; invalidate_sprite_2((rct_sprite*)vehicle); @@ -2279,9 +2364,12 @@ static void peep_update_ride_sub_state_5(rct_peep* peep){ peep_on_enter_or_exit_ride(peep, peep->current_ride, 0); } -/* rct2: 0x00693028*/ +/** + * + * rct2: 0x00693028 + */ void peep_update_ride_sub_state_7(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); rct_vehicle* vehicle = GET_VEHICLE(ride->vehicles[peep->current_train]); uint8 ride_station = vehicle->current_station; @@ -2290,8 +2378,9 @@ void peep_update_ride_sub_state_7(rct_peep* peep){ vehicle = GET_VEHICLE(vehicle->next_vehicle_on_train); } - // Unsure why backward rotation is missing. - if (ride->mode != RIDE_MODE_FORWARD_ROTATION){ + // Check if ride is NOT Ferris Wheel. + if (ride->mode != RIDE_MODE_FORWARD_ROTATION && + ride->mode != RIDE_MODE_BACKWARD_ROTATION){ if (vehicle->num_peeps - 1 != peep->current_seat) return; } @@ -2308,10 +2397,10 @@ void peep_update_ride_sub_state_7(rct_peep* peep){ peep->current_ride_station = ride_station; - rct_ride_type* ride_entry = GET_RIDE_ENTRY(vehicle->ride_subtype); - rct_ride_type_vehicle* vehicle_entry = &ride_entry->vehicles[vehicle->vehicle_type]; + rct_ride_entry* ride_entry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicle_entry = &ride_entry->vehicles[vehicle->vehicle_type]; - if (!(vehicle_entry->var_14 & (1 << 10))){ + if (!(vehicle_entry->flags_b & VEHICLE_ENTRY_FLAG_B_10)){ sint16 x, y, z; x = ride->exits[peep->current_ride_station] & 0xFF; y = ride->exits[peep->current_ride_station] >> 8; @@ -2319,14 +2408,14 @@ void peep_update_ride_sub_state_7(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 exit_direction = map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 exit_direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); exit_direction ^= (1 << 1); - if (!(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & RIDE_TYPE_FLAG_16)){ + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_16)){ for (; vehicle->is_child; vehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride)){ uint16 trackType = vehicle->track_type >> 2; - if (trackType == 0 || trackType > 3) + if (trackType == TRACK_ELEM_FLAT || trackType > TRACK_ELEM_MIDDLE_STATION) continue; rct_map_element* inner_map = map_get_first_element_at(vehicle->track_x / 32, vehicle->track_y / 32); @@ -2342,16 +2431,16 @@ void peep_update_ride_sub_state_7(rct_peep* peep){ break; } - ride_entry = GET_RIDE_ENTRY(ride->subtype); + ride_entry = get_ride_entry(ride->subtype); vehicle_entry = &ride_entry->vehicles[ride_entry->default_vehicle]; uint8 shift_multiplier = 12; - if (vehicle_entry->var_14 & (1 << 14)){ + if (vehicle_entry->flags_b & VEHICLE_ENTRY_FLAG_B_14){ shift_multiplier = 9; } uint8 direction = exit_direction; - if (vehicle_entry->var_14 & ((1 << 14) | (1 << 12))){ + if (vehicle_entry->flags_b & (VEHICLE_ENTRY_FLAG_B_12 | VEHICLE_ENTRY_FLAG_B_14)){ direction = ((vehicle->sprite_direction + 3) / 8) + 1; direction &= 3; @@ -2403,19 +2492,19 @@ void peep_update_ride_sub_state_7(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 exit_direction = map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 exit_direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); x = ride->station_starts[peep->current_ride_station] & 0xFF; y = ride->station_starts[peep->current_ride_station] >> 8; map_element = ride_get_station_start_track_element(ride, peep->current_ride_station); - uint8 station_direction = (!map_element ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); + uint8 station_direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); vehicle = GET_VEHICLE(ride->vehicles[peep->current_train]); - ride_entry = GET_RIDE_ENTRY(vehicle->ride_subtype); - rct_ride_type_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; + ride_entry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; uint8 cl = peep->current_seat; uint8 ch = peep->current_seat & 0xF8; @@ -2465,9 +2554,12 @@ void peep_update_ride_sub_state_7(rct_peep* peep){ peep->sub_state = 13; } -/* rct2: 0x0069376A */ +/** + * + * rct2: 0x0069376A + */ static void peep_update_ride_prepare_for_state_9(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); sint16 x = ride->exits[peep->current_ride_station] & 0xFF; sint16 y = ride->exits[peep->current_ride_station] >> 8; @@ -2475,7 +2567,7 @@ static void peep_update_ride_prepare_for_state_9(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 exit_direction = map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 exit_direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); x *= 32; y *= 32; @@ -2487,9 +2579,9 @@ static void peep_update_ride_prepare_for_state_9(rct_peep* peep){ sint16 shift_multiplier = 20; - rct_ride_type* ride_type = GET_RIDE_ENTRY(ride->subtype); - rct_ride_type_vehicle* vehicle_entry = &ride_type->vehicles[ride_type->default_vehicle]; - if (vehicle_entry->var_14 & 0x5000){ + rct_ride_entry* ride_type = get_ride_entry(ride->subtype); + rct_ride_entry_vehicle* vehicle_entry = &ride_type->vehicles[ride_type->default_vehicle]; + if (vehicle_entry->flags_b & (VEHICLE_ENTRY_FLAG_B_12 | VEHICLE_ENTRY_FLAG_B_14)){ shift_multiplier = 32; } @@ -2505,7 +2597,10 @@ static void peep_update_ride_prepare_for_state_9(rct_peep* peep){ peep->sub_state = 9; } -/* rct2: 0x0069374F */ +/** + * + * rct2: 0x0069374F + */ static void peep_update_ride_sub_state_8(rct_peep* peep){ sint16 x, y, xy_distance; if (peep_update_action(&x, &y, &xy_distance, peep)){ @@ -2518,10 +2613,13 @@ static void peep_update_ride_sub_state_8(rct_peep* peep){ peep_update_ride_prepare_for_state_9(peep); } -/* rct2: 0x0069382E */ +/** + * + * rct2: 0x0069382E + */ static void peep_update_ride_sub_state_9(rct_peep* peep){ sint16 x, y, xy_distance; - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (peep_update_action(&x, &y, &xy_distance, peep)){ invalidate_sprite_2((rct_sprite*)peep); @@ -2549,10 +2647,13 @@ static void peep_update_ride_sub_state_9(rct_peep* peep){ peep->sub_state = 18; } -/* rct2: 0x006926AD */ +/** + * + * rct2: 0x006926AD + */ static void peep_update_ride_sub_state_12(rct_peep* peep){ sint16 x, y, xy_distance; - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (peep_update_action(&x, &y, &xy_distance, peep)){ sint16 z; @@ -2600,8 +2701,8 @@ static void peep_update_ride_sub_state_12(rct_peep* peep){ y = vehicle->y; } - rct_ride_type* ride_entry = GET_RIDE_ENTRY(vehicle->ride_subtype); - rct_ride_type_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; + rct_ride_entry* ride_entry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; x += vehicle_type->peep_loading_positions[peep->var_37 * 2 + 1]; y += vehicle_type->peep_loading_positions[peep->var_37 * 2 + 2]; @@ -2610,10 +2711,13 @@ static void peep_update_ride_sub_state_12(rct_peep* peep){ peep->destination_y = y; } -/* rct2: 0x0069357D */ +/** + * + * rct2: 0x0069357D + */ static void peep_update_ride_sub_state_13(rct_peep* peep){ sint16 x, y, xy_distance; - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (peep_update_action(&x, &y, &xy_distance, peep)){ sint16 z; @@ -2659,8 +2763,8 @@ static void peep_update_ride_sub_state_13(rct_peep* peep){ y = vehicle->y; } - rct_ride_type* ride_entry = GET_RIDE_ENTRY(vehicle->ride_subtype); - rct_ride_type_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; + rct_ride_entry* ride_entry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicle_type = &ride_entry->vehicles[vehicle->vehicle_type]; x += vehicle_type->peep_loading_positions[peep->var_37 * 2 + 1]; y += vehicle_type->peep_loading_positions[peep->var_37 * 2 + 2]; @@ -2678,7 +2782,7 @@ static void peep_update_ride_sub_state_13(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 exit_direction = map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 exit_direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); exit_direction ^= (1 << 1); x *= 32; @@ -2691,9 +2795,9 @@ static void peep_update_ride_sub_state_13(rct_peep* peep){ sint16 shift_multiplier = 20; - rct_ride_type* ride_type = GET_RIDE_ENTRY(ride->subtype); - rct_ride_type_vehicle* vehicle_entry = &ride_type->vehicles[ride_type->default_vehicle]; - if (vehicle_entry->var_14 & 0x5000){ + rct_ride_entry* ride_type = get_ride_entry(ride->subtype); + rct_ride_entry_vehicle* vehicle_entry = &ride_type->vehicles[ride_type->default_vehicle]; + if (vehicle_entry->flags_b & (VEHICLE_ENTRY_FLAG_B_12 | VEHICLE_ENTRY_FLAG_B_14)){ shift_multiplier = 32; } @@ -2707,10 +2811,13 @@ static void peep_update_ride_sub_state_13(rct_peep* peep){ peep->destination_y = y; } -/* rct2: 0x006927B3 */ +/** + * + * rct2: 0x006927B3 + */ static void peep_update_ride_sub_state_14(rct_peep* peep){ sint16 x, y, xy_distance; - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (peep_update_action(&x, &y, &xy_distance, peep)){ invalidate_sprite_2((rct_sprite*)peep); @@ -2745,7 +2852,7 @@ static void peep_update_ride_sub_state_14(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 exit_direction = map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 exit_direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); peep->var_37 = (exit_direction * 4) | (peep->var_37 & 0x30) | 1; x = ride->station_starts[peep->current_ride_station] & 0xFF; @@ -2780,9 +2887,12 @@ static void peep_update_ride_sub_state_14(rct_peep* peep){ peep->destination_y = y; } -/* rct2: 0x00692D83 */ +/** + * + * rct2: 0x00692D83 + */ static void peep_update_ride_sub_state_15(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (ride->type != RIDE_TYPE_SPIRAL_SLIDE) return; @@ -2795,13 +2905,13 @@ static void peep_update_ride_sub_state_15(rct_peep* peep){ peep->destination_x++; return; case 1: - if (ride->var_15D != 0) + if (ride->slide_in_use != 0) return; - ride->var_15D++; + ride->slide_in_use++; ride->slide_peep = peep->sprite_index; ride->slide_peep_t_shirt_colour = peep->tshirt_colour; - ride->var_176 = 0; + ride->spiral_slide_progress = 0; peep->destination_x++; return; case 2: @@ -2864,7 +2974,10 @@ static void peep_update_ride_sub_state_15(rct_peep* peep){ peep->sub_state = 14; } -/* rct2: 0x00692C6B */ +/** + * + * rct2: 0x00692C6B + */ static void peep_update_ride_sub_state_16(rct_peep* peep){ sint16 x, y, xy_distance; @@ -2875,7 +2988,7 @@ static void peep_update_ride_sub_state_16(rct_peep* peep){ return; } - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if ((peep->var_37 & 0x3) != 0){ if ((peep->var_37 & 0x3) == 3){ @@ -2907,7 +3020,7 @@ static void peep_update_ride_sub_state_16(rct_peep* peep){ rct_map_element* map_element = ride_get_station_exit_element(ride, x, y, z); - uint8 exit_direction = map_element->type & MAP_ELEMENT_DIRECTION_MASK; + uint8 exit_direction = (map_element == NULL ? 0 : map_element->type & MAP_ELEMENT_DIRECTION_MASK); exit_direction ^= (1 << 1); x *= 32; @@ -2930,7 +3043,10 @@ static void peep_update_ride_sub_state_16(rct_peep* peep){ peep->destination_y = y; } -/* rct2: 0x00692A83 */ +/** + * + * rct2: 0x00692A83 + */ static void peep_update_ride_sub_state_17(rct_peep* peep){ sint16 x, y, xy_distance; @@ -2941,7 +3057,7 @@ static void peep_update_ride_sub_state_17(rct_peep* peep){ return; } - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (peep->var_37 == 16){ peep_update_ride_prepare_for_state_9(peep); return; @@ -3068,10 +3184,13 @@ static void peep_update_ride_sub_state_17(rct_peep* peep){ } } -/* rct2: 0x006938D2 */ +/** + * + * rct2: 0x006938D2 + */ static void peep_update_ride_sub_state_18(rct_peep* peep){ sint16 x, y, xy_distance; - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (peep_update_action(&x, &y, &xy_distance, peep)){ invalidate_sprite_2((rct_sprite*)peep); @@ -3082,13 +3201,15 @@ static void peep_update_ride_sub_state_18(rct_peep* peep){ peep_on_enter_or_exit_ride(peep, peep->current_ride, 1); - if (peep->flags & PEEP_FLAGS_TRACKING){ - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; - RCT2_GLOBAL(0x13CE958, uint16) = ride->name; - RCT2_GLOBAL(0x13CE95A, uint32) = ride->name_arguments; + if (peep->peep_flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; - news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1934, peep->sprite_index); + if (gConfigNotifications.guest_left_ride) { + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, STR_PEEP_TRACKING_LEFT_RIDE_X, peep->sprite_index); + } } peep->var_79 = 0xFF; @@ -3118,7 +3239,10 @@ static void peep_update_ride_sub_state_18(rct_peep* peep){ } while (!map_element_is_last_for_tile(mapElement++)); } -/* rct2: 0x0069299C */ +/** + * + * rct2: 0x0069299C + */ static void peep_update_ride_sub_state_19(rct_peep* peep){ sint16 x, y, xy_distance; @@ -3132,10 +3256,13 @@ static void peep_update_ride_sub_state_19(rct_peep* peep){ peep->sub_state++; } -/* rct2: 0x006929BB */ +/** + * + * rct2: 0x006929BB + */ static void peep_update_ride_sub_state_20(rct_peep* peep){ sint16 x, y; - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (ride->type == RIDE_TYPE_FIRST_AID){ if (peep->nausea <= 35){ @@ -3180,7 +3307,10 @@ static void peep_update_ride_sub_state_20(rct_peep* peep){ peep_stop_purchase_thought(peep, ride->type); } -/* rct2: 0x00692935 */ +/** + * + * rct2: 0x00692935 + */ static void peep_update_ride_sub_state_21(rct_peep* peep){ sint16 x, y, xy_distance; @@ -3201,14 +3331,16 @@ static void peep_update_ride_sub_state_21(rct_peep* peep){ peep->state = PEEP_STATE_WALKING; peep_window_state_update(peep); - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); ride->total_customers++; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER; ride_update_satisfaction(ride, peep->happiness / 64); } -/* rct2: 0x691A30 +/** + * + * rct2: 0x691A30 * Used by entering_ride and queueing_front */ static void peep_update_ride(rct_peep* peep){ switch (peep->sub_state){ @@ -3288,15 +3420,19 @@ static void peep_update_ride(rct_peep* peep){ peep_update_ride_sub_state_21(peep); break; default: - RCT2_CALLPROC_X(RCT2_ADDRESS(0x9820DC, int)[peep->sub_state], 0, 0, 0, 0, (int)peep, 0, 0); + // Invalid peep sub-state + assert(false); + break; } } -/* rct2: 0x006C0E8B +/** + * + * rct2: 0x006C0E8B * Also used by inspecting. */ static void peep_update_fixing(int steps, rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (ride->type == RIDE_TYPE_NULL) { @@ -3306,18 +3442,600 @@ static void peep_update_fixing(int steps, rct_peep* peep){ return; } - RCT2_CALLPROC_X(RCT2_ADDRESS(0x006C0EB0, uint32)[peep->sub_state], steps, 0, 0, 0, (int)peep, (int)ride, 0); + bool progressToNextSubstate = true; + bool firstRun = true; + + while (progressToNextSubstate) { + switch (peep->sub_state) { + case 0: + progressToNextSubstate = peep_update_fixing_sub_state_0(ride); + break; + + case 1: + progressToNextSubstate = peep_update_fixing_sub_state_1(firstRun, peep, ride); + break; + + case 2: + case 3: + case 4: + case 5: + progressToNextSubstate = peep_update_fixing_sub_state_2345(firstRun, peep, ride); + break; + + case 6: + progressToNextSubstate = peep_update_fixing_sub_state_6(firstRun, peep, ride); + break; + + case 7: + progressToNextSubstate = peep_update_fixing_sub_state_7(firstRun, peep, ride); + break; + + case 8: + progressToNextSubstate = peep_update_fixing_sub_state_8(firstRun, peep); + break; + + case 9: + progressToNextSubstate = peep_update_fixing_sub_state_9(firstRun, peep, ride); + break; + + case 10: + progressToNextSubstate = peep_update_fixing_sub_state_10(firstRun, peep, ride); + break; + + case 11: + progressToNextSubstate = peep_update_fixing_sub_state_11(firstRun, peep, ride); + break; + + case 12: + progressToNextSubstate = peep_update_fixing_sub_state_12(firstRun, peep, ride); + break; + + case 13: + progressToNextSubstate = peep_update_fixing_sub_state_13(firstRun, steps, peep, ride); + break; + + case 14: + progressToNextSubstate = peep_update_fixing_sub_state_14(firstRun, peep, ride); + break; + + default: + log_error("Invalid substate"); + progressToNextSubstate = false; + } + + firstRun = false; + + if (!progressToNextSubstate) { + break; + } + + int subState = peep->sub_state; + uint32 ebp = RCT2_ADDRESS(0x992A18, uint32)[8]; + + if (peep->state != PEEP_STATE_INSPECTING) { + ebp = RCT2_ADDRESS(0x992A18, uint32)[ride->breakdown_reason_pending]; + } + + do { + subState++; + } while ((ebp & (1 << subState)) == 0); + + peep->sub_state = subState & 0xFF; + } } /** - * rct2: 0x69185D + * rct2: 0x006C0EEC + */ +static bool peep_update_fixing_sub_state_0(rct_ride *ride) { + ride->mechanic_status = RIDE_MECHANIC_STATUS_FIXING; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE; + + return true; +} + +/** + * rct2: 0x006C0F09 + */ +static bool peep_update_fixing_sub_state_1(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 x, y, tmp_xy_distance; + + if (!firstRun) { + rct_vehicle *vehicle = ride_get_broken_vehicle(ride); + if (vehicle == NULL) { + return true; + } + + while (true) { + if (vehicle->is_child == 0) { + break; + } + + uint8 trackType = vehicle->track_type >> 2; + if (trackType == TRACK_ELEM_END_STATION) { + break; + } + + if (trackType == TRACK_ELEM_BEGIN_STATION) { + break; + } + + if (trackType == TRACK_ELEM_MIDDLE_STATION) { + break; + } + + vehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride); + } + + rct_xy16 offset = word_981D6C[peep->var_78]; + peep->destination_x = (offset.x * -12) + vehicle->x; + peep->destination_y = (offset.y * -12) + vehicle->y; + peep->destination_tolerence = 2; + } + + invalidate_sprite_2((rct_sprite *) peep); + if (peep_update_action(&x, &y, &tmp_xy_distance, peep)) { + sprite_move(x, y, peep->z, (rct_sprite *) peep); + invalidate_sprite_2((rct_sprite *) peep); + return false; + } + + return true; +} + +/** + * rct2: 0x006C0FD3 + */ +static bool peep_update_fixing_sub_state_2345(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 tmp_x, tmp_y, tmp_distance; + + if (!firstRun) { + peep->sprite_direction = peep->var_78 << 3; + + peep->action = (scenario_rand() & 1) ? PEEP_ACTION_STAFF_FIX_2 : PEEP_ACTION_STAFF_FIX; + peep->action_sprite_image_offset = 0; + peep->action_frame = 0; + sub_693B58(peep); + invalidate_sprite_2((rct_sprite *) peep); + } + + if (peep->action == PEEP_ACTION_NONE_2) { + return true; + } + + peep_update_action(&tmp_x, &tmp_y, &tmp_distance, peep); + + uint8 actionFrame = (peep->action == PEEP_ACTION_STAFF_FIX) ? 0x25 : 0x50; + if (peep->action_frame != actionFrame) { + return false; + } + + rct_vehicle *vehicle = ride_get_broken_vehicle(ride); + if (vehicle == NULL) { + return true; + } + + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_BROKEN_CAR; + + return false; +} + +/** + * rct2: 0x006C107B + */ +static bool peep_update_fixing_sub_state_6(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 tmp_x, tmp_y, tmp_distance; + + if (!firstRun) { + peep->sprite_direction = peep->var_78 << 3; + peep->action = PEEP_ACTION_STAFF_FIX_3; + peep->action_sprite_image_offset = 0; + peep->action_frame = 0; + + sub_693B58(peep); + invalidate_sprite_2((rct_sprite *) peep); + } + + if (peep->action == PEEP_ACTION_NONE_2) { + return true; + } + + peep_update_action(&tmp_x, &tmp_y, &tmp_distance, peep); + if (peep->action_frame != 0x65) { + return false; + } + + rct_vehicle *vehicle = ride_get_broken_vehicle(ride); + if (vehicle == NULL) { + return true; + } + + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_BROKEN_TRAIN; + + return false; +} + +/** + * rct2: 0x006C1114 + */ +static bool peep_update_fixing_sub_state_7(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 x, y, tmp_distance; + + if (!firstRun) { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_HAS_NO_TRACK)) { + return true; + } + + uint16 stationPosition = ride->station_starts[peep->current_ride_station]; + if (stationPosition == 0xFFFF) { + return true; + } + + uint8 stationZ = ride->station_heights[peep->current_ride_station]; + uint16 stationX = (stationPosition & 0xFF) * 32; + uint16 stationY = (stationPosition >> 8) * 32; + + rct_map_element *mapElement = map_get_track_element_at(stationX, stationY, stationZ); + if (mapElement == NULL) { + log_error("Couldn't find map_element"); + return false; + } + + int direction = map_element_get_direction(mapElement); + rct_xy16 offset = RCT2_ADDRESS(0x992A3C, rct_xy16)[direction]; + + stationX += 16 + offset.x; + if (offset.x == 0) { + stationX = peep->destination_x; + } + + stationY += 16 + offset.y; + if (offset.y == 0) { + stationY = peep->destination_y; + } + + peep->destination_x = stationX; + peep->destination_y = stationY; + peep->destination_tolerence = 2; + } + + invalidate_sprite_2((rct_sprite *) peep); + if (!peep_update_action(&x, &y, &tmp_distance, peep)) { + return true; + } + + sprite_move(x, y, peep->z, (rct_sprite *) peep); + invalidate_sprite_2((rct_sprite *) peep); + + return false; +} + +/** + * rct2: 0x006C11F5 + */ +static bool peep_update_fixing_sub_state_8(bool firstRun, rct_peep *peep) { + sint16 tmp_x, tmp_y, tmp_xy_distance; + + if (!firstRun) { + peep->sprite_direction = peep->var_78 << 3; + peep->action = PEEP_ACTION_STAFF_CHECKBOARD; + peep->action_frame = 0; + peep->action_sprite_image_offset = 0; + + sub_693B58(peep); + invalidate_sprite_2((rct_sprite *) peep); + } + + if (peep->action == PEEP_ACTION_NONE_2) { + return true; + } + + peep_update_action(&tmp_x, &tmp_y, &tmp_xy_distance, peep); + + return false; +} + +/** + * rct2: 0x006C1239 + */ +static bool peep_update_fixing_sub_state_9(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 x, y, tmp_xy_distance; + + if (!firstRun) { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_HAS_NO_TRACK)) { + return true; + } + + uint16 stationPosition = ride->station_starts[peep->current_ride_station]; + if (stationPosition == 0xFFFF) { + return true; + } + + uint8 stationZ = ride->station_heights[peep->current_ride_station]; + + rct_xy_element input; + input.x = (stationPosition & 0xFF) * 32; + input.y = (stationPosition >> 8) * 32; + input.element = map_get_track_element_at_from_ride(input.x, input.y, stationZ, peep->current_ride); + if (input.element == NULL) { + return true; + } + + track_begin_end trackBeginEnd; + while (track_block_get_previous(input.x, input.y, input.element, &trackBeginEnd)) { + uint8 trackType = trackBeginEnd.begin_element->properties.track.type; + if (trackType == TRACK_ELEM_BEGIN_STATION || trackType == TRACK_ELEM_MIDDLE_STATION || trackType == TRACK_ELEM_END_STATION) { + input.x = trackBeginEnd.begin_x; + input.y = trackBeginEnd.begin_y; + input.element = trackBeginEnd.begin_element; + + RCT2_GLOBAL(0xF43914, uint32) = trackBeginEnd.begin_element->type & 3; + continue; + } + + break; + } + + // loc_6C12ED: + uint16 destinationX = input.x + 16; + uint16 destinationY = input.y + 16; + + uint8 direction = RCT2_GLOBAL(0xF43914, uint32); + rct_xy16 offset = RCT2_ADDRESS(0x992A3C, rct_xy16)[direction]; + + destinationX -= offset.x; + if (offset.x == 0) { + destinationX = peep->destination_x; + } + + destinationY -= offset.y; + if (offset.y == 0) { + destinationY = peep->destination_y; + } + + peep->destination_x = destinationX; + peep->destination_y = destinationY; + peep->destination_tolerence = 2; + } + + invalidate_sprite_2((rct_sprite *) peep); + + if (!peep_update_action(&x, &y, &tmp_xy_distance, peep)) { + return true; + } + + sprite_move(x, y, peep->z, (rct_sprite *) peep); + invalidate_sprite_2((rct_sprite *) peep); + + return false; +} + +/** + * rct2: 0x006C1368 + */ +static bool peep_update_fixing_sub_state_10(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 tmp_x, tmp_y, tmp_xy_distance; + + if (!firstRun) { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3 | RIDE_TYPE_FLAG_HAS_NO_TRACK)) { + return true; + } + + peep->sprite_direction = peep->var_78 << 3; + + peep->action = PEEP_ACTION_STAFF_FIX; + peep->action_frame = 0; + peep->action_sprite_image_offset = 0; + + sub_693B58(peep); + invalidate_sprite_2((rct_sprite *) peep); + } + + if (peep->action == PEEP_ACTION_NONE_2) { + return true; + } + + peep_update_action(&tmp_x, &tmp_y, &tmp_xy_distance, peep); + + return false; +} + +/** + * rct2: 0x006C13CE + */ +static bool peep_update_fixing_sub_state_11(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 tmp_x, tmp_y, tmp_xy_distance; + + if (!firstRun) { + peep->sprite_direction = peep->var_78 << 3; + + peep->action = PEEP_ACTION_STAFF_FIX_GROUND; + peep->action_frame = 0; + peep->action_sprite_image_offset = 0; + + sub_693B58(peep); + invalidate_sprite_2((rct_sprite *) peep); + } + + if (peep->action == PEEP_ACTION_NONE_2) { + return true; + } + + peep_update_action(&tmp_x, &tmp_y, &tmp_xy_distance, peep); + if (peep->action_frame == 0x28) { + ride->mechanic_status = 4; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE; + } + + if (peep->action_frame == 0x13 || + peep->action_frame == 0x19 || + peep->action_frame == 0x1F || + peep->action_frame == 0x25 || + peep->action_frame == 0x2B) { + audio_play_sound_at_location(SOUND_MECHANIC_FIX, peep->x, peep->y, peep->z); + } + + return false; +} + +/** + * rct2: 0x006C1474 + */ +static bool peep_update_fixing_sub_state_12(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 x, y, tmp_xy_distance; + + if (!firstRun) { + uint16 stationPosition = ride->exits[peep->current_ride_station]; + if (stationPosition == 0xFFFF) { + stationPosition = ride->entrances[peep->current_ride_station]; + + if (stationPosition == 0xFFFF) { + return true; + } + } + + uint16 stationX = (stationPosition & 0xFF) * 32; + uint16 stationY = (stationPosition >> 8) * 32; + + stationX += 16; + stationY += 16; + + rct_xy16 direction = word_981D6C[peep->var_78]; + + stationX += direction.x * 20; + stationY += direction.y * 20; + + peep->destination_x = stationX; + peep->destination_y = stationY; + peep->destination_tolerence = 2; + } + + invalidate_sprite_2((rct_sprite *) peep); + if (peep_update_action(&x, &y, &tmp_xy_distance, peep) == 0) { + return true; + } else { + sprite_move(x, y, peep->z, (rct_sprite *) peep); + invalidate_sprite_2((rct_sprite *) peep); + } + + return false; +} + +/** + * rct2: 0x006C1504 + */ +static bool peep_update_fixing_sub_state_13(bool firstRun, int steps, rct_peep *peep, rct_ride *ride) { + sint16 tmp_x, tmp_y, tmp_xy_distance; + + if (!firstRun) { + if (peep->state == PEEP_STATE_INSPECTING) { + sub_6B7588(peep->current_ride); + + peep->staff_rides_inspected++; + peep->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME | RIDE_INVALIDATE_RIDE_LIST; + + return true; + } + + peep->staff_rides_fixed++; + peep->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME | RIDE_INVALIDATE_RIDE_LIST; + + peep->sprite_direction = peep->var_78 << 3; + peep->action = PEEP_ACTION_STAFF_ANSWER_CALL_2; + peep->action_frame = 0; + peep->action_sprite_image_offset = 0; + + sub_693B58(peep); + invalidate_sprite_2((rct_sprite *) peep); + } + + if (peep->action != 0xFF) { + peep_update_action(&tmp_x, &tmp_y, &tmp_xy_distance, peep); + return false; + } + + ride_fix_breakdown(peep->current_ride, steps); + + return true; +} + +/** + * rct2: 0x006C157E + */ +static bool peep_update_fixing_sub_state_14(bool firstRun, rct_peep *peep, rct_ride *ride) { + sint16 x, y, xy_distance; + + if (!firstRun) { + uint16 exitPosition = ride->exits[peep->current_ride_station]; + if (exitPosition == 0xFFFF) { + exitPosition = ride->entrances[peep->current_ride_station]; + + if (exitPosition == 0xFFFF) { + peep_decrement_num_riders(peep); + peep->state = 0; + peep_window_state_update(peep); + return false; + } + } + + uint16 exitX = (exitPosition & 0xFF) * 32; + uint16 exitY = (exitPosition >> 8) * 32; + + exitX += 16; + exitY += 16; + + rct_xy16 ebx_direction = word_981D6C[peep->var_78]; + exitX -= ebx_direction.x * 19; + exitY -= ebx_direction.y * 19; + + peep->destination_x = exitX; + peep->destination_y = exitY; + peep->destination_tolerence = 2; + } + + invalidate_sprite_2((rct_sprite *) peep); + if (peep_update_action(&x, &y, &xy_distance, peep) == 0) { + peep_decrement_num_riders(peep); + peep->state = 0; + peep_window_state_update(peep); + + return false; + } + + uint16 z = ride->station_heights[peep->current_ride_station] * 8; + + if (xy_distance >= 16) { + z += RCT2_ADDRESS(0x0097D21C, uint8)[ride->type * 8]; + } + + sprite_move(x, y, z, (rct_sprite *) peep); + invalidate_sprite_2((rct_sprite *) peep); + + return false; +} + +/** + * rct2: 0x6B7588 + */ +static void sub_6B7588(int rideIndex) { + rct_ride *ride = get_ride(rideIndex); + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_DUE_INSPECTION; + + ride->reliability += ((100 - (ride->reliability >> 8)) >> 2) * (scenario_rand() & 0xFF); + ride->last_inspection = 0; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE | RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; +} + +/** + * + * rct2: 0x69185D */ static void peep_update_queuing(rct_peep* peep){ - if (!sub_68F3AE(peep)){ + if (!checkForPath(peep)){ remove_peep_from_queue(peep); return; } - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (ride->status == RIDE_STATUS_CLOSED || ride->status == RIDE_STATUS_TESTING){ remove_peep_from_queue(peep); peep_decrement_num_riders(peep); @@ -3364,7 +4082,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: @@ -3411,10 +4129,12 @@ static void peep_update_queuing(rct_peep* peep){ } } -/* rct2: 0x006BF567 */ +/** + * + * rct2: 0x006BF567 + */ 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){ @@ -3455,11 +4175,14 @@ static void peep_update_mowing(rct_peep* peep){ } } -/* rct2: 0x006BF7E6 */ +/** + * + * rct2: 0x006BF7E6 + */ 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; @@ -3507,12 +4230,15 @@ static void peep_update_watering(rct_peep* peep){ } } -/* rct2: 0x006BF6C9 */ +/** + * + * rct2: 0x006BF6C9 + */ 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; @@ -3551,16 +4277,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; @@ -3575,10 +4301,13 @@ static void peep_update_emptying_bin(rct_peep* peep){ } } -/* rct2: 0x6BF641 */ +/** + * + * rct2: 0x6BF641 + */ 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); @@ -3608,9 +4337,12 @@ static void peep_update_sweeping(rct_peep* peep){ peep_state_reset(peep); } -/* rct2: 0x6902A2 */ +/** + * + * rct2: 0x6902A2 + */ static void peep_update_1(rct_peep* peep){ - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; peep_decrement_num_riders(peep); @@ -3629,7 +4361,8 @@ static void peep_update_1(rct_peep* peep){ } /** - * rct2: 0x690009 + * + * rct2: 0x690009 */ static void peep_update_picked(rct_peep* peep){ if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x1F) return; @@ -3639,7 +4372,10 @@ static void peep_update_picked(rct_peep* peep){ } } -/* rct2: 0x6914CD */ +/** + * + * rct2: 0x6914CD + */ static void peep_update_leaving_park(rct_peep* peep){ if (peep->var_37 != 0){ sub_693C9E(peep); @@ -3669,10 +4405,13 @@ static void peep_update_leaving_park(rct_peep* peep){ peep_sprite_remove(peep); } -/* rct2: 0x6916D6 */ +/** + * + * rct2: 0x6916D6 + */ 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; @@ -3684,7 +4423,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); @@ -3784,7 +4523,10 @@ static void peep_update_entering_park(rct_peep* peep){ window_invalidate_by_class(WC_GUEST_LIST); } -/* rct2: 0x00690582*/ +/** + * + * rct2: 0x00690582 + */ static int peep_update_walking_find_bench(rct_peep* peep){ if (!peep_should_find_bench(peep))return 0; @@ -3799,16 +4541,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; @@ -3817,7 +4557,7 @@ static int peep_update_walking_find_bench(rct_peep* peep){ for (; !(edges & (1 << chosen_edge));)chosen_edge = (chosen_edge + 1) & 0x3; - uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[((peep->x & 0x1FE0) << 3) | (peep->y >> 5)]; + uint16 sprite_id = sprite_get_first_in_quadrant(peep->x, peep->y); uint8 free_edge = 3; for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->unknown.next_in_quadrant){ @@ -3876,16 +4616,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; @@ -3927,12 +4665,15 @@ static int peep_update_walking_find_bin(rct_peep* peep){ return 1; } -/* rct2: 0x00690848*/ +/** + * + * rct2: 0x00690848 + */ static void peep_update_walking_break_scenery(rct_peep* peep){ - if(gConfigCheat.disable_vandalism) + if(gCheatsDisableVandalism) return; - if (!(peep->flags & PEEP_FLAGS_ANGRY)){ + if (!(peep->peep_flags & PEEP_FLAGS_ANGRY)){ if (peep->happiness >= 48) return; if (peep->energy < 85) return; if (peep->state != PEEP_STATE_WALKING) return; @@ -3956,16 +4697,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; @@ -3997,12 +4736,15 @@ static void peep_update_walking_break_scenery(rct_peep* peep){ return; } -/* rct2: 0x006912A3 */ +/** + * + * rct2: 0x006912A3 + */ 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); + rct_ride* ride = get_ride(peep->current_ride); if (ride->type == RIDE_TYPE_NULL || ride->status != RIDE_STATUS_OPEN){ peep_decrement_num_riders(peep); peep->state = PEEP_STATE_FALLING; @@ -4054,7 +4796,7 @@ static void peep_update_buying(rct_peep* peep) } } else{ - rct_ride_type* ride_type = gRideTypeList[ride->subtype]; + rct_ride_entry* ride_type = get_ride_entry(ride->subtype); if (ride_type->shop_item_secondary != 0xFF){ money16 price = ride->price_secondary; @@ -4087,10 +4829,13 @@ static void peep_update_buying(rct_peep* peep) return; } -/* rct2: 0x00691089 */ +/** + * + * rct2: 0x00691089 + */ 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; @@ -4120,13 +4865,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; @@ -4137,7 +4881,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; } @@ -4146,17 +4890,17 @@ static void peep_update_using_bin(rct_peep* peep){ uint8 selected_bin = peep->var_37 * 2; // This counts down 2 = No rubbish, 0 = full - uint8 rubbish_in_bin = 0x3 & (map_element->properties.path.addition_status >> selected_bin); + uint8 space_left_in_bin = 0x3 & (map_element->properties.path.addition_status >> selected_bin); uint32 empty_containers = peep_empty_container_standard_flag(peep); for (uint8 cur_container = 0; cur_container < 32; cur_container++){ if (!(empty_containers & (1u << cur_container))) continue; - if (rubbish_in_bin != 0){ + if (space_left_in_bin != 0){ // OpenRCT2 modification: This previously used // the tick count as a simple random function // switched to scenario_rand as it is more reliable - if (scenario_rand() & 7) rubbish_in_bin--; + if ((scenario_rand() & 7) == 0) space_left_in_bin--; peep->item_standard_flags &= ~(1 << cur_container); peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY; peep_update_sprite_type(peep); @@ -4182,11 +4926,11 @@ static void peep_update_using_bin(rct_peep* peep){ for (uint8 cur_container = 0; cur_container < 32; cur_container++){ if (!(empty_containers & (1u << cur_container))) continue; - if (rubbish_in_bin != 0){ + if (space_left_in_bin != 0){ // OpenRCT2 modification: This previously used // the tick count as a simple random function // switched to scenario_rand as it is more reliable - if (scenario_rand() & 7) rubbish_in_bin--; + if ((scenario_rand() & 7) == 0) space_left_in_bin--; peep->item_extra_flags &= ~(1 << cur_container); peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY; @@ -4209,16 +4953,19 @@ static void peep_update_using_bin(rct_peep* peep){ // Place new amount in bin by first clearing the value map_element->properties.path.addition_status &= ~(3 << selected_bin); // Then placeing the new value. - map_element->properties.path.addition_status |= rubbish_in_bin << selected_bin; + map_element->properties.path.addition_status |= space_left_in_bin << selected_bin; map_invalidate_tile_zoom0(peep->next_x, peep->next_y, map_element->base_height << 3, map_element->clearance_height << 3); peep_state_reset(peep); } } -/* rct2: 0x006C16D7 */ +/** + * + * rct2: 0x006C16D7 + */ static void peep_update_heading_to_inspect(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (ride->type == RIDE_TYPE_NULL){ peep_decrement_num_riders(peep); @@ -4245,7 +4992,7 @@ static void peep_update_heading_to_inspect(rct_peep* peep){ if (peep->sub_state == 0){ peep->var_74 = 0; - sub_69A98C(peep); + peep_reset_pathfind_goal(peep); peep->sub_state = 2; } @@ -4262,7 +5009,7 @@ static void peep_update_heading_to_inspect(rct_peep* peep){ return; } - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); @@ -4322,9 +5069,12 @@ static void peep_update_heading_to_inspect(rct_peep* peep){ invalidate_sprite_2((rct_sprite*)peep); } -/* rct2: 0x006C0CB8 */ +/** + * + * rct2: 0x006C0CB8 + */ static void peep_update_answering(rct_peep* peep){ - rct_ride* ride = GET_RIDE(peep->current_ride); + rct_ride* ride = get_ride(peep->current_ride); if (ride->type == RIDE_TYPE_NULL || ride->mechanic_status != RIDE_MECHANIC_STATUS_HEADING){ @@ -4352,7 +5102,7 @@ static void peep_update_answering(rct_peep* peep){ peep->sub_state = 2; peep_window_state_update(peep); peep->var_74 = 0; - sub_69A98C(peep); + peep_reset_pathfind_goal(peep); return; } sint16 x, y, xy_distance; @@ -4372,7 +5122,7 @@ static void peep_update_answering(rct_peep* peep){ return; } - if (!sub_68F3AE(peep))return; + if (!checkForPath(peep))return; sub_693C9E(peep); @@ -4432,7 +5182,10 @@ static void peep_update_answering(rct_peep* peep){ invalidate_sprite_2((rct_sprite*)peep); } -/* rct2: 0x006BF483 */ +/** + * + * rct2: 0x006BF483 + */ static int peep_update_patrolling_find_watering(rct_peep* peep){ if (!(peep->staff_orders & STAFF_ORDERS_WATER_FLOWERS)) return 0; @@ -4489,7 +5242,10 @@ static int peep_update_patrolling_find_watering(rct_peep* peep){ return 0; } -/* rct2: 0x006BF3A1 */ +/** + * + * rct2: 0x006BF3A1 + */ static int peep_update_patrolling_find_bin(rct_peep* peep){ if (!(peep->staff_orders & STAFF_ORDERS_EMPTY_BINS)) return 0; @@ -4509,11 +5265,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; @@ -4521,7 +5274,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; @@ -4550,7 +5303,10 @@ static int peep_update_patrolling_find_bin(rct_peep* peep){ return 1; } -/* rct2: 0x006BF322 */ +/** + * + * rct2: 0x006BF322 + */ static int peep_update_patrolling_find_grass(rct_peep* peep){ if (!(peep->staff_orders & STAFF_ORDERS_MOWING)) return 0; @@ -4564,7 +5320,7 @@ static int peep_update_patrolling_find_grass(rct_peep* peep){ if ((map_element->properties.surface.terrain & MAP_ELEMENT_SURFACE_TERRAIN_MASK) != TERRAIN_GRASS) return 0; - if (map_element->properties.surface.grass_length < GRASS_LENGTH_CLEAR_1) + if ((map_element->properties.surface.grass_length & 0x7) < GRASS_LENGTH_CLEAR_1) return 0; peep_decrement_num_riders(peep); @@ -4577,12 +5333,15 @@ static int peep_update_patrolling_find_grass(rct_peep* peep){ return 1; } -/* rct2: 0x006BF295 */ +/** + * + * rct2: 0x006BF295 + */ static int peep_update_patrolling_find_sweeping(rct_peep* peep){ if (!(peep->staff_orders & STAFF_ORDERS_SWEEPING)) return 0; - uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[((peep->x & 0x1FE0) << 3) | (peep->y >> 5)]; + uint16 sprite_id = sprite_get_first_in_quadrant(peep->x, peep->y); for (rct_sprite* sprite = NULL; sprite_id != 0xFFFF; @@ -4609,10 +5368,13 @@ static int peep_update_patrolling_find_sweeping(rct_peep* peep){ return 0; } -/* rct2: 0x006BF1FD */ +/** + * + * rct2: 0x006BF1FD + */ 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; @@ -4647,11 +5409,14 @@ static void peep_update_patrolling(rct_peep* peep){ peep_update_patrolling_find_watering(peep); } -/* rct2: 0x0069030A */ +/** + * + * 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->peep_flags & PEEP_FLAGS_WAVING){ if (peep->action >= PEEP_ACTION_NONE_1){ if ((0xFFFF & scenario_rand()) < 936){ invalidate_sprite_2((rct_sprite*)peep); @@ -4666,7 +5431,7 @@ static void peep_update_walking(rct_peep* peep){ } } - if (peep->flags & PEEP_FLAGS_PHOTO){ + if (peep->peep_flags & PEEP_FLAGS_PHOTO){ if (peep->action >= PEEP_ACTION_NONE_1){ if ((0xFFFF & scenario_rand()) < 936){ invalidate_sprite_2((rct_sprite*)peep); @@ -4681,7 +5446,7 @@ static void peep_update_walking(rct_peep* peep){ } } - if (peep->flags & PEEP_FLAGS_PAINTING){ + if (peep->peep_flags & PEEP_FLAGS_PAINTING){ if (peep->action >= PEEP_ACTION_NONE_1){ if ((0xFFFF & scenario_rand()) < 936){ invalidate_sprite_2((rct_sprite*)peep); @@ -4696,7 +5461,7 @@ static void peep_update_walking(rct_peep* peep){ } } - if (peep->flags & PEEP_FLAGS_LITTER){ + if (peep->peep_flags & PEEP_FLAGS_LITTER){ if (!(peep->next_var_29 & 0x18)){ if ((0xFFFF & scenario_rand()) <= 4096){ int ebp = (scenario_rand() & 0x3) + 2; @@ -4724,8 +5489,10 @@ static void peep_update_walking(rct_peep* peep){ } else{ uint8 pos_extr = 0; - for (int container = peep_empty_container_extra_flag(peep); pos_extr < 32; pos_extr++)if (container&(1 << pos_extr))break; - peep->item_extra_flags &= ~(1 << pos_extr); + for (int container = peep_empty_container_extra_flag(peep); pos_extr < 32; pos_extr++) + if (container & (1u << pos_extr)) + break; + peep->item_extra_flags &= ~(1u << pos_extr); bp = RCT2_ADDRESS(0x97EFE8, uint8)[pos_extr]; } @@ -4772,7 +5539,7 @@ static void peep_update_walking(rct_peep* peep){ if (peep->state != PEEP_STATE_WALKING)return; - if (peep->flags & PEEP_FLAGS_LEAVING_PARK)return; + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)return; if (peep->nausea > 140)return; @@ -4797,13 +5564,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; } @@ -4817,10 +5582,10 @@ static void peep_update_walking(rct_peep* peep){ for (; !(edges & (1 << chosen_edge));)chosen_edge = (chosen_edge + 1) & 3; uint8 ride_to_view, ride_seat_to_view; - if (!sub_690B99(peep, chosen_edge, &ride_to_view, &ride_seat_to_view)) + if (!peep_find_ride_to_look_at(peep, chosen_edge, &ride_to_view, &ride_seat_to_view)) return; - uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[((peep->x & 0x1FE0) << 3) | (peep->y >> 5)]; + uint16 sprite_id = sprite_get_first_in_quadrant(peep->x, peep->y); for (rct_sprite* sprite; sprite_id != SPRITE_INDEX_NULL; sprite_id = sprite->unknown.next_in_quadrant){ sprite = &g_sprite_list[sprite_id]; @@ -4898,7 +5663,7 @@ static void peep_update_thoughts(rct_peep* peep){ peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_THOUGHTS; // Clear top thought, push others up - if (i < PEEP_MAX_THOUGHTS - 1) { + if (i < PEEP_MAX_THOUGHTS - 2) { memmove(&peep->thoughts[i], &peep->thoughts[i + 1], sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1)); } peep->thoughts[PEEP_MAX_THOUGHTS - 1].type = PEEP_THOUGHT_TYPE_NONE; @@ -4936,7 +5701,7 @@ static void peep_update(rct_peep *peep) unsigned int stepsToTake = peep->energy; if (stepsToTake < 95 && peep->state == PEEP_STATE_QUEUING) stepsToTake = 95; - if ((peep->flags & PEEP_FLAGS_SLOW_WALK) && peep->state != PEEP_STATE_QUEUING) + if ((peep->peep_flags & PEEP_FLAGS_SLOW_WALK) && peep->state != PEEP_STATE_QUEUING) stepsToTake /= 2; if (peep->action == 255 && (peep->next_var_29 & 4)) { stepsToTake /= 2; @@ -4947,8 +5712,7 @@ static void peep_update(rct_peep *peep) unsigned int carryCheck = peep->var_73 + stepsToTake; peep->var_73 = carryCheck; if (carryCheck <= 255) { - // loc_68FD3A - sub_68FD3A(peep); + peep_easter_egg_peep_interactions(peep); } else { // loc_68FD2F switch (peep->state) { @@ -5035,8 +5799,8 @@ static void peep_update(rct_peep *peep) /** * - * rct2: 0x0069BF41 - **/ + * rct2: 0x0069BF41 + */ void peep_problem_warnings_update() { rct_peep* peep; @@ -5063,7 +5827,7 @@ void peep_problem_warnings_update() hunger_counter++; break; } - ride = &g_ride_list[peep->guest_heading_to_ride_id]; + ride = get_ride(peep->guest_heading_to_ride_id); if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE)) hunger_counter++; break; @@ -5073,7 +5837,7 @@ void peep_problem_warnings_update() thirst_counter++; break; } - ride = &g_ride_list[peep->guest_heading_to_ride_id]; + ride = get_ride(peep->guest_heading_to_ride_id); if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_SELLS_DRINKS)) thirst_counter++; break; @@ -5083,7 +5847,7 @@ void peep_problem_warnings_update() bathroom_counter++; break; } - ride = &g_ride_list[peep->guest_heading_to_ride_id]; + ride = get_ride(peep->guest_heading_to_ride_id); if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_BATHROOM)) bathroom_counter++; break; @@ -5109,52 +5873,68 @@ void peep_problem_warnings_update() --warning_throttle[0]; else if ( hunger_counter >= PEEP_HUNGER_WARNING_THRESHOLD && hunger_counter >= guests_in_park / 16) { warning_throttle[0] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_HUNGRY, 20); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_HUNGRY, 20); + } } if (warning_throttle[1]) --warning_throttle[1]; else if (thirst_counter >= PEEP_THIRST_WARNING_THRESHOLD && thirst_counter >= guests_in_park / 16) { warning_throttle[1] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_THIRSTY, 21); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_ARE_THIRSTY, 21); + } } if (warning_throttle[2]) --warning_throttle[2]; else if (bathroom_counter >= PEEP_BATHROOM_WARNING_THRESHOLD && bathroom_counter >= guests_in_park / 16) { warning_throttle[2] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_CANT_FIND_BATHROOM, 22); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_CANT_FIND_BATHROOM, 22); + } } if (warning_throttle[3]) --warning_throttle[3]; else if (litter_counter >= PEEP_LITTER_WARNING_THRESHOLD && litter_counter >= guests_in_park / 32) { warning_throttle[3] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_LITTER, 26); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_LITTER, 26); + } } if (warning_throttle[4]) --warning_throttle[4]; else if (disgust_counter >= PEEP_DISGUST_WARNING_THRESHOLD && disgust_counter >= guests_in_park / 32) { warning_throttle[4] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISGUSTED_BY_PATHS, 31); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISGUSTED_BY_PATHS, 31); + } } if (warning_throttle[5]) --warning_throttle[5]; else if (vandalism_counter >= PEEP_VANDALISM_WARNING_THRESHOLD && vandalism_counter >= guests_in_park / 32) { warning_throttle[5] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_VANDALISM, 33); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_DISLIKE_VANDALISM, 33); + } } if (warning_throttle[6]) --warning_throttle[6]; else if (noexit_counter >= PEEP_NOEXIT_WARNING_THRESHOLD) { warning_throttle[6] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 27); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 27); + } } else if (lost_counter >= PEEP_LOST_WARNING_THRESHOLD) { warning_throttle[6] = 4; - news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 16); + if (gConfigNotifications.guest_warnings) { + news_item_add_to_queue(NEWS_ITEM_PEEPS, STR_PEEPS_GETTING_LOST_OR_STUCK, 16); + } } } @@ -5172,7 +5952,7 @@ void peep_update_crowd_noise() if (gGameSoundsOff) return; - if (!gConfigSound.sound) + if (!gConfigSound.sound_enabled) return; if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2) @@ -5225,7 +6005,7 @@ void peep_update_crowd_noise() if (!gCrowdSoundChannel) { gCrowdSoundChannel = Mixer_Play_Music(PATH_ID_CSS2, MIXER_LOOP_INFINITE, false); if (gCrowdSoundChannel) { - Mixer_Channel_SetGroup(gCrowdSoundChannel, MIXER_GROUP_NONE); + Mixer_Channel_SetGroup(gCrowdSoundChannel, MIXER_GROUP_SOUND); } } if (gCrowdSoundChannel) { @@ -5307,18 +6087,18 @@ 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; - peep->flags = 0; + peep->peep_flags = 0; 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; @@ -5402,10 +6182,10 @@ rct_peep *peep_generate(int x, int y, int z) peep->cash_in_pocket = cash; peep->cash_spent = 0; peep->time_in_park = -1; - peep->var_CC.x = 0xFF; - peep->var_CC.y = 0xFF; - peep->var_CC.z = 0xFF; - peep->var_CC.direction = 0xFF; + peep->pathfind_goal.x = 0xFF; + peep->pathfind_goal.y = 0xFF; + peep->pathfind_goal.z = 0xFF; + peep->pathfind_goal.direction = 0xFF; peep->item_standard_flags = 0; peep->item_extra_flags = 0; peep->guest_heading_to_ride_id = 0xFF; @@ -5452,7 +6232,7 @@ rct_peep *peep_generate(int x, int y, int z) * argument_2 (edx) */ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argument_2){ - rct_ride ride; + rct_ride *ride; switch (peep->state){ case PEEP_STATE_FALLING: @@ -5467,34 +6247,34 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum case PEEP_STATE_LEAVING_RIDE: case PEEP_STATE_ENTERING_RIDE: *argument_1 = STR_ON_RIDE; - ride = g_ride_list[peep->current_ride]; - if (ride_type_has_flag(ride.type, RIDE_TYPE_FLAG_IN_RIDE)) + ride = get_ride(peep->current_ride); + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IN_RIDE)) *argument_1 = STR_IN_RIDE; - *argument_1 |= (ride.name << 16); - *argument_2 = ride.name_arguments; + *argument_1 |= (ride->name << 16); + *argument_2 = ride->name_arguments; break; case PEEP_STATE_BUYING: - ride = g_ride_list[peep->current_ride]; - *argument_1 = STR_AT_RIDE | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->current_ride); + *argument_1 = STR_AT_RIDE | (ride->name << 16); + *argument_2 = ride->name_arguments; break; case PEEP_STATE_WALKING: case PEEP_STATE_USING_BIN: if (peep->guest_heading_to_ride_id != 0xFF){ - ride = g_ride_list[peep->guest_heading_to_ride_id]; - *argument_1 = STR_HEADING_FOR | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->guest_heading_to_ride_id); + *argument_1 = STR_HEADING_FOR | (ride->name << 16); + *argument_2 = ride->name_arguments; } else{ - *argument_1 = peep->flags & PEEP_FLAGS_LEAVING_PARK ? STR_LEAVING_PARK : STR_WALKING; + *argument_1 = peep->peep_flags & PEEP_FLAGS_LEAVING_PARK ? STR_LEAVING_PARK : STR_WALKING; *argument_2 = 0; } break; case PEEP_STATE_QUEUING_FRONT: case PEEP_STATE_QUEUING: - ride = g_ride_list[peep->current_ride]; - *argument_1 = STR_QUEUING_FOR | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->current_ride); + *argument_1 = STR_QUEUING_FOR | (ride->name << 16); + *argument_2 = ride->name_arguments; break; case PEEP_STATE_SITTING: *argument_1 = STR_SITTING; @@ -5502,13 +6282,13 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum break; case PEEP_STATE_WATCHING: if (peep->current_ride != 0xFF){ - ride = g_ride_list[peep->current_ride]; - *argument_1 = STR_WATCHING_RIDE | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->current_ride); + *argument_1 = STR_WATCHING_RIDE | (ride->name << 16); + *argument_2 = ride->name_arguments; if (peep->current_seat & 0x1) - *argument_1 = STR_WATCHING_CONSTRUCTION_OF | (ride.name << 16); + *argument_1 = STR_WATCHING_CONSTRUCTION_OF | (ride->name << 16); else - *argument_1 = STR_WATCHING_RIDE | (ride.name << 16); + *argument_1 = STR_WATCHING_RIDE | (ride->name << 16); } else{ *argument_1 = peep->current_seat & 0x1 ? STR_WATCHING_NEW_RIDE_BEING_CONSTRUCTED : STR_LOOKING_AT_SCENERY; @@ -5551,25 +6331,25 @@ void get_arguments_from_action(rct_peep* peep, uint32 *argument_1, uint32* argum *argument_2 = 0; } else{ - ride = g_ride_list[peep->current_ride]; - *argument_1 = STR_RESPONDING_TO_RIDE_BREAKDOWN_CALL | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->current_ride); + *argument_1 = STR_RESPONDING_TO_RIDE_BREAKDOWN_CALL | (ride->name << 16); + *argument_2 = ride->name_arguments; } break; case PEEP_STATE_FIXING: - ride = g_ride_list[peep->current_ride]; - *argument_1 = STR_FIXING_RIDE | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->current_ride); + *argument_1 = STR_FIXING_RIDE | (ride->name << 16); + *argument_2 = ride->name_arguments; break; case PEEP_STATE_HEADING_TO_INSPECTION: - ride = g_ride_list[peep->current_ride]; - *argument_1 = STR_HEADING_TO_RIDE_FOR_INSPECTION | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->current_ride); + *argument_1 = STR_HEADING_TO_RIDE_FOR_INSPECTION | (ride->name << 16); + *argument_2 = ride->name_arguments; break; case PEEP_STATE_INSPECTING: - ride = g_ride_list[peep->current_ride]; - *argument_1 = STR_INSPECTING_RIDE | (ride.name << 16); - *argument_2 = ride.name_arguments; + ride = get_ride(peep->current_ride); + *argument_1 = STR_INSPECTING_RIDE | (ride->name << 16); + *argument_2 = ride->name_arguments; break; } @@ -5587,7 +6367,7 @@ void get_arguments_from_thought(rct_peep_thought thought, uint32* argument_1, ui int esi = 0x009AC86C; if ((RCT2_ADDRESS(0x00981DB1, uint16)[thought.type] & 0xFF) & 1) { - rct_ride* ride = &g_ride_list[thought.item]; + rct_ride* ride = get_ride(thought.item); esi = (int)(&(ride->name)); } else if ((RCT2_ADDRESS(0x00981DB1, uint16)[thought.type] & 0xFF) & 2) { RCT2_GLOBAL(0x009AC86C, uint16) = ShopItemStringIds[thought.item].singular; @@ -5601,7 +6381,8 @@ void get_arguments_from_thought(rct_peep_thought thought, uint32* argument_1, ui } /** - * rct2: 0x00698827 + * + * rct2: 0x00698827 * returns 1 on pickup (CF not set) */ int peep_can_be_picked_up(rct_peep* peep){ @@ -5687,7 +6468,7 @@ int get_face_sprite_offset(rct_peep *peep){ } /** - * Function split into large and small sprite + * Function split into large and small sprite * rct2: 0x00698721 */ int get_peep_face_sprite_small(rct_peep *peep){ @@ -5695,7 +6476,7 @@ int get_peep_face_sprite_small(rct_peep *peep){ } /** - * Function split into large and small sprite + * Function split into large and small sprite * rct2: 0x00698721 */ int get_peep_face_sprite_large(rct_peep *peep){ @@ -5787,7 +6568,8 @@ static int peep_has_food_extra_flag(rct_peep* peep){ ); } -/* To simplify check of 0x36BA3E0 and 0x11FF78 +/** + * To simplify check of 0x36BA3E0 and 0x11FF78 * returns 0 on no food. */ int peep_has_food(rct_peep* peep){ @@ -5812,7 +6594,8 @@ static int peep_has_drink_extra_flag(rct_peep* peep){ ); } -/* To simplify check of NOT(0x12BA3C0 and 0x118F48) +/** + * To simplify check of NOT(0x12BA3C0 and 0x118F48) * returns 0 on no food. */ static int peep_has_drink(rct_peep* peep){ @@ -5847,7 +6630,7 @@ static int peep_has_empty_container(rct_peep* peep){ /* Simplifies 0x690582. Returns 1 if should find bench*/ static int peep_should_find_bench(rct_peep* peep){ - if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK)){ + if (!(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)){ if (peep_has_food(peep)){ if (peep->hunger < 128 || peep->happiness < 128){ if (!(peep->next_var_29 & 0x1C)){ @@ -5867,7 +6650,8 @@ static int peep_should_find_bench(rct_peep* peep){ } /** - * rct2: 0x699F5A + * + * rct2: 0x699F5A * al:thought_type * ah:thought_arguments * esi: peep @@ -5892,7 +6676,7 @@ void peep_insert_new_thought(rct_peep *peep, uint8 thought_type, uint8 thought_a // If the thought type has not changed then we need to move // it to the top of the thought list. This is done by first removing the // existing thought and placing it at the top. - if (i < PEEP_MAX_THOUGHTS - 1) { + if (i < PEEP_MAX_THOUGHTS - 2) { memmove(thought, thought + 1, sizeof(rct_peep_thought)*(PEEP_MAX_THOUGHTS - i - 1)); } break; @@ -5909,7 +6693,9 @@ void peep_insert_new_thought(rct_peep *peep, uint8 thought_type, uint8 thought_a peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_THOUGHTS; } -/* rct2: 0x00699FE3 +/** + * + * rct2: 0x00699FE3 * Stops peeps that are having thoughts * such as "I'm hungry" after visiting a food shop. * Works for Thirst/Hungry/Low Money/Bathroom @@ -5918,13 +6704,13 @@ static void peep_stop_purchase_thought(rct_peep* peep, uint8 ride_type){ uint8 thought_type = PEEP_THOUGHT_TYPE_HUNGRY; - if (!(RCT2_ADDRESS(0x97CF40, uint32)[ride_type * 2] & 0x800000)){ + if (!ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_SELLS_FOOD)){ thought_type = PEEP_THOUGHT_TYPE_THIRSTY; - if (!(RCT2_ADDRESS(0x97CF40, uint32)[ride_type * 2] & 0x1000000)){ + if (!ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_SELLS_DRINKS)){ thought_type = PEEP_THOUGHT_RUNNING_OUT; if (ride_type != RIDE_TYPE_CASH_MACHINE){ thought_type = PEEP_THOUGHT_TYPE_BATHROOM; - if (!(RCT2_ADDRESS(0x97CF40, uint32)[ride_type * 2] & 0x2000000)){ + if (!ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_IS_BATHROOM)){ return; } } @@ -5954,7 +6740,7 @@ static void peep_stop_purchase_thought(rct_peep* peep, uint8 ride_type){ void peep_set_map_tooltip(rct_peep *peep) { if (peep->type == PEEP_TYPE_GUEST) { - RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = peep->flags & PEEP_FLAGS_TRACKING ? 1450 : 1449; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = peep->peep_flags & PEEP_FLAGS_TRACKING ? 1450 : 1449; RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint32) = get_peep_face_sprite_small(peep); RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 6, uint16) = peep->name_string_idx; RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 8, uint32) = peep->id; @@ -5977,14 +6763,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); } } @@ -6024,7 +6811,7 @@ static int peep_update_queue_position(rct_peep* peep){ if (peep->sprite_direction != peep_next->sprite_direction) return 0; - switch (peep->sprite_direction / 8){ + switch (peep_next->sprite_direction / 8){ case 0: if (peep->x >= peep_next->x) return 0; @@ -6052,13 +6839,16 @@ 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; } -/* rct2: 0x00693EF2 */ +/** + * + * rct2: 0x00693EF2 + */ static int peep_return_to_center_of_tile(rct_peep* peep){ peep->var_78 ^= (1 << 1); peep->destination_x = (peep->x & 0xFFE0) + 16; @@ -6067,7 +6857,10 @@ static int peep_return_to_center_of_tile(rct_peep* peep){ return 1; } -/* rct2: 0x00693f2C*/ +/** + * + * rct2: 0x00693f2C + */ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element){ uint8 entranceType = map_element->properties.entrance.type; uint8 rideIndex = map_element->properties.entrance.ride_index; @@ -6111,7 +6904,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m peep->action_sprite_image_offset = RCT2_GLOBAL(0x00F1AEF0, uint8); peep->var_79 = rideIndex; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); uint16 previous_last = ride->last_peep_in_queue[stationNum]; ride->last_peep_in_queue[stationNum] = peep->sprite_index; peep->next_in_queue = previous_last; @@ -6125,12 +6918,14 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m peep_window_state_update(peep); peep->sub_state = 11; peep->time_in_queue = 0; - if (peep->flags & PEEP_FLAGS_TRACKING){ - RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; - RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; - RCT2_GLOBAL(0x0013CE958, rct_string_id) = ride->name; - RCT2_GLOBAL(0x0013CE95A, uint32) = ride->name_arguments; - news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1931, peep->sprite_index); + if (peep->peep_flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, rct_string_id) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; + if (gConfigNotifications.guest_queuing_for_ride) { + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, STR_PEEP_TRACKING_PEEP_JOINED_QUEUE_FOR_X, peep->sprite_index); + } } return 1; } @@ -6151,7 +6946,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m if (peep->state != PEEP_STATE_WALKING) return peep_return_to_center_of_tile(peep); - if (!(peep->flags & PEEP_FLAGS_LEAVING_PARK)){ + if (!(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK)){ // If the park is open and leaving flag isnt set return to center if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN) return peep_return_to_center_of_tile(peep); @@ -6169,10 +6964,12 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m peep_window_state_update(peep); peep->var_37 = 0; - if (peep->flags & PEEP_FLAGS_TRACKING){ - RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; - RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; - news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1935, peep->sprite_index); + if (peep->peep_flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + if (gConfigNotifications.guest_left_park) { + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, STR_PEEP_TRACKING_LEFT_PARK, peep->sprite_index); + } } return 1; } @@ -6273,7 +7070,7 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m RCT2_GLOBAL(RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, money32) += entranceFee; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_PARK_ENTRANCE_TICKETS * 4; peep_spend_money(peep, &peep->paid_to_enter, entranceFee); - peep->flags |= PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY; + peep->peep_flags |= PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY; } RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_ADMISSIONS, uint32)++; @@ -6292,7 +7089,10 @@ static int peep_interact_with_entrance(rct_peep* peep, sint16 x, sint16 y, rct_m } } -/* rct2: 0x006946D8 */ +/** + * + * rct2: 0x006946D8 + */ static int peep_footpath_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element, bool vandalism){ peep->next_x = (x & 0xFFE0); peep->next_y = (y & 0xFFE0); @@ -6333,7 +7133,7 @@ static int peep_footpath_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_ma uint16 crowded = 0; uint8 litter_count = 0; uint8 sick_count = 0; - uint16 sprite_id = RCT2_ADDRESS(0xF1EF60, uint16)[((x & 0x1FE0) << 3) | (y >> 5)]; + uint16 sprite_id = sprite_get_first_in_quadrant(x, y); for (rct_sprite* sprite; sprite_id != 0xFFFF; sprite_id = sprite->unknown.next_in_quadrant){ sprite = &g_sprite_list[sprite_id]; if (sprite->unknown.sprite_identifier == SPRITE_IDENTIFIER_PEEP){ @@ -6425,12 +7225,15 @@ static int peep_footpath_move_forward(rct_peep* peep, sint16 x, sint16 y, rct_ma return 1; } -/* rct2: 0x0069455E */ +/** + * + * rct2: 0x0069455E + */ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element){ // 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; @@ -6479,7 +7282,7 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e } peep->var_79 = rideIndex; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); uint16 old_last_peep = ride->last_peep_in_queue[stationNum]; ride->last_peep_in_queue[stationNum] = peep->sprite_index; @@ -6496,12 +7299,14 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e peep->sub_state = 10; peep->destination_tolerence = 2; peep->time_in_queue = 0; - if (peep->flags & PEEP_FLAGS_TRACKING){ - RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; - RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; - RCT2_GLOBAL(0x0013CE958, rct_string_id) = ride->name; - RCT2_GLOBAL(0x0013CE95A, uint32) = ride->name_arguments; - news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, 1931, peep->sprite_index); + if (peep->peep_flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, rct_string_id) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; + if (gConfigNotifications.guest_queuing_for_ride) { + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, STR_PEEP_TRACKING_PEEP_JOINED_QUEUE_FOR_X, peep->sprite_index); + } } return peep_footpath_move_forward(peep, x, y, map_element, vandalism_present); @@ -6518,10 +7323,13 @@ static int peep_interact_with_path(rct_peep* peep, sint16 x, sint16 y, rct_map_e } } -/* rct2: 0x00693F70 */ +/** + * + * rct2: 0x00693F70 + */ static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_element* map_element){ uint8 rideIndex = map_element->properties.track.ride_index; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) return 0; @@ -6537,7 +7345,7 @@ static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_e if (peep->var_79 == rideIndex) return peep_return_to_center_of_tile(peep); - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) return peep_return_to_center_of_tile(peep); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_PEEP_SHOULD_GO_INSIDE_FACILITY)){ @@ -6563,14 +7371,16 @@ static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_e peep_window_state_update(peep); peep->time_on_ride = 0; - ride->var_120++; - if (peep->flags & PEEP_FLAGS_TRACKING){ - RCT2_GLOBAL(0x0013CE952, rct_string_id) = peep->name_string_idx; - RCT2_GLOBAL(0x0013CE954, uint32) = peep->id; - RCT2_GLOBAL(0x0013CE958, rct_string_id) = ride->name; - RCT2_GLOBAL(0x0013CE95A, uint32) = ride->name_arguments; - rct_string_id string_id = ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IN_RIDE) ? 1933 : 1932; - news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, string_id, peep->sprite_index); + ride->cur_num_customers++; + if (peep->peep_flags & PEEP_FLAGS_TRACKING){ + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, rct_string_id) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; + rct_string_id string_id = ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IN_RIDE) ? STR_PEEP_TRACKING_PEEP_IS_IN_X : STR_PEEP_TRACKING_PEEP_IS_ON_X; + if (gConfigNotifications.guest_used_facility) { + news_item_add_to_queue(NEWS_ITEM_PEEP_ON_RIDE, string_id, peep->sprite_index); + } } return 1; } @@ -6587,7 +7397,10 @@ static int peep_interact_with_shop(rct_peep* peep, sint16 x, sint16 y, rct_map_e } } -/* rct2: 0x0069524E */ +/** + * + * rct2: 0x0069524E + */ static int peep_move_one_tile(uint8 direction, rct_peep* peep){ assert(direction <= 3); sint16 x = peep->next_x; @@ -6604,13 +7417,16 @@ static int peep_move_one_tile(uint8 direction, rct_peep* peep){ peep->destination_x = x + 16; peep->destination_y = y + 16; peep->destination_tolerence = 2; - if (peep->state == PEEP_STATE_QUEUING){ + if (peep->state != PEEP_STATE_QUEUING){ peep->destination_tolerence = (scenario_rand() & 7) + 2; } return 0; } -/* rct2: 0x00694C41 */ +/** + * + * rct2: 0x00694C41 + */ static int guest_surface_path_finding(rct_peep* peep){ sint16 x = peep->next_x; sint16 y = peep->next_y; @@ -6701,6 +7517,7 @@ rct_map_element* get_banner_on_path(rct_map_element *path_element) static int banner_clear_path_edges(rct_map_element *mapElement, int edges) { + if (RCT2_GLOBAL(0x00F1AEDD, uint8) & 0x80) return edges; rct_map_element *bannerElement = get_banner_on_path(mapElement); if (bannerElement != NULL) { do { @@ -6786,9 +7603,9 @@ static uint8 loc_6949B9( switch (map_element_get_type(mapElement)) { case MAP_ELEMENT_TYPE_TRACK: if (z != mapElement->base_height) continue; - int rideIndex = inputMapElement->properties.path.ride_index; - rct_ride *ride = GET_RIDE(rideIndex); - if (RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x20000) { + int rideIndex = mapElement->properties.track.ride_index; + rct_ride *ride = get_ride(rideIndex); + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) { *outRideIndex = rideIndex; return PATH_SEARCH_RIDE_ENTRANCE; } @@ -6862,7 +7679,10 @@ static uint8 sub_6949A4(sint16 x, sint16 y, sint16 z, rct_map_element *inputMapE return loc_6949B9(x, y, z, inputMapElement, chosenDirection, outRideIndex, 0); } -/* rct2: 0x00695225 */ +/** + * + * rct2: 0x00695225 + */ static int guest_path_find_aimless(rct_peep* peep, uint8 edges){ if (scenario_rand() & 1){ // If possible go straight @@ -6879,7 +7699,10 @@ static int guest_path_find_aimless(rct_peep* peep, uint8 edges){ } } -/* rct2: 0x0069A60A */ +/** + * + * rct2: 0x0069A60A + */ uint8 sub_69A60A(rct_peep* peep){ RCT2_GLOBAL(0x00F1AED8, uint32) = 0xC350; RCT2_GLOBAL(0x00F1AEDD, uint8) = 0x80; @@ -6889,14 +7712,14 @@ uint8 sub_69A60A(rct_peep* peep){ RCT2_GLOBAL(0x00F1AED8, uint32) = 0x3A98; RCT2_GLOBAL(0x00F1AEDD, uint8) = 0; - if ((peep->flags & PEEP_FLAGS_2)){ + if ((peep->peep_flags & PEEP_FLAGS_2)){ if ((scenario_rand() & 0xFFFF) <= 7281) - peep->flags &= ~PEEP_FLAGS_2; + peep->peep_flags &= ~PEEP_FLAGS_2; return 16; } - if (peep->flags & PEEP_FLAGS_LEAVING_PARK && + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK && peep->peep_is_lost_countdown < 90){ return 16; } @@ -6904,78 +7727,199 @@ uint8 sub_69A60A(rct_peep* peep){ if (peep->item_standard_flags & PEEP_ITEM_MAP) return 14; - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) return 14; return 10; } -/* rct2: 0x0069A5F0 */ -static int sub_69A5F0(sint16 x, sint16 y, sint16 z, rct_peep *peep, rct_map_element *map_element){ - //RCT2_GLOBAL(0x00F1AEDC, uint8) = sub_69A60A(peep); +/** + * + * rct2: 0x0069A997 + */ +static uint16 sub_69A997(sint16 x, sint16 y, uint8 z, uint8 counter, uint16 score, int test_edge) { + x += TileDirectionDelta[test_edge].x; + y += TileDirectionDelta[test_edge].y; - //// Redundant check to make sure peep is not null?? - //sint16 start_x = RCT2_GLOBAL(0x00F1AECE, sint16); - //sint16 start_y = RCT2_GLOBAL(0x00F1AED0, sint16); - //uint8 start_z = RCT2_GLOBAL(0x00F1AED2, uint8); - // - //uint8 edges = 0xF; - //if (peep->var_CC.x == (start_x / 32) && - // peep->var_CC.y == (start_y / 32) && - // peep->var_CC.z == start_z){ + ++counter; + if (--RCT2_GLOBAL(0x00F1AED4, sint32) < 0) return score; + if (counter > 200) return score; - // uint8 index = 0; - // for (; index < 4; ++index){ - // if (peep->var_D0[index].x == x && - // peep->var_D0[index].y == y && - // peep->var_D0[index].z == z){ - // edges = peep->var_D0[index].direction & 0xF; - // break; - // } - // } - //} + uint16 x_delta = abs(RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) - x); + uint16 y_delta = abs(RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) - y); + if (x_delta < y_delta) x_delta >>= 4; + else y_delta >>= 4; + uint16 new_score = x_delta + y_delta; + uint16 z_delta = abs(RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z, uint8) - z); + z_delta <<= 1; + new_score += z_delta; - //bool found = false; - //rct_map_element *destMapElement = map_get_first_element_at(x / 32, y / 32); - //do{ - // if (destMapElement->base_height != z) - // continue; + if (new_score < score || (new_score == score && counter < RCT2_GLOBAL(0x00F1AED3, uint8))) { + score = new_score; + RCT2_GLOBAL(0x00F1AED3, uint8) = counter; + if (score == 0) return score; + } - // if (map_element_get_type(destMapElement) != MAP_ELEMENT_TYPE_PATH) - // continue; + bool found = false; + rct_map_element *path = map_get_first_element_at(x / 32, y / 32); + do { + if (map_element_get_type(path) != MAP_ELEMENT_TYPE_PATH) continue; - // found = true; - // break; - //} while (!map_element_is_last_for_tile(destMapElement++)); + if (footpath_element_is_sloped(path) && + footpath_element_get_slope_direction(path) != test_edge) { + if ((footpath_element_get_slope_direction(path) ^ 2) != test_edge) continue; + if (path->base_height + 2 != z) continue; + } else { + if (path->base_height != z) continue; + if (footpath_element_is_wide(path)) continue; + } - //sint8 chosenDirection = 0xF; - //if (!found){ - // chosenDirection = 0xF; - // //goto 69A89C - //} + if (!footpath_element_is_queue(path) || + RCT2_GLOBAL(0x00F1AEE1, uint8) != path->properties.path.ride_index) { + if (path->type & RCT2_GLOBAL(0x00F1AEE0, uint8)) continue; + } - //edges &= path_get_permitted_edges(destMapElement); - //if (edges == 0){ - // chosenDirection = 0xF; - // // goto 69A89C - //} + found = true; + break; + } while (!map_element_is_last_for_tile(path++)); + if (!found) return score; - //chosenDirection = bitscanforward(edges); - //if (edges & ~(1 << chosenDirection) == 0){ - // // goto 69A8A1 chosenDirection - //} + uint8 edges = path_get_permitted_edges(path); + z = path->base_height; + edges &= ~(1 << (test_edge ^ 2)); + test_edge = bitscanforward(edges); + if (test_edge == -1) return score; - //for (; chosenDirection != -1; chosenDirection = bitscanforward(edges)){ - // edges &= ~(1 << chosenDirection); - // //69a814 - //} - ////69a895 - int eax = x, ebx, ecx = y, edx = z, esi = (int)peep, ebp, edi = (int)map_element; - RCT2_CALLFUNC_X(0x0069A5F0, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return ebp; + if ((edges & ~(1 << test_edge)) == 0) { + if (footpath_element_is_sloped(path) && + footpath_element_get_slope_direction(path) == test_edge) { + z += 2; + } + ++RCT2_GLOBAL(0x00F1AEDE, sint16); + return sub_69A997(x, y, z, counter, score, test_edge); + } + + if (RCT2_GLOBAL(0x00F1AEDE, sint16) != 0) { + --RCT2_GLOBAL(0x00F1AEDC, sint8); + } + --RCT2_GLOBAL(0x00F1AEDC, sint8); + if (RCT2_GLOBAL(0x00F1AEDC, sint8) < 0) return score; + + do { + edges &= ~(1 << test_edge); + int saved_f1aedc = *RCT2_ADDRESS(0x00F1AEDC, int); + uint8 height = z; + RCT2_GLOBAL(0x00F1AEDE, sint16) = 0; + if (footpath_element_is_sloped(path) && + footpath_element_get_slope_direction(path) == test_edge) { + height += 2; + } + score = sub_69A997(x, y, height, counter, score, test_edge); + *RCT2_ADDRESS(0x00F1AEDC, int) = saved_f1aedc; + } while ((test_edge = bitscanforward(edges)) != -1); + + return score; } -/* rct2: 0x006952C0 */ +/** + * + * rct2: 0x0069A5F0 + */ +int peep_pathfind_choose_direction(sint16 x, sint16 y, uint8 z, rct_peep *peep) { + RCT2_GLOBAL(0x00F1AEDC, uint8) = sub_69A60A(peep); + uint8 x_goal = RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) / 32; + uint8 y_goal = RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) / 32; + uint8 z_goal = RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z, uint8); + + uint8 edges = 0xF; + if (peep->pathfind_goal.x == x_goal && + peep->pathfind_goal.y == y_goal && + peep->pathfind_goal.z == z_goal) { + for (int i = 0; i < 4; ++i) { + if (peep->pathfind_history[i].x == x / 32 && + peep->pathfind_history[i].y == y / 32 && + peep->pathfind_history[i].z == z) { + edges = peep->pathfind_history[i].direction & 0xF; + break; + } + } + } + + rct_map_element *dest_map_element = map_get_first_element_at(x / 32, y / 32); + bool found = false; + do { + if (dest_map_element->base_height != z) continue; + if (map_element_get_type(dest_map_element) != MAP_ELEMENT_TYPE_PATH) continue; + found = true; + break; + } while (!map_element_is_last_for_tile(dest_map_element++)); + if (!found) return -1; + + edges &= path_get_permitted_edges(dest_map_element); + if (edges == 0) return -1; + + int chosen_edge = bitscanforward(edges); + if (edges & ~(1 << chosen_edge)) { + uint16 best_score = 0xFFFF; + uint8 best_sub = 0xFF; + + for (int test_edge = chosen_edge; test_edge != -1; test_edge = bitscanforward(edges)) { + edges &= ~(1 << test_edge); + uint8 height = z; + int saved_f1aedc = *RCT2_ADDRESS(0x00F1AEDC, int); + if (footpath_element_is_sloped(dest_map_element) && + footpath_element_get_slope_direction(dest_map_element) == test_edge) + height += 0x2; + + RCT2_GLOBAL(0x00F1AED3, uint8) = 0xFF; + RCT2_GLOBAL(0x00F1AED4, int) = RCT2_GLOBAL(0x00F1AED8, int); + RCT2_GLOBAL(0x00F1AEDE, uint16) = 0; + uint16 score = sub_69A997(x, y, height, 0, 0xFFFF, test_edge); + *RCT2_ADDRESS(0x00F1AEDC, int) = saved_f1aedc; + + if (score < best_score || (score == best_score && RCT2_GLOBAL(0x00F1AED3, uint8) < best_sub)) { + chosen_edge = test_edge; + best_score = score; + best_sub = RCT2_GLOBAL(0x00F1AED3, uint8); + } + } + } + + if (peep->pathfind_goal.direction > 3 || + peep->pathfind_goal.x != x_goal || + peep->pathfind_goal.y != y_goal || + peep->pathfind_goal.z != z_goal) { + peep->pathfind_goal.x = x_goal; + peep->pathfind_goal.y = y_goal; + peep->pathfind_goal.z = z_goal; + peep->pathfind_goal.direction = 0; + memset(peep->pathfind_history, 0xFF, sizeof(peep->pathfind_history)); // Clear pathfinding history + } + + for (int i = 0; i < 4; ++i) { + if (peep->pathfind_history[i].x == x / 32 && + peep->pathfind_history[i].y == y / 32 && + peep->pathfind_history[i].z == z) { + peep->pathfind_history[i].direction &= ~(1 << chosen_edge); + return chosen_edge; + } + } + + int i = peep->pathfind_goal.direction++; + peep->pathfind_goal.direction &= 0x3; + peep->pathfind_history[i].x = x / 32; + peep->pathfind_history[i].y = y / 32; + peep->pathfind_history[i].z = (uint8)z; + peep->pathfind_history[i].direction = 0xF; + peep->pathfind_history[i].direction &= ~(1 << chosen_edge); + + return chosen_edge; +} + +/** + * + * rct2: 0x006952C0 + */ static int guest_path_find_entering_park(rct_peep *peep, rct_map_element *map_element, uint8 edges){ uint8 chosenEntrance = 0xFF; uint16 nearestDist = 0xFFFF; @@ -6999,14 +7943,14 @@ static int guest_path_find_entering_park(rct_peep *peep, rct_map_element *map_el sint16 x = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, sint16)[chosenEntrance]; sint16 y = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, sint16)[chosenEntrance]; sint16 z = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, sint16)[chosenEntrance]; - RCT2_GLOBAL(0x00F1AECE, sint16) = x; - RCT2_GLOBAL(0x00F1AED0, sint16) = y; - RCT2_GLOBAL(0x00F1AED2, uint8) = z / 8; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z, uint8) = z / 8; RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; RCT2_GLOBAL(0x00F1AEE1, uint8) = 0xFF; - int chosenDirection = sub_69A5F0(peep->next_x, peep->next_y, peep->next_z, peep, map_element); + int chosenDirection = peep_pathfind_choose_direction(peep->next_x, peep->next_y, peep->next_z, peep); if (chosenDirection == -1) return guest_path_find_aimless(peep, edges); @@ -7014,7 +7958,10 @@ static int guest_path_find_entering_park(rct_peep *peep, rct_map_element *map_el return peep_move_one_tile(chosenDirection, peep); } -/* rct2: 0x0069536C */ +/** + * + * rct2: 0x0069536C + */ static int guest_path_find_leaving_park(rct_peep *peep, rct_map_element *map_element, uint8 edges){ rct2_peep_spawn* peepSpawn = &gPeepSpawns[0]; // Peeps for whatever reason return to their original spawn point @@ -7028,9 +7975,9 @@ static int guest_path_find_leaving_park(rct_peep *peep, rct_map_element *map_ele uint8 z = peepSpawn->z * 2; uint8 direction = peepSpawn->direction; - RCT2_GLOBAL(0x00F1AECE, sint16) = x; - RCT2_GLOBAL(0x00F1AED0, sint16) = y; - RCT2_GLOBAL(0x00F1AED2, uint8) = z; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z, uint8) = z; if (x == peep->next_x && y == peep->next_y){ return peep_move_one_tile(direction, peep); @@ -7038,18 +7985,27 @@ static int guest_path_find_leaving_park(rct_peep *peep, rct_map_element *map_ele RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; RCT2_GLOBAL(0x00F1AEE1, uint8) = 0xFF; - direction = sub_69A5F0(peep->next_x, peep->next_y, peep->next_z, peep, map_element); + direction = peep_pathfind_choose_direction(peep->next_x, peep->next_y, peep->next_z, peep); if (direction == 0xFF) return guest_path_find_aimless(peep, edges); else return peep_move_one_tile(direction, peep); } -/* rct2: 0x00695161 */ +/** + * + * rct2: 0x00695161 + */ static int guest_path_find_park_entrance(rct_peep* peep, rct_map_element *map_element, uint8 edges){ uint8 entranceNum; + + // Resolves already-corrupt guests (e.g. loaded from save) + if (peep->peep_flags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN && + (peep->current_ride >= 4 || + RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, sint16)[peep->current_ride] == (sint16)0x8000) + ) peep->peep_flags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN); - if (!(peep->flags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)){ + if (!(peep->peep_flags & PEEP_FLAGS_PARK_ENTRANCE_CHOSEN)){ uint8 chosenEntrance = 0xFF; uint16 nearestDist = 0xFFFF; for (entranceNum = 0; entranceNum < 4; ++entranceNum){ @@ -7070,21 +8026,21 @@ static int guest_path_find_park_entrance(rct_peep* peep, rct_map_element *map_el return guest_path_find_aimless(peep, edges); peep->current_ride = chosenEntrance; - peep->flags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; + peep->peep_flags |= PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; } entranceNum = peep->current_ride; sint16 x = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_X, sint16)[entranceNum]; sint16 y = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Y, sint16)[entranceNum]; sint16 z = RCT2_ADDRESS(RCT2_ADDRESS_PARK_ENTRANCE_Z, sint16)[entranceNum]; - RCT2_GLOBAL(0x00F1AECE, sint16) = x; - RCT2_GLOBAL(0x00F1AED0, sint16) = y; - RCT2_GLOBAL(0x00F1AED2, uint8) = z / 8; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z, uint8) = z / 8; RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; RCT2_GLOBAL(0x00F1AEE1, uint8) = 0xFF; - int chosenDirection = sub_69A5F0(peep->next_x, peep->next_y, peep->next_z, peep, map_element); + int chosenDirection = peep_pathfind_choose_direction(peep->next_x, peep->next_y, peep->next_z, peep); if (chosenDirection == -1) return guest_path_find_aimless(peep, edges); @@ -7092,7 +8048,10 @@ static int guest_path_find_park_entrance(rct_peep* peep, rct_map_element *map_el return peep_move_one_tile(chosenDirection, peep); } -/* rct2: 0x006A72C5 */ +/** + * + * rct2: 0x006A72C5 + */ static void get_ride_queue_end(sint16 *x, sint16 *y, sint16 *z, sint16 dist){ rct_map_element *mapElement = map_get_first_element_at(*x / 32, *y / 32); @@ -7210,7 +8169,10 @@ static void get_ride_queue_end(sint16 *x, sint16 *y, sint16 *z, sint16 dist){ *z = mapElement->base_height; } -/* rct2: 0x00694C35 */ +/** + * + * rct2: 0x00694C35 + */ static int guest_path_finding(rct_peep* peep) { sint16 x, y, z; @@ -7310,14 +8272,14 @@ static int guest_path_finding(rct_peep* peep) } } - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) return guest_path_find_park_entrance(peep, mapElement, edges); if (peep->guest_heading_to_ride_id == 0xFF) return guest_path_find_aimless(peep, edges); uint8 rideIndex = peep->guest_heading_to_ride_id; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride->status != RIDE_STATUS_OPEN) return guest_path_find_aimless(peep, edges); @@ -7382,12 +8344,12 @@ static int guest_path_finding(rct_peep* peep) z = ride->station_heights[closestStationNum]; get_ride_queue_end(&x, &y, &z, closestDist); - RCT2_GLOBAL(0x00F1AECE, sint16) = x; - RCT2_GLOBAL(0x00F1AED0, sint16) = y; - RCT2_GLOBAL(0x00F1AED2, uint8) = (uint8)z; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z, uint8) = (uint8)z; RCT2_GLOBAL(0x00F1AEE0, uint8) = 1; - direction = sub_69A5F0(peep->next_x, peep->next_y, peep->next_z, peep, mapElement); + direction = peep_pathfind_choose_direction(peep->next_x, peep->next_y, peep->next_z, peep); if (direction == -1){ return guest_path_find_aimless(peep, edges); } @@ -7419,7 +8381,7 @@ static int sub_693C9E(rct_peep *peep) result = guest_path_finding(peep); } else{ - result = RCT2_CALLPROC_X(0x006BF926, x, 0, y, 0, (int)peep, 0, 0) & 0x100; + result = staff_path_finding(peep); } if (result != 0) @@ -7512,7 +8474,7 @@ static int sub_693C9E(rct_peep *peep) /** * * rct2: 0x0069926C - * Expend type was previously an offset saved in 0x00F1AEC0 + * Expend type was previously an offset saved in 0x00F1AEC0 */ static void peep_spend_money(rct_peep *peep, money16 *peep_expend_type, money32 amount) { @@ -7535,7 +8497,7 @@ static void peep_spend_money(rct_peep *peep, money16 *peep_expend_type, money32 static void peep_set_has_ridden(rct_peep *peep, int rideIndex) { peep->rides_been_on[rideIndex / 8] |= 1 << (rideIndex % 8); - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); peep_set_has_ridden_ride_type(peep, ride->type); } @@ -7555,14 +8517,13 @@ static bool peep_has_ridden_ride_type(rct_peep *peep, int rideType) } /** - * + * Updates various peep stats upon entering a ride, as well as updating the + * ride's satisfaction value. * rct2: 0x0069545B - * Updates various peep stats upon entering a ride, as well as updating the - * ride's satisfaction value. */ static void peep_on_enter_ride(rct_peep *peep, int rideIndex) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); // Calculate how satisfying the ride is for the peep. Can range from -140 to +140. sint8 satisfaction = peep_calculate_ride_satisfaction(peep, ride); @@ -7588,7 +8549,7 @@ static void peep_on_enter_ride(rct_peep *peep, int rideIndex) peep_update_ride_nausea_growth(peep, ride); } -/* +/** * Check to see if the specified ride should become the peep's favourite. * For this, a "ride rating" is calculated based on the excitement of the ride and the peep's current happiness. * As this value cannot exceed 255, the happier the peep is, the more irrelevant the ride's excitement becomes. @@ -7600,12 +8561,12 @@ static void peep_on_enter_ride(rct_peep *peep, int rideIndex) */ static void peep_update_favourite_ride(rct_peep *peep, rct_ride *ride) { - peep->flags &= ~PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE; + peep->peep_flags &= ~PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE; uint8 peepRideRating = clamp(0, (ride->excitement / 4) + peep->happiness, 255); if (peepRideRating >= peep->favourite_ride_rating) { if (peep->happiness >= 160 && peep->happiness_growth_rate >= 160) { peep->favourite_ride_rating = peepRideRating; - peep->flags |= PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE; + peep->peep_flags |= PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE; } } } @@ -7758,7 +8719,7 @@ static sint8 peep_calculate_ride_satisfaction(rct_peep *peep, rct_ride *ride) return satisfaction; } -/* +/** * Update the nausea growth of the peep based on a ride. This is calculated based on: * - The nausea rating of the ride * - Their new happiness growth rate (the higher, the less nauseous) @@ -7776,9 +8737,9 @@ static void peep_update_ride_nausea_growth(rct_peep *peep, rct_ride *ride) static bool peep_should_go_on_ride_again(rct_peep *peep, rct_ride *ride) { - if (!(RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32) & 0x100000)) return false; + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_20)) return false; if (ride->excitement == (ride_rating)0xFFFF) return false; - if (ride->intensity > RIDE_RATING(10,00) && !gConfigCheat.ignore_ride_intensity) return false; + if (ride->intensity > RIDE_RATING(10,00) && !gCheatsIgnoreRideIntensity) return false; if (peep->happiness < 180) return false; if (peep->energy < 100) return false; if (peep->nausea > 160) return false; @@ -7809,7 +8770,7 @@ static bool peep_really_liked_ride(rct_peep *peep, rct_ride *ride) peep->happiness >= 215 && ((peep->nausea <= 120 && ride->excitement != (ride_rating)0xFFFF && - ride->intensity <= RIDE_RATING(10,00))||gConfigCheat.ignore_ride_intensity); + ride->intensity <= RIDE_RATING(10,00))||gCheatsIgnoreRideIntensity); } /** @@ -7818,10 +8779,10 @@ static bool peep_really_liked_ride(rct_peep *peep, rct_ride *ride) */ static void peep_on_exit_ride(rct_peep *peep, int rideIndex) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); - if (peep->flags & PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE) { - peep->flags &= ~PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE; + if (peep->peep_flags & PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE) { + peep->peep_flags &= ~PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE; peep->favourite_ride = rideIndex; // TODO fix this flag name or add another one peep->window_invalidate_flags |= PEEP_INVALIDATE_STAFF_STATS; @@ -7829,11 +8790,14 @@ static void peep_on_exit_ride(rct_peep *peep, int rideIndex) peep->happiness = peep->happiness_growth_rate; peep->nausea = peep->nausea_growth_rate; peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_STATS; + + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) + peep->peep_flags &= ~(PEEP_FLAGS_PARK_ENTRANCE_CHOSEN); if (peep_should_go_on_ride_again(peep, ride)) { peep->guest_heading_to_ride_id = rideIndex; peep->peep_is_lost_countdown = 200; - sub_69A98C(peep); + peep_reset_pathfind_goal(peep); rct_window *w = window_find_by_number(WC_PEEP, peep->sprite_index); if (w != NULL) { @@ -7848,7 +8812,7 @@ static void peep_on_exit_ride(rct_peep *peep, int rideIndex) } } - if (peep->flags & PEEP_FLAGS_NICE_RIDE) { + if (peep->peep_flags & PEEP_FLAGS_NICE_RIDE) { peep_insert_new_thought(peep, PEEP_THOUGHT_NICE_RIDE, 255); } @@ -7893,7 +8857,7 @@ static void peep_on_enter_or_exit_ride(rct_peep *peep, int rideIndex, int flags) */ static bool sub_69AF1E(rct_peep *peep, int rideIndex, int shopItem, money32 price) { - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); money32 value; bool has_voucher = false; @@ -8037,9 +9001,9 @@ loc_69B221: // The peep has now decided to buy the item (or, specifically, has not been // dissuaded so far). if (shopItem >= 32) - peep->item_extra_flags |= (1 << (shopItem - 32)); + peep->item_extra_flags |= (1u << (shopItem - 32)); else - peep->item_standard_flags |= (1 << shopItem); + peep->item_standard_flags |= (1u << shopItem); if (shopItem == SHOP_ITEM_TSHIRT) peep->tshirt_colour = ride->track_colour_main[0]; @@ -8054,7 +9018,7 @@ loc_69B221: peep->umbrella_colour = ride->track_colour_main[0]; if (shopItem == SHOP_ITEM_MAP) - sub_69A98C(peep); + peep_reset_pathfind_goal(peep); uint16 dl; if (shopItem >= 32) @@ -8078,11 +9042,13 @@ loc_69B221: peep->window_invalidate_flags |= PEEP_INVALIDATE_PEEP_INVENTORY; peep_update_sprite_type(peep); - if (peep->flags & PEEP_FLAGS_TRACKING) { - RCT2_GLOBAL(0x13CE952,uint16) = peep->name_string_idx; - RCT2_GLOBAL((0x13CE952 + 2), uint32) = peep->id; - RCT2_GLOBAL((0x13CE956 + 2), uint16) = (shopItem >= 32 ? STR_SHOP_ITEM_INDEFINITE_PHOTO2 + (shopItem - 32) : STR_SHOP_ITEM_INDEFINITE_BALLOON + shopItem); - news_item_add_to_queue(2, STR_PEEP_TRACKING_NOTIFICATION_BOUGHT_X, peep->sprite_index); + if (peep->peep_flags & PEEP_FLAGS_TRACKING) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS,uint16) = peep->name_string_idx; + RCT2_GLOBAL((RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2), uint32) = peep->id; + RCT2_GLOBAL((RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6), uint16) = (shopItem >= 32 ? STR_SHOP_ITEM_INDEFINITE_PHOTO2 + (shopItem - 32) : STR_SHOP_ITEM_INDEFINITE_BALLOON + shopItem); + if (gConfigNotifications.guest_bought_item) { + news_item_add_to_queue(2, STR_PEEP_TRACKING_NOTIFICATION_BOUGHT_X, peep->sprite_index); + } } if (shop_item_is_food(shopItem)) @@ -8121,7 +9087,7 @@ loc_69B221: ride->total_profit += (price - get_shop_item_cost(shopItem)); ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_INCOME; - ride->var_120++; + ride->cur_num_customers++; ride->total_customers++; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER; @@ -8135,14 +9101,14 @@ loc_69B221: static bool peep_should_use_cash_machine(rct_peep *peep, int rideIndex) { if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) return false; - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) return false; + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) return false; if (peep->cash_in_pocket > MONEY(20,00)) return false; if (115 + (scenario_rand() % 128) > peep->happiness) return false; if (peep->energy < 80) return false; - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); ride_update_satisfaction(ride, peep->happiness >> 6); - ride->var_120++; + ride->cur_num_customers++; ride->total_customers++; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER; return true; @@ -8152,45 +9118,446 @@ static bool peep_should_use_cash_machine(rct_peep *peep, int rideIndex) * * rct2: 0x0069A98C */ -static void sub_69A98C(rct_peep *peep) +static void peep_reset_pathfind_goal(rct_peep *peep) { - peep->var_CC.x = 0xFF; - peep->var_CC.y = 0xFF; - peep->var_CC.z = 0xFF; - peep->var_CC.direction = 0xFF; + peep->pathfind_goal.x = 0xFF; + peep->pathfind_goal.y = 0xFF; + peep->pathfind_goal.z = 0xFF; + peep->pathfind_goal.direction = 0xFF; +} + +static bool peep_has_valid_xy(rct_peep *peep) +{ + if (peep->x != (sint16)0x8000) { + if (peep->x < (256 * 32) && peep->y < (256 * 32)) { + return true; + } + } + + return false; +} + +static void peep_give_passing_peeps_purple_clothes(rct_peep *peep) +{ + if (peep_has_valid_xy(peep)) { + rct_peep *otherPeep; + uint16 spriteIndex = sprite_get_first_in_quadrant(peep->x, peep->y); + for (; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = otherPeep->next_in_quadrant) { + otherPeep = GET_PEEP(spriteIndex); + if (otherPeep->type == PEEP_TYPE_GUEST) { + int zDiff = abs(otherPeep->z - peep->z); + if (zDiff <= 32) { + otherPeep->tshirt_colour = COLOUR_BRIGHT_PURPLE; + otherPeep->trousers_colour = COLOUR_BRIGHT_PURPLE; + invalidate_sprite_2((rct_sprite*)peep); + } + } + } + } +} + +static void peep_give_passing_peeps_pizza(rct_peep *peep) +{ + if (peep_has_valid_xy(peep)) { + rct_peep *otherPeep; + uint16 spriteIndex = sprite_get_first_in_quadrant(peep->x, peep->y); + for (; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = otherPeep->next_in_quadrant) { + otherPeep = GET_PEEP(spriteIndex); + if (otherPeep->type == PEEP_TYPE_GUEST) { + int zDiff = abs(otherPeep->z - peep->z); + if (zDiff <= 32) { + if (!(otherPeep->item_standard_flags & PEEP_ITEM_PIZZA)) { + otherPeep->item_standard_flags |= PEEP_ITEM_PIZZA; + + int peepDirection = (peep->sprite_direction >> 3) ^ 2; + int otherPeepOppositeDirection = otherPeep->sprite_direction >> 3; + if (peepDirection == otherPeepOppositeDirection) { + if (otherPeep->action == PEEP_ACTION_NONE_1 || otherPeep->action == PEEP_ACTION_NONE_2) { + invalidate_sprite_2((rct_sprite*)peep); + otherPeep->action = PEEP_ACTION_WAVE_2; + otherPeep->action_frame = 0; + otherPeep->action_sprite_image_offset = 0; + sub_693B58(otherPeep); + invalidate_sprite_2((rct_sprite*)otherPeep); + } + } + invalidate_sprite_2((rct_sprite*)otherPeep); + } + } + } + } + } +} + +static void peep_make_passing_peeps_sick(rct_peep *peep) +{ + if (peep_has_valid_xy(peep)) { + rct_peep *otherPeep; + uint16 spriteIndex = sprite_get_first_in_quadrant(peep->x, peep->y); + for (; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = otherPeep->next_in_quadrant) { + otherPeep = GET_PEEP(spriteIndex); + if (otherPeep->type == PEEP_TYPE_GUEST) { + int zDiff = abs(otherPeep->z - peep->z); + if (zDiff <= 32) { + if (peep != otherPeep) { + if (otherPeep->action == PEEP_ACTION_NONE_1 || otherPeep->action == PEEP_ACTION_NONE_2) { + otherPeep->action = PEEP_ACTION_THROW_UP; + otherPeep->action_frame = 0; + otherPeep->action_sprite_image_offset = 0; + sub_693B58(otherPeep); + invalidate_sprite_2((rct_sprite*)otherPeep); + } + } + } + } + } + } +} + +static void peep_give_passing_peeps_ice_cream(rct_peep *peep) +{ + if (peep_has_valid_xy(peep)) { + rct_peep *otherPeep; + uint16 spriteIndex = sprite_get_first_in_quadrant(peep->x, peep->y); + for (; spriteIndex != SPRITE_INDEX_NULL; spriteIndex = otherPeep->next_in_quadrant) { + otherPeep = GET_PEEP(spriteIndex); + if (otherPeep->type == PEEP_TYPE_GUEST) { + int zDiff = abs(otherPeep->z - peep->z); + if (zDiff <= 32) { + if (peep != otherPeep) { + if (!(otherPeep->item_standard_flags & PEEP_ITEM_ICE_CREAM)) { + otherPeep->item_standard_flags |= PEEP_ITEM_ICE_CREAM; + peep_update_sprite_type(otherPeep); + } + } + } + } + } + } } /** * * rct2: 0x0068FD3A */ -static void sub_68FD3A(rct_peep *peep) +static void peep_easter_egg_peep_interactions(rct_peep *peep) { - RCT2_CALLPROC_X(0x0068FD3A, 0, 0, 0, 0, (int)peep, 0, 0); + if (peep->peep_flags & PEEP_FLAGS_PURPLE) { + peep_give_passing_peeps_purple_clothes(peep); + } + + if (peep->peep_flags & PEEP_FLAGS_PIZZA) { + peep_give_passing_peeps_pizza(peep); + } + + if (peep->peep_flags & PEEP_FLAGS_CONTAGIOUS) { + peep_make_passing_peeps_sick(peep); + } + + if (peep->peep_flags & PEEP_FLAGS_JOY) { + if (scenario_rand() <= 1456) { + if (peep->action == PEEP_ACTION_NONE_1 || peep->action == PEEP_ACTION_NONE_2) { + peep->action = PEEP_ACTION_JOY; + peep->action_frame = 0; + peep->action_sprite_image_offset = 0; + sub_693B58(peep); + invalidate_sprite_2((rct_sprite*)peep); + } + } + } + + if (peep->peep_flags & PEEP_FLAGS_ICE_CREAM) { + peep_give_passing_peeps_ice_cream(peep); + } +} + +/** + * rct2: 0x0069101A + * + * @return (CF) + */ +static bool sub_69101A(rct_map_element *esi) { + rct_ride *ride = get_ride(esi->properties.track.ride_index); + if (RCT2_ADDRESS(0x97C3AF, uint8)[ride->type] != 0) { + return true; + } + + if ((uint16) ride->excitement == 0xFFFF) { + return false; + } + + if (ride->excitement >= RIDE_RATING(4, 70)) { + return false; + } + + if (ride->intensity >= RIDE_RATING(4, 50)) { + return false; + } + + if (RideData4[ride->type].flags & 0x2000) { + if ((scenario_rand() & 0xFFFF) > 0x3333) { + return true; + } + } else if (RideData4[ride->type].flags & 0x4000) { + if ((scenario_rand() & 0xFFFF) > 0x1000) { + return true; + } + } else { + return true; + } + + return false; } /** * * rct2: 0x00690B99 + * + * @param edge (eax) + * @param peep (esi) + * @param[out] rideToView (cl) + * @param[out] rideSeatToView (ch) + * @return !CF */ -static bool sub_690B99(rct_peep *peep, int edge, uint8 *rideToView, uint8 *rideSeatToView) +static bool peep_find_ride_to_look_at(rct_peep *peep, uint8 edge, uint8 *rideToView, uint8 *rideSeatToView) { - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = edge; - esi = (int)peep; - if (RCT2_CALLFUNC_X(0x00690B99, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp) & 0x100) - return false; + rct_map_element *mapElement, *surfaceElement; - *rideToView = ecx & 0xFF; - *rideSeatToView = (ecx >> 8) & 0xFF; - return true; + surfaceElement = map_get_surface_element_at(peep->next_x / 32, peep->next_y / 32); + + mapElement = surfaceElement; + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_FENCE) continue; + if (map_element_get_direction(mapElement) != edge) continue; + if (g_wallSceneryEntries[mapElement->properties.fence.type]->wall.flags2 & WALL_SCENERY_FLAG4) continue; + if (peep->next_z + 4 <= mapElement->base_height) continue; + if (peep->next_z + 1 >= mapElement->clearance_height) continue; + + return false; + } while (!map_element_is_last_for_tile(mapElement++)); + + + uint16 x = peep->next_x + TileDirectionDelta[edge].x; + uint16 y = peep->next_y + TileDirectionDelta[edge].y; + if (x > 255 * 32 || y > 255 * 32) { + return false; + } + + surfaceElement = map_get_surface_element_at(x / 32, y / 32); + + + mapElement = surfaceElement; + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_FENCE) continue; + if ((map_element_get_direction(mapElement) ^ 0x2) != edge) continue; + if (g_wallSceneryEntries[mapElement->properties.fence.type]->wall.flags2 & WALL_SCENERY_FLAG4) continue; + // TODO: Check whether this shouldn't be <=, as the other loops use. If so, also extract as loop A. + if (peep->next_z + 4 >= mapElement->base_height) continue; + if (peep->next_z + 1 >= mapElement->clearance_height) continue; + + return false; + } while (!map_element_is_last_for_tile(mapElement++)); + + + // TODO: Extract loop B + mapElement = surfaceElement; + do { + if (mapElement->clearance_height + 1 < peep->next_z) continue; + if (peep->next_z + 6 < mapElement->base_height) continue; + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK) { + if (!sub_69101A(mapElement)) { + return loc_690FD0(peep, rideToView, rideSeatToView, mapElement); + } + } + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { + if (!(g_largeSceneryEntries[mapElement->properties.scenerymultiple.type & 0x3FF]->large_scenery.flags & 0x10)) { + continue; + } + + *rideSeatToView = 0; + if (mapElement->clearance_height >= peep->next_z + 8) { + *rideSeatToView = 0x02; + } + + *rideToView = 0xFF; + + return true; + } + } while (!map_element_is_last_for_tile(mapElement++)); + + + // TODO: Extract loop C + mapElement = surfaceElement; + do { + if (mapElement->clearance_height + 1 < peep->next_z) continue; + if (peep->next_z + 6 < mapElement->base_height) continue; + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SURFACE) continue; + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) continue; + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_FENCE) { + if (g_wallSceneryEntries[mapElement->properties.fence.type]->wall.flags2 & WALL_SCENERY_FLAG4) { + continue; + } + } + + return false; + } while (!map_element_is_last_for_tile(mapElement++)); + + + x += TileDirectionDelta[edge].x; + y += TileDirectionDelta[edge].y; + if (x > 255 * 32 || y > 255 * 32) { + return false; + } + + surfaceElement = map_get_surface_element_at(x / 32, y / 32); + + + // TODO: extract loop A + mapElement = surfaceElement; + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_FENCE) continue; + if ((map_element_get_direction(mapElement) ^ 0x2) != edge) continue; + if (g_wallSceneryEntries[mapElement->properties.fence.type]->wall.flags2 & WALL_SCENERY_FLAG4) continue; + if (peep->next_z + 6 <= mapElement->base_height) continue; + if (peep->next_z >= mapElement->clearance_height) continue; + + return false; + } while (!map_element_is_last_for_tile(mapElement++)); + + + // TODO: Extract loop B + mapElement = surfaceElement; + do { + if (mapElement->clearance_height + 1 < peep->next_z) continue; + if (peep->next_z + 8 < mapElement->base_height) continue; + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK) { + if (!sub_69101A(mapElement)) { + return loc_690FD0(peep, rideToView, rideSeatToView, mapElement); + } + } + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { + if (!(g_largeSceneryEntries[mapElement->properties.scenerymultiple.type & 0x3FF]->large_scenery.flags & 0x10)) { + continue; + } + + *rideSeatToView = 0; + if (mapElement->clearance_height >= peep->next_z + 8) { + *rideSeatToView = 0x02; + } + + *rideToView = 0xFF; + + return true; + } + } while (!map_element_is_last_for_tile(mapElement++)); + + + // TODO: Extract loop C + mapElement = surfaceElement; + do { + if (mapElement->clearance_height + 1 < peep->next_z) continue; + if (peep->next_z + 8 < mapElement->base_height) continue; + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SURFACE) continue; + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) continue; + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_FENCE) { + if (g_wallSceneryEntries[mapElement->properties.fence.type]->wall.flags2 & WALL_SCENERY_FLAG4) { + continue; + } + } + + return false; + } while (!map_element_is_last_for_tile(mapElement++)); + + x += TileDirectionDelta[edge].x; + y += TileDirectionDelta[edge].y; + if (x > 255 * 32 || y > 255 * 32) { + return false; + } + + surfaceElement = map_get_surface_element_at(x / 32, y / 32); + + + // TODO: extract loop A + mapElement = surfaceElement; + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_FENCE) continue; + if ((map_element_get_direction(mapElement) ^ 0x2) != edge) continue; + if (g_wallSceneryEntries[mapElement->properties.fence.type]->wall.flags2 & WALL_SCENERY_FLAG4) continue; + if (peep->next_z + 8 <= mapElement->base_height) continue; + if (peep->next_z >= mapElement->clearance_height) continue; + + return false; + } while (!map_element_is_last_for_tile(mapElement++)); + + + // TODO: Extract loop B + mapElement = surfaceElement; + do { + if (mapElement->clearance_height + 1 < peep->next_z) continue; + if (peep->next_z + 10 < mapElement->base_height) continue; + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK) { + if (!sub_69101A(mapElement)) { + return loc_690FD0(peep, rideToView, rideSeatToView, mapElement); + } + } + + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { + if (!(g_largeSceneryEntries[mapElement->properties.scenerymultiple.type & 0x3FF]->large_scenery.flags & 0x10)) { + continue; + } + + *rideSeatToView = 0; + if (mapElement->clearance_height >= peep->next_z + 8) { + *rideSeatToView = 0x02; + } + + *rideToView = 0xFF; + + return true; + } + } while (!map_element_is_last_for_tile(mapElement++)); + + return false; +} + +bool loc_690FD0(rct_peep *peep, uint8 *rideToView, uint8 *rideSeatToView, rct_map_element *esi) { + rct_ride *ride = get_ride(esi->properties.track.ride_index); + + *rideToView = esi->properties.track.ride_index; + if ((uint16) ride->excitement == 0xFFFF) { + *rideSeatToView = 1; + if (ride->status != RIDE_STATUS_OPEN) { + if (esi->clearance_height > peep->next_z + 8) { + *rideSeatToView |= (1 << 1); + } + + return true; + } + } else { + *rideSeatToView = 0; + if (ride->status == RIDE_STATUS_OPEN && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)) { + if (esi->clearance_height > peep->next_z + 8) { + *rideSeatToView = 0x02; + } + + return true; + } + } + + return false; } /** - * + * Gets the height including the bit depending on how far up the slope the peep + * is. * rct2: 0x00694921 - * Gets the height including the bit depending - * on how far up the slope the peep is. */ static int peep_get_height_on_slope(rct_peep *peep, int x, int y) { @@ -8227,15 +9594,14 @@ static void peep_reset_ride_heading(rct_peep *peep) } /** - * + * This function is called whenever a peep is deciding whether or not they want + * to go on a ride or visit a shop. They may be physically present at the + * ride/shop, or they may just be thinking about it. * rct2: 0x006960AB - * - * This function is called whenever a peep is deciding whether or not they want to go on a ride or visit a shop. - * They may be physically present at the ride/shop, or they may just be thinking about it. */ static bool peep_should_go_on_ride(rct_peep *peep, int rideIndex, int entranceNum, int flags) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); // Indicates if the peep is about to enter a queue (as opposed to entering an entrance directly from a path) bool peepAtQueue = flags & PEEP_RIDE_DECISION_AT_QUEUE; @@ -8243,93 +9609,117 @@ static bool peep_should_go_on_ride(rct_peep *peep, int rideIndex, int entranceNu // Indicates whether a peep is physically at the ride, or is just thinking about going on the ride. bool peepAtRide = !(flags & PEEP_RIDE_DECISION_THINKING); - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_8)) { - if (ride->status == RIDE_STATUS_OPEN && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)) { + if (ride->status == RIDE_STATUS_OPEN && !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)) { - // Peeps that are leaving the park will refuse to go on any rides, with the exception of free transport rides. - if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF || ride->price != 0) { - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) { - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); - return false; - } + // Peeps that are leaving the park will refuse to go on any rides, with the exception of free transport rides. + if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF || ride->price != 0) { + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) { + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); + return false; + } + } + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) { + return peep_should_go_to_shop(peep, rideIndex, peepAtRide); + } + + // This used to check !(flags & 2), but the function is only ever called with flags = 0, 1 or 6. + // This means we can use the existing !(flags & 4) check. + if (peepAtRide) { + // Peeps won't join a queue that has 1000 peeps already in it. + if (ride->queue_length[entranceNum] >= 1000) { + peep_tried_to_enter_full_queue(peep, rideIndex); + return false; } - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & RIDE_TYPE_FLAG_IS_SHOP) { - return peep_should_go_to_shop(peep, rideIndex, peepAtRide); - } - - // This used to check !(flags & 2), but the function is only ever called with flags = 0, 1 or 6. - // This means we can use the existing !(flags & 4) check. - if (peepAtRide) { - // Peeps won't join a queue that has 1000 peeps already in it. - if (ride->queue_length[entranceNum] >= 1000) { + // Rides without queues can only have one peep waiting at a time. + if (!peepAtQueue) { + if (ride->last_peep_in_queue[entranceNum] != 0xFFFF) { peep_tried_to_enter_full_queue(peep, rideIndex); return false; } + } + else { + // Check if there's room in the queue for the peep to enter. + if (ride->last_peep_in_queue[entranceNum] != 0xFFFF) { + rct_peep *lastPeepInQueue = GET_PEEP(ride->last_peep_in_queue[entranceNum]); + if (abs(lastPeepInQueue->z - peep->z) <= 6) { + int dx = abs(lastPeepInQueue->x - peep->x); + int dy = abs(lastPeepInQueue->y - peep->y); + int maxD = max(dx, dy); - // Rides without queues can only have one peep waiting at a time. - if (!peepAtQueue) { - if (ride->last_peep_in_queue[entranceNum] != 0xFFFF) { - peep_tried_to_enter_full_queue(peep, rideIndex); - return false; - } - } - else { - // Check if there's room in the queue for the peep to enter. - if (ride->last_peep_in_queue[entranceNum] != 0xFFFF) { - rct_peep *lastPeepInQueue = GET_PEEP(ride->last_peep_in_queue[entranceNum]); - if (abs(lastPeepInQueue->z - peep->z) <= 6) { - int dx = abs(lastPeepInQueue->x - peep->x); - int dy = abs(lastPeepInQueue->y - peep->y); - int maxD = max(dx, dy); + // Unlike normal paths, peeps cannot overlap when queueing for a ride. + // This check enforces a minimum distance between peeps entering the queue. + if (maxD < 8) { + peep_tried_to_enter_full_queue(peep, rideIndex); + return false; + } - // Unlike normal paths, peeps cannot overlap when queueing for a ride. - // This check enforces a minimum distance between peeps entering the queue. - if (maxD < 8) { - peep_tried_to_enter_full_queue(peep, rideIndex); - return false; - } - - // This checks if there's a peep standing still at the very end of the queue. - if (maxD <= 13 - && lastPeepInQueue->time_in_queue > 10) { - peep_tried_to_enter_full_queue(peep, rideIndex); - return false; - } + // This checks if there's a peep standing still at the very end of the queue. + if (maxD <= 13 + && lastPeepInQueue->time_in_queue > 10) { + peep_tried_to_enter_full_queue(peep, rideIndex); + return false; } } } } + } - // Assuming the queue conditions are met, peeps will always go on free transport rides. - // Ride ratings, recent crashes and weather will all be ignored. - if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF || ride->price != 0) { - if (peep->previous_ride == rideIndex) { - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); + // Assuming the queue conditions are met, peeps will always go on free transport rides. + // Ride ratings, recent crashes and weather will all be ignored. + if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_TRANSPORT_RIDE) || ride->value == 0xFFFF || ride->price != 0) { + if (peep->previous_ride == rideIndex) { + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); + return false; + } + + // Basic price checks + if (ride->price != 0 && !peep_has_voucher_for_free_ride(peep, rideIndex)) { + + if (ride->price > peep->cash_in_pocket) { + if (peepAtRide) { + if (peep->cash_in_pocket <= 0) { + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SPENT_MONEY, 255); + } + else { + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_AFFORD_0, rideIndex); + } + } + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); return false; } + } - // Basic price checks - if (ride->price != 0 && !peep_has_voucher_for_free_ride(peep, rideIndex)) { + // If happy enough, peeps will ignore the fact that a ride has recently crashed. + if (ride->last_crash_type != RIDE_CRASH_TYPE_NONE && peep->happiness < 225) { + if (peepAtRide) { + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_NOT_SAFE, rideIndex); + if (peep->happiness_growth_rate >= 64) { + peep->happiness_growth_rate -= 8; + } + ride_update_popularity(ride, 0); + } + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); + return false; + } - if (ride->price > peep->cash_in_pocket) { - if (peepAtRide) { - if (peep->cash_in_pocket <= 0) { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SPENT_MONEY, 255); - } - else { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_CANT_AFFORD_0, rideIndex); - } - } - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); + + if (ride->excitement != (ride_rating)0xFFFF) { + // If a peep has already decided that they're going to go on a ride, they'll skip the weather and + // excitment check and will only do a basic intensity check when they arrive at the ride itself. + if (rideIndex == peep->guest_heading_to_ride_id) { + if (ride->intensity > RIDE_RATING(10, 00) && !gCheatsIgnoreRideIntensity) { + peep_ride_is_too_intense(peep, rideIndex, peepAtRide); return false; } } - // If happy enough, peeps will ignore the fact that a ride has recently crashed. - if (ride->last_crash_type != RIDE_CRASH_TYPE_NONE && peep->happiness < 225) { + // Peeps won't go on rides that aren't sufficiently undercover while it's raining. + // The threshold is fairly low and only requires about 10-15% of the ride to be undercover. + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8) != 0 && (ride->undercover_portion >> 5) < 3) { if (peepAtRide) { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_NOT_SAFE, rideIndex); + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_NOT_WHILE_RAINING, rideIndex); if (peep->happiness_growth_rate >= 64) { peep->happiness_growth_rate -= 8; } @@ -8339,22 +9729,34 @@ static bool peep_should_go_on_ride(rct_peep *peep, int rideIndex, int entranceNu return false; } - - if (ride->excitement != (ride_rating)0xFFFF) { - // If a peep has already decided that they're going to go on a ride, they'll skip the weather and - // excitment check and will only do a basic intensity check when they arrive at the ride itself. - if (rideIndex == peep->guest_heading_to_ride_id) { - if (ride->intensity > RIDE_RATING(10, 00) && !gConfigCheat.ignore_ride_intensity) { - peep_ride_is_too_intense(peep, rideIndex, peepAtRide); - return false; + if (!gCheatsIgnoreRideIntensity) { + // Intensity calculations. Even though the max intensity can go up to 15, it's capped + // at 10.0 (before happiness calculations). A full happiness bar will increase the max + // intensity and decrease the min intensity by about 2.5. + ride_rating maxIntensity = min((peep->intensity >> 4) * 100, 1000) + peep->happiness; + ride_rating minIntensity = ((peep->intensity & 0x0F) * 100) - peep->happiness; + if (ride->intensity < minIntensity) { + if (peepAtRide) { + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_MORE_THRILLING, rideIndex); + if (peep->happiness_growth_rate >= 64) { + peep->happiness_growth_rate -= 8; + } + ride_update_popularity(ride, 0); } + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); + return false; + } + if (ride->intensity > maxIntensity) { + peep_ride_is_too_intense(peep, rideIndex, peepAtRide); + return false; } - // Peeps won't go on rides that aren't sufficiently undercover while it's raining. - // The threshold is fairly low and only requires about 10-15% of the ride to be undercover. - if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8) != 0 && (ride->undercover_portion >> 5) < 3) { + // Nausea calculations. + ride_rating maxNausea = NauseaMaximumThresholds[(peep->nausea_tolerance & 3)] + peep->happiness; + + if (ride->nausea > maxNausea) { if (peepAtRide) { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_NOT_WHILE_RAINING, rideIndex); + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SICKENING, rideIndex); if (peep->happiness_growth_rate >= 64) { peep->happiness_growth_rate -= 8; } @@ -8364,118 +9766,80 @@ static bool peep_should_go_on_ride(rct_peep *peep, int rideIndex, int entranceNu return false; } - if (!gConfigCheat.ignore_ride_intensity) { - // Intensity calculations. Even though the max intensity can go up to 15, it's capped - // at 10.0 (before happiness calculations). A full happiness bar will increase the max - // intensity and decrease the min intensity by about 2.5. - ride_rating maxIntensity = min((peep->intensity >> 4) * 100, 1000) + peep->happiness; - ride_rating minIntensity = ((peep->intensity & 0x0F) * 100) - peep->happiness; - if (ride->intensity < minIntensity) { - if (peepAtRide) { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_MORE_THRILLING, rideIndex); - if (peep->happiness_growth_rate >= 64) { - peep->happiness_growth_rate -= 8; - } - ride_update_popularity(ride, 0); - } - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); - return false; - } - if (ride->intensity > maxIntensity) { - peep_ride_is_too_intense(peep, rideIndex, peepAtRide); - return false; - } - - // Nausea calculations. - ride_rating maxNausea = NauseaMaximumThresholds[(peep->nausea_tolerance & 3)] + peep->happiness; - - if (ride->nausea > maxNausea) { - if (peepAtRide) { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_SICKENING, rideIndex); - if (peep->happiness_growth_rate >= 64) { - peep->happiness_growth_rate -= 8; - } - ride_update_popularity(ride, 0); - } - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); - return false; - } - - // Very nauseous peeps will only go on very gentle rides. - if (ride->nausea >= FIXED_2DP(1, 40) && peep->nausea > 160) { - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); - return false; - } - } - } - - // If the ride has not yet been rated and is capable of having g-forces, - // there's a 90% chance that the peep will ignore it. - if ((ride->excitement == (ride_rating)0xFFFF) - && (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_PEEP_CHECK_GFORCES)) { - if ((scenario_rand() & 0xFFFF) > 0x1999U) { + // Very nauseous peeps will only go on very gentle rides. + if (ride->nausea >= FIXED_2DP(1, 40) && peep->nausea > 160) { peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); return false; } + } + } - if (!gConfigCheat.ignore_ride_intensity) { - if (ride->max_positive_vertical_g > FIXED_2DP(5, 00) - || ride->max_negative_vertical_g < FIXED_2DP(-4, 00) - || ride->max_lateral_g > FIXED_2DP(4, 00)) { - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); - return false; - } - } + // If the ride has not yet been rated and is capable of having g-forces, + // there's a 90% chance that the peep will ignore it. + if ((ride->excitement == (ride_rating)0xFFFF) + && (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_PEEP_CHECK_GFORCES)) { + if ((scenario_rand() & 0xFFFF) > 0x1999U) { + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); + return false; } - uint32 value = ride->value; - - // If the value of the ride hasn't yet been calculated, peeps will be willing to pay any amount for the ride. - if (value != 0xFFFF && !peep_has_voucher_for_free_ride(peep, rideIndex)) { - - // The amount peeps are willing to pay is decreased by 75% if they had to pay to enter the park. - if (peep->flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY) - value /= 4; - - // Peeps won't pay more than twice the value of the ride. - if (ride->price > (money16)(value * 2)) { - if (peepAtRide) { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_BAD_VALUE, rideIndex); - if (peep->happiness_growth_rate < 60) { - peep->happiness_growth_rate -= 16; - } - ride_update_popularity(ride, 0); - } - peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); + if (!gCheatsIgnoreRideIntensity) { + if (ride->max_positive_vertical_g > FIXED_2DP(5, 00) + || ride->max_negative_vertical_g < FIXED_2DP(-4, 00) + || ride->max_lateral_g > FIXED_2DP(4, 00)) { + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); return false; } + } + } - // A ride is good value if the price is 50% or less of the ride value and the peep didn't pay to enter the park. - if (ride->price <= (money16)(value / 2) && peepAtRide) { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { - if (!(peep->flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY)) { - peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_GOOD_VALUE, rideIndex); - } + uint32 value = ride->value; + + // If the value of the ride hasn't yet been calculated, peeps will be willing to pay any amount for the ride. + if (value != 0xFFFF && !peep_has_voucher_for_free_ride(peep, rideIndex)) { + + // The amount peeps are willing to pay is decreased by 75% if they had to pay to enter the park. + if (peep->peep_flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY) + value /= 4; + + // Peeps won't pay more than twice the value of the ride. + if (ride->price > (money16)(value * 2)) { + if (peepAtRide) { + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_BAD_VALUE, rideIndex); + if (peep->happiness_growth_rate < 60) { + peep->happiness_growth_rate -= 16; + } + ride_update_popularity(ride, 0); + } + peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, true); + return false; + } + + // A ride is good value if the price is 50% or less of the ride value and the peep didn't pay to enter the park. + if (ride->price <= (money16)(value / 2) && peepAtRide) { + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { + if (!(peep->peep_flags & PEEP_FLAGS_HAS_PAID_FOR_PARK_ENTRY)) { + peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_GOOD_VALUE, rideIndex); } } } } - - // At this point, the peep has decided to go on the ride. - if (peepAtRide) { - ride_update_popularity(ride, 1); - if ((peep->flags & PEEP_FLAGS_INTAMIN) && ride_type_is_intamin(ride->type)) { - peep_insert_new_thought(peep, PEEP_THOUGHT_EXCITED, 255); - } - } - - if (rideIndex == peep->guest_heading_to_ride_id) { - peep_reset_ride_heading(peep); - } - - ride->lifecycle_flags &= ~RIDE_LIFECYCLE_QUEUE_FULL; - return true; } + + // At this point, the peep has decided to go on the ride. + if (peepAtRide) { + ride_update_popularity(ride, 1); + if ((peep->peep_flags & PEEP_FLAGS_INTAMIN) && ride_type_is_intamin(ride->type)) { + peep_insert_new_thought(peep, PEEP_THOUGHT_EXCITED, 255); + } + } + + if (rideIndex == peep->guest_heading_to_ride_id) { + peep_reset_ride_heading(peep); + } + + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_QUEUE_FULL; + return true; } peep_chose_not_to_go_on_ride(peep, rideIndex, peepAtRide, false); @@ -8484,7 +9848,7 @@ static bool peep_should_go_on_ride(rct_peep *peep, int rideIndex, int entranceNu static void peep_ride_is_too_intense(rct_peep *peep, int rideIndex, bool peepAtRide) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); if (peepAtRide) { peep_insert_new_thought(peep, PEEP_THOUGHT_TYPE_INTENSE, rideIndex); @@ -8508,23 +9872,27 @@ static void peep_chose_not_to_go_on_ride(rct_peep *peep, int rideIndex, bool pee } } -/* +/** * When the queue is full, peeps will ignore the ride when thinking about what to go on next. * Does not effect peeps that walk up to the queue entrance. * This flag is reset the next time a peep successfully joins the queue. */ static void peep_tried_to_enter_full_queue(rct_peep *peep, int rideIndex) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); ride->lifecycle_flags |= RIDE_LIFECYCLE_QUEUE_FULL; peep->previous_ride = rideIndex; peep->previous_ride_time_out = 0; + //Change status "Heading to" to "Walking" if queue is full + if (rideIndex == peep->guest_heading_to_ride_id) { + peep_reset_ride_heading(peep); + } } static bool peep_should_go_to_shop(rct_peep *peep, int rideIndex, bool peepAtShop) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); // Peeps won't go to the same shop twice in a row. if (rideIndex == peep->previous_ride) { @@ -8593,7 +9961,7 @@ static void peep_pick_ride_to_go_on(rct_peep *peep) if (peep->state != PEEP_STATE_WALKING) return; if (peep->guest_heading_to_ride_id != 255) return; - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) return; + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) return; if (peep_has_food(peep)) return; if (peep->x == (sint16)0x8000) return; @@ -8654,7 +10022,7 @@ static void peep_pick_ride_to_go_on(rct_peep *peep) if (!(RCT2_ADDRESS(0x00F1AD98, uint32)[i >> 5] & (1u << (i & 0x1F)))) continue; - rct_ride *ride = GET_RIDE(i); + rct_ride *ride = get_ride(i); if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_QUEUE_FULL)) { if (peep_should_go_on_ride(peep, i, 0, PEEP_RIDE_DECISION_THINKING)) { *nextPotentialRide++ = i; @@ -8667,7 +10035,7 @@ static void peep_pick_ride_to_go_on(rct_peep *peep) int mostExcitingRideIndex = -1; ride_rating mostExcitingRideRating = 0; for (int i = 0; i < numPotentialRides; i++) { - ride = GET_RIDE(potentialRides[i]); + ride = get_ride(potentialRides[i]); if (ride->excitement == (ride_rating)0xFFFF) continue; if (ride->excitement > mostExcitingRideRating) { mostExcitingRideIndex = potentialRides[i]; @@ -8680,7 +10048,7 @@ static void peep_pick_ride_to_go_on(rct_peep *peep) // Head to that ride peep->guest_heading_to_ride_id = mostExcitingRideIndex; peep->peep_is_lost_countdown = 200; - sub_69A98C(peep); + peep_reset_pathfind_goal(peep); // Invalidate windows rct_window *w = window_find_by_number(WC_PEEP, peep->sprite_index); @@ -8706,10 +10074,10 @@ static void peep_head_for_nearest_ride_type(rct_peep *peep, int rideType) if (peep->state != PEEP_STATE_SITTING && peep->state != PEEP_STATE_WATCHING && peep->state != PEEP_STATE_WALKING) { return; } - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) return; + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) return; if (peep->x == (sint16)0x8000) return; if (peep->guest_heading_to_ride_id != 255) { - ride = GET_RIDE(peep->guest_heading_to_ride_id); + ride = get_ride(peep->guest_heading_to_ride_id); if (ride->type == rideType) { return; } @@ -8745,7 +10113,7 @@ static void peep_head_for_nearest_ride_type(rct_peep *peep, int rideType) if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; int rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == rideType) { RCT2_ADDRESS(0x00F1AD98, uint32)[rideIndex >> 5] |= (1u << (rideIndex & 0x1F)); } @@ -8763,7 +10131,7 @@ static void peep_head_for_nearest_ride_type(rct_peep *peep, int rideType) if (!(RCT2_ADDRESS(0x00F1AD98, uint32)[i >> 5] & (1u << (i & 0x1F)))) continue; - rct_ride *ride = GET_RIDE(i); + rct_ride *ride = get_ride(i); if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_QUEUE_FULL)) { if (peep_should_go_on_ride(peep, i, 0, PEEP_RIDE_DECISION_THINKING)) { *nextPotentialRide++ = i; @@ -8776,7 +10144,7 @@ static void peep_head_for_nearest_ride_type(rct_peep *peep, int rideType) int closestRideIndex = -1; int closestRideDistance = INT_MAX; for (int i = 0; i < numPotentialRides; i++) { - ride = GET_RIDE(potentialRides[i]); + ride = get_ride(potentialRides[i]); int rideX = (ride->station_starts[0] & 0xFF) * 32; int rideY = (ride->station_starts[0] >> 8) * 32; int distance = abs(rideX - peep->x) + abs(rideY - peep->y); @@ -8791,7 +10159,7 @@ static void peep_head_for_nearest_ride_type(rct_peep *peep, int rideType) // Head to that ride peep->guest_heading_to_ride_id = closestRideIndex; peep->peep_is_lost_countdown = 200; - sub_69A98C(peep); + peep_reset_pathfind_goal(peep); // Invalidate windows rct_window *w = window_find_by_number(WC_PEEP, peep->sprite_index); @@ -8814,16 +10182,16 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep *peep, int rideTypeFl if (peep->state != PEEP_STATE_SITTING && peep->state != PEEP_STATE_WATCHING && peep->state != PEEP_STATE_WALKING) { return; } - if (peep->flags & PEEP_FLAGS_LEAVING_PARK) return; + if (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) return; if (peep->x == (sint16)0x8000) return; if (peep->guest_heading_to_ride_id != 255) { - ride = GET_RIDE(peep->guest_heading_to_ride_id); - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & 0x03800000) { + ride = get_ride(peep->guest_heading_to_ride_id); + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_BATHROOM | RIDE_TYPE_FLAG_SELLS_DRINKS | RIDE_TYPE_FLAG_SELLS_FOOD)) { return; } } - if ((rideTypeFlags & 0x002000000) && peep_has_food(peep)) { + if ((rideTypeFlags & RIDE_TYPE_FLAG_IS_BATHROOM) && peep_has_food(peep)) { return; } @@ -8841,7 +10209,7 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep *peep, int rideTypeFl // Consider all rides in the park int i; FOR_ALL_RIDES(i, ride) { - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & rideTypeFlags) { + if (ride_type_has_flag(ride->type, rideTypeFlags)) { RCT2_ADDRESS(0x00F1AD98, uint32)[i >> 5] |= (1u << (i & 0x1F)); } } @@ -8857,8 +10225,8 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep *peep, int rideTypeFl if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; int rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); - if (RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride->type * 2] & rideTypeFlags) { + ride = get_ride(rideIndex); + if (ride_type_has_flag(ride->type, rideTypeFlags)) { RCT2_ADDRESS(0x00F1AD98, uint32)[rideIndex >> 5] |= (1u << (rideIndex & 0x1F)); } } while (!map_element_is_last_for_tile(mapElement++)); @@ -8875,7 +10243,7 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep *peep, int rideTypeFl if (!(RCT2_ADDRESS(0x00F1AD98, uint32)[i >> 5] & (1u << (i & 0x1F)))) continue; - rct_ride *ride = GET_RIDE(i); + rct_ride *ride = get_ride(i); if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_QUEUE_FULL)) { if (peep_should_go_on_ride(peep, i, 0, PEEP_RIDE_DECISION_THINKING)) { *nextPotentialRide++ = i; @@ -8888,7 +10256,7 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep *peep, int rideTypeFl int closestRideIndex = -1; int closestRideDistance = INT_MAX; for (int i = 0; i < numPotentialRides; i++) { - ride = GET_RIDE(potentialRides[i]); + ride = get_ride(potentialRides[i]); int rideX = (ride->station_starts[0] & 0xFF) * 32; int rideY = (ride->station_starts[0] >> 8) * 32; int distance = abs(rideX - peep->x) + abs(rideY - peep->y); @@ -8903,7 +10271,7 @@ static void peep_head_for_nearest_ride_with_flags(rct_peep *peep, int rideTypeFl // Head to that ride peep->guest_heading_to_ride_id = closestRideIndex; peep->peep_is_lost_countdown = 200; - sub_69A98C(peep); + peep_reset_pathfind_goal(peep); // Invalidate windows rct_window *w = window_find_by_number(WC_PEEP, peep->sprite_index); @@ -8950,13 +10318,84 @@ static void peep_give_real_name(rct_peep *peep) peep->name_string_idx = dx; } +static int peep_name_compare(const utf8 *a, const utf8 *b) +{ + // TODO be smarter about numbers being on the end + // e.g. Handyman 10 should go after Handyman 4 + return _stricmp(a, b); +} + /** * * rct2: 0x00699115 */ void peep_update_name_sort(rct_peep *peep) { - RCT2_CALLPROC_X(0x00699115, 0, 0, 0, 0, (int)peep, 0, 0); + RCT2_GLOBAL(0x009C383C, uint8) = 49; + + // Remove peep from sprite list + uint16 nextSpriteIndex = peep->next; + uint16 prevSpriteIndex = peep->previous; + if (prevSpriteIndex != SPRITE_INDEX_NULL) { + rct_peep *prevPeep = GET_PEEP(prevSpriteIndex); + prevPeep->next = nextSpriteIndex; + } else { + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16) = nextSpriteIndex; + } + + if (nextSpriteIndex != SPRITE_INDEX_NULL) { + rct_peep *nextPeep = GET_PEEP(nextSpriteIndex); + nextPeep->previous = prevSpriteIndex; + } + + // Get peep name + utf8 name[256]; + uint32 peepIndex = peep->id; + format_string_to_upper(name, peep->name_string_idx, &peepIndex); + + rct_peep *otherPeep; + uint16 spriteIndex; + FOR_ALL_PEEPS(spriteIndex, otherPeep) { + // Get other peep name + utf8 otherName[256]; + peepIndex = otherPeep->id; + format_string_to_upper(otherName, otherPeep->name_string_idx, &peepIndex); + + // Check if peep should go before this one + if (peep_name_compare(name, otherName) >= 0) { + continue; + } + + // Place peep before this one + peep->previous = otherPeep->previous; + otherPeep->previous = peep->sprite_index; + if (peep->previous != SPRITE_INDEX_NULL) { + rct_peep *prevPeep = GET_PEEP(peep->previous); + peep->next = prevPeep->next; + prevPeep->next = peep->sprite_index; + } else { + peep->next = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16) = peep->sprite_index; + } + goto finish_peep_sort; + } + + // Place peep at the end + FOR_ALL_PEEPS(spriteIndex, otherPeep) { + if (otherPeep->next == SPRITE_INDEX_NULL) { + otherPeep->next = peep->sprite_index; + peep->previous = otherPeep->sprite_index; + peep->next = SPRITE_INDEX_NULL; + goto finish_peep_sort; + } + } + + RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16) = peep->sprite_index; + peep->next = SPRITE_INDEX_NULL; + peep->previous = SPRITE_INDEX_NULL; + +finish_peep_sort: + RCT2_GLOBAL(0x009C383C, uint8) = 48; // This is required at the moment because this function reorders peeps in the sprite list openrct2_reset_object_tween_locations(); @@ -9017,7 +10456,7 @@ static void peep_read_map(rct_peep *peep) static bool peep_heading_for_ride_or_park_exit(rct_peep *peep) { - return (peep->flags & PEEP_FLAGS_LEAVING_PARK) || peep->guest_heading_to_ride_id != 0xFF; + return (peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) || peep->guest_heading_to_ride_id != 0xFF; } money32 set_peep_name(int flags, int state, uint16 sprite_index, uint8* text_1, uint8* text_2, uint8* text_3) { @@ -9038,16 +10477,16 @@ money32 set_peep_name(int flags, int state, uint16 sprite_index, uint8* text_1, return 0; rct_peep* peep = GET_PEEP(sprite_index); - RCT2_GLOBAL(0x0013CE952, uint32) = peep->id; - utf8* curName = RCT2_ADDRESS(0x00141ED68, utf8); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = peep->id; + utf8* curName = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, utf8); rct_string_id curId = peep->name_string_idx; - format_string(curName, curId, RCT2_ADDRESS(0x0013CE952, void)); + format_string(curName, curId, RCT2_ADDRESS(RCT2_ADDRESS_COMMON_FORMAT_ARGS, void)); if (strcmp(curName, fullText) == 0) return 0; if (*fullText == '\0') { - RCT2_GLOBAL(0x00141E9AC, rct_string_id) = 1455; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = 1455; return MONEY32_UNDEFINED; } @@ -9066,24 +10505,24 @@ money32 set_peep_name(int flags, int state, uint16 sprite_index, uint8* text_1, peep_update_name_sort(peep); - peep->flags &= ~PEEP_FLAGS_WAVING; + peep->peep_flags &= ~PEEP_FLAGS_WAVING; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_KATIE_BRAYSHAW, peep)) { - peep->flags |= PEEP_FLAGS_WAVING; + peep->peep_flags |= PEEP_FLAGS_WAVING; } - peep->flags &= ~PEEP_FLAGS_PHOTO; + peep->peep_flags &= ~PEEP_FLAGS_PHOTO; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_CHRIS_SAWYER, peep)) { - peep->flags |= PEEP_FLAGS_PHOTO; + peep->peep_flags |= PEEP_FLAGS_PHOTO; } - peep->flags &= ~PEEP_FLAGS_PAINTING; + peep->peep_flags &= ~PEEP_FLAGS_PAINTING; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_SIMON_FOSTER, peep)) { - peep->flags |= PEEP_FLAGS_PAINTING; + peep->peep_flags |= PEEP_FLAGS_PAINTING; } - peep->flags &= ~PEEP_FLAGS_WOW; + peep->peep_flags &= ~PEEP_FLAGS_WOW; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_JOHN_WARDLEY, peep)) { - peep->flags |= PEEP_FLAGS_WOW; + peep->peep_flags |= PEEP_FLAGS_WOW; } if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_MELANIE_WARN, peep)) { @@ -9095,96 +10534,99 @@ money32 set_peep_name(int flags, int state, uint16 sprite_index, uint8* text_1, peep->nausea_growth_rate = 0; } - peep->flags &= ~PEEP_FLAGS_LITTER; + peep->peep_flags &= ~PEEP_FLAGS_LITTER; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_LISA_STIRLING, peep)) { - peep->flags |= PEEP_FLAGS_LITTER; + peep->peep_flags |= PEEP_FLAGS_LITTER; } - peep->flags &= ~PEEP_FLAGS_LOST; + peep->peep_flags &= ~PEEP_FLAGS_LOST; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_DONALD_MACRAE, peep)) { - peep->flags |= PEEP_FLAGS_LOST; + peep->peep_flags |= PEEP_FLAGS_LOST; } - peep->flags &= ~PEEP_FLAGS_HUNGER; + peep->peep_flags &= ~PEEP_FLAGS_HUNGER; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_KATHERINE_MCGOWAN, peep)) { - peep->flags |= PEEP_FLAGS_HUNGER; + peep->peep_flags |= PEEP_FLAGS_HUNGER; } - peep->flags &= ~PEEP_FLAGS_BATHROOM; + peep->peep_flags &= ~PEEP_FLAGS_BATHROOM; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_FRANCES_MCGOWAN, peep)) { - peep->flags |= PEEP_FLAGS_BATHROOM; + peep->peep_flags |= PEEP_FLAGS_BATHROOM; } - peep->flags &= ~PEEP_FLAGS_CROWDED; + peep->peep_flags &= ~PEEP_FLAGS_CROWDED; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_CORINA_MASSOURA, peep)) { - peep->flags |= PEEP_FLAGS_CROWDED; + peep->peep_flags |= PEEP_FLAGS_CROWDED; } - peep->flags &= ~PEEP_FLAGS_HAPPINESS; + peep->peep_flags &= ~PEEP_FLAGS_HAPPINESS; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_CAROL_YOUNG, peep)) { - peep->flags |= PEEP_FLAGS_HAPPINESS; + peep->peep_flags |= PEEP_FLAGS_HAPPINESS; } - peep->flags &= ~PEEP_FLAGS_NAUSEA; + peep->peep_flags &= ~PEEP_FLAGS_NAUSEA; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_MIA_SHERIDAN, peep)) { - peep->flags |= PEEP_FLAGS_NAUSEA; + peep->peep_flags |= PEEP_FLAGS_NAUSEA; } if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_KATIE_RODGER, peep)) { - peep->flags |= PEEP_FLAGS_LEAVING_PARK; - peep->flags &= ~PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; + peep->peep_flags |= PEEP_FLAGS_LEAVING_PARK; + peep->peep_flags &= ~PEEP_FLAGS_PARK_ENTRANCE_CHOSEN; } - peep->flags &= ~PEEP_FLAGS_PURPLE; + peep->peep_flags &= ~PEEP_FLAGS_PURPLE; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_EMMA_GARRELL, peep)) { - peep->flags |= PEEP_FLAGS_PURPLE; + peep->peep_flags |= PEEP_FLAGS_PURPLE; } - peep->flags &= ~PEEP_FLAGS_EATING; + peep->peep_flags &= ~PEEP_FLAGS_PIZZA; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_JOANNE_BARTON, peep)) { - peep->flags |= PEEP_FLAGS_EATING; + peep->peep_flags |= PEEP_FLAGS_PIZZA; } - peep->flags &= ~PEEP_FLAGS_CONTAGIOUS; + peep->peep_flags &= ~PEEP_FLAGS_CONTAGIOUS; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_FELICITY_ANDERSON, peep)) { - peep->flags |= PEEP_FLAGS_CONTAGIOUS; + peep->peep_flags |= PEEP_FLAGS_CONTAGIOUS; } - peep->flags &= ~PEEP_FLAGS_JOY; + peep->peep_flags &= ~PEEP_FLAGS_JOY; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_KATIE_SMITH, peep)) { - peep->flags |= PEEP_FLAGS_JOY; + peep->peep_flags |= PEEP_FLAGS_JOY; } - peep->flags &= ~PEEP_FLAGS_ANGRY; + peep->peep_flags &= ~PEEP_FLAGS_ANGRY; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_EILIDH_BELL, peep)) { - peep->flags |= PEEP_FLAGS_ANGRY; + peep->peep_flags |= PEEP_FLAGS_ANGRY; } - peep->flags &= ~PEEP_FLAGS_ICE_CREAM; + peep->peep_flags &= ~PEEP_FLAGS_ICE_CREAM; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_NANCY_STILLWAGON, peep)) { - peep->flags |= PEEP_FLAGS_ICE_CREAM; + peep->peep_flags |= PEEP_FLAGS_ICE_CREAM; } - peep->flags &= ~PEEP_FLAGS_NICE_RIDE; + peep->peep_flags &= ~PEEP_FLAGS_NICE_RIDE; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_ANDY_HINE, peep)) { - peep->flags |= PEEP_FLAGS_NICE_RIDE; + peep->peep_flags |= PEEP_FLAGS_NICE_RIDE; } - peep->flags &= ~PEEP_FLAGS_INTAMIN; + peep->peep_flags &= ~PEEP_FLAGS_INTAMIN; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_ELISSA_WHITE, peep)) { - peep->flags |= PEEP_FLAGS_INTAMIN; + peep->peep_flags |= PEEP_FLAGS_INTAMIN; } - peep->flags &= ~PEEP_FLAGS_HERE_WE_ARE; + peep->peep_flags &= ~PEEP_FLAGS_HERE_WE_ARE; if (peep_check_easteregg_name(EASTEREGG_PEEP_NAME_DAVID_ELLIS, peep)) { - peep->flags |= PEEP_FLAGS_HERE_WE_ARE; + peep->peep_flags |= PEEP_FLAGS_HERE_WE_ARE; } gfx_invalidate_screen(); return 0; } -/* rct2: 0x00698D6C */ +/** + * + * rct2: 0x00698D6C + */ void game_command_set_peep_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { *ebx = set_peep_name( *ebx & 0xFF, diff --git a/src/peep/peep.h b/src/peep/peep.h index c758f335b7..91a6daa30f 100644 --- a/src/peep/peep.h +++ b/src/peep/peep.h @@ -231,7 +231,9 @@ enum PEEP_ACTION_EVENTS { PEEP_ACTION_STAFF_FIX = 15, PEEP_ACTION_STAFF_FIX_2 = 16, PEEP_ACTION_STAFF_FIX_GROUND = 17, + PEEP_ACTION_STAFF_FIX_3 = 18, PEEP_ACTION_STAFF_WATERING = 19, + PEEP_ACTION_JOY = 20, PEEP_ACTION_READ_MAP = 21, PEEP_ACTION_WAVE = 22, PEEP_ACTION_STAFF_EMPTY_BIN = 23, @@ -265,7 +267,7 @@ enum PEEP_FLAGS { PEEP_FLAGS_HAPPINESS = (1 << 14), // The peep will start increasing happiness PEEP_FLAGS_NAUSEA = (1 << 15), // Makes the peep feel sick (e.g. after an extreme ride) PEEP_FLAGS_PURPLE = (1 << 16), // Makes surrounding peeps purple - PEEP_FLAGS_EATING = (1 << 17), // Reduces hunger + PEEP_FLAGS_PIZZA = (1 << 17), // Gives passing peeps pizza PEEP_FLAGS_EXPLODE = (1 << 18), PEEP_FLAGS_RIDE_SHOULD_BE_MARKED_AS_FAVOURITE = (1 << 19), PEEP_FLAGS_PARK_ENTRANCE_CHOSEN = (1 << 20), //Set when the nearest park entrance has been chosen @@ -273,7 +275,7 @@ enum PEEP_FLAGS { PEEP_FLAGS_CONTAGIOUS = (1 << 22), // Makes any peeps in surrounding tiles sick PEEP_FLAGS_JOY = (1 << 23), // Makes the peep jump in joy PEEP_FLAGS_ANGRY = (1 << 24), - PEEP_FLAGS_ICE_CREAM = (1 << 25), // Gives the peeps infront of them in queue ice cream + PEEP_FLAGS_ICE_CREAM = (1 << 25), // Gives passing peeps ice cream and they wave back PEEP_FLAGS_NICE_RIDE = (1 << 26), // Makes the peep think "Nice ride! But not as good as the Phoenix..." on exiting a ride PEEP_FLAGS_INTAMIN = (1 << 27), // Makes the peep think "I'm so excited - It's an Intamin ride!" while riding on a Intamin PEEP_FLAGS_HERE_WE_ARE = (1 << 28), // Makes the peep think "...and here we are on X!" while riding a ride @@ -389,7 +391,7 @@ typedef struct { // Height from center of sprite to bottom uint8 sprite_height_negative; // 0x09 uint16 sprite_index; // 0x0A - uint16 var_0C; + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -408,7 +410,7 @@ typedef struct { uint16 next_y; // 0x26 uint8 next_z; // 0x28 uint8 next_var_29; // 0x29 - uint8 outside_of_park; + uint8 outside_of_park; // 0x2A uint8 state; // 0x2B uint8 sub_state; // 0x2C uint8 sprite_type; // 0x2D @@ -458,9 +460,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 +492,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 @@ -498,9 +502,9 @@ typedef struct { uint8 peep_is_lost_countdown; // 0xC6 }; uint8 photo1_ride_ref; // 0xC7 - uint32 flags; // 0xC8 - rct_xyzd8 var_CC; - rct_xyzd8 var_D0[4]; + uint32 peep_flags; // 0xC8 + rct_xyzd8 pathfind_goal; // 0xCC + rct_xyzd8 pathfind_history[4]; // 0xD0 uint8 no_action_frame_no; // 0xE0 // 0x3F Litter Count split into lots of 3 with time, 0xC0 Time since last recalc uint8 litter_count; // 0xE1 @@ -637,4 +641,6 @@ void peep_update_names(bool realNames); void game_command_set_peep_name(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +int peep_pathfind_choose_direction(sint16 x, sint16 y, uint8 z, rct_peep *peep); + #endif diff --git a/src/peep/staff.c b/src/peep/staff.c index b187d632b3..16f36389c2 100644 --- a/src/peep/staff.c +++ b/src/peep/staff.c @@ -25,7 +25,9 @@ #include "../interface/viewport.h" #include "../localisation/string_ids.h" #include "../management/finance.h" +#include "../util/util.h" #include "../world/sprite.h" +#include "../world/footpath.h" #include "peep.h" #include "staff.h" @@ -109,7 +111,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,14 +132,14 @@ 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; newPeep->var_C4 = 0; newPeep->type = PEEP_TYPE_STAFF; newPeep->outside_of_park = 0; - newPeep->flags = 0; + newPeep->peep_flags = 0; newPeep->paid_to_enter = 0; newPeep->paid_on_rides = 0; newPeep->paid_on_food = 0; @@ -181,10 +184,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; @@ -248,10 +251,10 @@ void game_command_hire_new_staff_member(int* eax, int* ebx, int* ecx, int* edx, } newPeep->time_in_park = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); - newPeep->var_CC.x = 0xFF; - newPeep->var_CC.y = 0xFF; - newPeep->var_CC.z = 0xFF; - newPeep->var_CC.direction = 0xFF; + newPeep->pathfind_goal.x = 0xFF; + newPeep->pathfind_goal.y = 0xFF; + newPeep->pathfind_goal.z = 0xFF; + newPeep->pathfind_goal.direction = 0xFF; uint8 colour = RCT2_ADDRESS(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8)[staff_type > 2 ? 2 : staff_type]; newPeep->tshirt_colour = colour; @@ -292,15 +295,21 @@ 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; sprite_type += 4; peep->sprite_type = sprite_type; - peep->flags &= ~PEEP_FLAGS_SLOW_WALK; + peep->peep_flags &= ~PEEP_FLAGS_SLOW_WALK; if(RCT2_ADDRESS(0x00982134, uint8)[sprite_type] & 1){ - peep->flags |= PEEP_FLAGS_SLOW_WALK; + peep->peep_flags |= PEEP_FLAGS_SLOW_WALK; } peep->action_frame = 0; sub_693B58(peep); @@ -326,10 +335,23 @@ void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int * int x = *eax; int y = *ecx; uint16 sprite_id = *edx; - rct_peep *peep = &g_sprite_list[sprite_id].peep; + if (sprite_id >= MAX_SPRITES) + { + *ebx = MONEY32_UNDEFINED; + log_warning("Invalid sprite id %u", sprite_id); + return; + } + rct_sprite *sprite = &g_sprite_list[sprite_id]; + if (sprite->unknown.sprite_identifier != SPRITE_IDENTIFIER_PEEP || sprite->peep.type != PEEP_TYPE_STAFF) + { + *ebx = MONEY32_UNDEFINED; + log_warning("Invalid type of sprite %u for game command", sprite_id); + return; + } + rct_peep *peep = &sprite->peep; int patrolOffset = peep->staff_id * (64 * 64 / 8); int patrolIndex = ((x & 0x1F80) >> 7) | ((y & 0x1F80) >> 1); - int mask = 1 << (patrolIndex & 0x1F); + int mask = 1u << (patrolIndex & 0x1F); int base = patrolIndex >> 5; uint32 *patrolBits = (uint32*)(RCT2_ADDRESS_STAFF_PATROL_AREAS + patrolOffset + (base * 4)); @@ -365,14 +387,26 @@ 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); } *ebx = 0; } -/* +/** * Updates the colour of the given staff type. */ void update_staff_colour(uint8 staffType, uint16 colour) @@ -380,7 +414,7 @@ void update_staff_colour(uint8 staffType, uint16 colour) game_do_command(0, (staffType << 8) | GAME_COMMAND_FLAG_APPLY, 0, (colour << 8) | 4, GAME_COMMAND_SET_STAFF_COLOUR, 0, 0); } -/* +/** * Hires a new staff member of the given type. If the hire cannot be completed (eg. the maximum * number of staff is reached or there are too many people in the game) it returns 0xFFFF. */ @@ -428,14 +462,14 @@ void staff_update_greyed_patrol_areas() } } -int staff_is_location_in_patrol_area(rct_peep *peep, int x, int y) +static int staff_is_location_in_patrol_area(rct_peep *peep, int x, int y) { // Patrol quads are stored in a bit map (8 patrol quads per byte) // Each patrol quad is 4x4 // Therefore there are in total 64 x 64 patrol quads in the 256 x 256 map int patrolOffset = peep->staff_id * (64 * 64 / 8); int patrolIndex = ((x & 0x1F80) >> 7) | ((y & 0x1F80) >> 1); - int mask = 1 << (patrolIndex & 0x1F); + int mask = 1u << (patrolIndex & 0x1F); int base = patrolIndex >> 5; uint32 *patrolBits = (uint32*)(RCT2_ADDRESS_STAFF_PATROL_AREAS + patrolOffset + (base * 4)); @@ -446,17 +480,52 @@ int staff_is_location_in_patrol_area(rct_peep *peep, int x, int y) * * rct2: 0x006C0905 */ -int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y) +int staff_is_location_in_patrol(rct_peep *staff, int x, int y) { // Check if location is in the park - if (!map_is_location_owned(x, y, mechanic->z)) + if (!map_is_location_owned_or_has_rights(x, y)) return 0; - // Check if mechanic has patrol area - if (!(RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[mechanic->staff_id] & 2)) + // Check if staff has patrol area + if (!(RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[staff->staff_id] & 2)) return 1; - return staff_is_location_in_patrol_area(mechanic, x, y); + return staff_is_location_in_patrol_area(staff, x, y); +} + +/** + * + * rct2: 0x006C095B + * returns 0xF if not in a valid patrol area + */ +static uint8 staff_get_valid_patrol_directions(rct_peep* peep, sint16 x, sint16 y) { + uint8 directions = 0; + + if (staff_is_location_in_patrol(peep, x - 32, y)) { + directions |= (1 << 0); + } + + if (staff_is_location_in_patrol(peep, x, y + 32)) { + directions |= (1 << 1); + } + + if (staff_is_location_in_patrol(peep, x + 32, y)) { + directions |= (1 << 2); + } + + if (staff_is_location_in_patrol(peep, x, y - 32)) { + directions |= (1 << 3); + } + + if (directions == 0) { + directions = 0xF; + } + + // For backwards compatibility. + // Remove when all references to 0x00F43910 removed + RCT2_GLOBAL(0x00F43910, uint32) = directions; + + return directions; } /** @@ -489,3 +558,656 @@ bool staff_is_patrol_area_set(int staffIndex, int x, int y) int bitIndex = (x | y) & 0x1F; return gStaffPatrolAreas[peepOffset + offset] & (1 << bitIndex); } + +/** + * + * rct2: 0x006BFBE8 + * + * Returns 0xFF when no nearby litter or unpathable litter + */ +static uint8 staff_handyman_direction_to_nearest_litter(rct_peep* peep){ + uint16 nearestLitterDist = (uint16)-1; + rct_litter* nearestLitter = NULL; + rct_litter* litter = NULL; + + for(uint16 litterIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_LITTER, uint16); litterIndex != 0xFFFF; litterIndex = litter->next){ + litter = &g_sprite_list[litterIndex].litter; + + uint16 distance = + abs(litter->x - peep->x) + + abs(litter->y - peep->y) + + abs(litter->z - peep->z) * 4; + + if (distance < nearestLitterDist){ + nearestLitterDist = distance; + nearestLitter = litter; + } + } + + if (nearestLitterDist > 0x60){ + return 0xFF; + } + + rct_xy16 litterTile = { + .x = nearestLitter->x & 0xFFE0, + .y = nearestLitter->y & 0xFFE0 + }; + + if (!staff_is_location_in_patrol(peep, litterTile.x, litterTile.y)){ + return 0xFF; + } + + litterTile.x += 16; + litterTile.y += 16; + + sint16 x_diff = litterTile.x - peep->x; + sint16 y_diff = litterTile.y - peep->y; + + uint8 nextDirection = 0; + + if (abs(x_diff) <= abs(y_diff)){ + nextDirection = y_diff < 0 ? 3 : 1; + } + else { + nextDirection = x_diff < 0 ? 0 : 2; + } + + rct_xy16 nextTile = { + .x = (nearestLitter->x & 0xFFE0) - TileDirectionDelta[nextDirection].x, + .y = (nearestLitter->y & 0xFFE0) - TileDirectionDelta[nextDirection].y + }; + + sint16 nextZ = ((peep->z + 8) & 0xFFF0) / 8; + + rct_map_element* mapElement = map_get_first_element_at(nextTile.x / 32, nextTile.y / 32); + + do { + if (mapElement->base_height != nextZ) + continue; + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE || + map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK){ + return 0xFF; + } + } while(!map_element_is_last_for_tile(mapElement++)); + + nextTile.x = (peep->x & 0xFFE0) + TileDirectionDelta[nextDirection].x; + nextTile.y = (peep->y & 0xFFE0) + TileDirectionDelta[nextDirection].y; + + mapElement = map_get_first_element_at(nextTile.x / 32, nextTile.y / 32); + + do { + if (mapElement->base_height != nextZ) + continue; + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_ENTRANCE || + map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK){ + return 0xFF; + } + } while(!map_element_is_last_for_tile(mapElement++)); + + return nextDirection; +} + +/** + * + * rct2: 0x006BF931 + */ +static uint8 staff_handyman_direction_to_uncut_grass(rct_peep* peep, uint8 valid_directions) { + if (!(peep->next_var_29 & 0x18)) { + + rct_map_element* mapElement = map_get_surface_element_at(peep->next_x / 32, peep->next_y / 32); + + if (peep->next_z != mapElement->base_height) + return 0xFF; + + if (peep->next_var_29 & 0x4) { + if ((mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK) != RCT2_ADDRESS(0x0098D800, uint8)[peep->next_var_29 & 0x3]) + return 0xFF; + } + else if ((mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK) != 0) + return 0xFF; + } + + uint8 chosenDirection = scenario_rand() & 0x3; + for (uint8 i = 0; i < 4; ++i, ++chosenDirection) { + chosenDirection &= 0x3; + + if (!(valid_directions & (1 << chosenDirection))) { + continue; + } + + rct_xy16 chosenTile = { + .x = peep->next_x + TileDirectionDelta[chosenDirection].x, + .y = peep->next_y + TileDirectionDelta[chosenDirection].y, + }; + + if (chosenTile.x > 0x1FFF || chosenTile.y > 0x1FFF) + continue; + + rct_map_element* mapElement = map_get_surface_element_at(chosenTile.x / 32, chosenTile.y / 32); + + if (map_element_get_terrain(mapElement) != 0) + continue; + + if (abs(mapElement->base_height - peep->next_z) > 2) + continue; + + if ((mapElement->properties.surface.grass_length & 0x7) < GRASS_LENGTH_CLEAR_1) + continue; + + return chosenDirection; + } + return 0xFF; +} + +/** + * + * rct2: 0x006BFD9C + */ +static int staff_handyman_direction_rand_surface(rct_peep* peep, uint8 validDirections) { + uint8 direction = scenario_rand() & 3; + for (int i = 0; i < 4; ++i, ++direction) { + direction &= 3; + if (!(validDirections & (1 << direction))) + continue; + + rct_xy16 chosenTile = { + .x = peep->next_x + TileDirectionDelta[direction].x, + .y = peep->next_y + TileDirectionDelta[direction].y, + }; + + if (map_surface_is_blocked(chosenTile.x, chosenTile.y)) + continue; + + break; + } + // If it tries all directions this is required + // to make it back to the first direction and + // override validDirections + direction &= 3; + return direction; +} + +/** + * + * rct2: 0x006BFBA8 + */ +static int staff_path_finding_handyman(rct_peep* peep) +{ + peep->var_E2++; + + uint8 litterDirection = 0xFF; + uint8 validDirections = staff_get_valid_patrol_directions(peep, peep->next_x, peep->next_y); + + if ((peep->staff_orders & STAFF_ORDERS_SWEEPING) && + ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + peep->sprite_index) & 0xFFF) > 110) { + litterDirection = staff_handyman_direction_to_nearest_litter(peep); + } + + uint8 direction = 0xFF; + if (litterDirection == 0xFF && + (peep->staff_orders & STAFF_ORDERS_MOWING) && + peep->var_E2 >= 12 + ) { + direction = staff_handyman_direction_to_uncut_grass(peep, validDirections); + } + + if (direction == 0xFF) { + if (peep->next_var_29 & 0x18) { + direction = staff_handyman_direction_rand_surface(peep, validDirections); + } else { + rct_map_element* mapElement = map_get_path_element_at( + peep->next_x / 32, + peep->next_y / 32, + peep->next_z); + + if (mapElement == NULL) + return 1; + + uint8 pathDirections = (mapElement->properties.path.edges & validDirections) & 0xF; + if (pathDirections == 0) { + direction = staff_handyman_direction_rand_surface(peep, validDirections); + } else { + bool chooseRandom = true; + if (litterDirection != 0xFF && pathDirections & (1 << litterDirection)) { + if ((scenario_rand() & 0xFFFF) >= 0x1999) { + chooseRandom = false; + direction = litterDirection; + } + } else { + pathDirections &= ~(1 << (peep->var_78 ^ (1 << 1))); + if (pathDirections == 0) { + pathDirections |= 1 << (peep->var_78 ^ (1 << 1)); + } + } + + if (chooseRandom == true) { + do { + direction = scenario_rand() & 3; + } while ((pathDirections & (1 << direction)) == 0); + } + } + } + } + + // countof(TileDirectionDelta) + assert(direction < 8); + + rct_xy16 chosenTile = { + .x = peep->next_x + TileDirectionDelta[direction].x, + .y = peep->next_y + TileDirectionDelta[direction].y + }; + + while (chosenTile.x > 0x1FFF || chosenTile.y > 0x1FFF) { + direction = staff_handyman_direction_rand_surface(peep, validDirections); + chosenTile.x = peep->next_x + TileDirectionDelta[direction].x; + chosenTile.y = peep->next_y + TileDirectionDelta[direction].y; + } + + peep->var_78 = direction; + peep->destination_x = chosenTile.x + 16; + peep->destination_y = chosenTile.y + 16; + peep->destination_tolerence = 3; + if (peep->state == PEEP_STATE_QUEUING) { + peep->destination_tolerence = (scenario_rand() & 7) + 2; + } + return 0; +} + +uint8 staff_direction_surface(rct_peep* peep, uint8 initialDirection) { + uint8 direction = initialDirection; + for (int i = 0; i < 3; ++i) { + // Looks left and right from initial direction + switch (i) { + case 1: + direction++; + if (scenario_rand() & 1) { + direction -= 2; + } + break; + case 2: + direction -= 2; + break; + } + + direction &= 3; + + if (fence_in_the_way( + peep->next_x, + peep->next_y, + peep->next_z, + peep->next_z + 4, + direction) == true) + continue; + + if (fence_in_the_way( + peep->next_x, + peep->next_y, + peep->next_z, + peep->next_z + 4, + direction ^ (1 << 1)) == true) + continue; + + rct_xy16 chosenTile = { + .x = peep->next_x + TileDirectionDelta[direction].x, + .y = peep->next_y + TileDirectionDelta[direction].y + }; + + if (map_surface_is_blocked(chosenTile.x, chosenTile.y) == false) { + return direction; + } + } + return initialDirection; +} + +/** + * + * rct2: 0x006BFF45 + */ +static uint8 staff_mechanic_direction_surface(rct_peep* peep) { + uint8 direction = scenario_rand() & 3; + + if ((peep->state == PEEP_STATE_ANSWERING || peep->state == PEEP_STATE_HEADING_TO_INSPECTION) && + scenario_rand() & 1) { + + rct_ride* ride = get_ride(peep->current_ride); + + uint16 location = ride->exits[peep->current_ride_station]; + if (location == 0xFFFF) { + location = ride->entrances[peep->current_ride_station]; + } + + rct_xy16 chosenTile = { + .x = (location & 0xFF) * 32, + .y = (location >> 8) * 32 + }; + + sint16 x_diff = chosenTile.x - peep->x; + sint16 y_diff = chosenTile.y - peep->y; + + if (abs(x_diff) <= abs(y_diff)) { + direction = y_diff < 0 ? 3 : 1; + } + else { + direction = x_diff < 0 ? 0 : 2; + } + } + + return staff_direction_surface(peep, direction); +} + +/** + * + * rct2: 0x006C02D1 + */ +static uint8 staff_mechanic_direction_path_rand(rct_peep* peep, uint8 pathDirections) { + if (scenario_rand() & 1) { + if (pathDirections & (1 << peep->var_78)) + return peep->var_78; + } + + // Modified from original to spam scenario_rand less + uint8 direction = scenario_rand() & 3; + for (int i = 0; i < 4; ++i, ++direction) { + direction &= 3; + if (pathDirections & (1 << direction)) + return direction; + } + // This will never happen as pathDirections always has a bit set. + return peep->var_78; +} + +/** + * + * rct2: 0x006C0121 + */ +static uint8 staff_mechanic_direction_path(rct_peep* peep, uint8 validDirections, rct_map_element* pathElement) { + uint8 direction = 0xFF; + uint8 pathDirections = pathElement->properties.path.edges & 0xF; + if (peep->state != PEEP_STATE_ANSWERING && peep->state != PEEP_STATE_HEADING_TO_INSPECTION) { + pathDirections &= validDirections; + } + + if (pathDirections == 0) { + return staff_mechanic_direction_surface(peep); + } + + pathDirections &= ~(1 << (peep->var_78 ^ (1 << 1))); + if (pathDirections == 0) { + pathDirections |= (1 << (peep->var_78 ^ (1 << 1))); + } + + direction = bitscanforward(pathDirections); + pathDirections &= ~(1 << direction); + if (pathDirections == 0) { + if (peep->state != PEEP_STATE_ANSWERING && peep->state != PEEP_STATE_HEADING_TO_INSPECTION) { + return direction; + } + + if (peep->sub_state != 2) { + return direction; + } + peep->sub_state = 3; + } + + pathDirections |= (1 << direction); + + if (peep->state == PEEP_STATE_ANSWERING || peep->state == PEEP_STATE_HEADING_TO_INSPECTION) { + rct_ride* ride = get_ride(peep->current_ride); + uint8 z = ride->station_heights[peep->current_ride_station]; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Z, uint8) = z; + + uint16 location = ride->exits[peep->current_ride_station]; + if (location == 0xFFFF) { + location = ride->entrances[peep->current_ride_station]; + } + + rct_xy16 chosenTile = { + .x = (location & 0xFF) * 32, + .y = (location >> 8) * 32 + }; + + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) = chosenTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) = chosenTile.y; + + bool entranceFound = false; + rct_map_element* mapElement = map_get_first_element_at(chosenTile.x / 32, chosenTile.y / 32); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE) + continue; + + if (mapElement->base_height != z) + continue; + + if (mapElement->properties.entrance.type != ENTRANCE_TYPE_RIDE_ENTRANCE && + mapElement->properties.entrance.type != ENTRANCE_TYPE_RIDE_EXIT) + continue; + + entranceFound = true; + break; + } while (!map_element_is_last_for_tile(mapElement++)); + + if (entranceFound == false) { + return staff_mechanic_direction_path_rand(peep, pathDirections); + } + + uint8 entranceDirection = map_element_get_direction(mapElement); + chosenTile.x -= TileDirectionDelta[entranceDirection].x; + chosenTile.y -= TileDirectionDelta[entranceDirection].y; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_X, sint16) = chosenTile.x; + RCT2_GLOBAL(RCT2_ADDRESS_PEEP_PATHFINDING_GOAL_Y, sint16) = chosenTile.y; + + if (chosenTile.x == peep->next_x && + chosenTile.y == peep->next_y && + z == peep->next_z) { + return entranceDirection; + } + + RCT2_GLOBAL(0x00F1AEE0, uint8) = 0; + RCT2_GLOBAL(0x00F1AEE1, uint8) = 0xFF; + + int pathfindDirection = peep_pathfind_choose_direction(peep->next_x, peep->next_y, peep->next_z, peep); + + if (pathfindDirection == -1) { + return staff_mechanic_direction_path_rand(peep, pathDirections); + } + + return (uint8)pathfindDirection; + } + return staff_mechanic_direction_path_rand(peep, pathDirections); +} + +/** + * + * rct2: 0x006BFF2C + */ +static int staff_path_finding_mechanic(rct_peep* peep) { + uint8 validDirections = staff_get_valid_patrol_directions(peep, peep->next_x, peep->next_y); + uint8 direction = 0xFF; + if (peep->next_var_29 & 0x18) { + direction = staff_mechanic_direction_surface(peep); + } + else { + rct_map_element* pathElement = map_get_path_element_at(peep->next_x / 32, peep->next_y / 32, peep->next_z); + if (pathElement == NULL) + return 1; + + direction = staff_mechanic_direction_path(peep, validDirections, pathElement); + } + + // countof(TileDirectionDelta) + assert(direction < 8); + + rct_xy16 chosenTile = { + .x = peep->next_x + TileDirectionDelta[direction].x, + .y = peep->next_y + TileDirectionDelta[direction].y + }; + + while (chosenTile.x > 0x1FFF || chosenTile.y > 0x1FFF) { + direction = staff_mechanic_direction_surface(peep); + chosenTile.x = peep->next_x + TileDirectionDelta[direction].x; + chosenTile.y = peep->next_y + TileDirectionDelta[direction].y; + } + + peep->var_78 = direction; + peep->destination_x = chosenTile.x + 16; + peep->destination_y = chosenTile.y + 16; + peep->destination_tolerence = (scenario_rand() & 7) + 2; + + return 0; +} + +/** +* +* rct2: 0x006C050B +*/ +static uint8 staff_direction_path(rct_peep* peep, uint8 validDirections, rct_map_element* pathElement) { + uint8 direction = 0xFF; + uint8 pathDirections = pathElement->properties.path.edges & 0xF; + if (peep->state != PEEP_STATE_ANSWERING && peep->state != PEEP_STATE_HEADING_TO_INSPECTION) { + pathDirections &= validDirections; + } + + if (pathDirections == 0) { + return staff_direction_surface(peep, scenario_rand() & 3); + } + + pathDirections &= ~(1 << (peep->var_78 ^ (1 << 1))); + if (pathDirections == 0) { + pathDirections |= (1 << (peep->var_78 ^ (1 << 1))); + } + + direction = bitscanforward(pathDirections); + pathDirections &= ~(1 << direction); + if (pathDirections == 0) { + return direction; + } + + pathDirections |= (1 << direction); + + direction = scenario_rand() & 3; + for (int i = 0; i < 4; ++i, ++direction) { + direction &= 3; + if (pathDirections & (1 << direction)) + return direction; + } + + // This will never happen as pathDirections will always have a bit set + return direction; +} + +/** + * + * rct2: 0x006C0351 + */ +static int staff_path_finding_misc(rct_peep* peep) { + uint8 validDirections = staff_get_valid_patrol_directions(peep, peep->next_x, peep->next_y); + + uint8 direction = 0xFF; + if (peep->next_var_29 & 0x18) { + direction = staff_direction_surface(peep, scenario_rand() & 3); + } + else { + rct_map_element* pathElement = map_get_path_element_at(peep->next_x / 32, peep->next_y / 32, peep->next_z); + if (pathElement == NULL) + return 1; + + direction = staff_direction_path(peep, validDirections, pathElement); + } + + rct_xy16 chosenTile = { + .x = peep->next_x + TileDirectionDelta[direction].x, + .y = peep->next_y + TileDirectionDelta[direction].y + }; + + while (chosenTile.x > 0x1FFF || chosenTile.y > 0x1FFF) { + direction = staff_direction_surface(peep, scenario_rand() & 3); + chosenTile.x = peep->next_x + TileDirectionDelta[direction].x; + chosenTile.y = peep->next_y + TileDirectionDelta[direction].y; + } + + peep->var_78 = direction; + peep->destination_x = chosenTile.x + 16; + peep->destination_y = chosenTile.y + 16; + peep->destination_tolerence = (scenario_rand() & 7) + 2; + + return 0; +} + +/** + * + * rct2: 0x006C086D + */ +static void staff_entertainer_update_nearby_peeps(rct_peep* peep) { + uint16 spriteIndex; + rct_peep* guest; + + FOR_ALL_GUESTS(spriteIndex, guest) { + if (guest->x == SPRITE_LOCATION_NULL) + continue; + + sint16 z_dist = abs(peep->z - guest->z); + if (z_dist > 48) + continue; + + sint16 x_dist = abs(peep->x - guest->x); + sint16 y_dist = abs(peep->y - guest->y); + + if (x_dist > 96) + continue; + + if (y_dist > 96) + continue; + + if (peep->state == PEEP_STATE_WALKING) { + peep->happiness_growth_rate = min(peep->happiness_growth_rate + 4, 255); + } + else if (peep->state == PEEP_STATE_QUEUING) { + peep->time_in_queue -= 200; + peep->happiness_growth_rate = min(peep->happiness_growth_rate + 3, 255); + } + } +} + +/** + * + * rct2: 0x006C05AE + */ +static int staff_path_finding_entertainer(rct_peep* peep) { + + if (((scenario_rand() & 0xFFFF) <= 0x4000) && + (peep->action == PEEP_ACTION_NONE_1 || peep->action == PEEP_ACTION_NONE_2)) { + + invalidate_sprite_2((rct_sprite*)peep); + + peep->action = scenario_rand() & 1 ? PEEP_ACTION_WAVE_2 : PEEP_ACTION_JOY; + peep->action_frame = 0; + peep->action_sprite_image_offset = 0; + + sub_693B58(peep); + invalidate_sprite_2((rct_sprite*)peep); + staff_entertainer_update_nearby_peeps(peep); + } + + return staff_path_finding_misc(peep); +} + +/** + * + * rct2: 0x006BF926 + */ +int staff_path_finding(rct_peep* peep) { + switch (peep->staff_type) { + case STAFF_TYPE_HANDYMAN: + return staff_path_finding_handyman(peep); + case STAFF_TYPE_MECHANIC: + return staff_path_finding_mechanic(peep); + case STAFF_TYPE_SECURITY: + return staff_path_finding_misc(peep); + case STAFF_TYPE_ENTERTAINER: + return staff_path_finding_entertainer(peep); + + default: + assert(false); + return 0; + } +} diff --git a/src/peep/staff.h b/src/peep/staff.h index 396246edd3..06b5197ca4 100644 --- a/src/peep/staff.h +++ b/src/peep/staff.h @@ -59,11 +59,12 @@ void game_command_set_staff_patrol(int *eax, int *ebx, int *ecx, int *edx, int * void game_command_fire_staff_member(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void staff_reset_modes(); -void update_staff_colour(uint8 staffType, uint16 color); +void update_staff_colour(uint8 staffType, uint16 colour); uint16 hire_new_staff_member(uint8 staffType); void staff_update_greyed_patrol_areas(); -int mechanic_is_location_in_patrol(rct_peep *mechanic, int x, int y); +int staff_is_location_in_patrol(rct_peep *mechanic, int x, int y); +int staff_path_finding(rct_peep* peep); void staff_reset_stats(); bool staff_is_patrol_area_set(int staffIndex, int x, int y); -#endif \ No newline at end of file +#endif diff --git a/src/platform/crash.cpp b/src/platform/crash.cpp new file mode 100644 index 0000000000..0cb686184e --- /dev/null +++ b/src/platform/crash.cpp @@ -0,0 +1,135 @@ +#include +#include "crash.h" + +#ifdef USE_BREAKPAD +#include + +#if defined(__WINDOWS__) + #include + #include + #include +#elif defined(__LINUX__) + #include + #define BREAKPAD_PATH "/tmp" +#else + #error Breakpad support not implemented yet for this platform +#endif + +extern "C" { + #include "../localisation/language.h" + #include "../scenario.h" + #include "platform.h" +} + +#include "../core/Console.hpp" + +#define WSZ(x) L"" x + +static bool OnCrash(const wchar_t * dumpPath, + const wchar_t * miniDumpId, + void * context, + EXCEPTION_POINTERS * exinfo, + MDRawAssertionInfo * assertion, + bool succeeded) +{ + if (!succeeded) + { + constexpr const char * DumpFailedMessage = "Failed to create the dump. Nothing left to do. Please file an issue with OpenRCT2 on Github and provide latest save."; + printf("%s\n", DumpFailedMessage); + MessageBoxA(NULL, DumpFailedMessage, OPENRCT2_NAME, MB_OK | MB_ICONERROR); + return succeeded; + } + + wchar_t dumpFilePath[MAX_PATH]; + wchar_t saveFilePath[MAX_PATH]; + wsprintfW(dumpFilePath, L"%s%s.dmp", dumpPath, miniDumpId); + wsprintfW(saveFilePath, L"%s%s.sv6", dumpPath, miniDumpId); + + wprintf(L"Dump Path: %s\n", dumpFilePath); + wprintf(L"Dump Id: %s\n", miniDumpId); + wprintf(L"Version: %s\n", WSZ(OPENRCT2_VERSION)); + wprintf(L"Commit: %s\n", WSZ(OPENRCT2_COMMIT_SHA1_SHORT)); + + utf8 * saveFilePathUTF8 = widechar_to_utf8(saveFilePath); + SDL_RWops * rw = SDL_RWFromFile(saveFilePathUTF8, "wb+"); + free(saveFilePathUTF8); + + bool savedGameDumped = false; + if (rw != NULL) { + scenario_save(rw, 0x80000000); + savedGameDumped = true; + SDL_RWclose(rw); + } + + constexpr const wchar_t * MessageFormat = L"A crash has occurred and dump was created at\n%s.\n\nPlease create an issue with OpenRCT2 on Github and provide the dump and save.\n\nVersion: %s\nCommit: %s"; + wchar_t message[MAX_PATH * 2]; + swprintf_s(message, + MessageFormat, + dumpFilePath, + WSZ(OPENRCT2_VERSION), + WSZ(OPENRCT2_COMMIT_SHA1_SHORT)); + + // Cannot use platform_show_messagebox here, it tries to set parent window already dead. + MessageBoxW(NULL, message, WSZ(OPENRCT2_NAME), MB_OK | MB_ICONERROR); + HRESULT coInitializeResult = CoInitialize(NULL); + if (SUCCEEDED(coInitializeResult)) + { + ITEMIDLIST * pidl = ILCreateFromPathW(dumpPath); + ITEMIDLIST * files[2]; + uint32 numFiles = 0; + + files[numFiles++] = ILCreateFromPathW(dumpFilePath); + if (savedGameDumped) + { + files[numFiles++] = ILCreateFromPathW(saveFilePath); + } + if (pidl != nullptr) { + HRESULT result = SHOpenFolderAndSelectItems(pidl, numFiles, (LPCITEMIDLIST *)files, 0); + ILFree(pidl); + for (uint32 i = 0; i < numFiles; i++) + { + ILFree(files[i]); + } + } + CoUninitialize(); + } + + // Return whether the dump was successful + return succeeded; +} + +static std::wstring GetDumpDirectory() +{ + char userDirectory[MAX_PATH]; + platform_get_user_directory(userDirectory, NULL); + + wchar_t * userDirectoryW = utf8_to_widechar(userDirectory); + auto result = std::wstring(userDirectoryW); + free(userDirectoryW); + + return result; +} + +#endif // USE_BREAKPAD + +// Using non-null pipe name here lets breakpad try setting OOP crash handling +constexpr const wchar_t * PipeName = L"openrct2-bpad"; + +extern "C" CExceptionHandler crash_init() +{ +#ifdef USE_BREAKPAD + // Path must exist and be RW! + auto exHandler = new google_breakpad::ExceptionHandler( + GetDumpDirectory(), + 0, + OnCrash, + 0, + google_breakpad::ExceptionHandler::HANDLER_ALL, + MiniDumpWithDataSegs, + PipeName, + 0); + return reinterpret_cast(exHandler); +#else // USE_BREAKPAD + return nullptr; +#endif // USE_BREAKPAD +} diff --git a/src/platform/crash.h b/src/platform/crash.h new file mode 100644 index 0000000000..35c0d1f74b --- /dev/null +++ b/src/platform/crash.h @@ -0,0 +1,15 @@ +#ifndef _OPENRCT2_CRASH_ +#define _OPENRCT2_CRASH_ + +typedef void * CExceptionHandler; + +#ifdef __cplusplus +extern "C" +{ +#endif + CExceptionHandler crash_init(); +#ifdef __cplusplus +} +#endif + +#endif /* _OPENRCT2_CRASH_ */ diff --git a/src/platform/linux.c b/src/platform/linux.c index 7f9dcca4d3..994610c648 100644 --- a/src/platform/linux.c +++ b/src/platform/linux.c @@ -18,10 +18,19 @@ * along with this program. If not, see . *****************************************************************************/ -#if defined(__linux__) +#include "../common.h" -#include "platform.h" +#ifdef __LINUX__ + +#include #include +#include +#include + +#include "../localisation/language.h" +#include "../localisation/string_ids.h" +#include "../util/util.h" +#include "platform.h" // See http://syprog.blogspot.ru/2011/12/listing-loaded-shared-objects-in-linux.html struct lmap { @@ -36,6 +45,30 @@ struct dummy { struct dummy* ptr; }; +typedef enum { DT_NONE, DT_KDIALOG, DT_ZENITY } dialog_type; + +void platform_get_exe_path(utf8 *outPath) +{ + char exePath[MAX_PATH]; + ssize_t bytesRead; + bytesRead = readlink("/proc/self/exe", exePath, MAX_PATH); + if (bytesRead == -1) { + log_fatal("failed to read /proc/self/exe"); + } + exePath[bytesRead - 1] = '\0'; + char *exeDelimiter = strrchr(exePath, platform_get_path_separator()); + if (exeDelimiter == NULL) + { + log_error("should never happen here"); + outPath[0] = '\0'; + return; + } + int exeDelimiterIndex = (int)(exeDelimiter - exePath); + + exePath[exeDelimiterIndex] = '\0'; + safe_strcpy(outPath, exePath, exeDelimiterIndex + 1); +} + bool platform_check_steam_overlay_attached() { void* processHandle = dlopen(NULL, RTLD_NOW); @@ -56,4 +89,383 @@ bool platform_check_steam_overlay_attached() { return false; } +/** + * Default directory fallback is: + * - (command line argument) + * - $XDG_CONFIG_HOME/OpenRCT2 + * - /home/[uid]/.config/OpenRCT2 + */ +void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const char *separator) { + const char *configdir = getenv("XDG_CONFIG_HOME"); + log_verbose("configdir = '%s'", configdir); + if (configdir == NULL) + { + log_verbose("configdir was null, used getuid, now is = '%s'", homedir); + if (homedir == NULL) + { + log_fatal("Couldn't find user data directory"); + exit(-1); + return; + } + + strncat(buffer, homedir, MAX_PATH - 1); + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, ".config", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + } + else + { + strncat(buffer, configdir, MAX_PATH - 1); + } + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, "OpenRCT2", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); +} + +/** + * Default directory fallback is: + * - (command line argument) + * - /data + * - /usr/local/share/openrct2 + * - /var/lib/openrct2 + * - /usr/share/openrct2 + */ +void platform_posix_sub_resolve_openrct_data_path(utf8 *out) { + static const utf8 *searchLocations[] = { + "../share/openrct2", +#ifdef ORCT2_RESOURCE_DIR + // defined in CMakeLists.txt + ORCT2_RESOURCE_DIR, +#endif // ORCT2_RESOURCE_DIR + "/usr/local/share/openrct2", + "/var/lib/openrct2", + "/usr/share/openrct2", + }; + for (size_t i = 0; i < countof(searchLocations); i++) + { + log_verbose("Looking for OpenRCT2 data in %s", searchLocations[i]); + if (platform_directory_exists(searchLocations[i])) + { + out[0] = '\0'; + safe_strcpy(out, searchLocations[i], MAX_PATH); + return; + } + } +} + + +void execute_cmd(char *command, int *exit_value, char *buf, size_t *buf_size) { + FILE *f; + size_t n_chars; + + log_verbose("executing \"%s\"...\n", command); + f = popen(command, "r"); + + if (buf && buf_size) { + n_chars = fread(buf, 1, *buf_size, f); + + // some commands may return a new-line terminated result, trim that… + if (n_chars > 0 && buf[n_chars - 1] == '\n') { + buf[n_chars - 1] = '\0'; + } + // make sure string is null-terminated + if (n_chars == *buf_size) { + n_chars--; + } + buf[n_chars] = '\0'; + + // account for null terminator + *buf_size = n_chars + 1; + } else { + fflush(f); + } + + if (exit_value) + *exit_value = pclose(f); + else + pclose(f); +} + +dialog_type get_dialog_app(char *cmd, size_t *cmd_size) { + int exit_value; + size_t size; + dialog_type dtype; + + /* + * prefer zenity as it offers more required features, e.g., overwrite + * confirmation and selecting only existing files + */ + + dtype = DT_ZENITY; + size = *cmd_size; + execute_cmd("which zenity", &exit_value, cmd, &size); + + if (exit_value != 0) { + dtype = DT_KDIALOG; + size = *cmd_size; + execute_cmd("which kdialog", &exit_value, cmd, &size); + + if (exit_value != 0) { + log_error("no dialog (zenity or kdialog) found\n"); + return DT_NONE; + } + } + + cmd[size-1] = '\0'; + + *cmd_size = size; + + return dtype; +} + +bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc) { + int exit_value; + char executable[MAX_PATH]; + char cmd[MAX_PATH]; + char result[MAX_PATH]; + size_t size; + dialog_type dtype; + char *action; + char *flags; + char filter[MAX_PATH] = { 0 }; + char filterPatternRegex[64]; + char *allFilesPatternDescription; + int allFilesPatternLength = 0; + + size = MAX_PATH; + dtype = get_dialog_app(executable, &size); + + switch (dtype) { + case DT_KDIALOG: + switch (desc->type) { + case FD_OPEN: + action = "--getopenfilename"; + break; + case FD_SAVE: + action = "--getsavefilename"; + break; + } + + { + bool first = true; + for (int j = 0; j < countof(desc->filters); j++) { + if (desc->filters[j].pattern && desc->filters[j].name) { + char filterTemp[100] = { 0 }; + if (first) { + snprintf(filterTemp, countof(filterTemp), "%s | %s", desc->filters[j].pattern, desc->filters[j].name); + first = false; + } else { + snprintf(filterTemp, countof(filterTemp), "\\n%s | %s", desc->filters[j].pattern, desc->filters[j].name); + } + safe_strcat(filter, filterTemp, countof(filter)); + } + } + char filterTemp[100] = { 0 }; + if (first) { + snprintf(filterTemp, countof(filterTemp), "*|%s", (char *)language_get_string(STR_ALL_FILES)); + } else { + snprintf(filterTemp, countof(filterTemp), "\\n*|%s", (char *)language_get_string(STR_ALL_FILES)); + } + safe_strcat(filter, filterTemp, countof(filter)); + + // kdialog wants filters space-delimited and we don't expect ';' anywhere else, + // this is much easier and quicker to do than being overly careful about replacing + // it only where truly needed. + int filterSize = strlen(filter); + for (int i = 0; i < filterSize + 3; i++) { + if (filter[i] == ';') { + filter[i] = ' '; + } + } + } + + snprintf(cmd, MAX_PATH, "%s --title \"%s\" %s ~ \"%s\"", executable, desc->title, action, filter); + break; + case DT_ZENITY: + action = "--file-selection"; + switch (desc->type) { + case FD_SAVE: + flags = "--confirm-overwrite --save"; + break; + case FD_OPEN: + flags = ""; + break; + } + + // Zenity seems to be case sensitive, while Kdialog isn't. + for (int j = 0; j < countof(desc->filters); j++) { + if (desc->filters[j].pattern && desc->filters[j].name) { + int regexIterator = 0; + for(int i = 0; i <= strlen(desc->filters[j].pattern); i++) { + if (isalpha(desc->filters[j].pattern[i])) { + filterPatternRegex[regexIterator+0] = '['; + filterPatternRegex[regexIterator+1] = (char)toupper(desc->filters[j].pattern[i]); + filterPatternRegex[regexIterator+2] = (char)tolower(desc->filters[j].pattern[i]); + filterPatternRegex[regexIterator+3] = ']'; + regexIterator += 3; + } + else if(desc->filters[j].pattern[i] == ';') { + filterPatternRegex[regexIterator] = ' '; + } + else { + filterPatternRegex[regexIterator] = (char)desc->filters[j].pattern[i]; + } + regexIterator++; + } + filterPatternRegex[regexIterator+1] = 0; + + char filterTemp[100] = { 0 }; + snprintf(filterTemp, countof(filterTemp), " --file-filter=\"%s | %s\"", desc->filters[j].name, filterPatternRegex); + safe_strcat(filter, filterTemp, countof(filter)); + } + } + char filterTemp[100] = { 0 }; + snprintf(filterTemp, countof(filterTemp), " --file-filter=\"%s | *\"", (char *)language_get_string(STR_ALL_FILES)); + safe_strcat(filter, filterTemp, countof(filter)); + + snprintf(cmd, MAX_PATH, "%s %s %s --title=\"%s\" / %s", executable, action, flags, desc->title, filter); + break; + default: return 0; + } + + size = MAX_PATH; + execute_cmd(cmd, &exit_value, result, &size); + + if (exit_value != 0) { + return 0; + } + + result[size-1] = '\0'; + log_verbose("filename = %s", result); + + if (desc->type == FD_OPEN && access(result, F_OK) == -1) { + char msg[MAX_PATH]; + + snprintf(msg, MAX_PATH, "\"%s\" not found: %s, please choose another file\n", result, strerror(errno)); + platform_show_messagebox(msg); + + return platform_open_common_file_dialog(outFilename, desc); + } else + if (desc->type == FD_SAVE && access(result, F_OK) != -1 && dtype == DT_KDIALOG) { + snprintf(cmd, MAX_PATH, "%s --yesno \"Overwrite %s?\"", executable, result); + + size = MAX_PATH; + execute_cmd(cmd, &exit_value, 0, 0); + + if (exit_value != 0) { + return 0; + } + } + + strncpy(outFilename, result, MAX_PATH); + + return 1; +} + +utf8 *platform_open_directory_browser(utf8 *title) { + size_t size; + dialog_type dtype; + int exit_value; + char cmd[MAX_PATH]; + char executable[MAX_PATH]; + char result[MAX_PATH]; + char *return_value; + + size = MAX_PATH; + dtype = get_dialog_app(executable, &size); + + switch (dtype) { + case DT_KDIALOG: + snprintf(cmd, MAX_PATH, "%s --title \"%s\" --getexistingdirectory /", executable, title); + break; + case DT_ZENITY: + snprintf(cmd, MAX_PATH, "%s --title=\"%s\" --file-selection --directory /", executable, title); + break; + default: return 0; + } + + size = MAX_PATH; + execute_cmd(cmd, &exit_value, result, &size); + + if (exit_value != 0) { + return NULL; + } + + result[size-1] = '\0'; + + return_value = (char*) malloc(strlen(result)+1); + strcpy(return_value, result); + + return return_value; +} + +void platform_show_messagebox(char *message) { + size_t size; + dialog_type dtype; + int exit_value; + char cmd[MAX_PATH]; + char executable[MAX_PATH]; + + log_verbose(message); + + size = MAX_PATH; + dtype = get_dialog_app(executable, &size); + + switch (dtype) { + case DT_KDIALOG: + snprintf(cmd, MAX_PATH, "%s --title \"OpenRCT2\" --msgbox \"%s\"", executable, message); + break; + case DT_ZENITY: + snprintf(cmd, MAX_PATH, "%s --title=\"OpenRCT2\" --info --text=\"%s\"", executable, message); + break; + default: + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_WARNING, "OpenRCT2", message, gWindow); + return; + } + + size = MAX_PATH; + execute_cmd(cmd, 0, 0, 0); +} + +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) +{ + assert(buffer != NULL); + assert(font != NULL); + + log_verbose("Looking for font %s with FontConfig.", font->font_name); + FcConfig* config = FcInitLoadConfigAndFonts(); + if (!config) + { + log_error("Failed to initialize FontConfig library"); + FcFini(); + return false; + } + FcPattern* pat = FcNameParse((const FcChar8*) font->font_name); + + FcConfigSubstitute(config, pat, FcMatchPattern); + FcDefaultSubstitute(pat); + + bool found = false; + FcResult result = FcResultNoMatch; + FcPattern* match = FcFontMatch(config, pat, &result); + + if (match) + { + FcChar8* filename = NULL; + if (FcPatternGetString(match, FC_FILE, 0, &filename) == FcResultMatch) + { + found = true; + safe_strcpy(buffer, (utf8*) filename, MAX_PATH); + log_verbose("FontConfig provided font %s", filename); + } + FcPatternDestroy(match); + } else { + log_warning("Failed to find required font."); + } + + FcPatternDestroy(pat); + FcConfigDestroy(config); + FcFini(); + return found; +} + #endif diff --git a/src/platform/osx.c b/src/platform/osx.c deleted file mode 100644 index c1928d0f02..0000000000 --- a/src/platform/osx.c +++ /dev/null @@ -1,30 +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 . - *****************************************************************************/ - -#if defined(__APPLE__) && defined(__MACH__) - -#include "platform.h" - -bool platform_check_steam_overlay_attached() { - STUB(); - return false; -} - -#endif diff --git a/src/platform/osx.m b/src/platform/osx.m new file mode 100644 index 0000000000..f09e56b0f4 --- /dev/null +++ b/src/platform/osx.m @@ -0,0 +1,198 @@ +/***************************************************************************** + * 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 . + *****************************************************************************/ + +#if defined(__APPLE__) && defined(__MACH__) + +@import AppKit; +@import Foundation; +#include +#include "platform.h" +#include "../util/util.h" + +bool platform_check_steam_overlay_attached() { + STUB(); + return false; +} + +void platform_get_exe_path(utf8 *outPath) +{ + char exePath[MAX_PATH]; + uint32_t size = MAX_PATH; + int result = _NSGetExecutablePath(exePath, &size); + if (result != 0) { + log_fatal("failed to get path"); + } + exePath[MAX_PATH - 1] = '\0'; + char *exeDelimiter = strrchr(exePath, platform_get_path_separator()); + if (exeDelimiter == NULL) + { + log_error("should never happen here"); + outPath[0] = '\0'; + return; + } + int exeDelimiterIndex = (int)(exeDelimiter - exePath); + + safe_strcpy(outPath, exePath, exeDelimiterIndex + 1); + outPath[exeDelimiterIndex] = '\0'; +} + +/** + * Default directory fallback is: + * - (command line argument) + * - ~/Library/Application Support/OpenRCT2 + */ +void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const char *separator) { + if (homedir == NULL) + { + log_fatal("Couldn't find user data directory"); + exit(-1); + return; + } + + strncat(buffer, homedir, MAX_PATH - 1); + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, "Library", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, "Application Support", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, "OpenRCT2", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); +} + +/** + * Default directory fallback is: + * - (command line argument) + * - /data + * - + */ +void platform_posix_sub_resolve_openrct_data_path(utf8 *out) { + @autoreleasepool + { + NSBundle *bundle = [NSBundle mainBundle]; + if (bundle) + { + const utf8 *resources = bundle.resourcePath.UTF8String; + if (platform_directory_exists(resources)) + { + out[0] = '\0'; + safe_strcpy(out, resources, MAX_PATH); + return; + } + } + } +} + +void platform_show_messagebox(char *message) +{ + @autoreleasepool + { + NSAlert *alert = [[[NSAlert alloc] init] autorelease]; + [alert addButtonWithTitle:@"OK"]; + alert.messageText = [NSString stringWithUTF8String:message]; + alert.alertStyle = NSWarningAlertStyle; + [alert runModal]; + } +} + +utf8 *platform_open_directory_browser(utf8 *title) +{ + @autoreleasepool + { + NSOpenPanel *panel = [NSOpenPanel openPanel]; + panel.canChooseFiles = false; + panel.canChooseDirectories = true; + panel.allowsMultipleSelection = false; + utf8 *url = NULL; + if ([panel runModal] == NSFileHandlingPanelOKButton) + { + NSString *selectedPath = panel.URL.path; + const char *path = selectedPath.UTF8String; + url = (utf8*)malloc(strlen(path) + 1); + strcpy(url,path); + } + return url; + } +} + +bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc) { + @autoreleasepool + { + NSMutableArray *extensions = [NSMutableArray new]; + for (int i=0; i < countof(desc->filters); ++i) { + if (desc->filters[i].pattern != NULL) { + NSString *fp = [NSString stringWithUTF8String:desc->filters[i].pattern]; + fp = [fp stringByReplacingOccurrencesOfString:@"*." withString:@""]; + [extensions addObjectsFromArray:[fp componentsSeparatedByString:@";"]]; + } + } + + NSString *directory; + NSSavePanel *panel; + if (desc->type == FD_SAVE) + { + NSString *filePath = [NSString stringWithUTF8String:desc->default_filename]; + directory = filePath.stringByDeletingLastPathComponent; + NSString *basename = filePath.lastPathComponent; + panel = [NSSavePanel savePanel]; + panel.nameFieldStringValue = [NSString stringWithFormat:@"%@.%@", basename, extensions.firstObject]; + } + else if (desc->type == FD_OPEN) + { + directory = [NSString stringWithUTF8String:desc->initial_directory]; + NSOpenPanel *open = [NSOpenPanel openPanel]; + open.canChooseDirectories = false; + open.canChooseFiles = true; + open.allowsMultipleSelection = false; + panel = open; + } else { + return false; + } + + panel.title = [NSString stringWithUTF8String:desc->title]; + panel.allowedFileTypes = extensions; + panel.directoryURL = [NSURL fileURLWithPath:directory]; + if ([panel runModal] == NSFileHandlingPanelCancelButton){ + SDL_RaiseWindow(gWindow); + return false; + } else { + strcpy(outFilename, panel.URL.path.UTF8String); + SDL_RaiseWindow(gWindow); + return true; + } + } +} + +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) +{ + @autoreleasepool + { + CTFontDescriptorRef fontRef = CTFontDescriptorCreateWithNameAndSize((CFStringRef)[NSString stringWithUTF8String:font->font_name], 0.0); + CFURLRef url = (CFURLRef)CTFontDescriptorCopyAttribute(fontRef, kCTFontURLAttribute); + if (url) { + NSString *fontPath = [NSString stringWithString:[(NSURL *)CFBridgingRelease(url) path]]; + strcpy(buffer, fontPath.UTF8String); + return true; + } else { + return false; + } + } +} + +#endif diff --git a/src/platform/platform.h b/src/platform/platform.h index 085fe0c645..9a82d6cd60 100644 --- a/src/platform/platform.h +++ b/src/platform/platform.h @@ -21,20 +21,31 @@ #ifndef _PLATFORM_H_ #define _PLATFORM_H_ -#ifdef _WIN32 +#include "../common.h" + +#ifdef __WINDOWS__ #define HAVE_MATH_H -#endif // _WIN32 +#endif // __WINDOWS__ #include -#include "../common.h" +#include "../core/textinputbuffer.h" +#include "../drawing/font.h" #ifndef MAX_PATH #define MAX_PATH 260 #endif +#ifdef __MACOSX__ +#define KEYBOARD_PRIMARY_MODIFIER KMOD_GUI +#else +#define KEYBOARD_PRIMARY_MODIFIER KMOD_CTRL +#endif + #define INVALID_HANDLE -1 +#define TOUCH_DOUBLE_TIMEOUT 300 + typedef struct { int width, height; } resolution; @@ -63,6 +74,8 @@ typedef struct { unsigned char left, middle, right, any; int wheel; int old; + bool touch, touchIsDouble; + unsigned int touchDownTimestamp; } openrct2_cursor; enum { @@ -73,13 +86,25 @@ enum { CURSOR_PRESSED = CURSOR_DOWN | CURSOR_CHANGED, }; +typedef enum {FD_OPEN, FD_SAVE} filedialog_type; + +typedef struct { + uint8 type; + const utf8 *title; + const utf8 *initial_directory; + const utf8 *default_filename; + struct { + const utf8 *name; // E.g. "Image Files" + const utf8 *pattern; // E.g. "*.png;*.jpg;*.gif" + } filters[8]; +} file_dialog_desc; + extern openrct2_cursor gCursorState; extern const unsigned char *gKeysState; extern unsigned char *gKeysPressed; extern unsigned int gLastKeyPressed; -extern int gTextInputCursorPosition; -extern int gTextInputLength; +extern textinputbuffer gTextInput; extern bool gTextInputCompositionActive; extern utf8 gTextInputComposition[32]; extern int gTextInputCompositionStart; @@ -90,6 +115,8 @@ extern int gNumResolutions; extern resolution *gResolutions; extern SDL_Window *gWindow; +extern SDL_Color gPalette[256]; + extern bool gHardwareDisplay; extern bool gSteamOverlayActive; @@ -103,7 +130,7 @@ void platform_free(); void platform_trigger_resize(); void platform_update_palette(const uint8 *colours, int start_index, int num_colours); void platform_set_fullscreen_mode(int mode); -void platform_set_cursor(char cursor); +void platform_set_cursor(uint8 cursor); void platform_refresh_video(); void platform_process_messages(); int platform_scancode_to_rct_keycode(int sdl_key); @@ -113,6 +140,8 @@ void platform_get_date(rct2_date *out_date); void platform_get_time(rct2_time *out_time); // Platform specific definitions +void platform_get_exe_path(utf8 *outPath); +const char *platform_get_new_line(); char platform_get_path_separator(); bool platform_file_exists(const utf8 *path); bool platform_directory_exists(const utf8 *path); @@ -140,19 +169,26 @@ void platform_get_cursor_position(int *x, int *y); void platform_set_cursor_position(int x, int y); unsigned int platform_get_ticks(); void platform_resolve_user_data_path(); +void platform_resolve_openrct_data_path(); +void platform_get_openrct_data_path(utf8 *outPath); void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory); +utf8* platform_get_username(); void platform_show_messagebox(utf8 *message); -int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName); +bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc); utf8 *platform_open_directory_browser(utf8 *title); uint8 platform_get_locale_currency(); +uint8 platform_get_currency_value(const char *currencyCode); uint16 platform_get_locale_language(); uint8 platform_get_locale_measurement_format(); uint8 platform_get_locale_temperature_format(); +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer); bool platform_check_steam_overlay_attached(); +datetime64 platform_get_datetime_now_utc(); + // Windows specific definitions -#ifdef _WIN32 +#ifdef __WINDOWS__ #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -160,30 +196,6 @@ bool platform_check_steam_overlay_attached(); int windows_get_registry_install_info(rct2_install_info *installInfo, char *source, char *font, uint8 charset); HWND windows_get_window_handle(); -#endif // _WIN32 - -#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -#include -#define STUB() log_warning("Function %s at %s:%d is a stub.\n", __PRETTY_FUNCTION__, __FILE__, __LINE__) -#define _strcmpi _stricmp -#define _stricmp(x, y) strcasecmp((x), (y)) -#define _strnicmp(x, y, n) strncasecmp((x), (y), (n)) -#define _strdup(x) strdup((x)) - -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define RCT2_ENDIANESS __ORDER_LITTLE_ENDIAN__ -#define LOBYTE(w) ((uint8_t)(w)) -#define HIBYTE(w) ((uint8_t)(((uint16_t)(w)>>8)&0xFF)) -#endif // __BYTE_ORDER__ - -#ifndef RCT2_ENDIANESS -#error Unknown endianess! -#endif // RCT2_ENDIANESS - -#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) - -#if !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) - char *strndup(const char *src, size_t size); -#endif // !(POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) +#endif // __WINDOWS__ #endif diff --git a/src/platform/posix.c b/src/platform/posix.c index 98cffb1bd7..d7984e2b92 100644 --- a/src/platform/posix.c +++ b/src/platform/posix.c @@ -20,27 +20,37 @@ #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) -#include -#include -#include +#include #include +#include +#include +#include +#include +#include #include +#include +#include #include "../addresses.h" -#include "../cmdline.h" -#include "../openrct2.h" -#include "../localisation/language.h" -#include "../localisation/currency.h" #include "../config.h" -#include "platform.h" +#include "../localisation/language.h" +#include "../openrct2.h" #include "../util/util.h" +#include "platform.h" #include #include +#include +#include #include +#include +#include // The name of the mutex used to prevent multiple instances of the game from running -#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX" +#define SINGLE_INSTANCE_MUTEX_NAME "openrct2.lock" + +#define FILE_BUFFER_SIZE 4096 utf8 _userDataDirectoryPath[MAX_PATH] = { 0 }; +utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 }; /** * The function that is called directly from the host application (rct2.exe)'s WinMain. This will be removed when OpenRCT2 can @@ -48,10 +58,6 @@ utf8 _userDataDirectoryPath[MAX_PATH] = { 0 }; */ int main(int argc, const char **argv) { - //RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE) = hInstance; - //RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, LPSTR) = lpCmdLine; - - STUB(); int run_game = cmdline_run(argv, argc); if (run_game == 1) { @@ -92,6 +98,11 @@ char platform_get_path_separator() return '/'; } +const char *platform_get_new_line() +{ + return "\n"; +} + bool platform_file_exists(const utf8 *path) { wchar_t *wPath = utf8_to_widechar(path); @@ -101,7 +112,7 @@ bool platform_file_exists(const utf8 *path) buffer[len] = '\0'; free(wPath); bool exists = access(buffer, F_OK) != -1; - log_warning("file '%s' exists = %i", buffer, exists); + log_verbose("file '%s' exists = %i", buffer, exists); return exists; } @@ -148,10 +159,10 @@ bool platform_ensure_directory_exists(const utf8 *path) mode_t mask = getumask(); wchar_t *wPath = utf8_to_widechar(path); - int len = min(MAX_PATH, utf8_length(path)); + int len = min(MAX_PATH - 1, utf8_length(path)); char buffer[MAX_PATH]; wcstombs(buffer, wPath, len); - buffer[len - 1] = '\0'; + buffer[len] = '\0'; free(wPath); log_verbose("%s", buffer); const int result = mkdir(buffer, mask); @@ -162,13 +173,85 @@ bool platform_ensure_directory_exists(const utf8 *path) bool platform_directory_delete(const utf8 *path) { - STUB(); + log_verbose("Recursively deleting directory %s", path); + + FTS *ftsp; + FTSENT *p, *chp; + + // fts_open only accepts non const paths, so we have to take a copy + char* ourPath = (char*)malloc(strlen(path) + 1); + strcpy(ourPath, path); + + utf8* const patharray[2] = {ourPath, NULL}; + if ((ftsp = fts_open(patharray, FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOCHDIR, NULL)) == NULL) { + log_error("fts_open returned NULL"); + free(ourPath); + return false; + } + + chp = fts_children(ftsp, 0); + if (chp == NULL) { + log_verbose("No files to traverse, deleting directory %s", path); + if (remove(path) != 0) + { + log_error("Failed to remove %s, errno = %d", path, errno); + } + free(ourPath); + return true; // No files to traverse + } + + while ((p = fts_read(ftsp)) != NULL) { + switch (p->fts_info) { + case FTS_DP: // Directory postorder, which means + // the directory is empty + + case FTS_F: // File + if(remove(p->fts_path)) { + log_error("Could not remove %s", p->fts_path); + fts_close(ftsp); + free(ourPath); + return false; + } + break; + case FTS_ERR: + log_error("Error traversing %s", path); + fts_close(ftsp); + free(ourPath); + return false; + } + } + + free(ourPath); + fts_close(ftsp); + return true; } bool platform_lock_single_instance() { - STUB(); + char pidFilePath[MAX_PATH]; + + safe_strcpy(pidFilePath, _userDataDirectoryPath, sizeof(pidFilePath)); + safe_strcat_path(pidFilePath, SINGLE_INSTANCE_MUTEX_NAME, sizeof(pidFilePath)); + + // We will never close this file manually. The operating system will + // take care of that, because flock keeps the lock as long as the + // file is open and closes it automatically on file close. + // This is intentional. + int pidFile = open(pidFilePath, O_CREAT | O_RDWR, 0666); + + if (pidFile == -1) { + log_warning("Cannot open lock file for writing."); + return false; + } + if (flock(pidFile, LOCK_EX | LOCK_NB) == -1) { + if (errno == EWOULDBLOCK) { + log_warning("Another OpenRCT2 session has been found running."); + return false; + } + log_error("flock returned an uncatched errno: %d", errno); + return false; + } return true; } @@ -200,7 +283,7 @@ static int winfilter(const struct dirent *d) } name_upper[entry_length] = '\0'; bool match = fnmatch(g_file_pattern, name_upper, FNM_PATHNAME) == 0; - //log_warning("trying matching filename %s, result = %d", name_upper, match); + //log_verbose("trying matching filename %s, result = %d", name_upper, match); free(name_upper); return match; } @@ -217,7 +300,7 @@ int platform_enumerate_files_begin(const utf8 *pattern) if (converted == MAX_PATH) { log_warning("truncated string %s", npattern); } - log_warning("begin file search, pattern: %s", npattern); + log_verbose("begin file search, pattern: %s", npattern); char *file_name = strrchr(npattern, platform_get_path_separator()); char *dir_name; @@ -237,18 +320,18 @@ int platform_enumerate_files_begin(const utf8 *pattern) { g_file_pattern[j] = (char)toupper(g_file_pattern[j]); } - log_warning("looking for file matching %s", g_file_pattern); + log_verbose("looking for file matching %s", g_file_pattern); int cnt; for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { - safe_strncpy(enumFileInfo->pattern, npattern, sizeof(enumFileInfo->pattern)); + safe_strcpy(enumFileInfo->pattern, npattern, sizeof(enumFileInfo->pattern)); cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort); if (cnt < 0) { break; } - log_warning("found %d files matching in dir '%s'", cnt, dir_name); + log_verbose("found %d files matching in dir '%s'", cnt, dir_name); enumFileInfo->cnt = cnt; enumFileInfo->paths = malloc(cnt * sizeof(char *)); char **paths = enumFileInfo->paths; @@ -351,7 +434,7 @@ static int dirfilter(const struct dirent *d) return 0; } #if defined(_DIRENT_HAVE_D_TYPE) || defined(DT_UNKNOWN) - if (d->d_type == DT_DIR) + if (d->d_type == DT_DIR || d->d_type == DT_LNK) { return 1; } else { @@ -370,11 +453,11 @@ int platform_enumerate_directories_begin(const utf8 *directory) char *npattern = malloc(length+1); int converted; converted = wcstombs(npattern, wpattern, length); - npattern[length] = '\0'; + npattern[length - 1] = '\0'; if (converted == MAX_PATH) { log_warning("truncated string %s", npattern); } - log_warning("begin directory listing, path: %s", npattern); + log_verbose("begin directory listing, path: %s", npattern); // TODO: add some checking for stringness and directoryness @@ -382,13 +465,13 @@ int platform_enumerate_directories_begin(const utf8 *directory) for (int i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; if (!enumFileInfo->active) { - safe_strncpy(enumFileInfo->pattern, npattern, length); + safe_strcpy(enumFileInfo->pattern, npattern, length); cnt = scandir(npattern, &enumFileInfo->fileListTemp, dirfilter, alphasort); if (cnt < 0) { break; } - log_warning("found %d files in dir '%s'", cnt, npattern); + log_verbose("found %d files in dir '%s'", cnt, npattern); enumFileInfo->cnt = cnt; enumFileInfo->paths = malloc(cnt * sizeof(char *)); char **paths = enumFileInfo->paths; @@ -451,7 +534,7 @@ bool platform_enumerate_directories_next(int handle, utf8 *path) return false; } // so very, very wrong - safe_strncpy(path, basename(fileName), MAX_PATH); + safe_strcpy(path, basename(fileName), MAX_PATH); strncat(path, "/", MAX_PATH - strlen(path) - 1); return true; } else { @@ -480,29 +563,64 @@ void platform_enumerate_directories_end(int handle) } int platform_get_drives(){ - /* - return GetLogicalDrives(); - */ - STUB(); + // POSIX systems do not know drives. Return 0. return 0; } bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite) { - STUB(); + log_verbose("Copying %s to %s", srcPath, dstPath); + + FILE *dstFile; + + if (overwrite) { + dstFile = fopen(dstPath, "wb"); + } else { + // Portability note: check your libc's support for "wbx" + dstFile = fopen(dstPath, "wbx"); + } + + if (dstFile == NULL) { + if (errno == EEXIST) { + log_warning("platform_file_copy: Not overwriting %s, because overwrite flag == false", dstPath); + return 0; + } + + log_error("Could not open destination file %s for copying", dstPath); + return 0; + } + + // Open both files and check whether they are opened correctly + FILE *srcFile = fopen(srcPath, "rb"); + if (srcFile == NULL) { + fclose(dstFile); + log_error("Could not open source file %s for copying", srcPath); + return 0; + } + + size_t amount_read = 0; + + char* buffer = (char*) malloc(FILE_BUFFER_SIZE); + while ((amount_read = fread(buffer, FILE_BUFFER_SIZE, 1, srcFile))) { + fwrite(buffer, amount_read, 1, dstFile); + } + + fclose(srcFile); + fclose(dstFile); + free(buffer); + return 0; } bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath) { - STUB(); - return 0; + return rename(srcPath, dstPath) == 0; } 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) @@ -528,18 +646,22 @@ wchar_t *regular_to_wchar(const char* src) return w_buffer; } +void platform_posix_sub_user_data_path(char *buffer, const char *homedir, const char *separator); + /** * Default directory fallback is: * - (command line argument) - * - $XDG_CONFIG_HOME/OpenRCT2 - * - /home/[uid]/.config/OpenRCT2 + * - */ void platform_resolve_user_data_path() { const char separator[2] = { platform_get_path_separator(), 0 }; if (gCustomUserDataPath[0] != 0) { - realpath(gCustomUserDataPath, _userDataDirectoryPath); + if (realpath(gCustomUserDataPath, _userDataDirectoryPath) == NULL) { + log_error("Could not resolve path \"%s\"", gCustomUserDataPath); + return; + } // Ensure path ends with separator int len = strlen(_userDataDirectoryPath); @@ -552,45 +674,74 @@ void platform_resolve_user_data_path() char buffer[MAX_PATH]; buffer[0] = '\0'; log_verbose("buffer = '%s'", buffer); - const char *homedir = getenv("XDG_CONFIG_HOME"); - log_verbose("homedir = '%s'", homedir); - if (homedir == NULL) - { - homedir = getpwuid(getuid())->pw_dir; - log_verbose("homedir was null, used getuid, now is = '%s'", homedir); - if (homedir == NULL) - { - log_fatal("Couldn't find user data directory"); - exit(-1); - return; - } - strncat(buffer, homedir, MAX_PATH - 1); - strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); - strncat(buffer, ".config", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); - } - else - { - strncat(buffer, homedir, MAX_PATH - 1); - } - strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); - strncat(buffer, "OpenRCT2", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); - strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + const char *homedir = getpwuid(getuid())->pw_dir; + platform_posix_sub_user_data_path(buffer, homedir, separator); + log_verbose("OpenRCT2 user data directory = '%s'", buffer); int len = strnlen(buffer, MAX_PATH); wchar_t *w_buffer = regular_to_wchar(buffer); w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); - safe_strncpy(_userDataDirectoryPath, path, MAX_PATH); + safe_strcpy(_userDataDirectoryPath, path, MAX_PATH); free(path); } +void platform_get_openrct_data_path(utf8 *outPath) +{ + safe_strcpy(outPath, _openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath)); +} + +void platform_posix_sub_resolve_openrct_data_path(utf8 *out); + +/** + * Default directory fallback is: + * - (command line argument) + * - /data + * - + */ +void platform_resolve_openrct_data_path() +{ + const char separator[2] = { platform_get_path_separator(), 0 }; + + if (gCustomOpenrctDataPath[0] != 0) { + if (realpath(gCustomOpenrctDataPath, _openrctDataDirectoryPath)) { + log_error("Could not resolve path \"%s\"", gCustomUserDataPath); + return; + } + + // Ensure path ends with separator + int len = strlen(_openrctDataDirectoryPath); + if (_openrctDataDirectoryPath[len - 1] != separator[0]) { + strncat(_openrctDataDirectoryPath, separator, MAX_PATH - 1); + } + return; + } + + char buffer[MAX_PATH] = { 0 }; + platform_get_exe_path(buffer); + + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + log_verbose("Looking for OpenRCT2 data in %s", buffer); + if (platform_directory_exists(buffer)) + { + _openrctDataDirectoryPath[0] = '\0'; + safe_strcpy(_openrctDataDirectoryPath, buffer, MAX_PATH); + log_verbose("Found OpenRCT2 data in %s", _openrctDataDirectoryPath); + return; + } + + platform_posix_sub_resolve_openrct_data_path(_openrctDataDirectoryPath); + log_verbose("Trying to use OpenRCT2 data in %s", _openrctDataDirectoryPath); +} + void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory) { const char separator[2] = { platform_get_path_separator(), 0 }; char buffer[MAX_PATH]; - safe_strncpy(buffer, _userDataDirectoryPath, sizeof(buffer)); + safe_strcpy(buffer, _userDataDirectoryPath, sizeof(buffer)); if (subDirectory != NULL && subDirectory[0] != 0) { log_verbose("adding subDirectory '%s'", subDirectory); strncat(buffer, subDirectory, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); @@ -601,79 +752,64 @@ void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory) w_buffer[len] = '\0'; utf8 *path = widechar_to_utf8(w_buffer); free(w_buffer); - safe_strncpy(outPath, path, MAX_PATH); + safe_strcpy(outPath, path, MAX_PATH); free(path); log_verbose("outPath + subDirectory = '%s'", buffer); } -void platform_show_messagebox(char *message) -{ - STUB(); - log_warning(message); -} - -/** - * - * rct2: 0x004080EA - */ -int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName) -{ - STUB(); - return 0; -} - -utf8 *platform_open_directory_browser(utf8 *title) -{ - STUB(); - return NULL; -} - uint16 platform_get_locale_language(){ - /* - CHAR langCode[4]; + const char *langString = setlocale(LC_MESSAGES, ""); + if(langString != NULL){ + // The locale has the following form: + // language[_territory[.codeset]][@modifier] (see https://www.gnu.org/software/libc/manual/html_node/Locale-Names.html) + char pattern[32]; // longest on my system is 29 with codeset and modifier, so 32 for the pattern should be more than enough + //strip the codeset and modifier part + int length = strlen(langString); + { + for(int i = 0; i < length; ++i){ + if(langString[i] == '.' || langString[i] == '@'){ + length = i; + break; + } + } + } //end strip + strncpy(pattern,langString, length); //copy all until first '.' or '@' + pattern[length] = '\0'; + //find _ if present + const char *strip = strchr(pattern, '_'); + if(strip != NULL){ + pattern[strip - pattern] = '?'; // could also use '-', but '?' is more flexible. Maybe LanguagesDescriptors will change. pattern is now "language?territory" + } - if (GetLocaleInfo(LOCALE_USER_DEFAULT, - LOCALE_SABBREVLANGNAME, - (LPSTR)&langCode, - sizeof(langCode)) == 0){ - return LANGUAGE_UNDEFINED; - } + // Iterate through all available languages + for(int i = 1; i < LANGUAGE_COUNT; ++i){ + if(!fnmatch(pattern, LanguagesDescriptors[i].locale, 0)){ + return i; + } + } - if (strcmp(langCode, "ENG") == 0){ - return LANGUAGE_ENGLISH_UK; + //special cases :( + if(!fnmatch(pattern, "en_CA", 0)){ + return LANGUAGE_ENGLISH_US; + } + else if (!fnmatch(pattern, "zh_CN", 0)){ + return LANGUAGE_CHINESE_SIMPLIFIED; + } + else if (!fnmatch(pattern, "zh_TW", 0)){ + return LANGUAGE_CHINESE_TRADITIONAL; + } + + //no exact match found trying only language part + if(strip != NULL){ + pattern[strip - pattern] = '*'; + pattern[strip - pattern +1] = '\0'; // pattern is now "language*" + for(int i = 1; i < LANGUAGE_COUNT; ++i){ + if(!fnmatch(pattern, LanguagesDescriptors[i].locale, 0)){ + return i; + } + } + } } - else if (strcmp(langCode, "ENU") == 0){ - return LANGUAGE_ENGLISH_US; - } - else if (strcmp(langCode, "DEU") == 0){ - return LANGUAGE_GERMAN; - } - else if (strcmp(langCode, "NLD") == 0){ - return LANGUAGE_DUTCH; - } - else if (strcmp(langCode, "FRA") == 0){ - return LANGUAGE_FRENCH; - } - else if (strcmp(langCode, "HUN") == 0){ - return LANGUAGE_HUNGARIAN; - } - else if (strcmp(langCode, "PLK") == 0){ - return LANGUAGE_POLISH; - } - else if (strcmp(langCode, "ESP") == 0){ - return LANGUAGE_SPANISH; - } - else if (strcmp(langCode, "SVE") == 0){ - return LANGUAGE_SWEDISH; - } - else if (strcmp(langCode, "ITA") == 0){ - return LANGUAGE_ITALIAN; - } - else if (strcmp(langCode, "POR") == 0){ - return LANGUAGE_PORTUGUESE_BR; - } - */ - STUB(); return LANGUAGE_ENGLISH_UK; } @@ -686,90 +822,74 @@ time_t platform_file_get_modified_time(const utf8* path){ } uint8 platform_get_locale_currency(){ - /* - CHAR currCode[4]; + char *langstring = setlocale(LC_MONETARY, ""); - if (GetLocaleInfo(LOCALE_USER_DEFAULT, - LOCALE_SINTLSYMBOL, - (LPSTR)&currCode, - sizeof(currCode)) == 0){ - return CURRENCY_POUNDS; + if (langstring == NULL) { + return platform_get_currency_value(NULL); } - if (strcmp(currCode, "GBP") == 0){ - return CURRENCY_POUNDS; - } - else if (strcmp(currCode, "USD") == 0){ - return CURRENCY_DOLLARS; - } - else if (strcmp(currCode, "EUR") == 0){ - return CURRENCY_EUROS; - } - else if (strcmp(currCode, "SEK") == 0){ - return CURRENCY_KRONA; - } - else if (strcmp(currCode, "DEM") == 0){ - return CURRENCY_DEUTSCHMARK; - } - else if (strcmp(currCode, "ITL") == 0){ - return CURRENCY_LIRA; - } - else if (strcmp(currCode, "JPY") == 0){ - return CURRENCY_YEN; - } - else if (strcmp(currCode, "ESP") == 0){ - return CURRENCY_PESETA; - } - else if (strcmp(currCode, "FRF") == 0){ - return CURRENCY_FRANC; - } - else if (strcmp(currCode, "NLG") == 0){ - return CURRENCY_GUILDERS; - } - */ - STUB(); - return CURRENCY_POUNDS; + + struct lconv *lc = localeconv(); + + return platform_get_currency_value(lc->int_curr_symbol); } uint8 platform_get_locale_measurement_format(){ - /* - UINT measurement_system; - if (GetLocaleInfo(LOCALE_USER_DEFAULT, - LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, - (LPSTR)&measurement_system, - sizeof(measurement_system)) == 0){ - return MEASUREMENT_FORMAT_IMPERIAL; + // LC_MEASUREMENT is GNU specific. + #ifdef LC_MEASUREMENT + const char *langstring = setlocale(LC_MEASUREMENT, ""); + #else + const char *langstring = setlocale(LC_ALL, ""); + #endif + + if(langstring != NULL){ + //using https://en.wikipedia.org/wiki/Metrication#Chronology_and_status_of_conversion_by_country as reference + if(!fnmatch("*_US*", langstring, 0) || !fnmatch("*_MM*", langstring, 0) || !fnmatch("*_LR*", langstring, 0)){ + return MEASUREMENT_FORMAT_IMPERIAL; + } } - switch (measurement_system){ - case 0: - return MEASUREMENT_FORMAT_METRIC; - case 1: - default: - return MEASUREMENT_FORMAT_IMPERIAL; - }*/ - STUB(); return MEASUREMENT_FORMAT_METRIC; } uint8 platform_get_locale_temperature_format(){ - /* - // There does not seem to be a function to obtain this, just check the countries - UINT country; - if (GetLocaleInfo(LOCALE_USER_DEFAULT, - LOCALE_IMEASURE | LOCALE_RETURN_NUMBER, - (LPSTR)&country, - sizeof(country)) == 0){ - return TEMPERATURE_FORMAT_C; + // LC_MEASUREMENT is GNU specific. + #ifdef LC_MEASUREMENT + const char *langstring = setlocale(LC_MEASUREMENT, ""); + #else + const char *langstring = setlocale(LC_ALL, ""); + #endif + + if(langstring != NULL){ + if(!fnmatch("*_US*", langstring, 0) || !fnmatch("*_BS*", langstring, 0) || !fnmatch("*_BZ*", langstring, 0) || !fnmatch("*_PW*", langstring, 0)){ + return TEMPERATURE_FORMAT_F; + } } - switch (country){ - case CTRY_UNITED_STATES: - case CTRY_BELIZE: - return TEMPERATURE_FORMAT_F; - default: - return TEMPERATURE_FORMAT_C; - } - */ - STUB(); 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; +} + +utf8* platform_get_username() { + struct passwd* pw = getpwuid(getuid()); + + if (pw) { + return pw->pw_name; + } else { + return NULL; + } +} + #endif diff --git a/src/platform/shared.c b/src/platform/shared.c index ae34b6385e..8749755954 100644 --- a/src/platform/shared.c +++ b/src/platform/shared.c @@ -29,6 +29,7 @@ #include "../interface/keyboard_shortcut.h" #include "../interface/window.h" #include "../input.h" +#include "../localisation/currency.h" #include "../localisation/localisation.h" #include "../openrct2.h" #include "../title.h" @@ -41,10 +42,7 @@ openrct2_cursor gCursorState; const unsigned char *gKeysState; unsigned char *gKeysPressed; unsigned int gLastKeyPressed; -utf8 *gTextInput; -int gTextInputLength; -int gTextInputMaxLength; -int gTextInputCursorPosition = 0; +textinputbuffer gTextInput; bool gTextInputCompositionActive; utf8 gTextInputComposition[32]; @@ -158,7 +156,7 @@ void platform_update_fullscreen_resolutions() void platform_get_closest_resolution(int inWidth, int inHeight, int *outWidth, int *outHeight) { - int i, destinationArea, areaDiff, closestAreaDiff, closestWidth, closestHeight; + int i, destinationArea, areaDiff, closestAreaDiff, closestWidth = 640, closestHeight = 480; closestAreaDiff = -1; destinationArea = inWidth * inHeight; @@ -242,7 +240,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); } } @@ -335,7 +337,7 @@ static void platform_resize(int width, int height) gfx_invalidate_screen(); // Check if the window has been resized in windowed mode and update the config file accordingly - // This is called in rct2_update_2 and is only called after resizing a window has finished + // This is called in rct2_update and is only called after resizing a window has finished const int nonWindowFlags = SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_FULLSCREEN_DESKTOP; if (!(flags & nonWindowFlags)) { @@ -347,8 +349,22 @@ static void platform_resize(int width, int height) } } +/** + * @brief platform_trigger_resize + * Helper function to set various render target features. + * + * Does not get triggered on resize, but rather manually on config changes. + */ void platform_trigger_resize() { + char scale_quality_buffer[4]; // just to make sure we can hold whole uint8 + uint8 scale_quality = gConfigGeneral.scale_quality; + if (gConfigGeneral.use_nn_at_integer_scales && gConfigGeneral.window_scale == floor(gConfigGeneral.window_scale)) { + scale_quality = 0; + } + snprintf(scale_quality_buffer, sizeof(scale_quality_buffer), "%u", scale_quality); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scale_quality_buffer); + int w, h; SDL_GetWindowSize(gWindow, &w, &h); platform_resize(w, h); @@ -426,6 +442,7 @@ void platform_process_messages() gCursorState.middle &= ~CURSOR_CHANGED; gCursorState.right &= ~CURSOR_CHANGED; gCursorState.old = 0; + gCursorState.touch = false; while (SDL_PollEvent(&e)) { switch (e.type) { @@ -442,7 +459,7 @@ void platform_process_messages() SDL_RestoreWindow(gWindow); SDL_MaximizeWindow(gWindow); } - if (SDL_GetWindowFlags(gWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP) { + if ((SDL_GetWindowFlags(gWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { SDL_RestoreWindow(gWindow); SDL_SetWindowFullscreen(gWindow, SDL_WINDOW_FULLSCREEN_DESKTOP); } @@ -450,7 +467,7 @@ void platform_process_messages() if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) platform_resize(e.window.data1, e.window.data2); - if (gConfigSound.audio_focus && gConfigSound.sound) { + if (gConfigSound.audio_focus && gConfigSound.sound_enabled) { if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) { Mixer_SetVolume(1); } @@ -511,6 +528,50 @@ void platform_process_messages() break; } break; +// Apple sends touchscreen events for trackpads, so ignore these events on OS X +#ifndef __MACOSX__ + case SDL_FINGERMOTION: + RCT2_GLOBAL(0x0142406C, int) = (int)(e.tfinger.x * _screenBufferWidth); + RCT2_GLOBAL(0x01424070, int) = (int)(e.tfinger.y * _screenBufferHeight); + + gCursorState.x = (int)(e.tfinger.x * _screenBufferWidth); + gCursorState.y = (int)(e.tfinger.y * _screenBufferHeight); + break; + case SDL_FINGERDOWN: + RCT2_GLOBAL(0x01424318, int) = (int)(e.tfinger.x * _screenBufferWidth); + RCT2_GLOBAL(0x0142431C, int) = (int)(e.tfinger.y * _screenBufferHeight); + + gCursorState.touchIsDouble = (!gCursorState.touchIsDouble + && e.tfinger.timestamp - gCursorState.touchDownTimestamp < TOUCH_DOUBLE_TIMEOUT); + + if (gCursorState.touchIsDouble) { + store_mouse_input(3); + gCursorState.right = CURSOR_PRESSED; + gCursorState.old = 2; + } else { + store_mouse_input(1); + gCursorState.left = CURSOR_PRESSED; + gCursorState.old = 1; + } + gCursorState.touch = true; + gCursorState.touchDownTimestamp = e.tfinger.timestamp; + break; + case SDL_FINGERUP: + RCT2_GLOBAL(0x01424318, int) = (int)(e.tfinger.x * _screenBufferWidth); + RCT2_GLOBAL(0x0142431C, int) = (int)(e.tfinger.y * _screenBufferHeight); + + if (gCursorState.touchIsDouble) { + store_mouse_input(4); + gCursorState.left = CURSOR_RELEASED; + gCursorState.old = 4; + } else { + store_mouse_input(2); + gCursorState.left = CURSOR_RELEASED; + gCursorState.old = 3; + } + gCursorState.touch = true; + break; +#endif case SDL_KEYDOWN: if (gTextInputCompositionActive) break; @@ -530,85 +591,59 @@ void platform_process_messages() } // Text input + if (gTextInput.buffer == NULL) break; + + // Clear the input on Backspace (Windows/Linux) or Backspace (OS X) + if (e.key.keysym.sym == SDLK_BACKSPACE && (e.key.keysym.mod & KEYBOARD_PRIMARY_MODIFIER)) { + textinputbuffer_clear(&gTextInput); + console_refresh_caret(); + window_update_textbox(); + } // If backspace and we have input text with a cursor position none zero - if (e.key.keysym.sym == SDLK_BACKSPACE && gTextInputLength > 0 && gTextInput != NULL && gTextInputCursorPosition) { - int dstIndex = gTextInputCursorPosition; - do { - if (dstIndex == 0) break; - dstIndex--; - } while (!utf8_is_codepoint_start(&gTextInput[dstIndex])); - int removedCodepointSize = gTextInputCursorPosition - dstIndex; + if (e.key.keysym.sym == SDLK_BACKSPACE) { + if (gTextInput.selection_offset > 0) { + size_t endOffset = gTextInput.selection_offset; + textinputbuffer_cursor_left(&gTextInput); + gTextInput.selection_size = endOffset - gTextInput.selection_offset; + textinputbuffer_remove_selected(&gTextInput); - // When at max length don't shift the data left - // as it would buffer overflow. - if (gTextInputCursorPosition != gTextInputMaxLength) { - memmove(gTextInput + dstIndex, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - dstIndex); + console_refresh_caret(); + window_update_textbox(); } - gTextInput[gTextInputLength - removedCodepointSize] = '\0'; - gTextInputCursorPosition -= removedCodepointSize; - gTextInputLength -= removedCodepointSize; - console_refresh_caret(); - window_update_textbox(); - } - if (e.key.keysym.sym == SDLK_END){ - gTextInputCursorPosition = gTextInputLength; - console_refresh_caret(); } if (e.key.keysym.sym == SDLK_HOME) { - gTextInputCursorPosition = 0; + textinputbuffer_cursor_home(&gTextInput); console_refresh_caret(); } - if (e.key.keysym.sym == SDLK_DELETE && gTextInputLength > 0 && gTextInput != NULL && gTextInputCursorPosition != gTextInputLength) { - int dstIndex = gTextInputCursorPosition; - do { - if (dstIndex == gTextInputLength) break; - dstIndex++; - } while (!utf8_is_codepoint_start(&gTextInput[dstIndex])); - int removedCodepointSize = dstIndex - gTextInputCursorPosition; - - memmove(gTextInput + gTextInputCursorPosition, gTextInput + dstIndex, gTextInputMaxLength - dstIndex); - gTextInput[gTextInputMaxLength - removedCodepointSize] = '\0'; - gTextInputLength -= removedCodepointSize; + if (e.key.keysym.sym == SDLK_END) { + textinputbuffer_cursor_end(&gTextInput); + console_refresh_caret(); + } + if (e.key.keysym.sym == SDLK_DELETE) { + size_t startOffset = gTextInput.selection_offset; + textinputbuffer_cursor_right(&gTextInput); + gTextInput.selection_size = gTextInput.selection_offset - startOffset; + gTextInput.selection_offset = startOffset; + textinputbuffer_remove_selected(&gTextInput); console_refresh_caret(); window_update_textbox(); } - if (e.key.keysym.sym == SDLK_RETURN && gTextInput != NULL) { + if (e.key.keysym.sym == SDLK_RETURN) { window_cancel_textbox(); } - if (e.key.keysym.sym == SDLK_LEFT && gTextInput != NULL) { - do { - if (gTextInputCursorPosition == 0) break; - gTextInputCursorPosition--; - } while (!utf8_is_codepoint_start(&gTextInput[gTextInputCursorPosition])); + if (e.key.keysym.sym == SDLK_LEFT) { + textinputbuffer_cursor_left(&gTextInput); console_refresh_caret(); } - else if (e.key.keysym.sym == SDLK_RIGHT && gTextInput != NULL) { - do { - if (gTextInputCursorPosition == gTextInputLength) break; - gTextInputCursorPosition++; - } while (!utf8_is_codepoint_start(&gTextInput[gTextInputCursorPosition])); + else if (e.key.keysym.sym == SDLK_RIGHT) { + textinputbuffer_cursor_right(&gTextInput); console_refresh_caret(); } - // Checks GUI modifier key for MACs otherwise CTRL key -#ifdef MAC - else if (e.key.keysym.sym == SDLK_v && SDL_GetModState() & KMOD_GUI && gTextInput != NULL) { -#else - else if (e.key.keysym.sym == SDLK_v && SDL_GetModState() & KMOD_CTRL && gTextInput != NULL) { -#endif + else if (e.key.keysym.sym == SDLK_v && (SDL_GetModState() & KEYBOARD_PRIMARY_MODIFIER)) { if (SDL_HasClipboardText()) { utf8 *text = SDL_GetClipboardText(); - for (int i = 0; text[i] != '\0' && gTextInputLength < gTextInputMaxLength; i++) { - // If inserting in center of string make space for new letter - if (gTextInputLength > gTextInputCursorPosition){ - memmove(gTextInput + gTextInputCursorPosition + 1, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - 1); - gTextInput[gTextInputCursorPosition] = text[i]; - gTextInputLength++; - } else { - gTextInput[gTextInputLength++] = text[i]; - } - gTextInputCursorPosition++; - } + textinputbuffer_insert(&gTextInput, text); window_update_textbox(); } } @@ -633,35 +668,33 @@ void platform_process_messages() } break; case SDL_TEXTEDITING: - safe_strncpy(gTextInputComposition, e.edit.text, min(e.edit.length, 32)); + // When inputting Korean characters, `e.edit.length` is always Zero. + safe_strcpy(gTextInputComposition, e.edit.text, min((e.edit.length == 0) ? (strlen(e.edit.text)+1) : e.edit.length, 32)); gTextInputCompositionStart = e.edit.start; gTextInputCompositionLength = e.edit.length; - gTextInputCompositionActive = gTextInputComposition[0] != 0; + gTextInputCompositionActive = ((e.edit.length != 0 || strlen(e.edit.text) != 0) && gTextInputComposition[0] != 0); break; case SDL_TEXTINPUT: - if (gTextInputLength < gTextInputMaxLength && gTextInput){ - // HACK ` will close console, so don't input any text - if (e.text.text[0] == '`' && gConsoleOpen) - break; + // will receive an `SDL_TEXTINPUT` event when a composition is committed. + // so, set gTextInputCompositionActive to false. + gTextInputCompositionActive = false; - utf8 *newText = e.text.text; - int newTextLength = strlen(newText); + if (gTextInput.buffer == NULL) break; - // If inserting in center of string make space for new letter - if (gTextInputLength > gTextInputCursorPosition) { - memmove(gTextInput + gTextInputCursorPosition + newTextLength, gTextInput + gTextInputCursorPosition, gTextInputMaxLength - gTextInputCursorPosition - newTextLength); - memcpy(&gTextInput[gTextInputCursorPosition], newText, newTextLength); - gTextInputLength += newTextLength; - } else { - memcpy(&gTextInput[gTextInputLength], newText, newTextLength); - gTextInputLength += newTextLength; - gTextInput[gTextInputLength] = 0; - } - - gTextInputCursorPosition += newTextLength; - console_refresh_caret(); - window_update_textbox(); + // HACK ` will close console, so don't input any text + if (e.text.text[0] == '`' && gConsoleOpen) { + break; } + + // Entering formatting characters is not allowed + if (utf8_is_format_code(utf8_get_next(e.text.text, NULL))) { + break; + } + + utf8 *newText = e.text.text; + textinputbuffer_insert(&gTextInput, newText); + console_refresh_caret(); + window_update_textbox(); break; default: break; @@ -712,7 +745,6 @@ static void platform_create_window() exit(-1); } - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, 0); SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, gConfigGeneral.minimize_fullscreen_focus_loss ? "1" : "0"); platform_load_cursors(); @@ -735,11 +767,15 @@ static void platform_create_window() gWindow = SDL_CreateWindow( "OpenRCT2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_RESIZABLE ); + if (!gWindow) { log_fatal("SDL_CreateWindow failed %s", SDL_GetError()); exit(-1); } + SDL_SetWindowGrab(gWindow, gConfigGeneral.trap_cursor ? SDL_TRUE : SDL_FALSE); + SDL_SetWindowMinimumSize(gWindow, 720, 480); + // Set the update palette function pointer RCT2_GLOBAL(0x009E2BE4, update_palette_func) = platform_update_palette; @@ -751,6 +787,7 @@ static void platform_create_window() // Check if steam overlay renderer is loaded into the process gSteamOverlayActive = platform_check_steam_overlay_attached(); + platform_trigger_resize(); } int platform_scancode_to_rct_keycode(int sdl_key) @@ -774,23 +811,22 @@ void platform_free() SDL_Quit(); } -void platform_start_text_input(char* buffer, int max_length) +void platform_start_text_input(utf8* buffer, int max_length) { // TODO This doesn't work, and position could be improved to where text entry is SDL_Rect rect = { 10, 10, 100, 100 }; SDL_SetTextInputRect(&rect); SDL_StartTextInput(); - gTextInputMaxLength = max_length - 1; - gTextInput = buffer; - gTextInputCursorPosition = strnlen(gTextInput, max_length); - gTextInputLength = gTextInputCursorPosition; + + textinputbuffer_init(&gTextInput, buffer, max_length); } void platform_stop_text_input() { SDL_StopTextInput(); - gTextInput = NULL; + gTextInput.buffer = NULL; + gTextInputCompositionActive = false; } static void platform_unload_cursors() @@ -828,55 +864,21 @@ void platform_set_fullscreen_mode(int mode) } /** - * This is not quite the same as the below function as we don't want to - * derfererence the cursor before the function. + * This is not quite the same as the below function as we don't want to + * derfererence the cursor before the function. * rct2: 0x0407956 */ -void platform_set_cursor(char cursor) +void platform_set_cursor(uint8 cursor) { RCT2_GLOBAL(RCT2_ADDRESS_CURENT_CURSOR, uint8) = cursor; SDL_SetCursor(_cursors[cursor]); } /** * - * rct2: 0x0068352C + * rct2: 0x0068352C */ static void platform_load_cursors() { - RCT2_GLOBAL(0x14241BC, uint32) = 2; -#ifdef _WIN32 - HINSTANCE hInst = RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x74)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BLANK, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA1)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_UP_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x6D)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_UP_DOWN_ARROW, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x6E)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_POINT, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x70)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ZZZ, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x78)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_DIAGONAL_ARROWS, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x77)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PICKER, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x7C)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_TREE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x83)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FOUNTAIN_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x7F)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_STATUE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x80)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BENCH_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x81)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_CROSS_HAIR, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x82)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_BIN_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x84)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_LAMPPOST_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x85)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FENCE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8A)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_FLOWER_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x89)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PATH_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8B)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_DIG_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8D)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_WATER_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8E)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HOUSE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x8F)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_VOLCANO_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x90)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_WALK_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x91)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_PAINT_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x9E)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_ENTRANCE_DOWN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0x9F)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_OPEN, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA6)); - RCT2_GLOBAL(RCT2_ADDRESS_HCURSOR_HAND_CLOSED, HCURSOR) = LoadCursor(hInst, MAKEINTRESOURCE(0xA5)); -#else - STUB(); -#endif // _WIN32 - _cursors[0] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); _cursors[1] = SDL_CreateCursor(blank_cursor_data, blank_cursor_mask, 32, 32, BLANK_CURSOR_HOTX, BLANK_CURSOR_HOTY); _cursors[2] = SDL_CreateCursor(up_arrow_cursor_data, up_arrow_cursor_mask, 32, 32, UP_ARROW_CURSOR_HOTX, UP_ARROW_CURSOR_HOTY); @@ -905,7 +907,6 @@ static void platform_load_cursors() _cursors[25] = SDL_CreateCursor(hand_open_cursor_data, hand_open_cursor_mask, 32, 32, HAND_OPEN_CURSOR_HOTX, HAND_OPEN_CURSOR_HOTY); _cursors[26] = SDL_CreateCursor(hand_closed_cursor_data, hand_closed_cursor_mask, 32, 32, HAND_CLOSED_CURSOR_HOTX, HAND_CLOSED_CURSOR_HOTY); platform_set_cursor(CURSOR_ARROW); - RCT2_GLOBAL(0x14241BC, uint32) = 0; } void platform_refresh_video() @@ -1025,13 +1026,13 @@ static void platform_refresh_screenbuffer(int width, int height, int pitch) screenDPI->height = height; screenDPI->pitch = _screenBufferPitch - width; - RCT2_GLOBAL(0x009ABDF0, uint8) = 6; - RCT2_GLOBAL(0x009ABDF1, uint8) = 3; + RCT2_GLOBAL(0x009ABDF0, uint8) = 7; + RCT2_GLOBAL(0x009ABDF1, uint8) = 6; RCT2_GLOBAL(0x009ABDF2, uint8) = 1; - RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_WIDTH, uint16) = 64; - RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_HEIGHT, uint16) = 8; - RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32) = (width >> 6) + 1; - RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_ROWS, uint32) = (height >> 3) + 1; + RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_WIDTH, uint16) = 1 << RCT2_GLOBAL(0x009ABDF0, uint8); + RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_HEIGHT, uint16) = 1 << RCT2_GLOBAL(0x009ABDF1, uint8); + RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_COLUMNS, uint32) = (width >> RCT2_GLOBAL(0x009ABDF0, uint8)) + 1; + RCT2_GLOBAL(RCT2_ADDRESS_DIRTY_BLOCK_ROWS, uint32) = (height >> RCT2_GLOBAL(0x009ABDF1, uint8)) + 1; } void platform_hide_cursor() @@ -1058,3 +1059,17 @@ unsigned int platform_get_ticks() { return SDL_GetTicks(); } + +uint8 platform_get_currency_value(const char *currCode) { + if (currCode == NULL || strlen(currCode) < 3) { + return CURRENCY_POUNDS; + } + + for (int currency = 0; currency < CURRENCY_END; ++currency) { + if (strncmp(currCode, CurrencyDescriptors[currency].isoCode, 3) == 0) { + return currency; + } + } + + return CURRENCY_POUNDS; +} diff --git a/src/platform/windows.c b/src/platform/windows.c index 17f96bb738..deb82e5859 100644 --- a/src/platform/windows.c +++ b/src/platform/windows.c @@ -18,18 +18,19 @@ * along with this program. If not, see . *****************************************************************************/ -#ifdef _WIN32 +#include "../common.h" + +#ifdef __WINDOWS__ #include +#include #include #include #include #include #include "../addresses.h" -#include "../cmdline.h" #include "../openrct2.h" #include "../localisation/language.h" -#include "../localisation/currency.h" #include "../util/util.h" #include "../config.h" #include "platform.h" @@ -38,6 +39,7 @@ #define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX" utf8 _userDataDirectoryPath[MAX_PATH] = { 0 }; +utf8 _openrctDataDirectoryPath[MAX_PATH] = { 0 }; utf8 **windows_get_command_line_args(int *outNumArgs); @@ -57,6 +59,11 @@ utf8 **windows_get_command_line_args(int *outNumArgs); // return 0; // } +/* DllMain is already defined in one of static libraries we implicitly depend + * on (libcrypto), which is their bug really, but since we don't do anything in + * here, just comment it out. + */ +#ifndef __MINGW32__ /** * Entry point for when the DLL is loaded. This will be removed when OpenRCT2 can be built as a stand alone application. */ @@ -64,6 +71,7 @@ BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved) { return TRUE; } +#endif // __MINGW32__ /** * The function that is called directly from the host application (rct2.exe)'s WinMain. This will be removed when OpenRCT2 can @@ -87,7 +95,7 @@ __declspec(dllexport) int StartOpenRCT(HINSTANCE hInstance, HINSTANCE hPrevInsta } free(argv); - if (runGame) { + if (runGame == 1) { openrct2_launch(); } @@ -141,6 +149,11 @@ char platform_get_path_separator() return '\\'; } +const char *platform_get_new_line() +{ + return "\r\n"; +} + bool platform_file_exists(const utf8 *path) { wchar_t *wPath = utf8_to_widechar(path); @@ -182,10 +195,10 @@ bool platform_directory_delete(const utf8 *path) wchar_t *wPath = utf8_to_widechar(path); wcsncpy(pszFrom, wPath, MAX_PATH); - free(wPath); // Needs to be double-null terminated for some weird reason pszFrom[wcslen(wPath) + 1] = 0; + free(wPath); SHFILEOPSTRUCTW fileop; fileop.hwnd = NULL; // no status display @@ -255,6 +268,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; @@ -263,18 +318,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; @@ -305,8 +370,10 @@ int platform_enumerate_directories_begin(const utf8 *directory) wchar_t *wDirectory = utf8_to_widechar(directory); - if (wcslen(wDirectory) + 3 >= MAX_PATH) + if (wcslen(wDirectory) + 3 >= MAX_PATH) { + free(wDirectory); return INVALID_HANDLE; + } for (i = 0; i < countof(_enumerateFileInfoList); i++) { enumFileInfo = &_enumerateFileInfoList[i]; @@ -407,6 +474,51 @@ bool platform_file_delete(const utf8 *path) return success == TRUE; } +void platform_resolve_openrct_data_path() +{ + wchar_t wOutPath[MAX_PATH]; + const char separator[2] = { platform_get_path_separator(), 0 }; + + if (gCustomOpenrctDataPath[0] != 0) { + wchar_t *customUserDataPathW = utf8_to_widechar(gCustomOpenrctDataPath); + if (GetFullPathNameW(customUserDataPathW, countof(wOutPath), wOutPath, NULL) == 0) { + log_fatal("Unable to resolve path '%s'.", gCustomOpenrctDataPath); + exit(-1); + } + utf8 *outPathTemp = widechar_to_utf8(wOutPath); + safe_strcpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath)); + free(outPathTemp); + free(customUserDataPathW); + + // Ensure path ends with separator + int len = strlen(_userDataDirectoryPath); + if (_userDataDirectoryPath[len - 1] != separator[0]) { + strcat(_userDataDirectoryPath, separator); + } + return; + } + char buffer[MAX_PATH] = { 0 }; + platform_get_exe_path(buffer); + + strncat(buffer, separator, MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + strncat(buffer, "data", MAX_PATH - strnlen(buffer, MAX_PATH) - 1); + + if (platform_directory_exists(buffer)) + { + _openrctDataDirectoryPath[0] = '\0'; + safe_strcpy(_openrctDataDirectoryPath, buffer, sizeof(_openrctDataDirectoryPath)); + return; + } else { + log_fatal("Unable to resolve openrct data path."); + exit(-1); + } +} + +void platform_get_openrct_data_path(utf8 *outPath) +{ + safe_strcpy(outPath, _openrctDataDirectoryPath, sizeof(_openrctDataDirectoryPath)); +} + /** * Default directory fallback is: * - (command line argument) @@ -424,10 +536,10 @@ void platform_resolve_user_data_path() exit(-1); } utf8 *outPathTemp = widechar_to_utf8(wOutPath); - safe_strncpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath)); + safe_strcpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath)); free(outPathTemp); free(customUserDataPathW); - + // Ensure path ends with separator int len = strlen(_userDataDirectoryPath); if (_userDataDirectoryPath[len - 1] != separator[0]) { @@ -438,7 +550,7 @@ void platform_resolve_user_data_path() if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE, NULL, 0, wOutPath))) { utf8 *outPathTemp = widechar_to_utf8(wOutPath); - safe_strncpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath)); + safe_strcpy(_userDataDirectoryPath, outPathTemp, sizeof(_userDataDirectoryPath)); free(outPathTemp); strcat(_userDataDirectoryPath, separator); @@ -461,7 +573,7 @@ void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory) } } -void platform_show_messagebox(char *message) +void platform_show_messagebox(utf8 *message) { MessageBoxA(windows_get_window_handle(), message, "OpenRCT2", MB_OK); } @@ -470,72 +582,95 @@ void platform_show_messagebox(char *message) * * rct2: 0x004080EA */ -int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName) +bool platform_open_common_file_dialog(utf8 *outFilename, file_dialog_desc *desc) { - wchar_t wctitle[256], wcfilename[MAX_PATH], wcfilterPattern[256], wcfilterName[256]; - wchar_t initialDirectory[MAX_PATH], *dotAddress, *slashAddress; OPENFILENAMEW openFileName; - BOOL result; - int tmp; - DWORD commonFlags; + wchar_t wcFilename[MAX_PATH]; - MultiByteToWideChar(CP_UTF8, 0, title, -1, wctitle, countof(wctitle)); - MultiByteToWideChar(CP_UTF8, 0, filename, -1, wcfilename, countof(wcfilename)); - MultiByteToWideChar(CP_UTF8, 0, filterPattern, -1, wcfilterPattern, countof(wcfilterPattern)); - MultiByteToWideChar(CP_UTF8, 0, filterName, -1, wcfilterName, countof(wcfilterName)); - - // Get directory path from given filename - lstrcpyW(initialDirectory, wcfilename); - dotAddress = wcsrchr(initialDirectory, '.'); - if (dotAddress != NULL) { - slashAddress = wcsrchr(initialDirectory, '\\'); - if (slashAddress < dotAddress) - *(slashAddress + 1) = 0; + // Copy default filename to result filename buffer + if (desc->default_filename == NULL) { + wcFilename[0] = 0; + } else { + wchar_t *wcDefaultFilename = utf8_to_widechar(desc->default_filename); + lstrcpyW(wcFilename, wcDefaultFilename); + free(wcDefaultFilename); } - // Clear filename - if (type != 0) - wcfilename[0] = 0; - // Set open file name options memset(&openFileName, 0, sizeof(OPENFILENAMEW)); openFileName.lStructSize = sizeof(OPENFILENAMEW); openFileName.hwndOwner = windows_get_window_handle(); - openFileName.lpstrFile = wcfilename; openFileName.nMaxFile = MAX_PATH; - openFileName.lpstrInitialDir = initialDirectory; - openFileName.lpstrTitle = wctitle; + openFileName.lpstrTitle = utf8_to_widechar(desc->title); + openFileName.lpstrInitialDir = utf8_to_widechar(desc->initial_directory); + openFileName.lpstrFile = wcFilename; - // Copy filter name - lstrcpyW((wchar_t*)0x01423800, wcfilterName); + utf8 filters[256]; + utf8 *ch = filters; + for (int i = 0; i < countof(desc->filters); i++) { + if (desc->filters[i].name != NULL) { + strcpy(ch, desc->filters[i].name); + ch = strchr(ch, 0) + 1; + strcpy(ch, desc->filters[i].pattern); + ch = strchr(ch, 0) + 1; + } + } + assert(ch != filters); + *ch = 0; - // Copy filter pattern - int wcfilterNameLength = lstrlenW(wcfilterName); - int wcfilterPatternLength = lstrlenW(wcfilterPattern); - - lstrcpyW((wchar_t*)0x01423800 + wcfilterNameLength + 1, wcfilterPattern); - *((wchar_t*)((wchar_t*)0x01423800 + wcfilterNameLength + 1 + wcfilterPatternLength + 1)) = 0; - openFileName.lpstrFilter = (wchar_t*)0x01423800; - - // - tmp = RCT2_GLOBAL(0x009E2C74, uint32); - if (RCT2_GLOBAL(0x009E2BB8, uint32) == 2 && RCT2_GLOBAL(0x009E1AF8, uint32) == 1) - RCT2_GLOBAL(0x009E2C74, uint32) = 1; - - // Open dialog - commonFlags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; - if (type == 0) { - openFileName.Flags = commonFlags | OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT; - result = GetSaveFileNameW(&openFileName); - } else if (type == 1) { - openFileName.Flags = commonFlags | OFN_NONETWORKBUTTON | OFN_FILEMUSTEXIST; - result = GetOpenFileNameW(&openFileName); + // HACK: Replace all null terminators with 0x01 so that we convert the entire string + size_t fullLength = (size_t)(ch - filters); + for (size_t i = 0; i < fullLength; i++) { + if (filters[i] == '\0') { + filters[i] = 1; + } + } + wchar_t *wcFilter = utf8_to_widechar(filters); + fullLength = lstrlenW(wcFilter); + for (size_t i = 0; i < fullLength; i++) { + if (wcFilter[i] == 1) { + wcFilter[i] = '\0'; + } } - // - RCT2_GLOBAL(0x009E2C74, uint32) = tmp; + openFileName.lpstrFilter = wcFilter; - WideCharToMultiByte(CP_UTF8, 0, wcfilename, countof(wcfilename), filename, MAX_PATH, NULL, NULL); + // Open dialog + BOOL result = false; + DWORD commonFlags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR; + if (desc->type == FD_OPEN) { + openFileName.Flags = commonFlags | OFN_NONETWORKBUTTON | OFN_FILEMUSTEXIST; + result = GetOpenFileNameW(&openFileName); + } else if (desc->type == FD_SAVE) { + openFileName.Flags = commonFlags | OFN_CREATEPROMPT | OFN_OVERWRITEPROMPT; + result = GetSaveFileNameW(&openFileName); + } + + // Clean up + free((void*)openFileName.lpstrTitle); + free((void*)openFileName.lpstrInitialDir); + free((void*)openFileName.lpstrFilter); + + if (result) { + utf8 *resultFilename = widechar_to_utf8(openFileName.lpstrFile); + strcpy(outFilename, resultFilename); + free(resultFilename); + + // If there is no extension, append the pattern + const utf8 *outFilenameExtension = path_get_extension(outFilename); + if (str_is_null_or_empty(outFilenameExtension)) { + int filterIndex = openFileName.nFilterIndex - 1; + + assert(filterIndex >= 0); + assert(filterIndex < countof(desc->filters)); + + const utf8 *pattern = desc->filters[filterIndex].pattern; + const utf8 *patternExtension = path_get_extension(pattern); + if (!str_is_null_or_empty(patternExtension)) { + strcat(outFilename, patternExtension); + } + } + } return result; } @@ -734,45 +869,15 @@ time_t platform_file_get_modified_time(const utf8* path) uint8 platform_get_locale_currency() { CHAR currCode[4]; - if (GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SINTLSYMBOL, (LPSTR)&currCode, sizeof(currCode)) == 0 ) { - return CURRENCY_POUNDS; + return platform_get_currency_value(NULL); } - if (strcmp(currCode, "GBP") == 0){ - return CURRENCY_POUNDS; - } - else if (strcmp(currCode, "USD") == 0){ - return CURRENCY_DOLLARS; - } - else if (strcmp(currCode, "EUR") == 0){ - return CURRENCY_EUROS; - } - else if (strcmp(currCode, "SEK") == 0){ - return CURRENCY_KRONA; - } - else if (strcmp(currCode, "DEM") == 0){ - return CURRENCY_DEUTSCHMARK; - } - else if (strcmp(currCode, "ITL") == 0){ - return CURRENCY_LIRA; - } - else if (strcmp(currCode, "JPY") == 0){ - return CURRENCY_YEN; - } - else if (strcmp(currCode, "ESP") == 0){ - return CURRENCY_PESETA; - } - else if (strcmp(currCode, "FRF") == 0){ - return CURRENCY_FRANC; - } - else if (strcmp(currCode, "NLG") == 0){ - return CURRENCY_GUILDERS; - } - return CURRENCY_POUNDS; + + return platform_get_currency_value(currCode); } uint8 platform_get_locale_measurement_format() @@ -783,15 +888,15 @@ uint8 platform_get_locale_measurement_format() (LPSTR)&measurement_system, sizeof(measurement_system)) == 0 ) { - return MEASUREMENT_FORMAT_IMPERIAL; + return MEASUREMENT_FORMAT_METRIC; } switch (measurement_system) { - case 0: - return MEASUREMENT_FORMAT_METRIC; case 1: - default: return MEASUREMENT_FORMAT_IMPERIAL; + case 0: + default: + return MEASUREMENT_FORMAT_METRIC; } } @@ -835,4 +940,76 @@ char *strndup(const char *src, size_t size) dst[len] = '\0'; return (char *)dst; } + +void platform_get_exe_path(utf8 *outPath) +{ + wchar_t exePath[MAX_PATH]; + wchar_t tempPath[MAX_PATH]; + wchar_t *exeDelimiter; + int exeDelimiterIndex; + + GetModuleFileNameW(NULL, exePath, MAX_PATH); + exeDelimiter = wcsrchr(exePath, platform_get_path_separator()); + exeDelimiterIndex = (int)(exeDelimiter - exePath); + lstrcpynW(tempPath, exePath, exeDelimiterIndex + 1); + tempPath[exeDelimiterIndex] = L'\0'; + _wfullpath(exePath, tempPath, MAX_PATH); + WideCharToMultiByte(CP_UTF8, 0, exePath, countof(exePath), outPath, MAX_PATH, NULL, NULL); +} + +bool platform_get_font_path(TTFFontDescriptor *font, utf8 *buffer) +{ +#if !defined(__MINGW32__) && ((NTDDI_VERSION >= NTDDI_VISTA) && !defined(_USING_V110_SDK71_) && !defined(_ATL_XP_TARGETING)) + wchar_t *fontFolder; + if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Fonts, 0, NULL, &fontFolder))) + { + // Convert wchar to utf8, then copy the font folder path to the buffer. + utf8 *outPathTemp = widechar_to_utf8(fontFolder); + strcpy(buffer, outPathTemp); + free(outPathTemp); + + CoTaskMemFree(fontFolder); + + // Append the requested font's file name. + const char separator[2] = { platform_get_path_separator(), 0 }; + strcat(buffer, separator); + strcat(buffer, font->filename); + return true; + } + else + { + return false; + } +#else + log_warning("Compatibility hack: falling back to C:\\Windows\\Fonts"); + strcpy(buffer, "C:\\Windows\\Fonts\\"); + strcat(buffer, font->filename); + return true; +#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; +} + +utf8* platform_get_username() { + static char username[UNLEN + 1]; + + DWORD usernameLength = UNLEN + 1; + if (!GetUserName(username, &usernameLength)) { + return NULL; + } + + return username; +} + #endif diff --git a/src/rct1.c b/src/rct1.c index 90fe58171d..cb2db19731 100644 --- a/src/rct1.c +++ b/src/rct1.c @@ -349,7 +349,7 @@ static void rct1_load_default_objects() continue; } - if (!object_load(j, &entries[j], NULL)) { + if (!object_load_chunk(j, &entries[j], NULL)) { error_string_quit(0x99990000 + (i * 0x100) + j, -1); return; } @@ -359,7 +359,7 @@ static void rct1_load_default_objects() // Water is a special case rct_object_entry *waterEntries = (rct_object_entry*)RCT1DefaultObjects[9].entries; rct_object_entry *waterEntry = &waterEntries[RCT2_GLOBAL(0x01358841, uint8) == 0 ? 0 : 1]; - if (!object_load(0, waterEntry, NULL)) { + if (!object_load_chunk(0, waterEntry, NULL)) { error_string_quit(0x99990900, -1); return; } @@ -612,7 +612,7 @@ static void rct1_clear_extra_tile_entries() *tilePointer++ = nextFreeMapElement++; } - RCT2_GLOBAL(0x0140E9A4, rct_map_element*) = nextFreeMapElement; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*) = nextFreeMapElement; } /** @@ -661,7 +661,7 @@ static void rct1_fix_colours() } mapElement = gMapElements; - while (mapElement < RCT2_GLOBAL(0x0140E9A4, rct_map_element*)) { + while (mapElement < RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*)) { if (mapElement->base_height != 255) { switch (map_element_get_type(mapElement)) { case MAP_ELEMENT_TYPE_SCENERY: @@ -712,13 +712,13 @@ static void rct1_fix_z() for (int i = 0; i < 4; i++) { ride->station_heights[i] /= 2; } - ride->var_116 /= 2; + ride->start_drop_height /= 2; ride->highest_drop_height = 1; - if (ride->var_11F != 255) { - ride->var_11F /= 2; + if (ride->cur_test_track_z != 255) { + ride->cur_test_track_z /= 2; } - ride->var_13E /= 2; - ride->var_13F /= 2; + ride->chairlift_bullwheel_z[0] /= 2; + ride->chairlift_bullwheel_z[1] /= 2; } for (int i = 0; i < RCT2_GLOBAL(0x0138B580, uint16); i++) { @@ -735,7 +735,7 @@ static void rct1_fix_z() } for (int i = 0; i < MAX_RIDE_MEASUREMENTS; i++) { - rideMeasurement = GET_RIDE_MEASUREMENT(i); + rideMeasurement = get_ride_measurement(i); if (rideMeasurement->ride_index == 255) continue; @@ -745,7 +745,7 @@ static void rct1_fix_z() } mapElement = gMapElements; - while (mapElement < RCT2_GLOBAL(0x0140E9A4, rct_map_element*)) { + while (mapElement < RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*)) { if (mapElement->base_height != 255) { mapElement->base_height /= 2; mapElement->clearance_height /= 2; @@ -765,7 +765,7 @@ static void rct1_fix_paths() int pathType, secondaryType, additions; mapElement = gMapElements; - while (mapElement < RCT2_GLOBAL(0x0140E9A4, rct_map_element*)) { + while (mapElement < RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*)) { switch (map_element_get_type(mapElement)) { case MAP_ELEMENT_TYPE_PATH: // Type @@ -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) { @@ -815,13 +814,14 @@ static void rct1_convert_wall(int *type, int *colourA, int *colourB, int *colour case 12: // creepy gate *colourA = 24; break; - case 26: // medium brown castle wall + case 26: // white wooden fence + *type = 12; + *colourA = 2; + break; + case 27: // red wooden fence *type = 12; *colourA = 25; break; - case 27: // tall castle wall with grey window - *type = 12; - *colourA = 2; case 50: // plate glass *colourA = 24; break; @@ -899,7 +899,10 @@ static void sub_69E891() #pragma region Tables -// rct2: 0x0097F0BC & 0x0098BC60 +/** + * + * rct2: 0x0097F0BC, 0x0098BC60 + */ const uint8 RCT1ColourConversionTable[32] = { 0, 1, 2, 4, 5, 6, 7, 9, 11, 12, 13, 14, 15, 16, 18, 19, @@ -1375,6 +1378,7 @@ static const rct_object_entry RCT1DefaultObjectsWall[] = { { 0x00000083, { "WSW " }, 0 }, { 0x00000083, { "WSWG " }, 0 }, { 0x00000083, { "WMW " }, 0 }, + { 0x00000083, { "WALLGL16" }, 0 }, { 0x00000083, { "WFW1 " }, 0 }, { 0x00000083, { "WFWG " }, 0 }, { 0x00000083, { "WPW1 " }, 0 }, @@ -1389,6 +1393,8 @@ static const rct_object_entry RCT1DefaultObjectsWall[] = { { 0x00000083, { "WBW " }, 0 }, { 0x00000083, { "WBR1 " }, 0 }, { 0x00000083, { "WBRG " }, 0 }, + { 0x00000083, { "WALLCFAR" }, 0 }, // Slot taken by white wooden fence in RCT1 + { 0x00000083, { "WALLPOST" }, 0 }, // Slot taken by red wooden fence in RCT1 { 0x00000083, { "WBR2 " }, 0 }, { 0x00000083, { "WBR3 " }, 0 }, { 0x00000083, { "WPW3 " }, 0 }, @@ -1430,7 +1436,6 @@ static const rct_object_entry RCT1DefaultObjectsWall[] = { { 0x00000083, { "WALLCB16" }, 0 }, { 0x00000083, { "WALLCB32" }, 0 }, { 0x00000083, { "WALLGL8 " }, 0 }, - { 0x00000083, { "WALLGL16" }, 0 }, { 0x00000083, { "WALLGL32" }, 0 }, { 0x00000083, { "WALLWD8 " }, 0 }, { 0x00000083, { "WALLWD16" }, 0 }, @@ -1806,7 +1811,7 @@ bool vehicleIsHigherInHierarchy(int track_type, char *currentVehicleName, char * return false; } -bool rideTypeShouldLoseSeparateFlag(rct_ride_type *ride) +bool rideTypeShouldLoseSeparateFlag(rct_ride_entry *ride) { if(!gConfigInterface.select_by_track_type) return false; diff --git a/src/rct1.h b/src/rct1.h index 4e1df84dac..0307647a52 100644 --- a/src/rct1.h +++ b/src/rct1.h @@ -502,13 +502,13 @@ enum { extern const uint8 RCT1ColourConversionTable[32]; -const uint8 gRideCategories[0x60]; +extern const uint8 gRideCategories[0x60]; bool rct1_read_sc4(const char *path, rct1_s4 *s4); bool rct1_read_sv4(const char *path, rct1_s4 *s4); void rct1_import_s4(rct1_s4 *s4); void rct1_fix_landscape(); bool vehicleIsHigherInHierarchy(int track_type, char *currentVehicleName, char *comparedVehicleName); -bool rideTypeShouldLoseSeparateFlag(rct_ride_type *ride); +bool rideTypeShouldLoseSeparateFlag(rct_ride_entry *ride); #endif diff --git a/src/rct2.c b/src/rct2.c index 23e2b88af6..e862f2d89a 100644 --- a/src/rct2.c +++ b/src/rct2.c @@ -20,7 +20,6 @@ #pragma warning(disable : 4996) // GetVersionExA deprecated -#include #include #include "addresses.h" #include "audio/audio.h" @@ -29,6 +28,7 @@ #include "drawing/drawing.h" #include "editor.h" #include "game.h" +#include "input.h" #include "interface/chat.h" #include "interface/console.h" #include "interface/viewport.h" @@ -54,6 +54,61 @@ #include "world/scenery.h" #include "world/sprite.h" +// rct2: 0x0097F67C +const char * const RCT2FilePaths[PATH_ID_END] = { + "Data\\g1.dat", + "Data\\plugin.dat", + "Data\\css1.dat", + "Data\\css2.dat", + "Data\\css4.dat", + "Data\\css5.dat", + "Data\\css6.dat", + "Data\\css7.dat", + "Data\\css8.dat", + "Data\\css9.dat", + "Data\\css11.dat", + "Data\\css12.dat", + "Data\\css13.dat", + "Data\\css14.dat", + "Data\\css15.dat", + "Data\\css3.dat", + "Data\\css17.dat", + "Data\\css18.dat", + "Data\\css19.dat", + "Data\\css20.dat", + "Data\\css21.dat", + "Data\\css22.dat", + "Saved Games\\scores.dat", + "Data\\css23.dat", + "Data\\css24.dat", + "Data\\css25.dat", + "Data\\css26.dat", + "Data\\css27.dat", + "Data\\css28.dat", + "Data\\css29.dat", + "Data\\css30.dat", + "Data\\css31.dat", + "Data\\css32.dat", + "Data\\css33.dat", + "Data\\css34.dat", + "Data\\css35.dat", + "Data\\css36.dat", + "Data\\css37.dat", + "Data\\css38.dat", + "Data\\CUSTOM1.WAV", + "Data\\CUSTOM2.WAV", + "Data\\css39.dat", + "Data\\css40.dat", + "Data\\css41.dat", + "Scenarios\\Six Flags Magic Mountain.SC6", + "Data\\css42.dat", + "Data\\css43.dat", + "Data\\css44.dat", + "Data\\css45.dat", + "Data\\css46.dat", + "Data\\css50.dat" +}; + uint32 gCurrentDrawCount = 0; typedef struct tm tm_t; @@ -63,9 +118,7 @@ void print_launch_information(); int rct2_init_directories(); int rct2_startup_checks(); -static void rct2_update_2(); - -static jmp_buf _end_update_jump; +static void rct2_draw_fps(); void rct2_quit() { @@ -73,16 +126,20 @@ void rct2_quit() window_save_prompt_open(); } +void rct2_dispose() +{ + gfx_unload_g2(); + gfx_unload_g1(); + object_unload_all(); +} + int rct2_init() { log_verbose("initialising game"); RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, uint32) = 0; RCT2_GLOBAL(0x009AC310, char*) = RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, char*); - get_system_time(); util_srand((unsigned int)time(0)); - RCT2_GLOBAL(0x009DEA69, short) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, short); - RCT2_GLOBAL(0x009DEA6B, short) = RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, short); if (!rct2_init_directories()) return 0; @@ -91,7 +148,7 @@ int rct2_init() config_reset_shortcut_keys(); config_shortcut_keys_load(); - RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) = 0; + gInputPlaceObjectModifier = PLACE_OBJECT_MODIFIER_NONE; // config_load(); object_list_load(); @@ -109,7 +166,6 @@ int rct2_init() } viewport_init_all(); news_item_init_queue(); - get_local_time(); reset_park_entrances(); user_string_clear_all(); reset_sprite_list(); @@ -149,7 +205,9 @@ int rct2_init_directories() if (!platform_original_game_data_exists(gConfigGeneral.game_path)) { log_verbose("install directory does not exist or invalid directory selected, %s", gConfigGeneral.game_path); if (!config_find_or_browse_install_directory()) { - log_fatal("Invalid RCT2 installation path. Please correct in config.ini."); + utf8 path[MAX_PATH]; + config_get_default_path(path); + log_fatal("Invalid RCT2 installation path. Please correct \"game_path\" in %s.", path); return 0; } } @@ -194,7 +252,7 @@ int rct2_init_directories() return 1; } -void subsitute_path(char *dest, const char *path, const char *filename) +void substitute_path(char *dest, const char *path, const char *filename) { while (*path != '*') { *dest++ = *path++; @@ -211,33 +269,9 @@ int rct2_startup_checks() if (!check_file_paths()) return 0; - if (!check_files_integrity()) - return 0; - return 1; } -void rct2_update() -{ - // Set 0x009DE564 to the value of esp - // RCT2 sets the stack pointer to the value of this address when ending the current game tick from anywhere - #ifdef _MSC_VER - __asm { - mov eax, 009DE564h - mov [eax], esp - } - #else - __asm__ ( "\ - \n\ - movl $0x009DE564, %%eax \n\ - movl %%esp, (%%eax) \n\ - " : : : "eax" ); - #endif - - if (!setjmp(_end_update_jump)) - rct2_update_2(); -} - void rct2_draw() { redraw_rain(); @@ -259,33 +293,85 @@ void rct2_draw() //game } + if (gConfigGeneral.show_fps) { + rct2_draw_fps(); + } + gCurrentDrawCount++; } -int rct2_open_file(const char *path) +static uint32 _lastFPSUpdateTicks; +static uint32 _lastFPSTicks; +static float _currentFPS; + +static float rct2_measure_fps() +{ + uint32 currentTicks = SDL_GetTicks(); + if (currentTicks - _lastFPSUpdateTicks > 500) { + _lastFPSUpdateTicks = currentTicks; + + uint32 frameDelta = currentTicks - _lastFPSTicks; + _currentFPS = 1000.0f / frameDelta; + } + _lastFPSTicks = currentTicks; + return _currentFPS; +} + +static void rct2_draw_fps() +{ + rct_drawpixelinfo *dpi = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); + int x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) / 2; + int y = 2; + + // Measure FPS + float fps = rct2_measure_fps(); + + // Format string + utf8 buffer[64]; + utf8 *ch = buffer; + ch = utf8_write_codepoint(ch, FORMAT_MEDIUMFONT); + ch = utf8_write_codepoint(ch, FORMAT_OUTLINE); + ch = utf8_write_codepoint(ch, FORMAT_WHITE); + + const char *formatString = (_currentFPS >= 100.0f ? "%.0f" : "%.1f"); + sprintf(ch, formatString, _currentFPS); + + // Draw Text + int stringWidth = gfx_get_string_width(buffer); + x = x - (stringWidth / 2); + gfx_draw_string(dpi, buffer, 0, x, y); + + // Make area dirty so the text doesn't get drawn over the last + gfx_set_dirty_blocks(x - 16, y - 4, gLastDrawStringX + 16, 16); +} + +bool rct2_open_file(const char *path) { char *extension = strrchr(path, '.'); - if (extension == NULL) - return 0; + if (extension == NULL) { + return false; + } extension++; if (_stricmp(extension, "sv6") == 0) { strcpy((char*)RCT2_ADDRESS_SAVED_GAMES_PATH_2, path); game_load_save(path); - return 1; + gFirstTimeSave = 0; + return true; } else if (_stricmp(extension, "sc6") == 0) { // TODO scenario install rct_scenario_basic scenarioBasic; strcpy(scenarioBasic.path, path); scenario_load_and_play_from_path(scenarioBasic.path); + return true; } else if (_stricmp(extension, "td6") == 0 || _stricmp(extension, "td4") == 0) { - return 1; + return true; } else if (!_stricmp(extension, "td6") || !_stricmp(extension, "td4")) { // TODO track design install - return 1; + return true; } - return 0; + return false; } /** @@ -293,11 +379,12 @@ int rct2_open_file(const char *path) * rct2: 0x00674C95 */ int check_file_paths() - { - for (int pathId = 0; pathId < PATH_ID_END; pathId++) - if (!check_file_path(pathId)) - return 0; - +{ + for (int pathId = 0; pathId < PATH_ID_END; pathId++) { + if (!check_file_path(pathId)) { + return 0; + } + } return 1; } @@ -313,69 +400,34 @@ int check_file_path(int pathId) switch (pathId) { case PATH_ID_G1: if (file == NULL) { - // A data file is missing from the installation directory. The original implementation - // asks for a CD-ROM path at this point and stores it in cdrom_path @ 0x9AA318. - // The file_on_cdrom[pathId] @ 0x009AA0B flag is set to 1 as well. - // For PATH_ID_SIXFLAGS_MAGICMOUNTAIN (and the now removed PATH_ID_SIXFLAGS_BUILDYOUROWN), - // the original implementation always assumes they are stored on CD-ROM. - // This has been removed for now for the sake of simplicity and could be added - // later in a more convenient way using the INI file. log_fatal("Could not find file %s", path); return 0; } break; case PATH_ID_CUSTOM1: - if (file != NULL) - gRideMusicInfoList[36]->length = (uint32)SDL_RWsize(file); // Store file size in music_custom1_size @ 0x009AF164 + if (file != NULL) { + // Store file size in music_custom1_size @ 0x009AF164 + gRideMusicInfoList[36]->length = (uint32)SDL_RWsize(file); + } break; case PATH_ID_CUSTOM2: - if (file != NULL) - gRideMusicInfoList[37]->length = (uint32)SDL_RWsize(file); // Store file size in music_custom2_size @ 0x009AF16E + if (file != NULL) { + // Store file size in music_custom2_size @ 0x009AF16E + gRideMusicInfoList[37]->length = (uint32)SDL_RWsize(file); + } break; } - if (file != NULL) + if (file != NULL) { SDL_RWclose(file); - - return 1; -} - -/** - * - * rct2: 0x00674C0B - */ -int check_files_integrity() - { - int i; - const char *path; -#ifdef _WIN32 - HANDLE file; - WIN32_FIND_DATA find_data; - - for (i = 0; files_to_check[i].pathId != PATH_ID_END; i++) { - path = get_file_path(files_to_check[i].pathId); - file = FindFirstFile(path, &find_data); - - if (file == INVALID_HANDLE_VALUE || find_data.nFileSizeLow != files_to_check[i].fileSize) { - if (file != INVALID_HANDLE_VALUE) - FindClose(file); - - log_fatal("Integrity check failed for %s", path); - return 0; - } - - FindClose(file); } -#else - STUB(); -#endif // _WIN32 return 1; } -void rct2_update_2() +void rct2_update() { int tick, tick2; @@ -388,9 +440,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(); @@ -399,7 +448,7 @@ void rct2_update_2() // Screens if (RCT2_GLOBAL(RCT2_ADDRESS_RUN_INTRO_TICK_PART, uint8) != 0) intro_update(); - else if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) + else if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) && !gOpenRCT2Headless) title_update(); else game_update(); @@ -411,30 +460,19 @@ void rct2_update_2() console_update(); } -void rct2_endupdate() -{ - longjmp(_end_update_jump, 0); -} - /** * * rct2: 0x00674E6C */ const utf8 *get_file_path(int pathId) { - static utf8 path[MAX_PATH]; // get_file_path_buffer @ 0x009E3605 - - // The original implementation checks if the file is on CD-ROM here (file_on_cdrom[pathId] @ 0x009AA0B1). - // If so, the CD-ROM path (cdrom_path @ 0x9AA318) is used instead. This has been removed for now for - // the sake of simplicity. + static utf8 path[MAX_PATH]; strcpy(path, gConfigGeneral.game_path); // Make sure base path is terminated with a slash - if (strlen(path) == 0 || path[strlen(path) - 1] != platform_get_path_separator()) - { - if (strlen(path) >= MAX_PATH - 1) - { - log_error("Path for %s too long", file_paths[pathId]); + if (strlen(path) == 0 || path[strlen(path) - 1] != platform_get_path_separator()) { + if (strlen(path) >= MAX_PATH - 1) { + log_error("Path for %s too long", RCT2FilePaths[pathId]); path[0] = '\0'; return path; } @@ -444,16 +482,14 @@ const utf8 *get_file_path(int pathId) } // Concatenate file path - if (strlen(path) + strlen(file_paths[pathId]) > MAX_PATH) { - log_error("Path for %s too long", file_paths[pathId]); + if (strlen(path) + strlen(RCT2FilePaths[pathId]) > MAX_PATH) { + log_error("Path for %s too long", RCT2FilePaths[pathId]); path[0] = '\0'; return path; } char *pathp = path + strnlen(path, sizeof(path)); - - strcat(path, file_paths[pathId]); - + strcat(path, RCT2FilePaths[pathId]); while (*pathp) { if (*pathp == '\\') *pathp = platform_get_path_separator(); pathp++; @@ -461,143 +497,3 @@ const utf8 *get_file_path(int pathId) return path; } - -/** - * Obtains basic system versions and capabilities. - * rct2: 0x004076B1 - */ -void get_system_info() -{ -#ifdef _WIN32 - OSVERSIONINFO versionInfo; - SYSTEM_INFO sysInfo; - MEMORYSTATUS memInfo; - - versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (GetVersionEx(&versionInfo)) { - RCT2_GLOBAL(RCT2_ADDRESS_OS_PLATFORM_ID, uint32) = versionInfo.dwPlatformId; - RCT2_GLOBAL(RCT2_ADDRESS_OS_MAJOR_VERSION, uint32) = versionInfo.dwMajorVersion; - RCT2_GLOBAL(RCT2_ADDRESS_OS_MINOR_VERSION, uint32) = versionInfo.dwMinorVersion; - RCT2_GLOBAL(RCT2_ADDRESS_OS_BUILD_NUMBER, uint32) = versionInfo.dwBuildNumber; - } else { -#endif // _WIN32 - RCT2_GLOBAL(RCT2_ADDRESS_OS_PLATFORM_ID, uint32) = -1; - RCT2_GLOBAL(RCT2_ADDRESS_OS_MAJOR_VERSION, uint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_OS_MINOR_VERSION, uint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_OS_BUILD_NUMBER, uint32) = 0; -#ifdef _WIN32 - } - - GetSystemInfo(&sysInfo); - // RCT2 only has 2 bytes reserved for OEM_ID even though it should be a DWORD - RCT2_GLOBAL(RCT2_ADDRESS_SYS_OEM_ID, uint16) = (uint16)sysInfo.dwOemId; - RCT2_GLOBAL(RCT2_ADDRESS_SYS_CPU_LEVEL, uint16) = sysInfo.wProcessorLevel; - RCT2_GLOBAL(RCT2_ADDRESS_SYS_CPU_REVISION, uint16) = sysInfo.wProcessorRevision; - RCT2_GLOBAL(RCT2_ADDRESS_SYS_CPU_NUMBER, uint32) = sysInfo.dwNumberOfProcessors; - - GlobalMemoryStatus(&memInfo); - RCT2_GLOBAL(RCT2_ADDRESS_MEM_TOTAL_PHYSICAL, uint32) = memInfo.dwTotalPhys; - RCT2_GLOBAL(RCT2_ADDRESS_MEM_TOTAL_PAGEFILE, uint32) = memInfo.dwTotalPageFile; - RCT2_GLOBAL(RCT2_ADDRESS_MEM_TOTAL_VIRTUAL, uint32) = memInfo.dwTotalVirtual; - - DWORD size = 80; - GetUserName((char*)RCT2_ADDRESS_OS_USER_NAME, &size); - size = 80; - GetComputerName((char*)RCT2_ADDRESS_OS_COMPUTER_NAME, &size); - - // Screen Display Width/Height but RCT_ADDRESS_SCREEN_HEIGHT/WIDTH already taken? - RCT2_GLOBAL(0x01423C08, sint32) = GetSystemMetrics(SM_CXSCREEN); - RCT2_GLOBAL(0x01423C0C, sint32) = GetSystemMetrics(SM_CYSCREEN); - - HDC screenHandle = GetDC(NULL); - if (screenHandle) { - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_CAP_BPP, sint32) = GetDeviceCaps(screenHandle, BITSPIXEL); - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_CAP_RASTER_STRETCH, sint32) = GetDeviceCaps(screenHandle, RASTERCAPS) >> 8; - ReleaseDC(NULL, screenHandle); - } else { - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_CAP_BPP, sint32) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_CAP_RASTER_STRETCH, sint32) = 0; - } - - RCT2_GLOBAL(0x01423C1C, uint32) = (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_CAP_BPP, sint32) >= 8); - if (RCT2_GLOBAL(RCT2_ADDRESS_OS_MAJOR_VERSION, uint32) < 4 || RCT2_GLOBAL(0x1423C10, sint32) < 4) - RCT2_GLOBAL(0x1423C18, sint32) = 0; - else - RCT2_GLOBAL(0x1423C18, sint32) = 1; - - RCT2_GLOBAL(0x01423C20, uint32) = (SDL_HasMMX() == SDL_TRUE); -#else - STUB(); -#endif // _WIN32 -} - - -/** - * Obtains os system time (day, month, year and day of the week). - * rct2: 0x00407671 - */ -void get_system_time() -{ - rct2_date date; - platform_get_date(&date); - RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAY, sint16) = date.day; - RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MONTH, sint16) = date.month; - RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_YEAR, sint16) = date.year; - RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_DAYOFWEEK, sint16) = date.day_of_week; -} - -/** - * Obtains os local time (hour and minute) - * rct2: 0x006C45E7; - */ -void get_local_time() -{ - rct2_time t; - platform_get_time(&t); - RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_HOUR, sint16) = t.hour; - RCT2_GLOBAL(RCT2_ADDRESS_OS_TIME_MINUTE, sint16) = t.minute; -} - -/** - * RCT2 and this DLL can not free each other's allocated memory blocks. Use this to allocate memory if RCT2 is still able to - * free it. - * rct2: 0x004068B2 - */ -void *rct2_malloc(size_t numBytes) -{ - #ifdef _WIN32 - return RCT2_CALLFUNC_1(0x004068B2, void*, size_t, numBytes); - #else - //log_warning("call rct's function"); - return malloc(numBytes); - #endif // _WIN32 -} - -/** - * RCT2 and this DLL can not free each other's allocated memory blocks. Use this to reallocate memory if RCT2 is still able to - * free it. - * rct2: 0x004068BD - */ -void *rct2_realloc(void *block, size_t numBytes) -{ - #ifdef _WIN32 - return RCT2_CALLFUNC_2(0x004068BD, void*, void*, size_t, block, numBytes); - #else - //log_warning("call rct's function"); - return realloc(block, numBytes); - #endif // _WIN32 -} - -/** - * RCT2 and this DLL can not free each other's allocated memory blocks. Use this to free memory that was allocated by RCT2. - * rct2: 0x004068CD - */ -void rct2_free(void *block) -{ - #ifdef _WIN32 - RCT2_CALLPROC_1(0x004068CD, void*, block); - #else - //log_warning("call rct's function"); - free(block); - #endif // _WIN32 -} diff --git a/src/rct2.h b/src/rct2.h index 63c2cd7f1f..1a5aa30746 100644 --- a/src/rct2.h +++ b/src/rct2.h @@ -21,6 +21,8 @@ #ifndef _RCT2_H_ #define _RCT2_H_ +#include + #ifndef _USE_MATH_DEFINES #define _USE_MATH_DEFINES #endif @@ -41,14 +43,14 @@ #include #endif -typedef signed char sint8; -typedef signed short sint16; -typedef signed long sint32; -typedef signed long long sint64; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned long uint32; -typedef unsigned long long uint64; +typedef int8_t sint8; +typedef int16_t sint16; +typedef int32_t sint32; +typedef int64_t sint64; +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; typedef char utf8; typedef utf8* utf8string; @@ -56,6 +58,9 @@ typedef const utf8* const_utf8string; typedef wchar_t utf16; typedef utf16* utf16string; +typedef uint32 codepoint_t; +typedef uint8 colour_t; + #define rol8(x, shift) (((uint8)(x) << (shift)) | ((uint8)(x) >> (8 - (shift)))) #define ror8(x, shift) (((uint8)(x) >> (shift)) | ((uint8)(x) << (8 - (shift)))) #define rol16(x, shift) (((uint16)(x) << (shift)) | ((uint16)(x) >> (16 - (shift)))) @@ -64,50 +69,91 @@ typedef utf16* utf16string; #define ror32(x, shift) (((uint32)(x) >> (shift)) | ((uint32)(x) << (32 - (shift)))) #define rol64(x, shift) (((uint64)(x) << (shift)) | ((uint32)(x) >> (64 - (shift)))) #define ror64(x, shift) (((uint64)(x) >> (shift)) | ((uint32)(x) << (64 - (shift)))) + +#ifndef __cplusplus +// in C++ you should be using Math::Min and Math::Max #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif +#endif // __cplusplus + #define sgn(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0)) #define clamp(l, x, h) (min(h, max(l, x))) // Rounds an integer down to the given power of 2. y must be a power of 2. #define floor2(x, y) ((x) & (~((y) - 1))) -#define countof(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x]))))) + +#ifndef __cplusplus +// in C++ you should be using Util::CountOf +#ifdef __GNUC__ +/** + * Force a compilation error if condition is true, but also produce a + * result (of value 0 and type size_t), so the expression can be used + * e.g. in a structure initializer (or where-ever else comma expressions + * aren't permitted). + */ +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) + +/* &a[0] degrades to a pointer: a different type from an array */ +#define __must_be_array(a) \ + BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0]))) + +// based on http://lxr.free-electrons.com/source/include/linux/kernel.h#L54 +#define countof(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) +#elif defined (_MSC_VER) + #define countof(arr) _countof(arr) +#else + #define countof(arr) (sizeof(arr) / sizeof((arr)[0])) +#endif // __GNUC__ +#endif // __cplusplus #ifndef _MSC_VER // use similar struct packing as MSVC for our structs #pragma pack(1) #endif -#define OPENRCT2_NAME "OpenRCT2" -#define OPENRCT2_VERSION "0.0.3.1" -#define OPENRCT2_ARCHITECTURE "x86" -#ifdef _WIN32 - #define OPENRCT2_PLATFORM "Windows" -#endif // _WIN32 -#ifdef __linux__ - #define OPENRCT2_PLATFORM "Linux" -#endif -#if defined(__APPLE__) && defined(__MACH__) - #define OPENRCT2_PLATFORM "OS X" -#endif -#ifndef OPENRCT2_PLATFORM - #error Unknown platform! -#endif -#define OPENRCT2_TIMESTAMP __DATE__ " " __TIME__ +#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) +#include +#define STUB() log_warning("Function %s at %s:%d is a stub.\n", __PRETTY_FUNCTION__, __FILE__, __LINE__) +#define _strcmpi _stricmp +#define _stricmp(x, y) strcasecmp((x), (y)) +#define _strnicmp(x, y, n) strncasecmp((x), (y), (n)) +#define _strdup(x) strdup((x)) + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define RCT2_ENDIANESS __ORDER_LITTLE_ENDIAN__ +#define LOBYTE(w) ((uint8_t)(w)) +#define HIBYTE(w) ((uint8_t)(((uint16_t)(w)>>8)&0xFF)) +#endif // __BYTE_ORDER__ + +#ifndef RCT2_ENDIANESS +#error Unknown endianess! +#endif // RCT2_ENDIANESS + +#endif // defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) + +#if !(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) + char *strndup(const char *src, size_t size); +#endif // !(POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700) + +// BSD and OS X has MAP_ANON instead of MAP_ANONYMOUS +#ifndef MAP_ANONYMOUS + #define MAP_ANONYMOUS MAP_ANON +#endif + +#include "version.h" -// The following constants are for automated build servers -#define OPENRCT2_BUILD_NUMBER "" -#define OPENRCT2_BUILD_SERVER "" -#define OPENRCT2_BRANCH "" -#define OPENRCT2_COMMIT_SHA1 "" -#define OPENRCT2_COMMIT_SHA1_SHORT "" #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; @@ -132,9 +178,6 @@ typedef fixed32_1dp money32; #define MONEY_FREE MONEY(0,00) #define MONEY32_UNDEFINED ((money32)0x80000000) -#ifndef MAX_PATH -#define MAX_PATH 260 -#endif typedef void (EMPTY_ARGS_VOID_POINTER)(); typedef unsigned short rct_string_id; @@ -216,91 +259,22 @@ enum { PATH_ID_END }; -// rct2 @ 0x0097F67C -static const char * const file_paths[] = -{ - "Data\\g1.dat", - "Data\\plugin.dat", - "Data\\css1.dat", - "Data\\css2.dat", - "Data\\css4.dat", - "Data\\css5.dat", - "Data\\css6.dat", - "Data\\css7.dat", - "Data\\css8.dat", - "Data\\css9.dat", - "Data\\css11.dat", - "Data\\css12.dat", - "Data\\css13.dat", - "Data\\css14.dat", - "Data\\css15.dat", - "Data\\css3.dat", - "Data\\css17.dat", - "Data\\css18.dat", - "Data\\css19.dat", - "Data\\css20.dat", - "Data\\css21.dat", - "Data\\css22.dat", - "Saved Games\\scores.dat", - "Data\\css23.dat", - "Data\\css24.dat", - "Data\\css25.dat", - "Data\\css26.dat", - "Data\\css27.dat", - "Data\\css28.dat", - "Data\\css29.dat", - "Data\\css30.dat", - "Data\\css31.dat", - "Data\\css32.dat", - "Data\\css33.dat", - "Data\\css34.dat", - "Data\\css35.dat", - "Data\\css36.dat", - "Data\\css37.dat", - "Data\\css38.dat", - "Data\\CUSTOM1.WAV", - "Data\\CUSTOM2.WAV", - "Data\\css39.dat", - "Data\\css40.dat", - "Data\\css41.dat", - "Scenarios\\Six Flags Magic Mountain.SC6", - "Data\\css42.dat", - "Data\\css43.dat", - "Data\\css44.dat", - "Data\\css45.dat", - "Data\\css46.dat", - "Data\\css50.dat" -}; - -// Files to check (rct2 @ 0x0097FB5A) -static const struct file_to_check -{ - int pathId; // ID of file - unsigned int fileSize; // Expected size in bytes -} files_to_check[] = { - { PATH_ID_END, 0 } -}; +extern const char * const RCT2FilePaths[PATH_ID_END]; extern uint32 gCurrentDrawCount; int rct2_init(); +void rct2_dispose(); void rct2_update(); void rct2_draw(); -void rct2_endupdate(); -void subsitute_path(char *dest, const char *path, const char *filename); +void substitute_path(char *dest, const char *path, const char *filename); int check_mutex(); int check_file_paths(); int check_file_path(int pathId); int check_files_integrity(); const char *get_file_path(int pathId); -void get_system_info(); -void get_system_time(); -void get_local_time(); -void *rct2_malloc(size_t numBytes); -void *rct2_realloc(void *block, size_t numBytes); -void rct2_free(void *block); void rct2_quit(); -int rct2_open_file(const char *path); +bool rct2_open_file(const char *path); #endif diff --git a/src/ride/cable_lift.c b/src/ride/cable_lift.c new file mode 100644 index 0000000000..6917ce3e31 --- /dev/null +++ b/src/ride/cable_lift.c @@ -0,0 +1,483 @@ +#include "../world/sprite.h" +#include "cable_lift.h" +#include "ride.h" +#include "track.h" + +static void cable_lift_update_moving_to_end_of_station(rct_vehicle *vehicle); +static void cable_lift_update_waiting_to_depart(rct_vehicle *vehicle); +static void cable_lift_update_departing(rct_vehicle *vehicle); +static void cable_lift_update_travelling(rct_vehicle *vehicle); +static void cable_lift_update_arriving(rct_vehicle *vehicle); + +rct_vehicle *cable_lift_segment_create(int rideIndex, int x, int y, int z, int direction, uint16 var_44, sint32 remaining_distance, bool head) +{ + rct_ride *ride = get_ride(rideIndex); + rct_vehicle *current = &(create_sprite(1)->vehicle); + current->sprite_identifier = SPRITE_IDENTIFIER_VEHICLE; + current->ride = rideIndex; + current->ride_subtype = 0xFF; + if (head) { + move_sprite_to_list((rct_sprite*)current, SPRITE_LINKEDLIST_OFFSET_VEHICLE); + ride->cable_lift = current->sprite_index; + } + current->is_child = head ? 0 : 1; + current->var_44 = var_44; + current->remaining_distance = remaining_distance; + current->sprite_width = 10; + current->sprite_height_negative = 10; + current->sprite_height_positive = 10; + current->friction = 100; + current->num_seats = 0; + current->speed = 20; + current->powered_acceleration = 80; + current->velocity = 0; + current->acceleration = 0; + current->var_4A = 0; + current->swinging_car_var_0 = 0; + current->var_4E = 0; + current->restraints_position = 0; + current->var_BA = 0; + current->var_B6 = 0; + current->var_B8 = 0; + current->sound1_id = 0xFF; + current->sound2_id = 0xFF; + current->var_C4 = 0; + current->var_C5 = 0; + current->var_C8 = 0; + current->var_CA = 0; + current->scream_sound_id = 0xFF; + current->vehicle_sprite_type = 0; + current->bank_rotation = 0; + for (int j = 0; j < 32; j++) { + current->peep[j] = SPRITE_INDEX_NULL; + } + current->var_CD = 0; + current->sprite_direction = direction << 3; + current->track_x = x; + current->track_y = y; + + z = z * 8; + current->track_z = z; + z += RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + + sprite_move(16, 16, z, (rct_sprite*)current); + current->track_type = (TRACK_ELEM_CABLE_LIFT_HILL << 2) | (current->sprite_direction >> 3); + current->track_progress = 164; + current->update_flags = VEHICLE_UPDATE_FLAG_1; + current->status = VEHICLE_STATUS_MOVING_TO_END_OF_STATION; + current->sub_state = 0; + current->num_peeps = 0; + current->next_free_seat = 0; + return current; +} + +void cable_lift_update(rct_vehicle *vehicle) +{ + switch (vehicle->status) { + case VEHICLE_STATUS_MOVING_TO_END_OF_STATION: + cable_lift_update_moving_to_end_of_station(vehicle); + break; + case VEHICLE_STATUS_WAITING_FOR_PASSENGERS: + // Stays in this state until a train puts it into next state + break; + case VEHICLE_STATUS_WAITING_TO_DEPART: + cable_lift_update_waiting_to_depart(vehicle); + break; + case VEHICLE_STATUS_DEPARTING: + cable_lift_update_departing(vehicle); + break; + case VEHICLE_STATUS_TRAVELLING: + cable_lift_update_travelling(vehicle); + break; + case VEHICLE_STATUS_ARRIVING: + cable_lift_update_arriving(vehicle); + break; + } +} + +/** + * + * rct2: 0x006DF8A4 + */ +static void cable_lift_update_moving_to_end_of_station(rct_vehicle *vehicle) +{ + if (vehicle->velocity >= -439800) + vehicle->acceleration = -2932; + + if (vehicle->velocity < -439800) { + vehicle->velocity -= vehicle->velocity / 16; + vehicle->acceleration = 0; + } + + if (!(cable_lift_update_track_motion(vehicle) & (1 << 0))) + return; + + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_WAITING_FOR_PASSENGERS; +} + +/** + * + * rct2: 0x006DF8F1 + */ +static void cable_lift_update_waiting_to_depart(rct_vehicle *vehicle) +{ + if (vehicle->velocity >= -58640) + vehicle->acceleration = -14660; + + if (vehicle->velocity < -58640) { + vehicle->velocity -= vehicle->velocity / 16; + vehicle->acceleration = 0; + } + + cable_lift_update_track_motion(vehicle); + + // Next check to see if the second part of the cable lift + // is at the front of the passenger vehicle to simulate the + // cable being attached underneath the train. + rct_vehicle* passengerVehicle = GET_VEHICLE(vehicle->cable_lift_target); + rct_vehicle* cableLiftSecondPart = GET_VEHICLE(vehicle->prev_vehicle_on_ride); + + sint16 dist_x = abs(passengerVehicle->x - cableLiftSecondPart->x); + sint16 dist_y = abs(passengerVehicle->y - cableLiftSecondPart->y); + + if (dist_x + dist_y > 2) + return; + + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 0; +} + +/** + * + * rct2: 0x006DF97A + */ +static void cable_lift_update_departing(rct_vehicle *vehicle) +{ + vehicle->sub_state++; + if (vehicle->sub_state < 16) + return; + + rct_vehicle* passengerVehicle = GET_VEHICLE(vehicle->cable_lift_target); + vehicle->status = VEHICLE_STATUS_TRAVELLING; + passengerVehicle->status = VEHICLE_STATUS_TRAVELLING_CABLE_LIFT; +} + +/** + * + * rct2: 0x006DF99C + */ +static void cable_lift_update_travelling(rct_vehicle *vehicle) +{ + rct_vehicle* passengerVehicle = GET_VEHICLE(vehicle->cable_lift_target); + + vehicle->velocity = min(passengerVehicle->velocity, 439800); + vehicle->acceleration = 0; + if (passengerVehicle->update_flags & VEHICLE_UPDATE_FLAG_BROKEN_TRAIN) + return; + + if (!(cable_lift_update_track_motion(vehicle) & (1 << 1))) + return; + + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle->sub_state = 0; +} + +/** + * + * rct2: 0x006DF9F0 + */ +static void cable_lift_update_arriving(rct_vehicle *vehicle) +{ + vehicle->sub_state++; + if (vehicle->sub_state >= 64) + vehicle->status = VEHICLE_STATUS_MOVING_TO_END_OF_STATION; +} + +bool sub_6DF01A_loop(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + rct_xyz16 *unk_F64E20 = RCT2_ADDRESS(0x00F64E20, rct_xyz16); + + for (; vehicle->remaining_distance >= 13962; RCT2_GLOBAL(0x00F64E10, uint32)++) { + uint8 trackType = vehicle->track_type >> 2; + if (trackType == TRACK_ELEM_CABLE_LIFT_HILL && + vehicle->track_progress == 160) { + RCT2_GLOBAL(0x00F64E18, uint32) |= (1 << 1); + } + + uint16 trackProgress = vehicle->track_progress + 1; + + const rct_vehicle_info *moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, 0); + uint16 trackTotalProgress = *((uint16*)((int)moveInfo - 2)); + if (trackProgress >= trackTotalProgress) { + RCT2_GLOBAL(0x00F64E36, uint8) = gTrackDefinitions[trackType].vangle_end; + RCT2_GLOBAL(0x00F64E37, uint8) = gTrackDefinitions[trackType].bank_end; + rct_map_element* trackElement = + map_get_track_element_at_of_type_seq( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z / 8, + trackType, + 0); + + rct_xy_element input; + rct_xy_element output; + int outputZ; + int outputDirection; + + input.x = vehicle->track_x; + input.y = vehicle->track_y; + input.element = trackElement; + + if (!track_block_get_next(&input, &output, &outputZ, &outputDirection)) + return false; + + if (gTrackDefinitions[output.element->properties.track.type].vangle_start != RCT2_GLOBAL(0x00F64E36, uint8) || + gTrackDefinitions[output.element->properties.track.type].bank_start != RCT2_GLOBAL(0x00F64E37, uint8)) + return false; + + vehicle->track_x = output.x; + vehicle->track_y = output.y; + vehicle->track_z = outputZ; + vehicle->track_direction = outputDirection; + vehicle->track_type |= output.element->properties.track.type << 2; + trackProgress = 0; + } + + vehicle->track_progress = trackProgress; + moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, trackProgress); + rct_xyz16 unk = { + .x = moveInfo->x, + .y = moveInfo->y, + .z = moveInfo->z + }; + + unk.x += vehicle->track_x; + unk.y += vehicle->track_y; + unk.z += vehicle->track_z; + + uint8 bx = 0; + unk.z += RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + if (unk.x != unk_F64E20->x) + bx |= (1 << 0); + if (unk.y != unk_F64E20->y) + bx |= (1 << 1); + if (unk.z != unk_F64E20->z) + bx |= (1 << 2); + + vehicle->remaining_distance -= RCT2_ADDRESS(0x009A2930, sint32)[bx]; + unk_F64E20->x = unk.x; + unk_F64E20->y = unk.y; + unk_F64E20->z = unk.z; + + vehicle->sprite_direction = moveInfo->direction; + vehicle->bank_rotation = moveInfo->bank_rotation; + vehicle->vehicle_sprite_type = moveInfo->vehicle_sprite_type; + + if (vehicle->remaining_distance >= 13962) { + vehicle->acceleration += RCT2_ADDRESS(0x009A2970, sint32)[vehicle->vehicle_sprite_type]; + } + } + return true; +} + +bool sub_6DF21B_loop(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + rct_xyz16 *unk_F64E20 = RCT2_ADDRESS(0x00F64E20, rct_xyz16); + + for (; vehicle->remaining_distance < 0; RCT2_GLOBAL(0x00F64E10, uint32)++) { + uint16 trackProgress = vehicle->track_progress - 1; + const rct_vehicle_info *moveInfo; + + if ((sint16)trackProgress == -1) { + uint8 trackType = vehicle->track_type >> 2; + RCT2_GLOBAL(0x00F64E36, uint8) = gTrackDefinitions[trackType].vangle_start; + RCT2_GLOBAL(0x00F64E37, uint8) = gTrackDefinitions[trackType].bank_start; + rct_map_element* trackElement = + map_get_track_element_at_of_type_seq( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z / 8, + trackType, + 0); + + rct_xy_element input; + + input.x = vehicle->track_x; + input.y = vehicle->track_y; + input.element = trackElement; + track_begin_end output; + + if (!track_block_get_previous(input.x, input.y, input.element, &output)) + return false; + + if (gTrackDefinitions[output.begin_element->properties.track.type].vangle_end != RCT2_GLOBAL(0x00F64E36, uint8) || + gTrackDefinitions[output.begin_element->properties.track.type].bank_end != RCT2_GLOBAL(0x00F64E37, uint8)) + return false; + + vehicle->track_x = output.begin_x; + vehicle->track_y = output.begin_y; + vehicle->track_z = output.begin_z; + vehicle->track_direction = output.begin_direction; + vehicle->track_type |= output.begin_element->properties.track.type << 2; + + if (output.begin_element->properties.track.type == TRACK_ELEM_END_STATION) { + RCT2_GLOBAL(0x00F64E18, uint32) = (1 << 0); + } + + moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, 0); + uint16 trackTotalProgress = *((uint16*)((int)moveInfo - 2)); + trackProgress = trackTotalProgress - 1; + } + vehicle->track_progress = trackProgress; + + moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, trackProgress); + rct_xyz16 unk = { + .x = moveInfo->x, + .y = moveInfo->y, + .z = moveInfo->z + }; + + unk.x += vehicle->track_x; + unk.y += vehicle->track_y; + unk.z += vehicle->track_z; + + uint8 bx = 0; + unk.z += RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + if (unk.x != unk_F64E20->x) + bx |= (1 << 0); + if (unk.y != unk_F64E20->y) + bx |= (1 << 1); + if (unk.z != unk_F64E20->z) + bx |= (1 << 2); + + vehicle->remaining_distance += RCT2_ADDRESS(0x009A2930, sint32)[bx]; + unk_F64E20->x = unk.x; + unk_F64E20->y = unk.y; + unk_F64E20->z = unk.z; + + vehicle->sprite_direction = moveInfo->direction; + vehicle->bank_rotation = moveInfo->bank_rotation; + vehicle->vehicle_sprite_type = moveInfo->vehicle_sprite_type; + + if (vehicle->remaining_distance < 0) { + vehicle->acceleration += RCT2_ADDRESS(0x009A2970, sint32)[vehicle->vehicle_sprite_type]; + } + } + return true; +} + +/** + * + * rct2: 0x006DEF56 + */ +int cable_lift_update_track_motion(rct_vehicle *cableLift) +{ + rct_ride* ride = get_ride(cableLift->ride); + + RCT2_GLOBAL(0x00F64E2C, uint8) = 0; + RCT2_GLOBAL(0x00F64E04, rct_vehicle*) = cableLift; + RCT2_GLOBAL(0x00F64E18, uint32) = 0; + RCT2_GLOBAL(0x00F64E1C, uint32) = (uint32)-1; + + cableLift->velocity += cableLift->acceleration; + RCT2_GLOBAL(0x00F64E08, sint32) = cableLift->velocity; + RCT2_GLOBAL(0x00F64E0C, sint32) = (cableLift->velocity / 1024) * 42; + + rct_vehicle* frontVehicle = cableLift; + if (cableLift->velocity < 0) { + frontVehicle = vehicle_get_tail(cableLift); + } + + RCT2_GLOBAL(0x00F64E00, rct_vehicle*) = frontVehicle; + + for (rct_vehicle* vehicle = frontVehicle;;) { + vehicle->acceleration = RCT2_ADDRESS(0x009A2970, sint32)[vehicle->vehicle_sprite_type]; + RCT2_GLOBAL(0x00F64E10, uint32) = 1; + vehicle->remaining_distance += RCT2_GLOBAL(0x00F64E0C, sint32); + + if (vehicle->remaining_distance < 0 || vehicle->remaining_distance >= 13962) { + rct_xyz16 *unk_F64E20 = RCT2_ADDRESS(0x00F64E20, rct_xyz16); + unk_F64E20->x = vehicle->x; + unk_F64E20->y = vehicle->y; + unk_F64E20->z = vehicle->z; + invalidate_sprite_2((rct_sprite*)vehicle); + + while (true) { + if (vehicle->remaining_distance < 0) { + if (sub_6DF21B_loop(vehicle) == true) { + break; + } + else { + RCT2_GLOBAL(0x00F64E18, uint32) |= (1 << 5); + RCT2_GLOBAL(0x00F64E0C, uint32) -= vehicle->remaining_distance - 13962; + vehicle->remaining_distance = 13962; + vehicle->acceleration += RCT2_ADDRESS(0x009A2970, uint32)[vehicle->vehicle_sprite_type]; + RCT2_GLOBAL(0x00F64E10, uint32)++; + continue; + } + } + else { + if (sub_6DF01A_loop(vehicle) == true) { + break; + } + else { + RCT2_GLOBAL(0x00F64E18, uint32) |= (1 << 5); + RCT2_GLOBAL(0x00F64E0C, uint32) -= vehicle->remaining_distance + 1; + vehicle->remaining_distance = -1; + vehicle->acceleration += RCT2_ADDRESS(0x009A2970, uint32)[vehicle->vehicle_sprite_type]; + RCT2_GLOBAL(0x00F64E10, uint32)++; + } + } + } + sprite_move( + unk_F64E20->x, + unk_F64E20->y, + unk_F64E20->z, + (rct_sprite*)vehicle); + + invalidate_sprite_2((rct_sprite*)vehicle); + } + vehicle->acceleration /= RCT2_GLOBAL(0x00F64E10, uint32); + if (RCT2_GLOBAL(0x00F64E08, sint32) >= 0) { + if (vehicle->next_vehicle_on_train == 0xFFFF) + break; + vehicle = GET_VEHICLE(vehicle->next_vehicle_on_train); + } + else { + if (vehicle == cableLift) + break; + vehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride); + } + } + + uint32 vehicleCount = 0; + uint16 frictionTotal = 0; + sint32 var2CTotal = 0; + + for (uint16 spriteId = cableLift->sprite_index; spriteId != 0xFFFF;) { + rct_vehicle* vehicle = GET_VEHICLE(spriteId); + vehicleCount++; + frictionTotal += vehicle->friction; + var2CTotal += vehicle->acceleration; + spriteId = vehicle->next_vehicle_on_train; + } + + sint32 ecx = (var2CTotal / vehicleCount) >> 9; + ecx -= cableLift->velocity >> 12; + + sint32 edx = cableLift->velocity >> 8; + edx *= edx; + if (cableLift->velocity < 0) + edx = -edx; + edx >>= 4; + ecx -= edx / frictionTotal; + + cableLift->acceleration = ecx; + return RCT2_GLOBAL(0x00F64E18, uint32); +} diff --git a/src/ride/cable_lift.h b/src/ride/cable_lift.h new file mode 100644 index 0000000000..95b32757c4 --- /dev/null +++ b/src/ride/cable_lift.h @@ -0,0 +1,11 @@ +#ifndef _CABLE_LIFT_H_ +#define _CABLE_LIFT_H_ + +#include "../common.h" +#include "vehicle.h" + +rct_vehicle *cable_lift_segment_create(int rideIndex, int x, int y, int z, int direction, uint16 var_44, sint32 remaining_distance, bool head); +void cable_lift_update(rct_vehicle *vehicle); +int cable_lift_update_track_motion(rct_vehicle *cableLift); + +#endif diff --git a/src/ride/ride.c b/src/ride/ride.c index 7340a3e298..4ea00806fc 100644 --- a/src/ride/ride.c +++ b/src/ride/ride.c @@ -45,6 +45,8 @@ #include "../world/map.h" #include "../world/map_animation.h" #include "../world/sprite.h" +#include "../world/scenery.h" +#include "cable_lift.h" #include "ride.h" #include "ride_data.h" #include "track.h" @@ -126,8 +128,8 @@ static const int RideInspectionInterval[] = { 10, 20, 30, 45, 60, 120, 0, 0 }; -rct_ride_type **gRideTypeList = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_type*); -rct_ride* g_ride_list = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride); +rct_ride_entry **gRideTypeList = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_ENTRIES, rct_ride_entry*); +rct_ride* gRideList = RCT2_ADDRESS(RCT2_ADDRESS_RIDE_LIST, rct_ride); bool gGotoStartPlacementMode = false; int gRideRemoveTrackPieceCallbackX; int gRideRemoveTrackPieceCallbackY; @@ -154,10 +156,44 @@ static void ride_update(int rideIndex); static void ride_update_vehicle_colours(int rideIndex); static void ride_set_vehicle_colours_to_random_preset(rct_ride *ride, uint8 preset_index); static void maze_entrance_hedge_removal(int x, int y, rct_map_element *mapElement); +void loc_6DDF9C(rct_ride *ride, rct_map_element *mapElement); +static void maze_entrance_hedge_replacement(int x, int y, rct_map_element *mapElement); -rct_ride_type *ride_get_entry(rct_ride *ride) +rct_ride *get_ride(int index) { - return GET_RIDE_ENTRY(ride->subtype); + if (index < 0 || index >= MAX_RIDES) + { + log_error("invalid index %d for ride", index); + return NULL; + } + return &gRideList[index]; +} + +rct_ride_entry *get_ride_entry(int index) +{ + if (index < 0 || index >= object_entry_group_counts[0]) + { + log_error("invalid index %d for ride type", index); + return NULL; + } + return gRideTypeList[index]; +} + +rct_ride_measurement *get_ride_measurement(int index) +{ + return &(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement)[index]); +} + +rct_ride_entry *get_ride_entry_by_ride(rct_ride *ride) +{ + rct_ride_entry *type = get_ride_entry(ride->subtype); + if (type == NULL) + { + char oldname[128]; + format_string(oldname, ride->name, &ride->name_arguments); + log_error("Invalid ride subtype for ride %s", oldname); + } + return type; } /** @@ -212,8 +248,9 @@ int ride_get_max_queue_time(rct_ride *ride) } /** - * rct2: 0x006AC916 - */ + * + * rct2: 0x006AC916 + */ void ride_update_favourited_stat() { int i; @@ -228,7 +265,7 @@ void ride_update_favourited_stat() if (peep->linked_list_type_offset != SPRITE_LINKEDLIST_OFFSET_PEEP) return; if (peep->favourite_ride != 0xff) { - ride = &g_ride_list[peep->favourite_ride]; + ride = &gRideList[peep->favourite_ride]; ride->guests_favourite++; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER; @@ -269,27 +306,20 @@ money16 get_shop_hot_value(int shopItem) /** * - * rct2: 0x006AC3AB + * rct2: 0x006AC3AB */ money32 ride_calculate_income_per_hour(rct_ride *ride) { - rct_ride_type *entry; - money32 incomePerHour, priceMinusCost; + rct_ride_entry *entry; + money32 customersPerHour, priceMinusCost; int currentShopItem; - entry = GET_RIDE_ENTRY(ride->subtype); - incomePerHour = - ride->var_124 + - ride->var_126 + - ride->var_128 + - ride->var_12A + - ride->var_12C + - ride->var_12E + - ride->age + - ride->running_cost + - ride->var_134 + - ride->var_136; - incomePerHour *= 12; + // Get entry by ride to provide better reporting + entry = get_ride_entry_by_ride(ride); + if (entry == NULL) { + return 0; + } + customersPerHour = ride_customers_per_hour(ride); priceMinusCost = ride->price; currentShopItem = entry->shop_item; @@ -309,27 +339,22 @@ money32 ride_calculate_income_per_hour(rct_ride *ride) priceMinusCost /= 2; } - incomePerHour *= priceMinusCost; - return incomePerHour; + return customersPerHour * priceMinusCost; } /** * - * rct2: 0x006CAF80 + * rct2: 0x006CAF80 * ax result x * bx result y * dl ride index * esi result map element */ -int sub_6CAF80(int rideIndex, rct_xy_element *output) +bool ride_try_get_origin_element(int rideIndex, rct_xy_element *output) { + rct_map_element *resultMapElement = NULL; + map_element_iterator it; - rct_map_element *resultMapElement; - int foundSpecialTrackPiece; - - resultMapElement = NULL; - foundSpecialTrackPiece = 0; - map_element_iterator_begin(&it); do { if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_TRACK) @@ -340,9 +365,9 @@ int sub_6CAF80(int rideIndex, rct_xy_element *output) // Found a track piece for target ride // Check if its not the station or ??? (but allow end piece of station) - int specialTrackPiece = ( - it.element->properties.track.type != 2 && - it.element->properties.track.type != 3 && + bool specialTrackPiece = ( + it.element->properties.track.type != TRACK_ELEM_BEGIN_STATION && + it.element->properties.track.type != TRACK_ELEM_MIDDLE_STATION && (RCT2_ADDRESS(0x0099BA64, uint8)[it.element->properties.track.type * 16] & 0x10) ); @@ -358,8 +383,7 @@ int sub_6CAF80(int rideIndex, rct_xy_element *output) } if (specialTrackPiece) { - foundSpecialTrackPiece = 1; - return 1; + return true; } } while (map_element_iterator_next(&it)); @@ -376,12 +400,11 @@ int sub_6CAF80(int rideIndex, rct_xy_element *output) */ bool track_block_get_next_from_zero(sint16 x, sint16 y, sint16 z_start, uint8 rideIndex, uint8 direction_start, rct_xy_element *output, int *z, int *direction) { - rct_ride* ride = GET_RIDE(rideIndex); - RCT2_GLOBAL(0x00F441D3, uint8) = direction_start; + rct_ride* ride = get_ride(rideIndex); if (!(direction_start & (1 << 2))){ - x += RCT2_ADDRESS(0x00993CCC, sint16)[RCT2_GLOBAL(0x00F441D3, uint8) * 2]; - y += RCT2_ADDRESS(0x00993CCE, sint16)[RCT2_GLOBAL(0x00F441D3, uint8) * 2]; + x += TileDirectionDelta[direction_start].x; + y += TileDirectionDelta[direction_start].y; } rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32); @@ -409,7 +432,7 @@ bool track_block_get_next_from_zero(sint16 x, sint16 y, sint16 z_start, uint8 ri (mapElement->type & MAP_ELEMENT_DIRECTION_MASK)) & MAP_ELEMENT_DIRECTION_MASK) | (nextTrackCoordinate->rotation_begin & (1 << 2)); - if (nextRotation != RCT2_GLOBAL(0x00F441D3, uint8)) + if (nextRotation != direction_start) continue; sint16 nextZ = nextTrackCoordinate->z_begin - nextTrackBlock->z + mapElement->base_height * 8; @@ -424,7 +447,7 @@ bool track_block_get_next_from_zero(sint16 x, sint16 y, sint16 z_start, uint8 ri return 1; } while (!map_element_is_last_for_tile(mapElement++)); - if (direction != NULL) *direction = RCT2_GLOBAL(0x00F441D3, uint8); + if (direction != NULL) *direction = direction_start; if (z != NULL) *z = z_start; output->x = x; output->y = y; @@ -434,13 +457,12 @@ bool track_block_get_next_from_zero(sint16 x, sint16 y, sint16 z_start, uint8 ri /** * - * rct2: 0x006C60C2 + * rct2: 0x006C60C2 */ bool track_block_get_next(rct_xy_element *input, rct_xy_element *output, int *z, int *direction) { uint8 rideIndex = input->element->properties.track.ride_index; - RCT2_GLOBAL(0x00F441D2, uint8) = rideIndex; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); const rct_preview_track* trackBlock = get_track_def_from_ride(ride, input->element->properties.track.type); uint8 sequence = input->element->properties.track.sequence & 0xF; @@ -489,22 +511,23 @@ bool track_block_get_next(rct_xy_element *input, rct_xy_element *output, int *z, return track_block_get_next_from_zero(x, y, OriginZ, rideIndex, directionStart, output, z, direction); } -/* rct2: 0x006C63D6 - * Returns the begin position / direction and end position / direction of the track piece that procedes the given location. - * Gets the previous track block coordinates from the - * coordinates of the first of element of a track block. - * Use track_block_get_previous if you are unsure if you are - * on the first element of a track block +/** + * Returns the begin position / direction and end position / direction of the + * track piece that procedes the given location. Gets the previous track block + * coordinates from the coordinates of the first of element of a track block. + * Use track_block_get_previous if you are unsure if you are on the first + * element of a track block + * rct2: 0x006C63D6 */ bool track_block_get_previous_from_zero(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8 direction, track_begin_end *outTrackBeginEnd){ - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); - RCT2_GLOBAL(0x00F441D3, uint8) = direction; + uint8 directionStart = direction; direction ^= (1 << 1); if (!(direction & (1 << 2))){ - x += RCT2_ADDRESS(0x00993CCC, sint16)[direction * 2]; - y += RCT2_ADDRESS(0x00993CCE, sint16)[direction * 2]; + x += TileDirectionDelta[direction].x; + y += TileDirectionDelta[direction].y; } rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32); @@ -512,7 +535,7 @@ bool track_block_get_previous_from_zero(sint16 x, sint16 y, sint16 z, uint8 ride outTrackBeginEnd->end_x = x; outTrackBeginEnd->end_y = y; outTrackBeginEnd->begin_element = NULL; - outTrackBeginEnd->begin_direction = RCT2_GLOBAL(0x00F441D3, uint8) ^ (1 << 1); + outTrackBeginEnd->begin_direction = directionStart ^ (1 << 1); return 0; } @@ -535,7 +558,7 @@ bool track_block_get_previous_from_zero(sint16 x, sint16 y, sint16 z, uint8 ride (mapElement->type & MAP_ELEMENT_DIRECTION_MASK)) & MAP_ELEMENT_DIRECTION_MASK) | (nextTrackCoordinate->rotation_end & (1 << 2)); - if (nextRotation != RCT2_GLOBAL(0x00F441D3, uint8)) + if (nextRotation != directionStart) continue; sint16 nextZ = nextTrackCoordinate->z_end - nextTrackBlock->z + mapElement->base_height * 8; @@ -576,7 +599,7 @@ bool track_block_get_previous_from_zero(sint16 x, sint16 y, sint16 z, uint8 ride nextTrackBlock->z; outTrackBeginEnd->begin_direction = nextRotation; - outTrackBeginEnd->end_direction = RCT2_GLOBAL(0x00F441D3, uint8) ^ (1 << 1); + outTrackBeginEnd->end_direction = directionStart ^ (1 << 1); return 1; } while (!map_element_is_last_for_tile(mapElement++)); @@ -584,22 +607,22 @@ bool track_block_get_previous_from_zero(sint16 x, sint16 y, sint16 z, uint8 ride outTrackBeginEnd->end_y = y; outTrackBeginEnd->begin_z = z; outTrackBeginEnd->begin_element = NULL; - outTrackBeginEnd->end_direction = RCT2_GLOBAL(0x00F441D3, uint8) ^ (1 << 1); + outTrackBeginEnd->end_direction = directionStart ^ (1 << 1); return 0; } /** * - * rct2: 0x006C6402 + * rct2: 0x006C6402 * - * @remarks outTrackBeginEnd.begin_x and outTrackBeginEnd.begin_y will be in the higher two bytes of ecx and edx where as - outTrackBeginEnd.end_x and outTrackBeginEnd.end_y will be in the lower two bytes (cx and dx). + * @remarks outTrackBeginEnd.begin_x and outTrackBeginEnd.begin_y will be in the + * higher two bytes of ecx and edx where as outTrackBeginEnd.end_x and + * outTrackBeginEnd.end_y will be in the lower two bytes (cx and dx). */ bool track_block_get_previous(int x, int y, rct_map_element *mapElement, track_begin_end *outTrackBeginEnd) { uint8 rideIndex = mapElement->properties.track.ride_index; - RCT2_GLOBAL(0x00F441D2, uint8) = rideIndex; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); const rct_preview_track* trackBlock = get_track_def_from_ride(ride, mapElement->properties.track.type); uint8 sequence = mapElement->properties.track.sequence & 0xF; @@ -642,7 +665,7 @@ bool track_block_get_previous(int x, int y, rct_map_element *mapElement, track_b /** * * Make sure to pass in the x and y of the start track element too. - * rct2: 0x006CB02F + * rct2: 0x006CB02F * ax result x * bx result y * esi input / output map element @@ -655,7 +678,7 @@ int ride_find_track_gap(rct_xy_element *input, rct_xy_element *output) int rideIndex; rideIndex = input->element->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_MAZE) return 0; @@ -685,7 +708,7 @@ int ride_find_track_gap(rct_xy_element *input, rct_xy_element *output) */ void ride_get_status(int rideIndex, int *formatSecondary, int *argument) { - rct_ride *ride = &g_ride_list[rideIndex]; + rct_ride *ride = get_ride(rideIndex); if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) { *formatSecondary = STR_CRASHED; @@ -697,6 +720,17 @@ void ride_get_status(int rideIndex, int *formatSecondary, int *argument) } if (ride->status == RIDE_STATUS_CLOSED) { *formatSecondary = STR_CLOSED; + + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) { + *argument = ride->num_riders; + + if (*argument == 1) { + *formatSecondary = STR_CLOSED_WITH_PERSON; + } else if (*argument > 1) { + *formatSecondary = STR_CLOSED_WITH_PEOPLE; + } + } + return; } if (ride->status == RIDE_STATUS_TESTING) { @@ -775,7 +809,7 @@ void ride_init_all() rct_ride_measurement *ride_measurement; for (i = 0; i < MAX_RIDES; i++) { - ride = &g_ride_list[i]; + ride = get_ride(i); ride->type = RIDE_TYPE_NULL; } @@ -783,7 +817,7 @@ void ride_init_all() RCT2_GLOBAL(0x0138B591, sint8) = 0; for (i = 0; i < MAX_RIDE_MEASUREMENTS; i++) { - ride_measurement = GET_RIDE_MEASUREMENT(i); + ride_measurement = get_ride_measurement(i); ride_measurement->ride_index = 255; } } @@ -807,16 +841,21 @@ void reset_all_ride_build_dates() static int ride_check_if_construction_allowed(rct_ride *ride) { + rct_ride_entry *rideType = get_ride_entry_by_ride(ride); + if (rideType == NULL) { + window_error_open(STR_INVALID_RIDE_TYPE, STR_CANT_EDIT_INVALID_RIDE_TYPE); + return 0; + } if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { - RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING); return 0; } if (ride->status != RIDE_STATUS_CLOSED) { - RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_MUST_BE_CLOSED_FIRST); return 0; } @@ -844,7 +883,7 @@ static rct_window *ride_create_or_find_construction_window(int rideIndex) int ride_create_ride(ride_list_item listItem) { int eax, ebx, ecx, edx, esi, edi, ebp; - edx = *((uint16*)&listItem); + edx = listItem.ride_type_and_entry; eax = 0; ecx = 0; ebx = GAME_COMMAND_FLAG_APPLY; @@ -861,7 +900,7 @@ int ride_create_ride(ride_list_item listItem) /** * - * rct2: 0x006B4800 + * rct2: 0x006B4800 */ void ride_construct_new(ride_list_item listItem) { @@ -877,14 +916,14 @@ void ride_construct_new(ride_list_item listItem) /** * - * rct2: 0x006B4857 + * rct2: 0x006B4857 */ void ride_construct(int rideIndex) { rct_xy_element trackElement; rct_window *w; - if (sub_6CAF80(rideIndex, &trackElement)) { + if (ride_try_get_origin_element(rideIndex, &trackElement)) { ride_find_track_gap(&trackElement, &trackElement); w = window_get_main(); @@ -897,7 +936,7 @@ void ride_construct(int rideIndex) /** * - * rct2: 0x006DD4D5 + * rct2: 0x006DD4D5 */ static void ride_remove_cable_lift(rct_ride *ride) { @@ -918,7 +957,7 @@ static void ride_remove_cable_lift(rct_ride *ride) /** * - * rct2: 0x006DD506 + * rct2: 0x006DD506 */ static void ride_remove_vehicles(rct_ride *ride) { @@ -943,20 +982,20 @@ static void ride_remove_vehicles(rct_ride *ride) } for (i = 0; i < 4; i++) - ride->var_066[i] = 255; + ride->train_at_station[i] = 255; } } /** * - * rct2: 0x006DD4AC + * rct2: 0x006DD4AC */ void ride_clear_for_construction(int rideIndex) { rct_ride *ride; rct_window *w; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); ride_measurement_clear(ride); @@ -973,7 +1012,7 @@ void ride_clear_for_construction(int rideIndex) /** * - * rct2: 0x006664DF + * rct2: 0x006664DF */ void ride_remove_peeps(int rideIndex) { @@ -983,7 +1022,7 @@ void ride_remove_peeps(int rideIndex) rct_map_element *mapElement; rct_peep *peep; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); // Find first station stationIndex = -1; @@ -1004,7 +1043,7 @@ void ride_remove_peeps(int rideIndex) exitZ = ride->station_heights[stationIndex]; mapElement = ride_get_station_exit_element(ride, exitX, exitY, exitZ); - exitDirection = mapElement->type & 3; + exitDirection = (mapElement == NULL ? 0 : mapElement->type & MAP_ELEMENT_DIRECTION_MASK); exitX = (exitX * 32) - (RCT2_ADDRESS(0x00981D6C, sint16)[exitDirection * 2] * 20) + 16; exitY = (exitY * 32) - (RCT2_ADDRESS(0x00981D6E, sint16)[exitDirection * 2] * 20) + 16; exitZ = (exitZ * 8) + 2; @@ -1057,13 +1096,13 @@ void ride_remove_peeps(int rideIndex) } ride->num_riders = 0; - ride->var_15D = 0; + ride->slide_in_use = 0; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN; } /** * Gets the origin track element (sequence 0). Seems to do more than that though and even invalidates track. - * rct2: 0x006C683D + * rct2: 0x006C683D * ax : x * bx : direction << 8, type * cx : y @@ -1209,7 +1248,7 @@ int sub_6C683D(int* x, int* y, int* z, int direction, int type, uint16 extra_par /** * - * rct2: 0x006C96C0 + * rct2: 0x006C96C0 */ void sub_6C96C0() { @@ -1232,13 +1271,12 @@ void sub_6C96C0() _currentTrackSelectionFlags &= ~2; rideIndex = _currentRideIndex; - RCT2_GLOBAL(0x00F441D2, uint8) = rideIndex; x = RCT2_GLOBAL(0x00F440C5, uint16); y = RCT2_GLOBAL(0x00F440C7, uint16); z = RCT2_GLOBAL(0x00F440C9, uint16); - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_MAZE) { game_do_command(x , 41 | (0 << 8), y , rideIndex | (2 << 8), GAME_COMMAND_SET_MAZE_TRACK, z, 0); game_do_command(x , 41 | (1 << 8), y + 16, rideIndex | (2 << 8), GAME_COMMAND_SET_MAZE_TRACK, z, 0); @@ -1311,14 +1349,14 @@ void sub_6C9627() /** * - * rct2: 0x006C9B19 + * rct2: 0x006C9B19 */ static void ride_construction_reset_current_piece() { rct_ride *ride; - ride = GET_RIDE(_currentRideIndex); - if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15) || ride->num_stations == 0) { + ride = get_ride(_currentRideIndex); + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK) || ride->num_stations == 0) { _currentTrackCurve = RCT2_GLOBAL(0x0097CC68 + (ride->type * 2), uint8) | 0x100; _currentTrackSlopeEnd = 0; _currentTrackBankEnd = 0; @@ -1337,7 +1375,7 @@ static void ride_construction_reset_current_piece() /** * - * rct2: 0x006C9800 + * rct2: 0x006C9800 */ void ride_construction_set_default_next_piece() { @@ -1351,9 +1389,8 @@ void ride_construction_set_default_next_piece() switch (_rideConstructionState) { case RIDE_CONSTRUCTION_STATE_FRONT: rideIndex = _currentRideIndex; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); - RCT2_GLOBAL(0x00F441D2, uint8) = rideIndex; x = _currentTrackBeginX; y = _currentTrackBeginY; z = _currentTrackBeginZ; @@ -1365,7 +1402,7 @@ void ride_construction_set_default_next_piece() mapElement = trackBeginEnd.begin_element; trackType = mapElement->properties.track.type; - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15)) { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK)) { ride_construction_reset_current_piece(); return; } @@ -1408,9 +1445,8 @@ void ride_construction_set_default_next_piece() break; case RIDE_CONSTRUCTION_STATE_BACK: rideIndex = _currentRideIndex; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); - RCT2_GLOBAL(0x00F441D2, uint8) = rideIndex; x = _currentTrackBeginX; y = _currentTrackBeginY; z = _currentTrackBeginZ; @@ -1463,7 +1499,7 @@ void ride_construction_set_default_next_piece() /** * - * rct2: 0x006C9296 + * rct2: 0x006C9296 */ void ride_select_next_section() { @@ -1521,7 +1557,7 @@ void ride_select_next_section() /** * - * rct2: 0x006C93B8 + * rct2: 0x006C93B8 */ void ride_select_previous_section() { @@ -1571,7 +1607,7 @@ void ride_select_previous_section() /** * - * rct2: 0x006CC2CA + * rct2: 0x006CC2CA */ static int ride_modify_entrance_or_exit(rct_map_element *mapElement, int x, int y) { @@ -1600,7 +1636,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, uint8) & INPUT_FLAG_TOOL_ACTIVE) || + !(gInputFlags & INPUT_FLAG_TOOL_ACTIVE) || RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) != WC_RIDE_CONSTRUCTION ) { // Replace entrance / exit @@ -1608,7 +1644,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, uint8) |= 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; @@ -1629,7 +1665,7 @@ static int ride_modify_entrance_or_exit(rct_map_element *mapElement, int x, int /** * - * rct2: 0x006CC287 + * rct2: 0x006CC287 */ int ride_modify_maze(rct_map_element *mapElement, int x, int y) { @@ -1646,25 +1682,30 @@ int ride_modify_maze(rct_map_element *mapElement, int x, int y) /** * - * rct2: 0x006CC056 + * rct2: 0x006CC056 */ int ride_modify(rct_xy_element *input) { int rideIndex, x, y, z, direction, type; rct_xy_element mapElement, endOfTrackElement; rct_ride *ride; + rct_ride_entry *rideType; rct_window *constructionWindow; mapElement = *input; rideIndex = mapElement.element->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); + if (ride == NULL) { + return 0; + } + rideType = get_ride_entry_by_ride(ride); - if (!ride_check_if_construction_allowed(ride)) + if ((rideType == NULL) || !ride_check_if_construction_allowed(ride)) return 0; if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) { - RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; window_error_open(STR_CANT_START_CONSTRUCTION_ON, STR_LOCAL_AUTHORITY_FORBIDS_DEMOLITION_OR_MODIFICATIONS_TO_THIS_RIDE); return 0; } @@ -1705,7 +1746,7 @@ int ride_modify(rct_xy_element *input) _currentTrackSelectionFlags = 0; _rideConstructionArrowPulseTime = 0; - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15)) { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK)) { sub_6C84CE(); return 1; } @@ -1744,7 +1785,7 @@ int ride_modify(rct_xy_element *input) /** * - * rct2: 0x006CC3FB + * rct2: 0x006CC3FB */ int sub_6CC3FB(int rideIndex) { @@ -1752,7 +1793,7 @@ int sub_6CC3FB(int rideIndex) rct_window *w; tool_cancel(); - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (!ride_check_if_construction_allowed(ride)) return 0; @@ -1763,9 +1804,9 @@ 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); + ride = get_ride(_currentRideIndex); _currentTrackCurve = RCT2_ADDRESS(0x0097CC68, uint8)[ride->type * 2] | 0x100; _currentTrackSlopeEnd = 0; @@ -1828,10 +1869,10 @@ void ride_update_all() static void ride_update(int rideIndex) { int i; - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); - if (ride->var_1CA != 0) - ride->var_1CA--; + if (ride->vehicle_change_timeout != 0) + ride->vehicle_change_timeout--; ride_music_update(rideIndex); @@ -1841,21 +1882,17 @@ static void ride_update(int rideIndex) ride_update_station(ride, i); // Update financial statistics - ride->var_122++; - if (ride->var_122 >= 960) { - ride->var_122 = 0; + ride->num_customers_timeout++; - ride->var_136 = ride->var_134; - ride->var_134 = ride->running_cost; - ride->running_cost = ride->age; - ride->age = ride->var_12E; - ride->var_12E = ride->var_12C; - ride->var_12C = ride->var_12A; - ride->var_12A = ride->var_128; - ride->var_128 = ride->var_126; - ride->var_126 = ride->var_124; - ride->var_124 = ride->var_120; - ride->var_120 = 0; + if (ride->num_customers_timeout >= 960) { + // This is meant to update about every 30 seconds + ride->num_customers_timeout = 0; + + // Shift number of customers history, start of the array is the most recent one + memmove(ride->num_customers + 1, ride->num_customers, 9 * sizeof(*(ride->num_customers))); + ride->num_customers[0] = ride->cur_num_customers; + + ride->cur_num_customers = 0; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER; ride->income_per_hour = ride_calculate_income_per_hour(ride); @@ -1900,35 +1937,33 @@ static void ride_update(int rideIndex) */ static void ride_chairlift_update(rct_ride *ride) { - int x, y, z, ax, bx, cx; + int x, y, z; if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) return; - if (!(ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED))) - return; - if (ride->breakdown_reason_pending == 0) + if ((ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) && + ride->breakdown_reason_pending == 0) return; - ax = ride->operation_option * 2048; - bx = ride->var_148; - cx = bx + ax; - ride->var_148 = cx; - if (bx >> 14 == cx >> 14) + uint16 old_chairlift_bullwheel_rotation = ride->chairlift_bullwheel_rotation >> 14; + ride->chairlift_bullwheel_rotation += ride->speed * 2048; + if (old_chairlift_bullwheel_rotation == ride->speed / 8) return; - x = (ride->var_13A & 0xFF) * 32; - y = (ride->var_13A >> 8) * 32; - z = ride->var_13E * 8; + x = ride->chairlift_bullwheel_location[0].x * 32; + y = ride->chairlift_bullwheel_location[0].y * 32; + z = ride->chairlift_bullwheel_z[0] * 8; map_invalidate_tile_zoom1(x, y, z, z + (4 * 8)); - x = (ride->var_13C & 0xFF) * 32; - y = (ride->var_13C >> 8) * 32; - z = ride->var_13F * 8; + x = ride->chairlift_bullwheel_location[1].x * 32; + y = ride->chairlift_bullwheel_location[1].y * 32; + z = ride->chairlift_bullwheel_z[1] * 8; map_invalidate_tile_zoom1(x, y, z, z + (4 * 8)); } /** - * rct2: 0x0069A3A2 + * + * rct2: 0x0069A3A2 * edi: ride (in code as bytes offset from start of rides list) * bl: happiness */ @@ -1944,7 +1979,9 @@ void ride_update_satisfaction(rct_ride* ride, uint8 happiness) { } } -/* rct2: 0x0069A3D7 +/** + * + * rct2: 0x0069A3D7 * Updates the ride popularity * edi : ride * bl : pop_amount @@ -1973,14 +2010,14 @@ static void ride_spiral_slide_update(rct_ride *ride) if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 3) return; - if (ride->var_15D == 0) + if (ride->slide_in_use == 0) return; - ride->var_176++; - if (ride->var_176 >= 48) { - ride->var_15D--; + ride->spiral_slide_progress++; + if (ride->spiral_slide_progress >= 48) { + ride->slide_in_use--; - peep = &(g_sprite_list[ride->maze_tiles].peep); + peep = GET_PEEP(ride->slide_peep); peep->destination_x++; } @@ -2090,7 +2127,7 @@ static int get_age_penalty(rct_ride *ride) { static void ride_breakdown_update(int rideIndex) { int breakdownReason, unreliabilityAccumulator; - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 255) return; @@ -2098,27 +2135,23 @@ static void ride_breakdown_update(int rideIndex) return; if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) - ride->var_19C++; + ride->downtime_history[0]++; if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 8191)) { - int ax = - ride->var_19C + - ride->var_19D + - ride->var_19E + - ride->var_19F + - ride->var_1A0 + - ride->var_1A2 + - ride->var_1A3; - ride->downtime = min(ax / 2, 100); + int totalDowntime = + ride->downtime_history[0] + + ride->downtime_history[1] + + ride->downtime_history[2] + + ride->downtime_history[3] + + ride->downtime_history[4] + + ride->downtime_history[5] + + ride->downtime_history[6] + + ride->downtime_history[7]; + ride->downtime = min(totalDowntime / 2, 100); - ride->var_1A3 = ride->var_1A2; - ride->var_1A2 = ride->var_1A1; - ride->var_1A1 = ride->var_1A0; - ride->var_1A0 = ride->var_19F; - ride->var_19F = ride->var_19E; - ride->var_19E = ride->var_19D; - ride->var_19D = ride->var_19C; - ride->var_19C = 0; + memmove(&ride->downtime_history[1], ride->downtime_history, sizeof(ride->downtime_history) - 1); + + ride->downtime_history[0] = 0; ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAINTENANCE; } @@ -2138,7 +2171,8 @@ static void ride_breakdown_update(int rideIndex) // // a 0.8% chance, less the breakdown factor which accumulates as the game // continues. - if ((ride->reliability == 0 || (int)(scenario_rand() & 0x2FFFFF) <= 1 + RIDE_INITIAL_RELIABILITY - ride->reliability) && !gConfigCheat.disable_all_breakdowns) { + if ((ride->reliability == 0 || (int)(scenario_rand() & 0x2FFFFF) <= 1 + RIDE_INITIAL_RELIABILITY - ride->reliability) + && !gCheatsDisableAllBreakdowns) { breakdownReason = ride_get_new_breakdown_problem(ride); if (breakdownReason != -1) ride_prepare_breakdown(rideIndex, breakdownReason); @@ -2152,13 +2186,13 @@ static void ride_breakdown_update(int rideIndex) static int ride_get_new_breakdown_problem(rct_ride *ride) { int availableBreakdownProblems, monthsOld, totalProbability, randomProbability, problemBits, breakdownProblem; - rct_ride_type *entry; + rct_ride_entry *entry; // Brake failure is more likely when its raining _breakdownProblemProbabilities[BREAKDOWN_BRAKES_FAILURE] = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, uint8) == 0 ? 3 : 20; - entry = ride_get_entry(ride); + entry = get_ride_entry_by_ride(ride); if (entry->flags & RIDE_ENTRY_FLAG_14) return -1; @@ -2197,7 +2231,7 @@ static int ride_get_new_breakdown_problem(rct_ride *ride) return -1; // If brakes failure is disabled, also take it out of the equation (see above comment why) - if (gConfigCheat.disable_brakes_failure) + if (gCheatsDisableBrakesFailure) return -1; monthsOld = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint8) - ride->build_date; @@ -2217,7 +2251,7 @@ void ride_prepare_breakdown(int rideIndex, int breakdownReason) rct_ride *ride; rct_vehicle *vehicle; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) return; @@ -2226,8 +2260,8 @@ void ride_prepare_breakdown(int rideIndex, int breakdownReason) ride->breakdown_reason_pending = breakdownReason; ride->mechanic_status = RIDE_MECHANIC_STATUS_UNDEFINED; - ride->var_1AC = 0; - ride->var_1AD = 0; + ride->breakdown_sound_modifier = 0; + ride->not_fixed_timeout = 0; switch (breakdownReason) { case BREAKDOWN_SAFETY_CUT_OUT: @@ -2289,11 +2323,13 @@ void ride_prepare_breakdown(int rideIndex, int breakdownReason) */ void ride_breakdown_add_news_item(int rideIndex) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); - RCT2_GLOBAL(0x0013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x0013CE952 + 2, uint32) = ride->name_arguments; - news_item_add_to_queue(NEWS_ITEM_RIDE, 1927, rideIndex); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; + if (gConfigNotifications.ride_broken_down) { + news_item_add_to_queue(NEWS_ITEM_RIDE, STR_RIDE_IS_BROKEN_DOWN, rideIndex); + } } /** @@ -2302,22 +2338,27 @@ void ride_breakdown_add_news_item(int rideIndex) */ static void ride_breakdown_status_update(int rideIndex) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); // Warn player if ride hasnt been fixed for ages if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { - ride->var_1AD++; - if (ride->var_1AD == 0) - ride->var_1AD -= 16; + ride->not_fixed_timeout++; + // When there has been a full 255 timeout ticks this + // will force timeout ticks to keep issueing news every + // 16 ticks. Note there is no reason to do this. + if (ride->not_fixed_timeout == 0) + ride->not_fixed_timeout -= 16; if ( - !(ride->var_1AD & 15) && + !(ride->not_fixed_timeout & 15) && ride->mechanic_status != RIDE_MECHANIC_STATUS_FIXING && ride->mechanic_status != RIDE_MECHANIC_STATUS_4 ) { - RCT2_GLOBAL(0x0013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x0013CE952 + 2, uint32) = ride->name_arguments; - news_item_add_to_queue(NEWS_ITEM_RIDE, 1929, rideIndex); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; + if (gConfigNotifications.ride_warnings) { + news_item_add_to_queue(NEWS_ITEM_RIDE, STR_RIDE_IS_STILL_NOT_FIXED, rideIndex); + } } } @@ -2334,7 +2375,7 @@ static void ride_mechanic_status_update(int rideIndex, int mechanicStatus) rct_ride *ride; rct_peep *mechanic; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); switch (mechanicStatus) { case RIDE_MECHANIC_STATUS_UNDEFINED: breakdownReason = ride->breakdown_reason_pending; @@ -2397,7 +2438,7 @@ static void ride_call_mechanic(int rideIndex, rct_peep *mechanic, int forInspect { rct_ride *ride; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); peep_decrement_num_riders(mechanic); mechanic->state = forInspection ? PEEP_STATE_HEADING_TO_INSPECTION : PEEP_STATE_ANSWERING; peep_window_state_update(mechanic); @@ -2419,7 +2460,7 @@ static void ride_call_closest_mechanic(int rideIndex) rct_peep *mechanic; int forInspection; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); forInspection = (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN)) == 0; mechanic = ride_find_closest_mechanic(ride, forInspection); @@ -2453,8 +2494,8 @@ rct_peep *ride_find_closest_mechanic(rct_ride *ride, int forInspection) x *= 32; y *= 32; direction = mapElement->type & 3; - x -= RCT2_ADDRESS(0x00993CCC, sint16)[direction * 2]; - y -= RCT2_ADDRESS(0x00993CCE, sint16)[direction * 2]; + x -= TileDirectionDelta[direction].x; + y -= TileDirectionDelta[direction].y; x += 16; y += 16; @@ -2472,7 +2513,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; @@ -2493,21 +2534,21 @@ rct_peep *find_closest_mechanic(int x, int y, int forInspection) } if (map_is_location_in_park(x, y)) - if (!mechanic_is_location_in_patrol(peep, x & 0xFFE0, y & 0xFFE0)) + if (!staff_is_location_in_patrol(peep, x & 0xFFE0, y & 0xFFE0)) continue; 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) @@ -2580,7 +2621,7 @@ static void ride_music_update(int rideIndex) { int x, y, z; rct_vehicle *vehicle; - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); if ( !(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_MUSIC_ON_DEFAULT) && @@ -2606,19 +2647,19 @@ static void ride_music_update(int rideIndex) if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN)) { if (ride->breakdown_reason_pending == BREAKDOWN_CONTROL_FAILURE) { if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 7)) - if (ride->var_1AC != 255) - ride->var_1AC++; + if (ride->breakdown_sound_modifier != 255) + ride->breakdown_sound_modifier++; } else { if ( (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) || ride->breakdown_reason_pending == BREAKDOWN_BRAKES_FAILURE || ride->breakdown_reason_pending == BREAKDOWN_CONTROL_FAILURE ) { - if (ride->var_1AC != 255) - ride->var_1AC++; + if (ride->breakdown_sound_modifier != 255) + ride->breakdown_sound_modifier++; } - if (ride->var_1AC == 255) { + if (ride->breakdown_sound_modifier == 255) { ride->music_tune_id = 255; return; } @@ -2629,7 +2670,7 @@ static void ride_music_update(int rideIndex) if (ride->music_tune_id == 255) { uint8 *musicStyleTunes = ride_music_style_tuneids[ride->music]; uint8 numTunes = *musicStyleTunes++; - ride->music_tune_id = musicStyleTunes[scenario_rand() % numTunes]; + ride->music_tune_id = musicStyleTunes[util_rand() % numTunes]; ride->music_position = 0; return; } @@ -2642,7 +2683,7 @@ static void ride_music_update(int rideIndex) // Alter sample rate for a power cut effect if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN)) { - sampleRate = ride->var_1AC * 70; + sampleRate = ride->breakdown_sound_modifier * 70; if (ride->breakdown_reason_pending != BREAKDOWN_CONTROL_FAILURE) sampleRate *= -1; sampleRate += 22050; @@ -2666,12 +2707,13 @@ void ride_measurement_clear(rct_ride *ride) if (ride->measurement_index == 255) return; - measurement = GET_RIDE_MEASUREMENT(ride->measurement_index); + measurement = get_ride_measurement(ride->measurement_index); measurement->ride_index = 255; ride->measurement_index = 255; } /** + * * rct2: 0x006B64F2 */ void ride_measurement_update(rct_ride_measurement *measurement) @@ -2681,7 +2723,7 @@ void ride_measurement_update(rct_ride_measurement *measurement) rct_vehicle *vehicle; int velocity, altitude, verticalG, lateralG; - ride = GET_RIDE(measurement->ride_index); + ride = get_ride(measurement->ride_index); spriteIndex = ride->vehicles[measurement->vehicle_index]; if (spriteIndex == SPRITE_INDEX_NULL) return; @@ -2689,7 +2731,7 @@ void ride_measurement_update(rct_ride_measurement *measurement) vehicle = GET_VEHICLE(spriteIndex); if (measurement->flags & RIDE_MEASUREMENT_FLAG_UNLOADING) { - if (vehicle->status != VEHICLE_STATUS_DEPARTING && vehicle->status != VEHICLE_STATUS_STOPPING) + if (vehicle->status != VEHICLE_STATUS_DEPARTING && vehicle->status != VEHICLE_STATUS_TRAVELLING_CABLE_LIFT) return; measurement->flags &= ~RIDE_MEASUREMENT_FLAG_UNLOADING; @@ -2703,7 +2745,12 @@ void ride_measurement_update(rct_ride_measurement *measurement) } uint8 trackType = (vehicle->track_type >> 2) & 0xFF; - if (trackType == 216 || trackType == 123 || trackType == 9 || trackType == 63 || trackType == 147 || trackType == 155) + if (trackType == 216 || + trackType == TRACK_ELEM_CABLE_LIFT_HILL || + trackType == TRACK_ELEM_25_DEG_UP_TO_FLAT || + trackType == TRACK_ELEM_60_DEG_UP_TO_FLAT || + trackType == TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT || + trackType == TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT) if (vehicle->velocity == 0) return; @@ -2742,6 +2789,7 @@ void ride_measurement_update(rct_ride_measurement *measurement) } /** + * * rct2: 0x006B6456 */ void ride_measurements_update() @@ -2757,11 +2805,11 @@ void ride_measurements_update() // For each ride measurement for (i = 0; i < MAX_RIDE_MEASUREMENTS; i++) { - measurement = GET_RIDE_MEASUREMENT(i); + measurement = get_ride_measurement(i); if (measurement->ride_index == 255) continue; - ride = GET_RIDE(measurement->ride_index); + ride = get_ride(measurement->ride_index); if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) continue; @@ -2775,7 +2823,7 @@ void ride_measurements_update() continue; vehicle = GET_VEHICLE(spriteIndex); - if (vehicle->status == VEHICLE_STATUS_DEPARTING || vehicle->status == VEHICLE_STATUS_STOPPING) { + if (vehicle->status == VEHICLE_STATUS_DEPARTING || vehicle->status == VEHICLE_STATUS_TRAVELLING_CABLE_LIFT) { measurement->vehicle_index = j; measurement->current_station = vehicle->current_station; measurement->flags |= RIDE_MEASUREMENT_FLAG_RUNNING; @@ -2795,7 +2843,7 @@ rct_ride_measurement *ride_get_existing_measurement(int rideIndex) rct_ride_measurement *measurement; for (i = 0; i < MAX_RIDE_MEASUREMENTS; i++) { - measurement = GET_RIDE_MEASUREMENT(i); + measurement = get_ride_measurement(i); if (measurement->ride_index == rideIndex) return measurement; } @@ -2809,7 +2857,7 @@ int ride_get_free_measurement() rct_ride_measurement *measurement; for (i = 0; i < MAX_RIDE_MEASUREMENTS; i++) { - measurement = GET_RIDE_MEASUREMENT(i); + measurement = get_ride_measurement(i); if (measurement->ride_index == 255) return i; } @@ -2819,7 +2867,7 @@ int ride_get_free_measurement() /** * - * rct2: 0x006B66D9 + * rct2: 0x006B66D9 */ rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message) { @@ -2828,7 +2876,7 @@ rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message uint32 lruTicks; int i, lruIndex; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); // Check if ride type supports data logging if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING)) { @@ -2846,7 +2894,7 @@ rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message lruIndex = 0; lruTicks = 0xFFFFFFFF; for (i = 0; i < MAX_RIDE_MEASUREMENTS; i++) { - measurement = GET_RIDE_MEASUREMENT(i); + measurement = get_ride_measurement(i); if (measurement->last_use_tick <= lruTicks) { lruTicks = measurement->last_use_tick; @@ -2855,10 +2903,10 @@ rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message } i = lruIndex; - measurement = GET_RIDE_MEASUREMENT(i); - GET_RIDE(measurement->ride_index)->measurement_index = 255; + measurement = get_ride_measurement(i); + get_ride(measurement->ride_index)->measurement_index = 255; } else { - measurement = GET_RIDE_MEASUREMENT(i); + measurement = get_ride_measurement(i); } measurement->ride_index = rideIndex; @@ -2876,7 +2924,7 @@ rct_ride_measurement *ride_get_measurement(int rideIndex, rct_string_id *message return measurement; } else { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = RideNameConvention[ride->type].vehicle_name; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = RideNameConvention[ride->type].station_name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = RideNameConvention[ride->type].station_name; if (message != NULL) *message = STR_DATA_LOGGING_WILL_START_WHEN_NEXT_LEAVES; return NULL; } @@ -2918,7 +2966,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) { - rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride_sub_type); + if (ride_sub_type >= 128) + { + return 0; + } + rct_ride_entry *rideEntry = get_ride_entry(ride_sub_type); + if (rideEntry == (rct_ride_entry *)0xFFFFFFFF) + { + return 0; + } vehicle_colour_preset_list *presetList = rideEntry->vehicle_preset_list; if (presetList->count == 255) return 255; @@ -2941,9 +2997,12 @@ static int ride_get_unused_preset_vehicle_colour(uint8 ride_type, uint8 ride_sub */ static void ride_set_vehicle_colours_to_random_preset(rct_ride *ride, uint8 preset_index) { - rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride->subtype); + rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); vehicle_colour_preset_list *presetList = rideEntry->vehicle_preset_list; + if (presetList->count != 255) { + assert(preset_index < presetList->count); + ride->colour_scheme_type = RIDE_COLOUR_SCHEME_ALL_SAME; vehicle_colour *preset = &presetList->list[preset_index]; ride->vehicle_colours[0].body_colour = preset->main; @@ -2965,8 +3024,9 @@ static void ride_set_vehicle_colours_to_random_preset(rct_ride *ride, uint8 pres #pragma region Reachability /** - * rct2: 0x006B7A5E - **/ + * + * rct2: 0x006B7A5E + */ void ride_check_all_reachable() { rct_ride *ride; @@ -2986,7 +3046,8 @@ void ride_check_all_reachable() } /** - * rct2: 0x006B7C59 + * + * rct2: 0x006B7C59 * @return 1 if the coordinate is reachable or has no entrance, 0 otherwise */ static int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, int index) @@ -3012,8 +3073,8 @@ static int ride_entrance_exit_is_reachable(uint16 coordinate, rct_ride* ride, in x *= 32; y *= 32; - x -= RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2]; - y -= RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2]; + x -= TileDirectionDelta[face_direction].x; + y -= TileDirectionDelta[face_direction].y; x /= 32; y /= 32; @@ -3032,16 +3093,20 @@ static void ride_entrance_exit_connected(rct_ride* ride, int ride_idx) if (entrance != 0xFFFF && !ride_entrance_exit_is_reachable(entrance, ride, i)) { // name of ride is parameter of the format string RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ride->name; - RCT2_GLOBAL(0x013CE954, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; + if (gConfigNotifications.ride_warnings) { news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx); + } ride->connected_message_throttle = 3; } if (exit != 0xFFFF && !ride_entrance_exit_is_reachable(exit, ride, i)) { // name of ride is parameter of the format string RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ride->name; - RCT2_GLOBAL(0x013CE954, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; + if (gConfigNotifications.ride_warnings) { news_item_add_to_queue(1, STR_EXIT_NOT_CONNECTED, ride_idx); + } ride->connected_message_throttle = 3; } @@ -3053,7 +3118,7 @@ static void ride_shop_connected(rct_ride* ride, int ride_idx) int x, y, count; rct_map_element *mapElement; - uint16 coordinate = ride->station_starts[0]; + uint16 coordinate = ride->station_starts[0]; if (coordinate == 0xFFFF) return; @@ -3068,7 +3133,7 @@ static void ride_shop_connected(rct_ride* ride, int ride_idx) uint16 entrance_directions = 0; uint8 track_type = mapElement->properties.track.type; - ride = &g_ride_list[mapElement->properties.track.ride_index]; + ride = get_ride(mapElement->properties.track.ride_index); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE)) { entrance_directions = RCT2_ADDRESS(0x0099CA64, uint8)[track_type * 16]; } else { @@ -3097,8 +3162,8 @@ static void ride_shop_connected(rct_ride* ride, int ride_idx) // Flip direction north<->south, east<->west uint8 face_direction = count ^ 2; - int y2 = y - RCT2_ADDRESS(0x00993CCE, sint16)[face_direction * 2]; - int x2 = x - RCT2_ADDRESS(0x00993CCC, sint16)[face_direction * 2]; + int y2 = y - TileDirectionDelta[face_direction].y; + int x2 = x - TileDirectionDelta[face_direction].x; if (map_coord_is_connected(x2 / 32, y2 / 32, mapElement->base_height, face_direction)) return; @@ -3106,8 +3171,10 @@ static void ride_shop_connected(rct_ride* ride, int ride_idx) // Name of ride is parameter of the format string RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ride->name; - RCT2_GLOBAL(0x013CE954, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; + if (gConfigNotifications.ride_warnings) { news_item_add_to_queue(1, STR_ENTRANCE_NOT_CONNECTED, ride_idx); + } ride->connected_message_throttle = 3; } @@ -3122,7 +3189,7 @@ static void ride_track_set_map_tooltip(rct_map_element *mapElement) rct_ride *ride; rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 0, uint16) = 2215; RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS + 2, uint16) = ride->name; @@ -3140,7 +3207,7 @@ static void ride_station_set_map_tooltip(rct_map_element *mapElement) rct_ride *ride; rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); stationIndex = map_get_station(mapElement); for (i = stationIndex; i >= 0; i--) @@ -3166,7 +3233,7 @@ static void ride_entrance_set_map_tooltip(rct_map_element *mapElement) rct_ride *ride; rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); // Get the station stationIndex = map_get_station(mapElement); @@ -3452,7 +3519,8 @@ void ride_music_update_final() rct_ride_music_params* edi = NULL; int ebx; if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)) { - if (!gGameSoundsOff && gConfigSound.sound && gConfigSound.ride_music && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) { + // TODO Allow circus music (CSS24) to play if ride music is disabled (that should be sound) + if (!gGameSoundsOff && gConfigSound.ride_music_enabled && !(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1)) { // set to stop music if volume <= 1 ? while (1) { int v8 = 0; @@ -3548,6 +3616,11 @@ void ride_music_update_final() offset = 0; } Mixer_Channel_SetOffset(ride_music->sound_channel, offset); + + // Move circus music to the sound mixer group + if (ride_music_info->path_id == PATH_ID_CSS24) { + Mixer_Channel_SetGroup(ride_music->sound_channel, MIXER_GROUP_SOUND); + } } return; } @@ -3574,121 +3647,218 @@ void ride_music_update_final() #pragma endregion -/* rct2: 0x006B5559 */ -void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +static bool ride_is_mode_valid(rct_ride *ride, uint8 mode) +{ + rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); + const uint8 *availableModes = ride_seek_available_modes(ride); + + if ((rideEntry->flags & RIDE_ENTRY_DISABLE_FIRST_TWO_OPERATING_MODES) && !gCheatsShowAllOperatingModes){ + availableModes += 2; + } + + for (; *availableModes != 0xFF; availableModes++) { + if (*availableModes == mode) { + return true; + } + } + + return false; +} + +static bool ride_is_valid_lift_hill_speed(rct_ride *ride, int speed) +{ + int minSpeed = gCheatsFastLiftHill ? 0 : RideLiftData[ride->type].minimum_speed; + int maxSpeed = gCheatsFastLiftHill ? 255 : RideLiftData[ride->type].maximum_speed; + return speed >= minSpeed && speed <= maxSpeed; +} + +static bool ride_is_valid_num_circuits(rct_ride *ride, int numCircuits) +{ + int minNumCircuits = 1; + int maxNumCircuits = gCheatsFastLiftHill ? 255 : 20; + return numCircuits >= minNumCircuits && numCircuits <= maxNumCircuits; +} + +static bool ride_is_valid_operation_option(rct_ride *ride, uint8 value) +{ + uint8 minValue = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 4, uint8); + uint8 maxValue = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 5, uint8); + if (ride->mode == RIDE_MODE_MAZE) { + // Allow 64 people in mazes under non-cheat settings. The old maximum of 16 was too little for even moderately big mazes. + maxValue = 64; + } + if (gCheatsFastLiftHill) { + minValue = 0; + maxValue = 255; + } + + return value >= minValue && value <= maxValue; +} + +static money32 ride_set_setting(uint8 rideIndex, uint8 setting, uint8 value, uint8 flags) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; - uint8 ride_id = *edx & 0xFF; - rct_ride* ride = GET_RIDE(ride_id); + rct_ride *ride = get_ride(rideIndex); + if (ride == NULL || ride->type == RIDE_TYPE_NULL) { + log_warning("Invalid ride: #%u.", rideIndex); + return MONEY32_UNDEFINED; + } - uint8 flags = *ebx & 0xFF; - uint8 new_value = (*ebx >> 8) & 0xFF; - - uint8 setting = (*edx >> 8) & 0xFF; - - if (setting == 0){ - if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN){ + switch (setting) { + case RIDE_SETTING_MODE: + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING; - *ebx = MONEY32_UNDEFINED; - return; + return MONEY32_UNDEFINED; } - if (ride->status != RIDE_STATUS_CLOSED){ + if (ride->status != RIDE_STATUS_CLOSED) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_MUST_BE_CLOSED_FIRST; - *ebx = MONEY32_UNDEFINED; - return; - } - } - - if (setting == 9 && - ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT && - new_value > 1){ - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_MULTICIRCUIT_NOT_POSSIBLE_WITH_CABLE_LIFT_HILL; - *ebx = MONEY32_UNDEFINED; - return; - } - - if (flags == 0){ - *ebx = 0; - return; - } - - switch (setting){ - case 0: - invalidate_test_results(ride_id); - ride_clear_for_construction(ride_id); - ride_remove_peeps(ride_id); - - rct_ride_type* ride_entry = GET_RIDE_ENTRY(ride->subtype); - const uint8* available_modes = ride_seek_available_modes(ride); - - if ((ride_entry->flags & RIDE_ENTRY_DISABLE_FIRST_TWO_OPERATING_MODES) && !gCheatsShowAllOperatingModes){ - available_modes += 2; + return MONEY32_UNDEFINED; } - uint8 default_mode = available_modes[0]; - for (; *available_modes != 0xFF; available_modes++){ - if (*available_modes == new_value) - break; + if (!ride_is_mode_valid(ride, value)) { + log_warning("Invalid ride mode."); + return MONEY32_UNDEFINED; } - if (*available_modes == 0xFF) new_value = default_mode; + if (flags & GAME_COMMAND_FLAG_APPLY) { + invalidate_test_results(rideIndex); + ride_clear_for_construction(rideIndex); + ride_remove_peeps(rideIndex); - if (available_modes[1] == 0xFF){ - if ((ride_entry->flags & RIDE_ENTRY_DISABLE_LAST_OPERATING_MODE) && !gCheatsShowAllOperatingModes) - new_value = default_mode; + ride->mode = value; + ride_update_max_vehicles(rideIndex); + } + break; + case RIDE_SETTING_DEPARTURE: + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride->depart_flags = value; + } + break; + case RIDE_SETTING_MIN_WAITING_TIME: + if (value > 250) { + log_warning("Invalid minimum waiting time."); + return MONEY32_UNDEFINED; } - ride->mode = new_value; - ride_update_max_vehicles(ride_id); - break; - case 1: - ride->depart_flags = new_value; - break; - case 2: - ride->min_waiting_time = new_value; - ride->max_waiting_time = max(new_value, ride->max_waiting_time); - break; - case 3: - ride->max_waiting_time = new_value; - ride->min_waiting_time = min(new_value, ride->min_waiting_time); - break; - case 4: - invalidate_test_results(ride_id); - ride->time_limit = new_value; - break; - case 5: - ride->inspection_interval = new_value; - break; - case 6: - ride->lifecycle_flags &= ~RIDE_LIFECYCLE_MUSIC; - if (new_value){ - ride->lifecycle_flags |= RIDE_LIFECYCLE_MUSIC; + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride->min_waiting_time = value; + ride->max_waiting_time = max(value, ride->max_waiting_time); } break; - case 7: - if (new_value != ride->music){ - ride->music = new_value; - ride->music_tune_id = 0xFF; + case RIDE_SETTING_MAX_WAITING_TIME: + if (value > 250) { + log_warning("Invalid maximum waiting time."); + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride->max_waiting_time = value; + ride->min_waiting_time = min(value, ride->min_waiting_time); } break; - case 8: - if (new_value != ride->lift_hill_speed){ - ride->lift_hill_speed = new_value; - invalidate_test_results(ride_id); + case RIDE_SETTING_OPERATION_OPTION: + if (!ride_is_valid_operation_option(ride, value)) { + log_warning("Invalid operation option value."); + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + invalidate_test_results(rideIndex); + ride->operation_option = value; } break; - case 9: - if (new_value != ride->num_circuits){ - ride->num_circuits = new_value; - invalidate_test_results(ride_id); + case RIDE_SETTING_INSPECTION_INTERVAL: + if (value > RIDE_INSPECTION_NEVER) { + log_warning("Invalid inspection interval."); + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride->inspection_interval = value; + } + break; + case RIDE_SETTING_MUSIC: + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_MUSIC; + if (value) { + ride->lifecycle_flags |= RIDE_LIFECYCLE_MUSIC; + } + } + break; + case RIDE_SETTING_MUSIC_TYPE: + if (value >= MUSIC_STYLE_COUNT) { + log_warning("Invalid music style."); + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + if (value != ride->music) { + ride->music = value; + ride->music_tune_id = 0xFF; + } + } + break; + case RIDE_SETTING_LIFT_HILL_SPEED: + if (!ride_is_valid_lift_hill_speed(ride, value)) { + log_warning("Invalid lift hill speed."); + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + if (value != ride->lift_hill_speed) { + ride->lift_hill_speed = value; + invalidate_test_results(rideIndex); + } + } + break; + case RIDE_SETTING_NUM_CIRCUITS: + if (ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT && value > 1) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_MULTICIRCUIT_NOT_POSSIBLE_WITH_CABLE_LIFT_HILL; + return MONEY32_UNDEFINED; + } + + if (!ride_is_valid_num_circuits(ride, value)) { + log_warning("Invalid number of circuits."); + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + if (value != ride->num_circuits) { + ride->num_circuits = value; + invalidate_test_results(rideIndex); + } } break; } - window_invalidate_by_number(WC_RIDE, ride_id); - *ebx = 0; + if (flags & GAME_COMMAND_FLAG_APPLY) { + if (ride->overall_view != (uint16)-1) { + rct_xyz16 coord; + coord.x = (ride->overall_view & 0xFF) * 32 + 16; + coord.y = (ride->overall_view >> 8) * 32 + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + + window_invalidate_by_number(WC_RIDE, rideIndex); + } + + return 0; +} + +/** + * + * rct2: 0x006B5559 + */ +void game_command_set_ride_setting(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + uint8 rideIndex = *edx & 0xFF; + uint8 setting = (*edx >> 8) & 0xFF; + uint8 newValue = (*ebx >> 8) & 0xFF; + uint8 flags = *ebx & 0xFF; + *ebx = ride_set_setting(rideIndex, setting, newValue, flags); } /** @@ -3725,7 +3895,8 @@ int ride_mode_check_valid_station_numbers(rct_ride *ride) return 1; } -/* returns stationIndex of first station on success +/** + * returns stationIndex of first station on success * -1 on failure. */ int ride_mode_check_station_present(rct_ride* ride){ @@ -3739,7 +3910,7 @@ int ride_mode_check_station_present(rct_ride* ride){ if (stationIndex == -1) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_NOT_YET_CONSTRUCTED; - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15)) + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK)) return -1; if (ride->type == RIDE_TYPE_MAZE) @@ -3758,7 +3929,7 @@ int ride_mode_check_station_present(rct_ride* ride){ */ int ride_check_for_entrance_exit(int rideIndex) { - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) return 1; @@ -3805,7 +3976,7 @@ int ride_check_for_entrance_exit(int rideIndex) */ void sub_6B5952(int rideIndex) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); for (int i = 0; i < 4; i++) { uint16 xy = ride->entrances[i]; @@ -3890,7 +4061,7 @@ bool ride_check_track_contains_inversions(rct_xy_element *input, rct_xy_element track_circuit_iterator it; rideIndex = input->element->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_MAZE) return true; @@ -3925,7 +4096,7 @@ bool ride_check_track_contains_banked(rct_xy_element *input, rct_xy_element *out track_circuit_iterator it; rideIndex = input->element->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_MAZE) return true; @@ -4006,7 +4177,7 @@ bool ride_check_start_and_end_is_station(rct_xy_element *input, rct_xy_element * rct_xy_element trackBack, trackFront; rideIndex = input->element->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); w = window_find_by_class(WC_RIDE_CONSTRUCTION); if (w != NULL && _rideConstructionState != RIDE_CONSTRUCTION_STATE_0 && rideIndex == _currentRideIndex) { @@ -4019,8 +4190,9 @@ bool ride_check_start_and_end_is_station(rct_xy_element *input, rct_xy_element * if (!(RCT2_GLOBAL(0x0099BA64 + (trackType * 16), uint32) & 0x10)) { return false; } - ride->var_13A = (trackBack.x >> 5) | ((trackBack.y >> 5) << 8); - ride->var_13E = trackBack.element->base_height; + ride->chairlift_bullwheel_location[0].x = trackBack.x >> 5; + ride->chairlift_bullwheel_location[0].y = trackBack.y >> 5; + ride->chairlift_bullwheel_z[0] = trackBack.element->base_height; // Check front of the track track_get_front(input, &trackFront); @@ -4028,8 +4200,9 @@ bool ride_check_start_and_end_is_station(rct_xy_element *input, rct_xy_element * if (!(RCT2_GLOBAL(0x0099BA64 + (trackType * 16), uint32) & 0x10)) { return false; } - ride->var_13C = (trackFront.x >> 5) | ((trackFront.y >> 5) << 8); - ride->var_13F = trackFront.element->base_height; + ride->chairlift_bullwheel_location[1].x = trackFront.x >> 5; + ride->chairlift_bullwheel_location[1].y = trackFront.y >> 5; + ride->chairlift_bullwheel_z[1] = trackFront.element->base_height; return true; } @@ -4138,7 +4311,7 @@ static void ride_set_block_points(rct_xy_element *startElement) */ void ride_set_start_finish_points(int rideIndex, rct_xy_element *startElement) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); switch (ride->type) { case RIDE_TYPE_BOAT_RIDE: @@ -4165,6 +4338,265 @@ static int sub_69ED9E() return max(0, miscSpriteCount + unkCount - 300); } +const rct_xy16 word_9A3AB4[4] = { + { 0, 0 }, + { 0, -96 }, + { -96, -96 }, + { -96, 0 }, +}; + +const rct_xy16 word_9A2A60[] = { + { 0, 16 }, + { 16, 31 }, + { 31, 16 }, + { 16, 0 }, + { 16, 16 }, + { 64, 64 }, + { 64, -32 }, + { -32, -32 }, + { -32, 64 }, +}; + +/** + * + * rct2: 0x006DD90D + */ +rct_vehicle *vehicle_create_car( + int rideIndex, + int vehicleEntryIndex, + int carIndex, + int vehicleIndex, + int x, + int y, + int z, + int *remainingDistance, + rct_map_element *mapElement +) { + registers regs = { 0 }; + + rct_ride *ride = get_ride(rideIndex); + rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); + rct_ride_entry_vehicle *vehicleEntry = &rideEntry->vehicles[vehicleEntryIndex]; + + rct_vehicle *vehicle = (rct_vehicle*)create_sprite(1); + vehicle->sprite_identifier = SPRITE_IDENTIFIER_VEHICLE; + vehicle->ride = rideIndex; + vehicle->ride_subtype = ride->subtype; + + vehicle->vehicle_type = vehicleEntryIndex; + vehicle->is_child = carIndex == 0 ? 0 : 1; + vehicle->var_44 = ror32(vehicleEntry->spacing, 10) & 0xFFFF; + regs.edx = vehicleEntry->spacing >> 1; + *remainingDistance -= regs.edx; + vehicle->remaining_distance = *remainingDistance; + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_14)) { + *remainingDistance -= regs.edx; + } + + // loc_6DD9A5: + vehicle->sprite_width = vehicleEntry->sprite_width; + vehicle->sprite_height_negative = vehicleEntry->sprite_height_negative; + vehicle->sprite_height_positive = vehicleEntry->sprite_height_positive; + vehicle->friction = vehicleEntry->car_friction; + vehicle->num_seats = vehicleEntry->num_seats; + vehicle->speed = vehicleEntry->powered_max_speed; + vehicle->powered_acceleration = vehicleEntry->powered_acceleration; + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->var_4A = 0; + vehicle->swinging_car_var_0 = 0; + vehicle->var_4E = 0; + vehicle->restraints_position = 0; + vehicle->var_BA = 0; + vehicle->var_B6 = 0; + vehicle->var_B8 = 0; + vehicle->sound1_id = 0xFF; + vehicle->sound2_id = 0xFF; + vehicle->next_vehicle_on_train = SPRITE_INDEX_NULL; + vehicle->var_C4 = 0; + vehicle->var_C5 = 0; + vehicle->var_C8 = 0; + vehicle->scream_sound_id = 255; + vehicle->vehicle_sprite_type = 0; + vehicle->bank_rotation = 0; + vehicle->target_seat_rotation = 4; + vehicle->seat_rotation = 4; + for (int i = 0; i < 32; i++) { + vehicle->peep[i] = SPRITE_INDEX_NULL; + } + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_15) { + // loc_6DDCA4: + vehicle->var_CD = 0; + int direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK; + x += word_9A3AB4[direction].x; + y += word_9A3AB4[direction].y; + z = mapElement->base_height * 8; + vehicle->track_x = x; + vehicle->track_y = y; + vehicle->track_z = z; + vehicle->current_station = map_get_station(mapElement); + + z += RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + + vehicle->track_type = mapElement->properties.track.type << 2; + vehicle->track_progress = 0; + vehicle->status = 0; + vehicle->sub_state = 0; + vehicle->update_flags = 0; + + rct_xy16 chosenLoc; + // loc_6DDD26: + do { + vehicle->sprite_direction = scenario_rand() & 0x1E; + chosenLoc.y = y + (scenario_rand() & 0xFF); + chosenLoc.x = x + (scenario_rand() & 0xFF); + } while (vehicle_update_bumper_car_collision(vehicle, chosenLoc.x, chosenLoc.y, NULL)); + + sprite_move(chosenLoc.x, chosenLoc.y, z, (rct_sprite*)vehicle); + } else { + regs.dl = 0; + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_12) { + regs.dl = 1; + } + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_14) { + // Choose which lane Go Kart should start in + regs.dl = 5; + if (vehicleIndex & 1) { + regs.dl = 6; + } + } + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_MINI_GOLF) { + regs.dl = 9; + vehicle->var_D3 = 0; + vehicle->var_D4 = 0; + vehicle->mini_golf_flags = 0; + } + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_4) { + if (!vehicle->is_child) { + regs.dl = 15; + } + } + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_5) { + regs.dl = 16; + } + vehicle->var_CD = regs.dl; + + vehicle->track_x = x; + vehicle->track_y = y; + + int direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK; + vehicle->sprite_direction = direction << 3; + + if (ride->type == RIDE_TYPE_SPACE_RINGS) { + direction = 4; + } else { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_16)) { + if (RCT2_GLOBAL(0x0097CC68 + (ride->type * 2), uint8) != 119) { + if (RCT2_GLOBAL(0x0097CC68 + (ride->type * 2), uint8) != 95) { + if (ride->type == RIDE_TYPE_ENTERPRISE) { + direction += 5; + } else { + direction = 4; + } + } + } + } + } + + x += word_9A2A60[direction].x; + y += word_9A2A60[direction].y; + vehicle->track_z = mapElement->base_height * 8; + + vehicle->current_station = map_get_station(mapElement); + z = mapElement->base_height * 8; + z += RCT2_GLOBAL(0x0097D21A + (ride->type * 8), uint8); + + sprite_move(x, y, z, (rct_sprite*)vehicle); + vehicle->track_type = (mapElement->properties.track.type << 2) | (vehicle->sprite_direction >> 3); + vehicle->track_progress = 31; + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_MINI_GOLF) { + vehicle->track_progress = 15; + } + vehicle->update_flags = VEHICLE_UPDATE_FLAG_1; + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_6) { + if (mapElement->properties.track.colour & 4) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_11; + } + } + vehicle->status = VEHICLE_STATUS_MOVING_TO_END_OF_STATION; + vehicle->sub_state = 0; + } + + // loc_6DDD5E: + vehicle->num_peeps = 0; + vehicle->next_free_seat = 0; + return vehicle; +} + +/** + * + * rct2: 0x006DD84C + */ +train_ref vehicle_create_train(int rideIndex, int x, int y, int z, int vehicleIndex, int *remainingDistance, rct_map_element *mapElement) +{ + rct_ride *ride = get_ride(rideIndex); + + uint8 trainLayout[42]; + ride_entry_get_train_layout(ride->subtype, ride->num_cars_per_train, trainLayout); + + train_ref train = { NULL, NULL }; + for (int carIndex = 0; carIndex < ride->num_cars_per_train; carIndex++) { + rct_vehicle *car = vehicle_create_car(rideIndex, trainLayout[carIndex], carIndex, vehicleIndex, x, y, z, remainingDistance, mapElement); + if (carIndex == 0) { + train.head = car; + } else { + // Link the previous car with this car + train.tail->next_vehicle_on_train = car->sprite_index; + train.tail->next_vehicle_on_ride = car->sprite_index; + car->prev_vehicle_on_ride = train.tail->sprite_index; + } + train.tail = car; + } + return train; +} + +void vehicle_create_trains(int rideIndex, int x, int y, int z, rct_map_element *mapElement) +{ + rct_ride *ride = get_ride(rideIndex); + train_ref firstTrain = { 0 }, lastTrain = { 0 }; + int remainingDistance = 0; + + for (int vehicleIndex = 0; vehicleIndex < ride->num_vehicles; vehicleIndex++) { + if (ride_is_block_sectioned(ride)) { + remainingDistance = 0; + } + train_ref train = vehicle_create_train(rideIndex, x, y, z, vehicleIndex, &remainingDistance, mapElement); + if (vehicleIndex == 0) { + firstTrain = train; + } else { + // Link the end of the previous train with the front of this train + lastTrain.tail->next_vehicle_on_ride = train.head->sprite_index; + train.head->prev_vehicle_on_ride = lastTrain.tail->sprite_index; + } + lastTrain = train; + + // Add train to ride vehicle list + move_sprite_to_list((rct_sprite*)train.head, SPRITE_LINKEDLIST_OFFSET_VEHICLE); + for (int i = 0; i < 32; i++) { + if (ride->vehicles[i] == SPRITE_INDEX_NULL) { + ride->vehicles[i] = train.head->sprite_index; + break; + } + } + } + + // Link the first train and last train together + firstTrain.head->prev_vehicle_on_ride = lastTrain.tail->sprite_index; + lastTrain.tail->next_vehicle_on_ride = firstTrain.head->sprite_index; +} + void vehicle_unset_var_48_b1(rct_vehicle *head) { uint16 spriteIndex; @@ -4199,8 +4631,8 @@ void ride_create_vehicles_find_first_block(rct_ride *ride, rct_xy_element *outXY rct_map_element *trackElement = firstElement; track_begin_end trackBeginEnd; while (track_block_get_previous(x, y, trackElement, &trackBeginEnd)) { - x = trackBeginEnd.begin_x; - y = trackBeginEnd.begin_y; + x = trackBeginEnd.end_x; + y = trackBeginEnd.end_y; trackElement = trackBeginEnd.begin_element; if (x == firstX && y == firstY && trackElement == firstElement) { break; @@ -4250,6 +4682,85 @@ void ride_create_vehicles_find_first_block(rct_ride *ride, rct_xy_element *outXY outXYElement->element = firstElement; } +/** + * + * rct2: 0x006DD84C + */ +bool ride_create_vehicles(rct_ride *ride, int rideIndex, rct_xy_element *element, int isApplying) +{ + ride_update_max_vehicles(rideIndex); + if (ride->subtype == 0xFF) { + return true; + } + + // Check if there are enough free sprite slots for all the vehicles + int totalCars = ride->num_vehicles * ride->num_cars_per_train; + if (totalCars > sub_69ED9E()) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_UNABLE_TO_CREATE_ENOUGH_VEHICLES; + return false; + } + + if (!isApplying) { + return true; + } + + rct_map_element *mapElement = element->element; + int x = element->x; + int y = element->y; + int z = element->element->base_height; + int direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK; + + // + if (ride->mode == RIDE_MODE_STATION_TO_STATION) { + x = element->x - TileDirectionDelta[direction].x; + y = element->y - TileDirectionDelta[direction].y; + + mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (mapElement->base_height != z) continue; + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + break; + } while (!map_element_is_last_for_tile(mapElement++)); + + z = mapElement->base_height; + direction = mapElement->type & MAP_ELEMENT_DIRECTION_MASK; + } + + vehicle_create_trains(rideIndex, x, y, z, mapElement); + // return true; + + // Initialise station departs +// 006DDDD0: + ride->lifecycle_flags |= RIDE_LIFECYCLE_ON_TRACK; + for (int i = 0; i < 4; i++) { + ride->station_depart[i] = (ride->station_depart[i] & 0x80) | 1; + } + + // + if (ride->type != RIDE_TYPE_SPACE_RINGS && !ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_16)) { + if (ride_is_block_sectioned(ride)) { + rct_xy_element firstBlock; + ride_create_vehicles_find_first_block(ride, &firstBlock); + loc_6DDF9C(ride, firstBlock.element); + } else { + for (int i = 0; i < ride->num_vehicles; i++) { + rct_vehicle *vehicle = GET_VEHICLE(ride->vehicles[i]); + + rct_ride_entry *rideType = get_ride_entry(vehicle->vehicle_type); + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_15)) { + vehicle_update_track_motion(vehicle, NULL); + } + + vehicle_unset_var_48_b1(vehicle); + } + } + } + ride_update_vehicle_colours(rideIndex); + return true; +} + /** * * rct2: 0x006DDF9C @@ -4261,19 +4772,21 @@ void loc_6DDF9C(rct_ride *ride, rct_map_element *mapElement) for (int i = 0; i < ride->num_vehicles; i++) { train = GET_VEHICLE(ride->vehicles[i]); if (i == 0) { - sub_6DAB4C(train, NULL); + vehicle_update_track_motion(train, NULL); vehicle_unset_var_48_b1(train); continue; } + vehicle_update_track_motion(train, NULL); + do { mapElement->flags |= (1 << 5); car = train; while (true) { car->velocity = 0; - car->var_2C = 0; + car->acceleration = 0; car->var_4A = 0; - car->var_24 += 13962; + car->remaining_distance += 13962; uint16 spriteIndex = car->next_vehicle_on_train; if (spriteIndex == SPRITE_INDEX_NULL) { @@ -4281,7 +4794,7 @@ void loc_6DDF9C(rct_ride *ride, rct_map_element *mapElement) } car = GET_VEHICLE(spriteIndex); } - } while (sub_6DAB4C(train, NULL) & 0x400); + } while (!(vehicle_update_track_motion(train, NULL) & 0x400)); mapElement->flags |= (1 << 5); car = train; @@ -4302,20 +4815,9 @@ void loc_6DDF9C(rct_ride *ride, rct_map_element *mapElement) } /** - * - * rct2: 0x006DD84C - */ -bool ride_create_vehicles(rct_ride *ride, int rideIndex, rct_xy_element *element, int isApplying) -{ - bool b = !(RCT2_CALLPROC_X(0x006DD84C, element->x, isApplying, element->y, rideIndex, (int)ride, (int)element->element, 0) & 0x100); - return b; -} - -/** - * + * Checks and initialises the cable lift track returns false if unable to find + * appropriate track. * rct2: 0x006D31A6 - * Checks and initialises the cable lift track - * returns false if unable to find appropriate track. */ static bool ride_initialise_cable_lift_track(rct_ride *ride, bool isApplying) { @@ -4417,7 +4919,7 @@ static bool ride_initialise_cable_lift_track(rct_ride *ride, bool isApplying) */ bool ride_create_cable_lift(int rideIndex, bool isApplying) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); if (ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED && ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT @@ -4463,10 +4965,10 @@ bool ride_create_cable_lift(int rideIndex, bool isApplying) uint16 var_44 = edx & 0xFFFF; edx = rol32(edx, 10) >> 1; ebx -= edx; - uint32 var_24 = ebx; + sint32 remaining_distance = ebx; ebx -= edx; - rct_vehicle *current = cable_lift_segment_create(rideIndex, x, y, z, direction, var_44, var_24, i == 0); + rct_vehicle *current = cable_lift_segment_create(rideIndex, x, y, z, direction, var_44, remaining_distance, i == 0); current->next_vehicle_on_train = SPRITE_INDEX_NULL; if (i == 0) { head = current; @@ -4481,7 +4983,7 @@ bool ride_create_cable_lift(int rideIndex, bool isApplying) tail->next_vehicle_on_ride = head->sprite_index; ride->lifecycle_flags |= RIDE_LIFECYCLE_CABLE_LIFT; - sub_6DEF56(head); + cable_lift_update_track_motion(head); return true; } @@ -4496,7 +4998,7 @@ void loc_6B51C0(int rideIndex) rct_xy_element trackElement; rct_window *w; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (RCT2_GLOBAL(0x0141F568, uint8) != RCT2_GLOBAL(0x013CA740, uint8)) return; @@ -4530,9 +5032,12 @@ void loc_6B51C0(int rideIndex) z = ride->station_heights[i] * 8; window_scroll_to_location(w, x, y, z); - sub_6CAF80(rideIndex, &trackElement); + ride_try_get_origin_element(rideIndex, &trackElement); ride_find_track_gap(&trackElement, &trackElement); - ride_modify(&trackElement); + int ok = ride_modify(&trackElement); + if (ok == 0) { + return; + } w = window_find_by_class(WC_RIDE_CONSTRUCTION); if (w != NULL) @@ -4549,7 +5054,7 @@ void loc_6B528A(rct_xy_element *trackElement) rct_ride *ride; rct_window *w; - ride = GET_RIDE(trackElement->element->properties.track.ride_index); + ride = get_ride(trackElement->element->properties.track.ride_index); if (RCT2_GLOBAL(0x0141F568, uint8) != RCT2_GLOBAL(0x013CA740, uint8)) return; @@ -4597,7 +5102,12 @@ int ride_is_valid_for_test(int rideIndex, int goingToBeOpen, int isApplying) rct_ride *ride; rct_xy_element trackElement, problematicTrackElement; - ride = GET_RIDE(rideIndex); + 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); @@ -4652,7 +5162,7 @@ int ride_is_valid_for_test(int rideIndex, int goingToBeOpen, int isApplying) } if (ride->subtype != 255) { - rct_ride_type *rideType = GET_RIDE_ENTRY(ride->subtype); + rct_ride_entry *rideType = get_ride_entry(ride->subtype); if (rideType->flags & RIDE_ENTRY_FLAG_NO_INVERSIONS) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TRACK_UNSUITABLE_FOR_TYPE_OF_TRAIN; if (ride_check_track_contains_inversions(&trackElement, &problematicTrackElement)) { @@ -4721,9 +5231,16 @@ int ride_is_valid_for_open(int rideIndex, int goingToBeOpen, int isApplying) rct_ride *ride; rct_xy_element trackElement, problematicTrackElement; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); - window_close_by_number(WC_RIDE_CONSTRUCTION, rideIndex); + // Check to see if construction tool in use. If it is close the construction window + // to set the track to its final state and clean up ghosts. + // We can't just call close as it would cause a stack overflow during shop creation + // with auto open on. + if (WC_RIDE_CONSTRUCTION == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) && + rideIndex == RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWNUMBER, rct_windownumber) && + (gInputFlags & INPUT_FLAG_TOOL_ACTIVE)) + window_close_by_number(WC_RIDE_CONSTRUCTION, rideIndex); stationIndex = ride_mode_check_station_present(ride); if (stationIndex == -1)return 0; @@ -4776,7 +5293,7 @@ int ride_is_valid_for_open(int rideIndex, int goingToBeOpen, int isApplying) } if (ride->subtype != 255) { - rct_ride_type *rideType = GET_RIDE_ENTRY(ride->subtype); + rct_ride_entry *rideType = get_ride_entry(ride->subtype); if (rideType->flags & RIDE_ENTRY_FLAG_NO_INVERSIONS) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TRACK_UNSUITABLE_FOR_TYPE_OF_TRAIN; if (ride_check_track_contains_inversions(&trackElement, &problematicTrackElement)) { @@ -4851,13 +5368,35 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e rct_ride *ride; rideIndex = *edx & 0xFF; + if (rideIndex >= MAX_RIDES) + { + log_warning("Invalid game command for ride %u", rideIndex); + *ebx = MONEY32_UNDEFINED; + return; + } targetStatus = (*edx >> 8) & 0xFF; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; - ride = GET_RIDE(rideIndex); + 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); + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + if (ride->overall_view != (uint16)-1) { + rct_xyz16 coord; + coord.x = (ride->overall_view & 0xFF) * 32 + 16; + coord.y = (ride->overall_view >> 8) * 32 + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + } + switch (targetStatus) { case RIDE_STATUS_CLOSED: if (*ebx & GAME_COMMAND_FLAG_APPLY) { @@ -4884,6 +5423,15 @@ void game_command_set_ride_status(int *eax, int *ebx, int *ecx, int *edx, int *e return; } + if (*ebx & GAME_COMMAND_FLAG_APPLY) { + // Fix #3183: Make sure we close the construction window so the ride finishes any editing code before opening + // otherwise vehicles get added to the ride incorrectly (such as to a ghost station) + rct_window *constructionWindow = window_find_by_number(WC_RIDE_CONSTRUCTION, rideIndex); + if (constructionWindow != NULL) { + window_close(constructionWindow); + } + } + if (targetStatus == RIDE_STATUS_TESTING) { if (!ride_is_valid_for_test(rideIndex, targetStatus == RIDE_STATUS_OPEN, *ebx & GAME_COMMAND_FLAG_APPLY)) { *ebx = MONEY32_UNDEFINED; @@ -4928,6 +5476,12 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi static char newName[128]; int rideIndex = (*ebx >> 8) & 0xFF; + if (rideIndex >= MAX_RIDES) + { + log_warning("Invalid game command for ride %u", rideIndex); + *ebx = MONEY32_UNDEFINED; + return; + } int nameChunkIndex = *eax & 0xFFFF; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; @@ -4936,6 +5490,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; @@ -4946,7 +5501,13 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi return; } - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", rideIndex); + *ebx = MONEY32_UNDEFINED; + return; + } format_string(oldName, ride->name, &ride->name_arguments); if (strcmp(oldName, newName) == 0) { *ebx = 0; @@ -4966,6 +5527,14 @@ void game_command_set_ride_name(int *eax, int *ebx, int *ecx, int *edx, int *esi } if (*ebx & GAME_COMMAND_FLAG_APPLY) { + if (ride->overall_view != (uint16)-1) { + rct_xyz16 coord; + coord.x = (ride->overall_view & 0xFF) * 32 + 16; + coord.y = (ride->overall_view >> 8) * 32 + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + // Free the old ride name user_string_free(ride->name); @@ -5023,9 +5592,10 @@ int ride_get_refund_price(int ride_id) continue; } + // Using GAME_COMMAND_FLAG_2 for below commands as a HACK to stop fences from being removed RCT2_GLOBAL(0x00F4413A, money32) += game_do_command( x, - GAME_COMMAND_FLAG_APPLY | (0 << 8), + GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (0 << 8), y, ride_id | (2 << 8), GAME_COMMAND_SET_MAZE_TRACK, @@ -5034,7 +5604,7 @@ int ride_get_refund_price(int ride_id) RCT2_GLOBAL(0x00F4413A, money32) += game_do_command( x, - GAME_COMMAND_FLAG_APPLY | (1 << 8), + GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (1 << 8), y + 16, ride_id | (2 << 8), GAME_COMMAND_SET_MAZE_TRACK, @@ -5043,7 +5613,7 @@ int ride_get_refund_price(int ride_id) RCT2_GLOBAL(0x00F4413A, money32) += game_do_command( x + 16, - GAME_COMMAND_FLAG_APPLY | (2 << 8), + GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (2 << 8), y + 16, ride_id | (2 << 8), GAME_COMMAND_SET_MAZE_TRACK, @@ -5052,7 +5622,7 @@ int ride_get_refund_price(int ride_id) RCT2_GLOBAL(0x00F4413A, money32) += game_do_command( x + 16, - GAME_COMMAND_FLAG_APPLY | (3 << 8), + GAME_COMMAND_FLAG_APPLY | GAME_COMMAND_FLAG_2 | (3 << 8), y, ride_id | (2 << 8), GAME_COMMAND_SET_MAZE_TRACK, @@ -5092,7 +5662,7 @@ static int ride_get_empty_slot() { rct_ride *ride; for (int i = 0; i < MAX_RIDES; i++) { - ride = GET_RIDE(i); + ride = get_ride(i); if (ride->type == RIDE_TYPE_NULL) { return i; } @@ -5102,7 +5672,7 @@ static int ride_get_empty_slot() static int ride_get_default_mode(rct_ride *ride) { - const rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride->subtype); + const rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); const uint8 *availableModes = RideAvailableModes; for (int i = 0; i < ride->type; i++) { @@ -5154,6 +5724,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]; @@ -5203,13 +5777,16 @@ static money32 ride_get_common_price(rct_ride *forRide) static money32 shop_item_get_common_price(rct_ride *forRide, int shopItem) { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_ride *ride; int i; FOR_ALL_RIDES(i, ride) { if (ride != forRide) { - rideEntry = GET_RIDE_ENTRY(ride->subtype); + rideEntry = get_ride_entry(ride->subtype); + if (rideEntry == NULL) { + continue; + } if (rideEntry->shop_item == shopItem) { return ride->price; } @@ -5225,9 +5802,9 @@ static money32 shop_item_get_common_price(rct_ride *forRide, int shopItem) static bool shop_item_has_common_price(int shopItem) { if (shopItem < 32) { - return RCT2_GLOBAL(0x01358838, uint32) & (1 << shopItem); + return RCT2_GLOBAL(0x01358838, uint32) & (1u << shopItem); } else { - return RCT2_GLOBAL(0x0135934C, uint32) & (1 << (shopItem - 32)); + return RCT2_GLOBAL(0x0135934C, uint32) & (1u << (shopItem - 32)); } } @@ -5239,13 +5816,19 @@ money32 ride_create(int type, int subType, int flags, int *outRideIndex, int *ou { char rideNameBuffer[256]; rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; int rideIndex, rideEntryIndex; + if (type > 90) + { + log_warning("Invalid request for ride type %u", type); + return MONEY32_UNDEFINED; + } + if (subType == 255) { uint8 *availableRideEntries = get_ride_entry_indices_for_ride_type(type); for (uint8 *rei = availableRideEntries; *rei != 255; rei++) { - rideEntry = GET_RIDE_ENTRY(*rei); + rideEntry = get_ride_entry(*rei); if ((rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) && !rideTypeShouldLoseSeparateFlag(rideEntry)) { subType = *rei; goto foundRideEntry; @@ -5257,17 +5840,22 @@ 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; } *outRideIndex = rideIndex; - // Ride/vehicle colour is calcualted before applying to ensure + // Ride/vehicle colour is calcualted before applying to ensure // correct colour is passed over the network. if (!(flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_NETWORKED)) { - *outRideColour = - ride_get_random_colour_preset_index(type) | + *outRideColour = + ride_get_random_colour_preset_index(type) | (ride_get_unused_preset_vehicle_colour(type, subType) << 8); } @@ -5277,8 +5865,13 @@ foundRideEntry: return 0; } - ride = GET_RIDE(rideIndex); - rideEntry = GET_RIDE_ENTRY(rideEntryIndex); + ride = get_ride(rideIndex); + rideEntry = get_ride_entry(rideEntryIndex); + if (rideEntry == (rct_ride_entry *)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); @@ -5330,7 +5923,7 @@ foundRideEntry: ride->station_starts[i] = 0xFFFF; ride->entrances[i] = 0xFFFF; ride->exits[i] = 0xFFFF; - ride->var_066[i] = 255; + ride->train_at_station[i] = 255; ride->queue_time[i] = 0; } @@ -5340,13 +5933,13 @@ foundRideEntry: ride->status = RIDE_STATUS_CLOSED; ride->lifecycle_flags = 0; - ride->var_1CA = 0; + ride->vehicle_change_timeout = 0; ride->num_stations = 0; ride->num_vehicles = 1; - ride->var_0CA = 32; + ride->proposed_num_vehicles = 32; ride->max_trains = 32; ride->num_cars_per_train = 1; - ride->var_0CB = 12; + ride->proposed_num_cars_per_train = 12; ride->min_waiting_time = 10; ride->max_waiting_time = 60; ride->depart_flags = RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH | 3; @@ -5356,19 +5949,19 @@ foundRideEntry: ride->music = RCT2_ADDRESS(0x0097D4F4, uint8)[ride->type * 8]; ride->operation_option = ( - RCT2_GLOBAL(0x0097CF40 + 4 + (ride->type * 8), uint8) + - RCT2_GLOBAL(0x0097CF40 + 4 + (ride->type * 8), uint8) + - RCT2_GLOBAL(0x0097CF40 + 4 + (ride->type * 8), uint8) + - RCT2_GLOBAL(0x0097CF40 + 5 + (ride->type * 8), uint8) + RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 4 + (ride->type * 8), uint8) + + RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 4 + (ride->type * 8), uint8) + + RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 4 + (ride->type * 8), uint8) + + RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 5 + (ride->type * 8), uint8) ) / 4; - ride->lift_hill_speed = RCT2_ADDRESS(0x0097D7C9, uint8)[ride->type * 4]; + ride->lift_hill_speed = RideLiftData[ride->type].minimum_speed; ride->measurement_index = 255; ride->excitement = (ride_rating)-1; - ride->var_120 = 0; - ride->var_122 = 0; - ride->var_148 = 0; + ride->cur_num_customers = 0; + ride->num_customers_timeout = 0; + ride->chairlift_bullwheel_rotation = 0; ride->price = 0; ride->price_secondary = 0; @@ -5419,19 +6012,7 @@ foundRideEntry: } } - // The next 10 variables are treated like an array of 10 items - ride->var_124 = 0; - ride->var_124 = 0; - ride->var_126 = 0; - ride->var_128 = 0; - ride->var_12A = 0; - ride->var_12C = 0; - ride->var_12E = 0; - ride->age = 0; - ride->running_cost = 0; - ride->var_134 = 0; - ride->var_136 = 0; - + memset(ride->num_customers, 0, sizeof(ride->num_customers)); ride->value = 0xFFFF; ride->satisfaction = 255; ride->satisfaction_time_out = 0; @@ -5443,7 +6024,7 @@ foundRideEntry: ride->total_customers = 0; ride->total_profit = 0; ride->num_riders = 0; - ride->var_15D = 0; + ride->slide_in_use = 0; ride->maze_tiles = 0; ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); ride->music_tune_id = 255; @@ -5455,8 +6036,7 @@ foundRideEntry: ride->inspection_interval = RIDE_INSPECTION_EVERY_30_MINUTES; ride->last_inspection = 0; ride->downtime = 0; - ride->var_19C = 0; - ride->var_1A0 = 0; + memset(ride->downtime_history, 0, sizeof(ride->downtime_history)); ride->no_primary_items_sold = 0; ride->no_secondary_items_sold = 0; ride->last_crash_type = RIDE_CRASH_TYPE_NONE; @@ -5507,7 +6087,6 @@ void game_command_callback_ride_construct_placed_back(int eax, int ebx, int ecx, int trackDirection, x, y, z; track_begin_end trackBeginEnd; - RCT2_GLOBAL(0x00F441D2, uint8) = _currentRideIndex; trackDirection = _currentTrackPieceDirection ^ 2; x = _currentTrackBeginX; y = _currentTrackBeginY; @@ -5532,6 +6111,7 @@ void game_command_callback_ride_construct_placed_back(int eax, int ebx, int ecx, _rideConstructionState = RIDE_CONSTRUCTION_STATE_0; } + window_ride_construction_do_station_check(); sub_6C84CE(); } @@ -5539,7 +6119,6 @@ void game_command_callback_ride_construct_placed_front(int eax, int ebx, int ecx { int trackDirection, x, y, z; - RCT2_GLOBAL(0x00F441D2, uint8) = _currentRideIndex; trackDirection = _currentTrackPieceDirection; x = _currentTrackBeginX; y = _currentTrackBeginY; @@ -5565,6 +6144,8 @@ void game_command_callback_ride_construct_placed_front(int eax, int ebx, int ecx _rideConstructionState = RIDE_CONSTRUCTION_STATE_0; } + window_ride_construction_do_station_check(); + window_ride_construction_do_entrance_exit_check(); sub_6C84CE(); } @@ -5596,11 +6177,23 @@ void game_command_callback_ride_remove_track_piece(int eax, int ebx, int ecx, in void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { uint8 ride_id = *(uint8*)edx; + if (ride_id >= MAX_RIDES) + { + log_warning("Invalid game command for ride %u", ride_id); + *ebx = MONEY32_UNDEFINED; + return; + } 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; @@ -5610,12 +6203,20 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; } - if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) && !gConfigCheat.build_in_pause_mode){ + if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; }else{ if(*ebx & GAME_COMMAND_FLAG_APPLY){ + if (ride->overall_view != (uint16)-1) { + rct_xyz16 coord; + coord.x = (ride->overall_view & 0xFF) * 32 + 16; + coord.y = (ride->overall_view >> 8) * 32 + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + if(!(*ebx & 8)){ window_close_by_number(WC_RIDE_CONSTRUCTION, ride_id); } @@ -5723,55 +6324,131 @@ void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi */ void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - uint8 ride_id = *edx; - uint8 type = *ebx >> 8; - uint8 value = *edx >> 8; - int index = *edi; - rct_ride *ride = &g_ride_list[ride_id]; - switch(type){ - case 0: - ride->track_colour_main[index] = value; - gfx_invalidate_screen(); - break; - case 1: - ride->track_colour_additional[index] = value; - gfx_invalidate_screen(); - break; - case 2: - *((uint8*)(&ride->vehicle_colours[index])) = value; - ride_update_vehicle_colours(ride_id); - break; - case 3: - *((uint8*)(&ride->vehicle_colours[index]) + 1) = value; - ride_update_vehicle_colours(ride_id); - break; - case 4: - ride->track_colour_supports[index] = value; - gfx_invalidate_screen(); - break; - case 5: - ride->colour_scheme_type &= ~(RIDE_COLOUR_SCHEME_DIFFERENT_PER_TRAIN | RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR); - ride->colour_scheme_type |= value; - for(int i = 1; i < countof(ride->vehicle_colours); i++){ - ride->vehicle_colours[i] = ride->vehicle_colours[0]; - ride->vehicle_colours_extended[i] = ride->vehicle_colours_extended[0]; - } - ride_update_vehicle_colours(ride_id); - break; - case 6: - ride->entrance_style = value; - RCT2_GLOBAL(0x01358840, uint8) = value; - gfx_invalidate_screen(); - break; - case 7: + bool apply = (*ebx & GAME_COMMAND_FLAG_APPLY); + + uint8 ride_id = *edx; + if (ride_id >= MAX_RIDES) + { + log_warning("Invalid game command for ride %u", ride_id); + *ebx = MONEY32_UNDEFINED; + return; + } + uint8 type = *ebx >> 8; + uint8 value = *edx >> 8; + int index = *edi; + + 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; + } + + if (apply && RCT2_GLOBAL(0x009A8C28, uint8) == 1) { + if (ride->overall_view != (uint16)-1) { + rct_xyz16 coord; + coord.x = (ride->overall_view & 0xFF) * 32 + 16; + coord.y = (ride->overall_view >> 8) * 32 + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + } + + *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; + return; + } + if (apply) { + 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; + return; + } + if (apply) { + 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; + return; + } + if (apply) { + *((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; + return; + } + if (apply) { + *((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; + return; + } + if (apply) { + ride->track_colour_supports[index] = value; + gfx_invalidate_screen(); + } + break; + case 5: + if (apply) { + ride->colour_scheme_type &= ~(RIDE_COLOUR_SCHEME_DIFFERENT_PER_TRAIN | RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR); + ride->colour_scheme_type |= value; + for (int i = 1; i < countof(ride->vehicle_colours); i++) { + ride->vehicle_colours[i] = ride->vehicle_colours[0]; + ride->vehicle_colours_extended[i] = ride->vehicle_colours_extended[0]; + } + ride_update_vehicle_colours(ride_id); + } + break; + case 6: + if (apply) { + ride->entrance_style = value; + RCT2_GLOBAL(0x01358840, uint8) = value; + 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; + return; + } else { + if (apply) { ride->vehicle_colours_extended[index] = value; ride_update_vehicle_colours(ride_id); - break; + } } - window_invalidate_by_number(WC_RIDE, ride_id); + break; } - *ebx = 0; + window_invalidate_by_number(WC_RIDE, ride_id); } /** @@ -5784,30 +6461,58 @@ 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_entry *rideEntry; bool secondary_price; flags = *ebx; ride_number = (*edx & 0xFF); - ride = GET_RIDE(ride_number); - ride_type = gRideTypeList[ride->subtype]; + if (ride_number >= MAX_RIDES) + { + log_warning("Invalid game command for ride %u", ride_number); + *ebx = MONEY32_UNDEFINED; + return; + } + ride = get_ride(ride_number); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", ride_number); + *ebx = MONEY32_UNDEFINED; + return; + } + rideEntry = get_ride_entry(ride->subtype); price = *edi; secondary_price = (*edx >> 8); + if (rideEntry == (rct_ride_entry *)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 RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_PARK_RIDE_TICKETS * 4; if (flags & 0x1) { + + if (ride->overall_view != (uint16)-1) { + rct_xyz16 coord; + coord.x = (ride->overall_view & 0xFF) * 32 + 16; + coord.y = (ride->overall_view >> 8) * 32 + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + 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); @@ -5822,7 +6527,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) { @@ -5838,33 +6543,33 @@ void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *es return; } } - ride = GET_RIDE(0); - ride_type = gRideTypeList[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) { - ride->price = price; - window_invalidate_by_number(WC_RIDE, count); - } - } - else { - ride->price = price; - 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 && - (shop_item == 0x3 || shop_item == 0x20 || shop_item == 0x21 || shop_item == 0x22))) { + ride = get_ride(0); - ride->price_secondary = price; - window_invalidate_by_number(WC_RIDE, count); + for (uint8 rideId = 0; rideId < 0xFF; rideId++, ride++) { + // Unplaced rides have a type of NULL + if (ride->type == RIDE_TYPE_NULL) + continue; + + rideEntry = get_ride_entry(ride->subtype); + + if (ride->type != RIDE_TYPE_TOILETS || shop_item != 0x1F) { + if (rideEntry->shop_item == shop_item) { + ride->price = price; + window_invalidate_by_number(WC_RIDE, rideId); } } - count++; - ride++; - ride_type = gRideTypeList[ride->subtype]; + else { + ride->price = price; + window_invalidate_by_number(WC_RIDE, rideId); + } + // If the shop item is the same or an on-ride photo + 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; + window_invalidate_by_number(WC_RIDE, rideId); + } } } } @@ -5875,52 +6580,181 @@ bool ride_type_has_flag(int rideType, int flag) } /* - * The next six functions are helpers to access ride data at the offset 10E & - * 110. We believe it stores three distinct values in the following format: + * The next eight functions are helpers to access ride data at the offset 10E & + * 110. Known as the turn counts. There are 3 different types (default, banked, sloped) + * and there are 4 counts as follows: * - * unknown1: bits 9-11 - * unknown2: bits 6-8 - * unknown3: low 5 bits + * 1 element turns: low 5 bits + * 2 element turns: bits 6-8 + * 3 element turns: bits 9-11 + * 4 element or more turns: bits 12-15 + * + * 4 plus elements only possible on sloped type. Falls back to 3 element + * if by some miracle you manage 4 element none sloped. */ -int get_var_10E_unk_1(rct_ride* ride) { - return (ride->var_10E >> 8) & 0x7; +void increment_turn_count_1_element(rct_ride* ride, uint8 type){ + uint16* turn_count; + switch (type){ + case 0: + turn_count = &ride->turn_count_default; + break; + case 1: + turn_count = &ride->turn_count_banked; + break; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return; + } + uint16 value = (*turn_count & TURN_MASK_1_ELEMENT) + 1; + *turn_count &= ~TURN_MASK_1_ELEMENT; + + if (value > TURN_MASK_1_ELEMENT) + value = TURN_MASK_1_ELEMENT; + *turn_count |= value; } -int get_var_10E_unk_2(rct_ride* ride) { - return (ride->var_10E >> 5) & 0x7; +void increment_turn_count_2_elements(rct_ride* ride, uint8 type){ + uint16* turn_count; + switch (type){ + case 0: + turn_count = &ride->turn_count_default; + break; + case 1: + turn_count = &ride->turn_count_banked; + break; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return; + } + uint16 value = (*turn_count & TURN_MASK_2_ELEMENTS) + 0x20; + *turn_count &= ~TURN_MASK_2_ELEMENTS; + + if (value > TURN_MASK_2_ELEMENTS) + value = TURN_MASK_2_ELEMENTS; + *turn_count |= value; } -int get_var_10E_unk_3(rct_ride* ride) { - return ride->var_10E & 0x1F; +void increment_turn_count_3_elements(rct_ride* ride, uint8 type){ + uint16* turn_count; + switch (type){ + case 0: + turn_count = &ride->turn_count_default; + break; + case 1: + turn_count = &ride->turn_count_banked; + break; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return; + } + uint16 value = (*turn_count & TURN_MASK_3_ELEMENTS) + 0x100; + *turn_count &= ~TURN_MASK_3_ELEMENTS; + + if (value > TURN_MASK_3_ELEMENTS) + value = TURN_MASK_3_ELEMENTS; + *turn_count |= value; } -int get_var_110_unk_1(rct_ride* ride) { - return (ride->var_110 >> 8) & 0x7; +void increment_turn_count_4_plus_elements(rct_ride* ride, uint8 type){ + uint16* turn_count; + switch (type){ + case 0: + case 1: + // Just incase fallback to 3 element turn + increment_turn_count_3_elements(ride, type); + return; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return; + } + uint16 value = (*turn_count & TURN_MASK_4_PLUS_ELEMENTS) + 0x800; + *turn_count &= ~TURN_MASK_4_PLUS_ELEMENTS; + + if (value > TURN_MASK_4_PLUS_ELEMENTS) + value = TURN_MASK_4_PLUS_ELEMENTS; + *turn_count |= value; } -int get_var_110_unk_2(rct_ride* ride) { - return (ride->var_110 >> 5) & 0x7; +int get_turn_count_1_element(rct_ride* ride, uint8 type) { + uint16* turn_count; + switch (type){ + case 0: + turn_count = &ride->turn_count_default; + break; + case 1: + turn_count = &ride->turn_count_banked; + break; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return 0; + } + + return (*turn_count) & TURN_MASK_1_ELEMENT; } -int get_var_110_unk_3(rct_ride* ride) { - return ride->var_110 & 0x1F; +int get_turn_count_2_elements(rct_ride* ride, uint8 type) { + uint16* turn_count; + switch (type){ + case 0: + turn_count = &ride->turn_count_default; + break; + case 1: + turn_count = &ride->turn_count_banked; + break; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return 0; + } + + return ((*turn_count) & TURN_MASK_2_ELEMENTS) >> 5; } -int get_var_112_unk_1(rct_ride* ride) { - return (ride->var_112 >> 11) & 0x3F; +int get_turn_count_3_elements(rct_ride* ride, uint8 type) { + uint16* turn_count; + switch (type){ + case 0: + turn_count = &ride->turn_count_default; + break; + case 1: + turn_count = &ride->turn_count_banked; + break; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return 0; + } + + return ((*turn_count) & TURN_MASK_3_ELEMENTS) >> 8; } -int get_var_112_unk_2(rct_ride* ride) { - return (ride->var_112 >> 8) & 7; -} +int get_turn_count_4_plus_elements(rct_ride* ride, uint8 type) { + uint16* turn_count; + switch (type){ + case 0: + case 1: + return 0; + case 2: + turn_count = &ride->turn_count_sloped; + break; + default: + return 0; + } -int get_var_112_unk_3(rct_ride* ride) { - return (ride->var_112 >> 5) & 7; -} - -int get_var_112_unk_4(rct_ride* ride) { - return ride->var_112 & 0x1F; + return ((*turn_count) & TURN_MASK_4_PLUS_ELEMENTS) >> 11; } bool ride_has_spinning_tunnel(rct_ride *ride) { @@ -6003,8 +6837,11 @@ void ride_all_has_any_track_elements(bool *rideIndexArray) } } -/* rct2: 0x006847BA */ -void set_vehicle_type_image_max_sizes(rct_ride_type_vehicle* vehicle_type, int num_images){ +/** + * + * rct2: 0x006847BA + */ +void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, int num_images){ uint8 bitmap[200][200] = { 0 }; rct_drawpixelinfo dpi = { @@ -6076,7 +6913,7 @@ void set_vehicle_type_image_max_sizes(rct_ride_type_vehicle* vehicle_type, int n // Moved from object paint - if (vehicle_type->var_12 & 0x2000){ + if (vehicle_type->flags_a & VEHICLE_ENTRY_FLAG_A_13){ bl += 16; } @@ -6087,7 +6924,7 @@ void set_vehicle_type_image_max_sizes(rct_ride_type_vehicle* vehicle_type, int n /** * - * rct2: 0x006CA28C + * rct2: 0x006CA28C */ money32 ride_get_entrance_or_exit_price(int rideIndex, int x, int y, int direction, int dh, int di) { @@ -6142,7 +6979,7 @@ int loc_6CD18E(short mapX, short mapY, short entranceMinX, short entranceMinY, s /** * - * rct2: 0x006CCF70 + * rct2: 0x006CCF70 */ void ride_get_entrance_or_exit_position_from_screen_position(int screenX, int screenY, int *outX, int *outY, int *outDirection) { @@ -6169,7 +7006,7 @@ void ride_get_entrance_or_exit_position_from_screen_position(int screenX, int sc } } - ride = GET_RIDE(RCT2_GLOBAL(0x00F44192, uint8)); + ride = get_ride(RCT2_GLOBAL(0x00F44192, uint8)); stationHeight = ride->station_heights[RCT2_GLOBAL(0x00F44193, uint8)]; screen_get_map_xy_with_z(screenX, screenY, stationHeight * 8, &mapX, &mapY); @@ -6293,7 +7130,6 @@ bool ride_select_backwards_from_front() track_begin_end trackBeginEnd; sub_6C9627(); - RCT2_GLOBAL(0x00F441D2, uint8) = _currentRideIndex; if (track_block_get_previous_from_zero(_currentTrackBeginX, _currentTrackBeginY, _currentTrackBeginZ, _currentRideIndex, _currentTrackPieceDirection, &trackBeginEnd)) { _rideConstructionState = RIDE_CONSTRUCTION_STATE_SELECTED; _currentTrackBeginX = trackBeginEnd.begin_x; @@ -6314,7 +7150,6 @@ bool ride_select_forwards_from_back() int x, y, z, direction; sub_6C9627(); - RCT2_GLOBAL(0x00F441D2, uint8) = _currentRideIndex; x = _currentTrackBeginX; y = _currentTrackBeginY; @@ -6349,7 +7184,7 @@ money32 ride_remove_track_piece(int x, int y, int z, int direction, int type) /** * - * rct2: 0x006B58EF + * rct2: 0x006B58EF */ bool ride_are_all_possible_entrances_and_exits_built(rct_ride *ride) { @@ -6372,11 +7207,11 @@ bool ride_are_all_possible_entrances_and_exits_built(rct_ride *ride) /** * - * rct2: 0x006B59C6 + * rct2: 0x006B59C6 */ void invalidate_test_results(int rideIndex) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); ride_measurement_clear(ride); ride->excitement = 0xFFFF; @@ -6396,16 +7231,19 @@ void invalidate_test_results(int rideIndex) /** * - * rct2: 0x006B7481 + * rct2: 0x006B7481 + * + * @param rideIndex (dl) + * @param reliabilityIncreaseFactor (ax) */ void ride_fix_breakdown(int rideIndex, int reliabilityIncreaseFactor) { - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); ride->lifecycle_flags &= ~RIDE_LIFECYCLE_BREAKDOWN_PENDING; ride->lifecycle_flags &= ~RIDE_LIFECYCLE_BROKEN_DOWN; ride->lifecycle_flags &= ~RIDE_LIFECYCLE_DUE_INSPECTION; - ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_CUSTOMER; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST | RIDE_INVALIDATE_RIDE_MAINTENANCE; if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK) { rct_vehicle *vehicle; @@ -6429,7 +7267,7 @@ void ride_fix_breakdown(int rideIndex, int reliabilityIncreaseFactor) /** * - * rct2: 0x006DE102 + * rct2: 0x006DE102 */ static void ride_update_vehicle_colours(int rideIndex) { @@ -6439,7 +7277,7 @@ static void ride_update_vehicle_colours(int rideIndex) uint16 spriteIndex; uint8 coloursExtended = 0; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_SPACE_RINGS || ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_16)) { gfx_invalidate_screen(); } @@ -6475,12 +7313,12 @@ static void ride_update_vehicle_colours(int rideIndex) /** * - * rct2: 0x006DE4CD + * rct2: 0x006DE4CD * trainLayout: Originally fixed to 0x00F64E38. This no longer postfixes with 255. */ void ride_entry_get_train_layout(int rideEntryIndex, int numCarsPerTrain, uint8 *trainLayout) { - rct_ride_type *rideEntry = GET_RIDE_ENTRY(rideEntryIndex); + rct_ride_entry *rideEntry = get_ride_entry(rideEntryIndex); for (int i = 0; i < numCarsPerTrain; i++) { uint8 vehicleType = rideEntry->default_vehicle; @@ -6569,16 +7407,16 @@ foundTrack: void ride_update_max_vehicles(int rideIndex) { rct_ride *ride; - rct_ride_type *rideEntry; - rct_ride_type_vehicle *vehicleEntry; + rct_ride_entry *rideEntry; + rct_ride_entry_vehicle *vehicleEntry; uint8 trainLayout[16], numCarsPerTrain, numVehicles; int trainLength, maxNumTrains; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->subtype == 0xFF) return; - rideEntry = GET_RIDE_ENTRY(ride->subtype); + rideEntry = get_ride_entry(ride->subtype); if (rideEntry->cars_per_flat_ride == 0xFF) { ride->num_cars_per_train = max(rideEntry->min_cars_in_train, ride->num_cars_per_train); ride->min_max_cars_per_train = rideEntry->max_cars_in_train | (rideEntry->min_cars_in_train << 4); @@ -6597,7 +7435,7 @@ void ride_update_max_vehicles(int rideIndex) int totalFriction = 0; for (int i = 0; i < numCars; i++) { vehicleEntry = &rideEntry->vehicles[trainLayout[i]]; - trainLength += vehicleEntry->var_04; + trainLength += vehicleEntry->spacing; totalFriction += vehicleEntry->car_friction; } @@ -6606,7 +7444,7 @@ void ride_update_max_vehicles(int rideIndex) break; } } - int newCarsPerTrain = max(ride->var_0CB, rideEntry->min_cars_in_train); + int newCarsPerTrain = max(ride->proposed_num_cars_per_train, rideEntry->min_cars_in_train); maxCarsPerTrain = max(maxCarsPerTrain, rideEntry->min_cars_in_train); newCarsPerTrain = min(maxCarsPerTrain, newCarsPerTrain); ride->min_max_cars_per_train = maxCarsPerTrain | (rideEntry->min_cars_in_train << 4); @@ -6629,7 +7467,7 @@ void ride_update_max_vehicles(int rideIndex) trainLength = 0; for (int i = 0; i < newCarsPerTrain; i++) { vehicleEntry = &rideEntry->vehicles[trainLayout[i]]; - trainLength += vehicleEntry->var_04; + trainLength += vehicleEntry->spacing; } int totalLength = trainLength / 2; @@ -6655,7 +7493,7 @@ void ride_update_max_vehicles(int rideIndex) int totalSpacing = 0; for (int i = 0; i < newCarsPerTrain; i++) { vehicleEntry = &rideEntry->vehicles[trainLayout[i]]; - totalSpacing += vehicleEntry->var_04; + totalSpacing += vehicleEntry->spacing; } totalSpacing >>= 13; @@ -6675,13 +7513,13 @@ void ride_update_max_vehicles(int rideIndex) } ride->max_trains = maxNumTrains; - numCarsPerTrain = min(ride->var_0CB, newCarsPerTrain); - numVehicles = min(ride->var_0CA, maxNumTrains); + numCarsPerTrain = min(ride->proposed_num_cars_per_train, newCarsPerTrain); + numVehicles = min(ride->proposed_num_vehicles, maxNumTrains); } else { ride->max_trains = rideEntry->cars_per_flat_ride; ride->min_max_cars_per_train = rideEntry->max_cars_in_train | (rideEntry->min_cars_in_train << 4); numCarsPerTrain = rideEntry->max_cars_in_train; - numVehicles = min(ride->var_0CA, rideEntry->cars_per_flat_ride); + numVehicles = min(ride->proposed_num_vehicles, rideEntry->cars_per_flat_ride); } // Refresh new current num vehicles / num cars per vehicle @@ -6734,84 +7572,166 @@ void ride_set_num_cars_per_vehicle(int rideIndex, int numCarsPerVehicle) ); } -/** - * - * rct2: 0x006B52D4 - */ -void game_command_set_ride_vehicles(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +static bool ride_entry_is_invented(int rideEntryIndex) { - rct_ride *ride; - rct_ride_type *rideEntry; - rct_window *w; - int rideIndex, commandType, value; + int quadIndex = rideEntryIndex >> 5; + int bitIndex = rideEntryIndex & 0x1F; + bool invented = (RCT2_ADDRESS(0x01357424, uint32)[quadIndex] & (1 << bitIndex)); + return invented; +} - commandType = (*ebx >> 8) & 0xFF; - rideIndex = *edx & 0xFF; - value = (*edx >> 8) & 0xFF; +static bool ride_is_vehicle_type_valid(rct_ride *ride, uint8 inputRideEntryIndex) +{ + bool selectionShouldBeExpanded; + int rideTypeIterator, rideTypeIteratorMax; - ride = GET_RIDE(rideIndex); + if (gCheatsShowVehiclesFromOtherTrackTypes && + !(ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE) || ride->type == RIDE_TYPE_MAZE || ride->type == RIDE_TYPE_MINI_GOLF) + ) { + selectionShouldBeExpanded = true; + rideTypeIterator = 0; + rideTypeIteratorMax = 90; + } else { + selectionShouldBeExpanded = false; + rideTypeIterator = ride->type; + rideTypeIteratorMax = ride->type; + } + + for (; rideTypeIterator <= rideTypeIteratorMax; rideTypeIterator++) { + if (selectionShouldBeExpanded) { + if (ride_type_has_flag(rideTypeIterator, RIDE_TYPE_FLAG_FLAT_RIDE)) continue; + if (rideTypeIterator == RIDE_TYPE_MAZE || rideTypeIterator == RIDE_TYPE_MINI_GOLF) continue; + } + + uint8 *rideEntryIndexPtr = get_ride_entry_indices_for_ride_type(rideTypeIterator); + for (uint8 *currentRideEntryIndex = rideEntryIndexPtr; *currentRideEntryIndex != 0xFF; currentRideEntryIndex++) { + uint8 rideEntryIndex = *currentRideEntryIndex; + if (rideEntryIndex == inputRideEntryIndex) { + if (!ride_entry_is_invented(rideEntryIndex)) { + return false; + } + + return true; + } + } + } + + return false; +} + +money32 ride_set_vehicles(uint8 rideIndex, uint8 setting, uint8 value, uint32 flags, uint8 ex) +{ + rct_ride_entry *rideEntry; + + rct_ride *ride = get_ride(rideIndex); + if (ride == NULL || ride->type == RIDE_TYPE_NULL) { + log_warning("Invalid game command for ride #%u", rideIndex); + return MONEY32_UNDEFINED; + } RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_RUNNING_COSTS * 4; if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_HAS_BROKEN_DOWN_AND_REQUIRES_FIXING; - *ebx = MONEY32_UNDEFINED; - return; + return MONEY32_UNDEFINED; } if (ride->status != RIDE_STATUS_CLOSED) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_MUST_BE_CLOSED_FIRST; - *ebx = MONEY32_UNDEFINED; - return; + return MONEY32_UNDEFINED; } - if (!(*ebx & GAME_COMMAND_FLAG_APPLY) && !(*ebx & GAME_COMMAND_FLAG_NETWORKED)) { - *eax = - ride_get_unused_preset_vehicle_colour(ride->type, ride->subtype); - } - - if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { - *ebx = 0; - return; - } - - invalidate_test_results(rideIndex); - ride_clear_for_construction(rideIndex); - ride_remove_peeps(rideIndex); - ride->var_1CA = 100; - if (ride->type != RIDE_TYPE_ENTERPRISE) { - gfx_invalidate_screen(); - } - - switch (commandType) { + switch (setting) { case RIDE_SET_VEHICLES_COMMAND_TYPE_NUM_TRAINS: - ride->var_0CA = value; - if (ride->type != RIDE_TYPE_SPACE_RINGS) { - gfx_invalidate_screen(); + if (!(flags & GAME_COMMAND_FLAG_APPLY)) { + return 0; } + + ride_clear_for_construction(rideIndex); + ride_remove_peeps(rideIndex); + ride->vehicle_change_timeout = 100; + + ride->proposed_num_vehicles = value; break; case RIDE_SET_VEHICLES_COMMAND_TYPE_NUM_CARS_PER_TRAIN: - rideEntry = GET_RIDE_ENTRY(ride->subtype); + if (!(flags & GAME_COMMAND_FLAG_APPLY)) { + return 0; + } + + ride_clear_for_construction(rideIndex); + ride_remove_peeps(rideIndex); + ride->vehicle_change_timeout = 100; + + invalidate_test_results(rideIndex); + rideEntry = get_ride_entry(ride->subtype); value = clamp(rideEntry->min_cars_in_train, value, rideEntry->max_cars_in_train); - ride->var_0CB = value; + ride->proposed_num_cars_per_train = value; break; case RIDE_SET_VEHICLES_COMMAND_TYPE_RIDE_ENTRY: + if (!ride_is_vehicle_type_valid(ride, value)) { + log_error("Invalid vehicle type."); + return MONEY32_UNDEFINED; + } + + if (!(flags & GAME_COMMAND_FLAG_APPLY)) { + return 0; + } + + ride_clear_for_construction(rideIndex); + ride_remove_peeps(rideIndex); + ride->vehicle_change_timeout = 100; + + invalidate_test_results(rideIndex); + rideEntry = get_ride_entry(ride->subtype); ride->subtype = value; - ride_set_vehicle_colours_to_random_preset(ride, *eax & 0xFF); + + uint8 preset = ex; + if (!(flags & GAME_COMMAND_FLAG_NETWORKED)) { + preset = ride_get_unused_preset_vehicle_colour(ride->type, ride->subtype); + } + ride_set_vehicle_colours_to_random_preset(ride, preset); + ride->proposed_num_cars_per_train = clamp(rideEntry->min_cars_in_train, ride->proposed_num_cars_per_train, rideEntry->max_cars_in_train); break; + default: + log_error("Unknown vehicle command."); + return MONEY32_UNDEFINED; } ride->num_circuits = 1; ride_update_max_vehicles(rideIndex); - w = window_find_by_number(WC_RIDE, rideIndex); + if (ride->overall_view != (uint16)-1) { + rct_xyz16 coord; + coord.x = (ride->overall_view & 0xFF) * 32 + 16; + coord.y = (ride->overall_view >> 8) * 32 + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + + rct_window *w = window_find_by_number(WC_RIDE, rideIndex); if (w != NULL) { if (w->page == 4) { w->var_48C = 0; } window_invalidate(w); } - *ebx = 0; + + gfx_invalidate_screen(); + return 0; +} + +/** + * + * rct2: 0x006B52D4 + */ +void game_command_set_ride_vehicles(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) +{ + uint8 rideIndex = *edx & 0xFF; + uint8 setting = (*ebx >> 8) & 0xFF; + uint8 value = (*edx >> 8) & 0xFF; + uint32 flags = *ebx; + uint8 ex = *eax & 0xFF; + *ebx = ride_set_vehicles(rideIndex, setting, value, flags, ex); } /** @@ -6820,13 +7740,236 @@ void game_command_set_ride_vehicles(int *eax, int *ebx, int *ecx, int *edx, int */ void sub_6CB945(int rideIndex) { - RCT2_CALLPROC_X(0x006CB945, 0, 0, 0, rideIndex, 0, 0, 0); + RCT2_GLOBAL(0x00F441C2, uint8) = rideIndex; + + rct_ride* ride = get_ride(rideIndex); + if (ride->type != RIDE_TYPE_MAZE) { + for (uint8 stationId = 0; stationId < 4; ++stationId) { + if (ride->station_starts[stationId] == 0xFFFF) + continue; + + rct_xyz16 location = { + .x = (ride->station_starts[stationId] & 0xFF) * 32, + .y = ((ride->station_starts[stationId] >> 8) & 0xFF) * 32, + .z = ride->station_heights[stationId] + }; + uint8 direction = 0xFF; + + bool specialTrack = false; + rct_map_element* mapElement = NULL; + + while (true) { + if (direction != 0xFF) { + location.x -= TileDirectionDelta[direction].x; + location.y -= TileDirectionDelta[direction].y; + } + mapElement = map_get_first_element_at(location.x / 32, location.y / 32); + + bool trackFound = false; + do { + if (mapElement->base_height != location.z) + continue; + + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) + continue; + + if (mapElement->properties.track.ride_index != rideIndex) + continue; + + // Only allow sequence 0 + if (mapElement->properties.track.sequence & 0xF) + continue; + + if (!(RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & (1 << 4))) + continue; + + trackFound = true; + break; + } while (!map_element_is_last_for_tile(mapElement++)); + + if (trackFound == false) { + break; + } + + mapElement->properties.track.sequence &= 0x8F; + mapElement->properties.track.sequence |= (stationId << 4); + + direction = map_element_get_direction(mapElement); + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3)) { + specialTrack = true; + break; + } + } + + if (specialTrack == false) + continue; + + + const rct_preview_track *trackBlock = get_track_def_from_ride(ride, mapElement->properties.track.type); + + while ((++trackBlock)->index != 0xFF) { + rct_xyz16 blockLocation = location; + + switch (direction) { + case 0: + blockLocation.x += trackBlock->x; + blockLocation.y += trackBlock->y; + break; + case 1: + blockLocation.x += trackBlock->y; + blockLocation.y -= trackBlock->x; + break; + case 2: + blockLocation.x -= trackBlock->x; + blockLocation.y -= trackBlock->y; + break; + case 3: + blockLocation.x -= trackBlock->y; + blockLocation.y += trackBlock->x; + break; + } + + blockLocation.z += trackBlock->z / 8; + + bool trackFound = false; + mapElement = map_get_first_element_at(blockLocation.x / 32, blockLocation.y / 32); + do { + if (blockLocation.z != mapElement->base_height) + continue; + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) + continue; + + if (!(RCT2_ADDRESS(0x0099BA64, uint8)[mapElement->properties.track.type * 16] & 0x10)) + continue; + + trackFound = true; + break; + } while (!map_element_is_last_for_tile(mapElement++)); + + if (trackFound == false) + break; + + mapElement->properties.track.sequence &= 0x8F; + mapElement->properties.track.sequence |= (stationId << 4); + } + } + } + + uint16* locationList = RCT2_ADDRESS(0x00F441B0, uint16); + + for (uint8 stationId = 0; stationId < 4; ++stationId) { + if (ride->entrances[stationId] != 0xFFFF) { + *locationList++ = ride->entrances[stationId]; + ride->entrances[stationId] = 0xFFFF; + } + + if (ride->exits[stationId] != 0xFFFF) { + *locationList++ = ride->exits[stationId]; + ride->exits[stationId] = 0xFFFF; + } + } + + *locationList++ = 0xFFFF; + + locationList = RCT2_ADDRESS(0x00F441B0, uint16); + + for (; *locationList != 0xFFFF; locationList++) { + uint16* locationList2 = locationList; + locationList2++; + + bool duplicateLocation = false; + do { + if (*locationList == *locationList2) { + duplicateLocation = true; + break; + } + } while (*locationList2++ != 0xFFFF); + + if (duplicateLocation == true) + continue; + + rct_xy16 location = { + .x = (*locationList & 0xFF) * 32, + .y = ((*locationList >> 8) & 0xFF) * 32 + }; + + rct_map_element* mapElement = map_get_first_element_at(location.x / 32, location.y / 32); + + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_ENTRANCE) + continue; + + if (mapElement->properties.entrance.ride_index != rideIndex) + continue; + + // If its a park entrance + if (mapElement->properties.entrance.type > ENTRANCE_TYPE_RIDE_EXIT) + continue; + + rct_xy16 nextLocation = location; + nextLocation.x += TileDirectionDelta[map_element_get_direction(mapElement)].x; + nextLocation.y += TileDirectionDelta[map_element_get_direction(mapElement)].y; + + bool shouldRemove = true; + rct_map_element* trackElement = map_get_first_element_at(nextLocation.x / 32, nextLocation.y / 32); + do { + if (map_element_get_type(trackElement) != MAP_ELEMENT_TYPE_TRACK) + continue; + + if (trackElement->properties.track.ride_index != rideIndex) + continue; + + if (trackElement->base_height != mapElement->base_height) + continue; + + uint32 edi = trackElement->properties.track.type * 16; + edi |= trackElement->properties.track.sequence & 0xF; + + uint8 direction = (map_element_get_direction(mapElement) - map_element_get_direction(trackElement) + 2) & 3; + + if (!(RCT2_GLOBAL(0x0099BA64 + edi, uint32) & (1 << direction))) + continue; + + uint8 stationId = 0; + if (trackElement->properties.track.type != TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP) { + stationId = (trackElement->properties.track.sequence >> 4) & 0x7; + } + + if (mapElement->properties.entrance.type == ENTRANCE_TYPE_RIDE_EXIT) { + if (ride->exits[stationId] != 0xFFFF) + break; + + ride->exits[stationId] = (location.x / 32) | ((location.y / 32) << 8); + } + else { + if (ride->entrances[stationId] != 0xFFFF) + break; + + ride->entrances[stationId] = (location.x / 32) | ((location.y / 32) << 8); + } + + mapElement->properties.entrance.index &= 0x8F; + mapElement->properties.entrance.index |= stationId << 4; + shouldRemove = false; + } while (!map_element_is_last_for_tile(trackElement++)); + + if (shouldRemove == true) { + sub_6A7594(); + maze_entrance_hedge_replacement(location.x, location.y, mapElement); + footpath_remove_edges_at(location.x, location.y, mapElement); + sub_6A759F(); + map_invalidate_tile_full(location.x, location.y); + map_element_remove(mapElement); + mapElement--; + } + } while (!map_element_is_last_for_tile(mapElement++)); + } } /** - * + * Removes the hedge walls for an entrance placement. * rct2: 0x00666CBE - * Removes the hedge walls for an entrance placement. */ static void maze_entrance_hedge_removal(int x, int y, rct_map_element *mapElement) { @@ -6862,9 +8005,8 @@ static void maze_entrance_hedge_removal(int x, int y, rct_map_element *mapElemen } /** - * + * Replaces the outer hedge walls for an entrance placement removal. * rct2: 0x00666D6F - * Replaces the outer hedge walls for an entrance placement removal. */ static void maze_entrance_hedge_replacement(int x, int y, rct_map_element *mapElement) { @@ -6906,7 +8048,7 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio return MONEY32_UNDEFINED; } - if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -6921,17 +8063,12 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio } sint16 clear_z = z / 8 + (is_exit ? 5 : 7); - RCT2_GLOBAL(0x009E32C4, sint16) = x; - RCT2_GLOBAL(0x009E32C6, sint16) = y; - - // Horrible hack until map_can_construct_with_clear_at is implemented. - RCT2_GLOBAL(0x009E32C8, uint8*) = (&flags) - 4; - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, (void*)0x0066637E, 0xF)) { + + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, RCT2_ADDRESS(0x009E32B8, money32))) { return MONEY32_UNDEFINED; } - if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & (1 << 2)) { + if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; return MONEY32_UNDEFINED; } @@ -6941,7 +8078,17 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio return MONEY32_UNDEFINED; } } else { - rct_ride* ride = GET_RIDE(rideIndex); + if (rideIndex >= MAX_RIDES) + { + log_warning("Invalid game command for ride %u", rideIndex); + return MONEY32_UNDEFINED; + } + rct_ride* ride = get_ride(rideIndex); + if (ride->type == RIDE_TYPE_NULL) + { + log_warning("Invalid game command for ride %u", rideIndex); + return MONEY32_UNDEFINED; + } if (ride->status != RIDE_STATUS_CLOSED) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_MUST_BE_CLOSED_FIRST; return MONEY32_UNDEFINED; @@ -7014,13 +8161,8 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio } sint8 clear_z = (z / 8) + (is_exit ? 5 : 7); - RCT2_GLOBAL(0x009E32C4, sint16) = x; - RCT2_GLOBAL(0x009E32C6, sint16) = y; - // Horrible hack until map_can_construct_with_clear_at is implemented. - RCT2_GLOBAL(0x009E32C8, uint8*) = (&flags) - 4; - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, (void*)0x0066637E, 0xF)) { + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z / 8, clear_z, &map_place_non_scenery_clear_func, 0xF, flags, RCT2_ADDRESS(0x009E32B8, money32))) { return MONEY32_UNDEFINED; } @@ -7035,7 +8177,14 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio } if (flags & GAME_COMMAND_FLAG_APPLY) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + rct_map_element* mapElement = map_element_insert(x / 32, y / 32, z / 8, 0xF); + assert(mapElement != NULL); mapElement->clearance_height = clear_z; mapElement->properties.entrance.type = is_exit; mapElement->properties.entrance.index = station_num << 4; @@ -7071,7 +8220,10 @@ money32 place_ride_entrance_or_exit(sint16 x, sint16 y, sint16 z, uint8 directio return RCT2_GLOBAL(0x009E32B8, money32); } -/* rct2: 0x006660A8 */ +/** + * + * rct2: 0x006660A8 + */ void game_command_place_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp){ *ebx = place_ride_entrance_or_exit( *eax & 0xFFFF, @@ -7086,10 +8238,20 @@ 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 (rideIndex >= MAX_RIDES) + { + log_warning("Invalid game command for ride %u", rideIndex); + return MONEY32_UNDEFINED; + } + 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){ + if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -7107,6 +8269,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; @@ -7125,6 +8292,12 @@ money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 return MONEY32_UNDEFINED; } + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + sub_6A7594(); maze_entrance_hedge_replacement(x, y, mapElement); footpath_remove_edges_at(x, y, mapElement); @@ -7149,7 +8322,10 @@ money32 remove_ride_entrance_or_exit(sint16 x, sint16 y, uint8 rideIndex, uint8 return 0; } -/* rct2: 0x0066640B */ +/** + * + * rct2: 0x0066640B + */ void game_command_remove_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp){ *ebx = remove_ride_entrance_or_exit( *eax & 0xFFFF, @@ -7160,21 +8336,29 @@ void game_command_remove_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int ); } +void ride_set_to_default_inspection_interval(int rideIndex) +{ + rct_ride *ride = get_ride(rideIndex); + uint8 defaultInspectionInterval = gConfigGeneral.default_inspection_interval; + if (ride->inspection_interval != defaultInspectionInterval) { + if (defaultInspectionInterval <= RIDE_INSPECTION_NEVER) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_OPERATING_MODE; + game_do_command(0, (defaultInspectionInterval << 8) | 1, 0, (5 << 8) | rideIndex, GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + } + } +} + /** * * rct2: 0x006B752C */ -void ride_crash(int rideIndex, int vehicleIndex) +void ride_crash(uint8 rideIndex, uint8 vehicleIndex) { rct_ride *ride; rct_vehicle *vehicle; rct_window *w; - // TODO Remove these when hook is no longer used - rideIndex &= 0xFF; - vehicleIndex &= 0xFF; - - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); vehicle = GET_VEHICLE(ride->vehicles[vehicleIndex]); if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO)) { @@ -7187,8 +8371,10 @@ void ride_crash(int rideIndex, int vehicleIndex) RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, rct_string_id) = ride->name; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; + if (gConfigNotifications.ride_crashed) { news_item_add_to_queue(NEWS_ITEM_RIDE, STR_RIDE_HAS_CRASHED, rideIndex); } +} bool ride_type_is_intamin(int rideType) { @@ -7346,3 +8532,38 @@ const uint8* ride_seek_available_modes(rct_ride *ride) return availableModes; } + +// Gets the approximate value of customers per hour for this ride. Multiplies ride_customers_in_last_5_minutes() by 12. +const uint32 ride_customers_per_hour(const rct_ride *ride) { + return ride_customers_in_last_5_minutes(ride) * 12; +} + +// Calculates the number of customers for this ride in the last 5 minutes (or more correctly 9600 game ticks) +const uint32 ride_customers_in_last_5_minutes(const rct_ride *ride) { + uint32 sum = ride->num_customers[0] + + ride->num_customers[1] + + ride->num_customers[2] + + ride->num_customers[3] + + ride->num_customers[4] + + ride->num_customers[5] + + ride->num_customers[6] + + ride->num_customers[7] + + ride->num_customers[8] + + ride->num_customers[9]; + return sum; +} + +rct_vehicle *ride_get_broken_vehicle(rct_ride *ride) { + uint16 vehicleIndex = ride->vehicles[ride->broken_vehicle]; + + if (vehicleIndex == 0xFFFF) { + return NULL; + } + + rct_vehicle *vehicle = GET_VEHICLE(vehicleIndex); + for (uint8 i = 0; i < ride->broken_car; i++) { + vehicle = GET_VEHICLE(vehicle->next_vehicle_on_train); + } + + return vehicle; +} diff --git a/src/ride/ride.h b/src/ride/ride.h index a54a49b105..4a3fa896cf 100644 --- a/src/ride/ride.h +++ b/src/ride/ride.h @@ -44,8 +44,13 @@ typedef struct { * Couples a ride type and subtype together. */ typedef struct { - uint8 type; - uint8 entry_index; + union { + struct { + uint8 type; + uint8 entry_index; + }; + uint16 ride_type_and_entry; + }; } ride_list_item; typedef struct { @@ -75,28 +80,33 @@ typedef struct { * size: unknown */ typedef struct { - rct_string_id name; // 0x000 - rct_string_id description; // 0x002 - uint32 images_offset; // 0x004 - uint32 flags; // 0x008 - uint8 ride_type[3]; // 0x00C - uint8 min_cars_in_train; // 0x00F - uint8 max_cars_in_train; // 0x010 - uint8 cars_per_flat_ride; // 0x011 - uint8 zero_cars; // 0x012 - uint8 tab_vehicle; // 0x013 - uint8 default_vehicle; // 0x014 - uint8 front_vehicle; // 0x015 - uint8 second_vehicle; // 0x016 - uint8 rear_vehicle; // 0x017 - uint8 third_vehicle; // 0x018 + rct_string_id name; // 0x000 + rct_string_id description; // 0x002 + uint32 images_offset; // 0x004 + uint32 flags; // 0x008 + uint8 ride_type[3]; // 0x00C + uint8 min_cars_in_train; // 0x00F + uint8 max_cars_in_train; // 0x010 + uint8 cars_per_flat_ride; // 0x011 + // Number of cars that can't hold passengers + uint8 zero_cars; // 0x012 + // The index to the vehicle type displayed in + // the vehicle tab. + uint8 tab_vehicle; // 0x013 + uint8 default_vehicle; // 0x014 + // Convert from first - fourth vehicle to + // vehicle structure + uint8 front_vehicle; // 0x015 + uint8 second_vehicle; // 0x016 + uint8 rear_vehicle; // 0x017 + uint8 third_vehicle; // 0x018 uint8 pad_019; - rct_ride_type_vehicle vehicles[4]; // 0x01A + rct_ride_entry_vehicle vehicles[4]; // 0x1A vehicle_colour_preset_list *vehicle_preset_list; // 0x1AE - sint8 excitement_multipler; // 0x1B2 - sint8 intensity_multipler; // 0x1B3 - sint8 nausea_multipler; // 0x1B4 - uint8 max_height; // 0x1B5 + sint8 excitement_multipler; // 0x1B2 + sint8 intensity_multipler; // 0x1B3 + sint8 nausea_multipler; // 0x1B4 + uint8 max_height; // 0x1B5 union { uint64 enabledTrackPieces; // 0x1B6 struct { @@ -107,7 +117,7 @@ typedef struct { uint8 category[2]; // 0x1BE uint8 shop_item; // 0x1C0 uint8 shop_item_secondary; // 0x1C1 -} rct_ride_type; +} rct_ride_entry; /** * Ride structure. @@ -138,7 +148,9 @@ typedef struct { uint8 station_heights[4]; // 0x05A uint8 station_length[4]; // 0x05E uint8 station_depart[4]; // 0x062 - uint8 var_066[4]; + // ride->vehicle index for current train waiting for passengers + // at station + uint8 train_at_station[4]; // 0x066 uint16 entrances[4]; // 0x06A uint16 exits[4]; // 0x072 uint16 last_peep_in_queue[4]; // 0x07A @@ -150,8 +162,8 @@ typedef struct { uint8 num_stations; // 0x0C7 uint8 num_vehicles; // 0x0C8 uint8 num_cars_per_train; // 0x0C9 - uint8 var_0CA; - uint8 var_0CB; + uint8 proposed_num_vehicles; // 0x0CA + uint8 proposed_num_cars_per_train; // 0x0CB uint8 max_trains; // 0x0CC uint8 min_max_cars_per_train; // 0x0CD uint8 min_waiting_time; // 0x0CE @@ -177,16 +189,25 @@ typedef struct { // (in RCT2, display_speed = (max_speed * 9) >> 18) sint32 max_speed; // 0x0D8 sint32 average_speed; // 0x0DC - uint8 pad_0E0[4]; + uint8 current_test_segment; // 0x0E0 + uint8 average_speed_test_timeout; // 0x0E1 + uint8 pad_0E2[0x2]; sint32 length[4]; // 0x0E4 uint16 time[4]; // 0x0F4 fixed16_2dp max_positive_vertical_g; // 0x0FC fixed16_2dp max_negative_vertical_g; // 0x0FE fixed16_2dp max_lateral_g; // 0x100 - uint8 pad_102[0xC]; - uint16 var_10E; - uint16 var_110; - uint16 var_112; + fixed16_2dp previous_vertical_g;// 0x102 + fixed16_2dp previous_lateral_g; // 0x104 + uint8 pad_106[0x2]; + uint32 testing_flags; // 0x108 + // x y map location of the current track piece during a test + // this is to prevent counting special tracks multiple times + rct_xy8 cur_test_track_location; // 0x10C + // Next 3 variables are related (XXXX XYYY ZZZa aaaa) + uint16 turn_count_default; // 0x10E X = current turn count + uint16 turn_count_banked; // 0x110 + uint16 turn_count_sloped; // 0x112 X = number turns > 3 elements union { uint8 inversions; // 0x114 (???X XXXX) uint8 holes; // 0x114 (???X XXXX) @@ -194,30 +215,25 @@ typedef struct { // It reaches the maximum value of 7 at about 50% undercover and doesn't increase beyond that. uint8 undercover_portion; // 0x114 (XXX?-????) }; - uint8 drops; // 0x115 (??XX XXXX) - uint8 var_116; + // Y is number of powered lifts, X is drops + uint8 drops; // 0x115 (YYXX XXXX) + uint8 start_drop_height; // 0x116 uint8 highest_drop_height; // 0x117 sint32 sheltered_length; // 0x118 - uint8 pad_11C[0x2]; - uint8 num_sheltered_sections; // 0x11E - uint8 var_11F; - sint16 var_120; - sint16 var_122; - sint16 var_124; - sint16 var_126; - sint16 var_128; - sint16 var_12A; - sint16 var_12C; - sint16 var_12E; - uint16 age; // 0x130 - sint16 running_cost; // 0x132 - sint16 var_134; - sint16 var_136; + // Unused always 0? Should affect nausea + uint16 var_11C; + uint8 num_sheltered_sections; // 0x11E (?abY YYYY) + // see cur_test_track_location + uint8 cur_test_track_z; // 0x11F + // Customer counter in the current 960 game tick (about 30 seconds) interval + uint16 cur_num_customers; // 0x120 + // Counts ticks to update customer intervals, resets each 960 game ticks. + uint16 num_customers_timeout; // 0x122 + // Customer count in the last 10 * 960 game ticks (sliding window) + uint16 num_customers[10]; // 0x124 money16 price; // 0x138 - sint16 var_13A; - sint16 var_13C; - uint8 var_13E; - uint8 var_13F; + rct_xy8 chairlift_bullwheel_location[2]; // 0x13A + uint8 chairlift_bullwheel_z[2]; // 0x13E union { rating_tuple ratings; // 0x140 struct { @@ -227,7 +243,7 @@ typedef struct { }; }; uint16 value; // 0x146 - uint16 var_148; + uint16 chairlift_bullwheel_rotation; // 0x148 uint8 satisfaction; // 0x14A uint8 satisfaction_time_out; // 0x14B uint8 satisfaction_next; // 0x14C @@ -241,7 +257,7 @@ typedef struct { uint8 popularity_next; // 0x15A When timeout reached this will be the next popularity uint8 num_riders; // 0x15B uint8 music_tune_id; // 0x15C - uint8 var_15D; + uint8 slide_in_use; // 0x15D union { uint16 slide_peep; // 0x15E uint16 maze_tiles; // 0x15E @@ -249,7 +265,7 @@ typedef struct { uint8 pad_160[0xE]; uint8 slide_peep_t_shirt_colour;// 0x16E uint8 pad_16F[0x7]; - uint8 var_176; + uint8 spiral_slide_progress; // 0x176 uint8 pad_177[0x9]; sint16 build_date; // 0x180 money16 upkeep_cost; // 0x182 @@ -274,18 +290,13 @@ typedef struct { uint8 downtime; // 0x199 uint8 inspection_interval; // 0x19A uint8 last_inspection; // 0x19B - uint8 var_19C; - uint8 var_19D; - uint8 var_19E; - uint8 var_19F; - uint8 var_1A0; - uint8 var_1A1; - uint8 var_1A2; - uint8 var_1A3; + uint8 downtime_history[8]; // 0x19C uint32 no_primary_items_sold; // 0x1A4 uint32 no_secondary_items_sold; // 0x1A8 - uint8 var_1AC; - uint8 var_1AD; + uint8 breakdown_sound_modifier; // 0x1AC + // Used to oscilate the sound when ride breaks down. + // 0 = no change, 255 = max change + uint8 not_fixed_timeout; // 0x1AD uint8 last_crash_type; // 0x1AE uint8 connected_message_throttle; // 0x1AF money32 income_per_hour; // 0x1B0 @@ -296,14 +307,14 @@ typedef struct { uint8 track_colour_supports[4]; // 0x1C4 uint8 music; // 0x1C8 uint8 entrance_style; // 0x1C9 - uint16 var_1CA; + uint16 vehicle_change_timeout; // 0x1CA uint8 num_block_brakes; // 0x1CC uint8 lift_hill_speed; // 0x1CD uint16 guests_favourite; // 0x1CE uint32 lifecycle_flags; // 0x1D0 uint8 vehicle_colours_extended[32]; // 0x1D4 uint16 total_air_time; // 0x1F4 - uint8 pad_1F6; + uint8 current_test_station; // 0x1F6 uint8 num_circuits; // 0x1F7 sint16 cable_lift_x; // 0x1F8 sint16 cable_lift_y; // 0x1FA @@ -382,9 +393,11 @@ enum { RIDE_ENTRY_FLAG_NO_INVERSIONS = 1 << 1, // 0x2 RIDE_ENTRY_FLAG_NO_BANKED_TRACK = 1 << 2, // 0x4 RIDE_ENTRY_FLAG_3 = 1 << 3, // 0x8 - RIDE_ENTRY_FLAG_4 = 1 << 4, // 0x10 - RIDE_ENTRY_FLAG_5 = 1 << 5, // 0x20 - RIDE_ENTRY_FLAG_6 = 1 << 6, // 0x40 + RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_1 = 1 << 4, // 0x10 + // Twist type rotation ride + RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_1 = 1 << 5, // 0x20 + // Lifting arm rotation ride (enterprise) + RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_2 = 1 << 6, // 0x40 RIDE_ENTRY_FLAG_7 = 1 << 7, // 0x80 RIDE_ENTRY_FLAG_8 = 1 << 8, // 0x100 RIDE_ENTRY_FLAG_9 = 1 << 9, // 0x200 @@ -398,7 +411,8 @@ enum { RIDE_ENTRY_DISABLE_FIRST_TWO_OPERATING_MODES = 1 << 17, // 0x20000 RIDE_ENTRY_FLAG_18 = 1 << 18, // 0x40000 RIDE_ENTRY_FLAG_19 = 1 << 19, // 0x80000 - RIDE_ENTRY_FLAG_20 = 1 << 20, // 0x100000 + // Must be set with swing mode 1 as well. + RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_2 = 1 << 20, // 0x100000 RIDE_ENTRY_FLAG_21 = 1 << 21, // 0x200000 RIDE_ENTRY_FLAG_22 = 1 << 22, // 0x400000 RIDE_ENTRY_FLAG_23 = 1 << 23, // 0x800000 @@ -412,6 +426,17 @@ enum { RIDE_ENTRY_FLAG_31 = 1 << 31, // 0x80000000 }; +enum{ + RIDE_TESTING_SHELTERED = (1 << 0), + RIDE_TESTING_TURN_LEFT = (1 << 1), + RIDE_TESTING_TURN_RIGHT = (1 << 2), + RIDE_TESTING_TURN_BANKED = (1 << 3), + RIDE_TESTING_TURN_SLOPED = (1 << 4), + RIDE_TESTING_DROP_DOWN = (1 << 5), + RIDE_TESTING_POWERED_LIFT = (1 << 6), + RIDE_TESTING_DROP_UP = (1 << 7), +}; + enum { RIDE_TYPE_NULL = 255, RIDE_TYPE_SPIRAL_ROLLER_COASTER = 0, @@ -524,7 +549,7 @@ enum { RIDE_MODE_ROTATING_LIFT, RIDE_MODE_STATION_TO_STATION, RIDE_MODE_SINGLE_RIDE_PER_ADMISSION, - RIDE_MODE_UNLIMITED_RIDES_PER_ADMISSION, + RIDE_MODE_UNLIMITED_RIDES_PER_ADMISSION = 10, RIDE_MODE_MAZE, RIDE_MODE_RACE, RIDE_MODE_BUMPERCAR, @@ -534,7 +559,7 @@ enum { RIDE_MODE_FORWARD_ROTATION, RIDE_MODE_BACKWARD_ROTATION, RIDE_MODE_FILM_AVENGING_AVIATORS, - RIDE_MODE_3D_FILM_MOUSE_TAILS, + RIDE_MODE_3D_FILM_MOUSE_TAILS = 20, RIDE_MODE_SPACE_RINGS, RIDE_MODE_BEGINNERS, RIDE_MODE_LIM_POWERED_LAUNCH, @@ -544,7 +569,7 @@ enum { RIDE_MODE_INTENSE, RIDE_MODE_BERSERK, RIDE_MODE_HAUNTED_HOUSE, - RIDE_MODE_CIRCUS_SHOW, + RIDE_MODE_CIRCUS_SHOW = 30, RIDE_MODE_DOWNWARD_LAUNCH, RIDE_MODE_CROOKED_HOUSE, RIDE_MODE_FREEFALL_DROP, @@ -601,7 +626,8 @@ enum { MUSIC_STYLE_MODERN, MUSIC_STYLE_PIRATES, MUSIC_STYLE_ROCK_STYLE_3, - MUSIC_STYLE_CANDY_STYLE + MUSIC_STYLE_CANDY_STYLE, + MUSIC_STYLE_COUNT }; enum { @@ -633,6 +659,14 @@ enum { RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH = 1 << 7 }; +enum { + WAIT_FOR_LOAD_QUARTER, + WAIT_FOR_LOAD_HALF, + WAIT_FOR_LOAD_THREE_QUARTER, + WAIT_FOR_LOAD_FULL, + WAIT_FOR_LOAD_ANY, +}; + enum { RIDE_COLOUR_SCHEME_MAIN, RIDE_COLOUR_SCHEME_ADDITIONAL_1, @@ -713,7 +747,7 @@ enum { RIDE_TYPE_FLAG_TRACK_ELEMENTS_HAVE_TWO_VARIETIES = 1 << 12, // used by rides with two variaties, like the u and o shapes of the dinghy slide and the dry and submerged track of the water coaster RIDE_TYPE_FLAG_13 = 1 << 13, // used only by maze, spiral slide and shops RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS = 1 << 14, - RIDE_TYPE_FLAG_15 = 1 << 15, // something to do with station, price and viewport zoom + RIDE_TYPE_FLAG_HAS_NO_TRACK = 1 << 15, RIDE_TYPE_FLAG_16 = 1 << 16, // something to do with vehicle colour scheme RIDE_TYPE_FLAG_IS_SHOP = 1 << 17, RIDE_TYPE_FLAG_18 = 1 << 18, @@ -810,6 +844,19 @@ enum { SHOP_ITEM_COUNT = 56 }; +enum { + RIDE_SETTING_MODE, + RIDE_SETTING_DEPARTURE, + RIDE_SETTING_MIN_WAITING_TIME, + RIDE_SETTING_MAX_WAITING_TIME, + RIDE_SETTING_OPERATION_OPTION, + RIDE_SETTING_INSPECTION_INTERVAL, + RIDE_SETTING_MUSIC, + RIDE_SETTING_MUSIC_TYPE, + RIDE_SETTING_LIFT_HILL_SPEED, + RIDE_SETTING_NUM_CIRCUITS, +}; + #define MAX_RIDES 255 #define MAX_RIDE_MEASUREMENTS 8 @@ -819,23 +866,23 @@ enum { #define STATION_DEPART_FLAG (1 << 7) #define STATION_DEPART_MASK (~STATION_DEPART_FLAG) -// rct2: 0x009ACFA4 -extern rct_ride_type **gRideTypeList; - -// rct2: 0x013628F8 -extern rct_ride* g_ride_list; +#define CURRENT_TURN_COUNT_MASK 0xF800 +#define TURN_MASK_1_ELEMENT 0x001F +#define TURN_MASK_2_ELEMENTS 0x00E0 +#define TURN_MASK_3_ELEMENTS 0x0700 +#define TURN_MASK_4_PLUS_ELEMENTS 0xF800 /** Helper macros until rides are stored in this module. */ -#define GET_RIDE(x) (&g_ride_list[x]) -#define GET_RIDE_MEASUREMENT(x) (&(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_MEASUREMENTS, rct_ride_measurement)[x])) -#define GET_RIDE_ENTRY(x) gRideTypeList[x] +rct_ride *get_ride(int index); +rct_ride_entry *get_ride_entry(int index); +rct_ride_measurement *get_ride_measurement(int index); /** * Helper macro loop for enumerating through all the non null rides. */ #define FOR_ALL_RIDES(i, ride) \ for (i = 0; i < MAX_RIDES; i++) \ - if ((ride = &g_ride_list[i])->type != RIDE_TYPE_NULL) + if ((ride = get_ride(i))->type != RIDE_TYPE_NULL) extern const uint8 gRideClassifications[255]; @@ -858,7 +905,7 @@ extern const uint8 gRideClassifications[255]; #define _currentTrackBeginX RCT2_GLOBAL(0x00F440A8, uint16) #define _currentTrackBeginY RCT2_GLOBAL(0x00F440AA, uint16) #define _currentTrackBeginZ RCT2_GLOBAL(0x00F440AC, uint16) -#define _currentTrackPieceDirection RCT2_GLOBAL(0x00F440AE, uint8) +#define _currentTrackPieceDirection RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) #define _currentTrackPieceType RCT2_GLOBAL(0x00F440AF, uint8) #define _currentTrackSelectionFlags RCT2_GLOBAL(0x00F440B0, uint8) #define _rideConstructionArrowPulseTime RCT2_GLOBAL(0x00F440B1, sint8) @@ -897,7 +944,7 @@ money32 get_shop_item_cost(int shopItem); money16 get_shop_base_value(int shopItem); money16 get_shop_hot_value(int shopItem); money16 get_shop_cold_value(int shopItem); -int sub_6CAF80(int rideIndex, rct_xy_element *output); +bool ride_try_get_origin_element(int rideIndex, rct_xy_element *output); int ride_find_track_gap(rct_xy_element *input, rct_xy_element *output); void ride_construct_new(ride_list_item listItem); void ride_construct(int rideIndex); @@ -909,7 +956,7 @@ int ride_get_total_time(rct_ride *ride); int ride_can_have_multiple_circuits(rct_ride *ride); track_colour ride_get_track_colour(rct_ride *ride, int colourScheme); vehicle_colour ride_get_vehicle_colour(rct_ride *ride, int vehicleIndex); -rct_ride_type *ride_get_entry(rct_ride *ride); +rct_ride_entry *get_ride_entry_by_ride(rct_ride *ride); uint8 *get_ride_entry_indices_for_ride_type(uint8 rideType); void reset_type_to_ride_entry_index_map(); void ride_measurement_clear(rct_ride *ride); @@ -940,23 +987,22 @@ void game_command_callback_ride_remove_track_piece(int eax, int ebx, int ecx, in void game_command_demolish_ride(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_set_ride_appearance(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_set_ride_price(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); + void ride_clear_for_construction(int rideIndex); -void set_vehicle_type_image_max_sizes(rct_ride_type_vehicle* vehicle_type, int num_images); +void set_vehicle_type_image_max_sizes(rct_ride_entry_vehicle* vehicle_type, int num_images); void invalidate_test_results(int rideIndex); void ride_select_next_section(); void ride_select_previous_section(); -int get_var_10E_unk_1(rct_ride* ride); -int get_var_10E_unk_2(rct_ride* ride); -int get_var_10E_unk_3(rct_ride* ride); -int get_var_110_unk_1(rct_ride* ride); -int get_var_110_unk_2(rct_ride* ride); -int get_var_110_unk_3(rct_ride* ride); -int get_var_112_unk_1(rct_ride* ride); -int get_var_112_unk_2(rct_ride* ride); -int get_var_112_unk_3(rct_ride* ride); -int get_var_112_unk_4(rct_ride* ride); +void increment_turn_count_1_element(rct_ride* ride, uint8 type); +void increment_turn_count_2_elements(rct_ride* ride, uint8 type); +void increment_turn_count_3_elements(rct_ride* ride, uint8 type); +void increment_turn_count_4_plus_elements(rct_ride* ride, uint8 type); +int get_turn_count_1_element(rct_ride* ride, uint8 type); +int get_turn_count_2_elements(rct_ride* ride, uint8 type); +int get_turn_count_3_elements(rct_ride* ride, uint8 type); +int get_turn_count_4_plus_elements(rct_ride* ride, uint8 type); uint8 ride_get_helix_sections(rct_ride *ride); bool ride_has_spinning_tunnel(rct_ride *ride); @@ -1004,8 +1050,10 @@ void game_command_set_ride_vehicles(int *eax, int *ebx, int *ecx, int *edx, int void game_command_place_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); void game_command_remove_ride_entrance_or_exit(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp); +void ride_set_to_default_inspection_interval(int rideIndex); + void sub_6CB945(int rideIndex); -void ride_crash(int rideIndex, int vehicleIndex); +void ride_crash(uint8 rideIndex, uint8 vehicleIndex); bool ride_type_is_intamin(int rideType); void sub_6C94D8(); @@ -1019,4 +1067,13 @@ const uint8* ride_seek_available_modes(rct_ride *ride); void window_ride_construction_mouseup_demolish_next_piece(int x, int y, int z, int direction, int type); +const uint32 ride_customers_per_hour(const rct_ride *ride); +const uint32 ride_customers_in_last_5_minutes(const rct_ride *ride); + +rct_vehicle * ride_get_broken_vehicle(rct_ride *ride); + +void window_ride_construction_do_station_check(); +void window_ride_construction_do_entrance_exit_check(); +void game_command_callback_place_ride_entrance_or_exit(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp); + #endif diff --git a/src/ride/ride_data.c b/src/ride/ride_data.c index c7cc940212..f5f95f4c5f 100644 --- a/src/ride/ride_data.c +++ b/src/ride/ride_data.c @@ -1,4 +1,4 @@ -/* +/** * Whether a particular ride has a running track or not. Will probably end up * being used in various places in the game. * @@ -11,6 +11,7 @@ #include "../localisation/localisation.h" #include "ride.h" #include "ride_data.h" +#include "../audio/audio.h" const bool hasRunningTrack[0x60] = { true, // 0 Spiral Roller coaster @@ -585,6 +586,100 @@ const uint8 rideUnknownData3[0x60] = { 10, // 59 LIM Launched Roller Coaster }; +// Data at 0x0097D21E +const uint8 rideBonusValue[0x60] = { + 85, // 00 Spiral Roller coaster + 90, // 01 Stand Up Coaster + 90, // 02 Suspended Swinging + 100, // 03 Inverted + 60, // 04 Steel Mini Coaster + 50, // 05 Mini Railroad + 60, // 06 Monorail + 50, // 07 Mini Suspended Coaster + 40, // 08 Boat Ride + 55, // 09 Wooden Wild Mine/Mouse + 60, // 0a Steeplechase/Motorbike/Soap + 50, // 0b Car Ride + 65, // 0c Launched Freefall + 75, // 0d Bobsleigh Coaster + 45, // 0e Observation Tower + 95, // 0f Looping Roller Coaster + 55, // 10 Dinghy Slide + 85, // 11 Mine Train Coaster + 55, // 12 Chairlift + 100, // 13 Corkscrew Roller Coaster + 40, // 14 Maze + 40, // 15 Spiral Slide + 55, // 16 Go Karts + 65, // 17 Log Flume + 70, // 18 River Rapids + 35, // 19 Bumper Cars + 35, // 1a Pirate Ship + 35, // 1b Swinging Inverter Ship + 15, // 1c Food Stall + 15, // 1d (none) + 15, // 1e Drink Stall + 15, // 1f (none) + 15, // 20 Shop (all types) + 45, // 21 Merry Go Round + 15, // 22 Balloon Stall (maybe) + 15, // 23 Information Kiosk + 5, // 24 Bathroom + 45, // 25 Ferris Wheel + 45, // 26 Motion Simulator + 45, // 27 3D Cinema + 55, // 28 Topspin + 30, // 29 Space Rings + 70, // 2a Reverse Freefall Coaster + 45, // 2b Elevator + 95, // 2c Vertical Drop Roller Coaster + 5, // 2d ATM + 40, // 2e Twist + 22, // 2f Haunted House + 5, // 30 First Aid + 39, // 31 Circus Show + 50, // 32 Ghost Train + 120, // 33 Twister Roller Coaster + 105, // 34 Wooden Roller Coaster + 65, // 35 Side-Friction Roller Coaster + 55, // 36 Wild Mouse + 100, // 37 Multi Dimension Coaster + 100, // 38 (none) + 100, // 39 Flying Roller Coaster + 100, // 3a (none) + 50, // 3b Virginia Reel + 65, // 3c Splash Boats + 45, // 3d Mini Helicopters + 100, // 3e Lay-down Roller Coaster + 60, // 3f Suspended Monorail + 100, // 40 (none) + 65, // 41 Reverser Roller Coaster + 35, // 42 Heartline Twister Roller Coaster + 23, // 43 Mini Golf + 120, // 44 Giga Coaster + 45, // 45 Roto-Drop + 35, // 46 Flying Saucers + 22, // 47 Crooked House + 45, // 48 Monorail Cycles + 80, // 49 Compact Inverted Coaster + 60, // 4a Water Coaster + 70, // 4b Air Powered Vertical Coaster + 55, // 4c Inverted Hairpin Coaster + 35, // 4d Magic Carpet + 40, // 4e Submarine Ride + 65, // 4f River Rafts + 15, // 50 (none) + 45, // 51 Enterprise + 15, // 52 (none) + 15, // 53 (none) + 15, // 54 (none) + 100, // 55 (none) + 75, // 56 Inverted Impulse Coaster + 60, // 57 Mini Roller Coaster + 70, // 58 Mine Ride + 55, // 59 LIM Launched Roller Coaster +}; + const rct_ride_name_convention RideNameConvention[96] = { { 1229, 1243, 1257, 0 }, // 00 Spiral Roller coaster { 1229, 1243, 1257, 0 }, // 01 Stand Up Coaster @@ -679,7 +774,10 @@ const rct_ride_name_convention RideNameConvention[96] = { { 1229, 1243, 1257, 0 } }; -/* rct2: 0x0097C8AC */ +/** + * + * rct2: 0x0097C8AC + */ const uint8 RideAvailableModes[] = { RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 00 Spiral Roller coaster RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 01 Stand Up Coaster @@ -733,7 +831,7 @@ const uint8 RideAvailableModes[] = { RIDE_MODE_CIRCUS_SHOW, 0xFF, // 31 Circus Show RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 32 Ghost Train RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 33 Twister Roller Coaster - RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 34 Wooden Roller Coaster + RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE, 0xFF, // 34 Wooden Roller Coaster RIDE_MODE_CONTINUOUS_CIRCUIT, 0xFF, // 35 Side-Friction Roller Coaster RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 36 Wild Mouse RIDE_MODE_CONTINUOUS_CIRCUIT, RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED, 0xFF, // 37 Multi Dimension Coaster @@ -889,100 +987,6 @@ const rct_ride_entrance_definition RideEntranceDefinitions[RIDE_ENTRANCE_STYLE_C { 0, 0, 2, STR_ENTRANCE_NONE, 0x00000000, 0, } // RIDE_ENTRANCE_STYLE_NONE }; -// Data read from 0x0097D7C9 4 bytes at a time -const uint8 RideLiftHillAdjustments[0x60] = { - 7, // Spiral Roller coaster - 4, // Stand Up Coaster - 4, // Suspended Swinging - 5, // Inverted - 4, // Steel Mini Coaster - 5, // Mini Railroad - 5, // Monorail - 4, // Mini Suspended Coaster - 5, // Boat Ride - 4, // Wooden Wild Mine/Mouse - 4, // Steeplechase/Motorbike/Soap Box Derby - 5, // Car Ride - 5, // Launched Freefall - 4, // Bobsleigh Coaster - 5, // Observation Tower - 4, // Looping Roller Coaster - 4, // Dinghy Slide - 4, // Mine Train Coaster - 5, // Chairlift - 4, // Corkscrew Roller Coaster - 5, // Maze - 5, // Spiral Slide - 5, // Go Karts - 5, // Log Flume - 5, // River Rapids - 5, // Bumper Cars - 5, // Pirate Ship - 5, // Swinging Inverter Ship - 5, // Food Stall - 5, // (none) - 5, // Drink Stall - 5, // (none) - 5, // Shop (all types) - 5, // Merry Go Round - 5, // Balloon Stall (maybe) - 5, // Information Kiosk - 5, // Bathroom - 5, // Ferris Wheel - 5, // Motion Simulator - 5, // 3D Cinema - 5, // Topspin - 5, // Space Rings - 5, // Reverse Freefall Coaster - 5, // Elevator - 4, // Vertical Drop Roller Coaster - 5, // ATM - 5, // Twist - 5, // Haunted House - 5, // First Aid - 5, // Circus Show - 5, // Ghost Train - 5, // Twister Roller Coaster - 5, // Wooden Roller Coaster - 3, // Side-Friction Roller Coaster - 4, // Wild Mouse - 4, // Multi Dimension Coaster - 4, // (none) - 4, // Flying Roller Coaster - 4, // (none) - 3, // Virginia Reel - 5, // Splash Boats - 5, // Mini Helicopters - 4, // Lay-down Roller Coaster - 5, // Suspended Monorail - 4, // (none) - 3, // Reverser Roller Coaster - 4, // Heartline Twister Roller Coaster - 5, // Mini Golf - 5, // Giga Coaster - 5, // Roto-Drop - 5, // Flying Saucers - 5, // Crooked House - 5, // Monorail Cycles - 4, // Compact Inverted Coaster - 4, // Water Coaster - 5, // Air Powered Vertical Coaster - 4, // Inverted Hairpin Coaster - 5, // Magic Carpet - 5, // Submarine Ride - 5, // River Rafts - 5, // (none) - 5, // Enterprise - 5, // (none) - 5, // (none) - 5, // (none) - 4, // (none) - 4, // Inverted Impulse Coaster - 4, // Mini Roller Coaster - 5, // Mine Ride - 4 // LIM Launched Roller Coaster -}; - // rct2: 0x0097D4F2 const rct_ride_data_4 RideData4[91] = { { RIDE_TYPE_FLAG4_ALLOW_MUSIC | RIDE_TYPE_FLAG4_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG4_HAS_ENTRANCE_EXIT | RIDE_TYPE_FLAG4_HAS_AIR_TIME | RIDE_TYPE_FLAG4_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG4_11 | RIDE_TYPE_FLAG4_13, MUSIC_STYLE_ROCK_STYLE_3, 0, 0, 0, 20, 20 }, // RIDE_TYPE_SPIRAL_ROLLER_COASTER @@ -1252,11 +1256,11 @@ const uint32 ShopItemImage[SHOP_ITEM_COUNT] = { 5110, // SHOP_ITEM_EMPTY_BOWL_BLUE }; -const rct_ride_type_vehicle CableLiftVehicle = { +const rct_ride_entry_vehicle CableLiftVehicle = { .rotation_frame_mask = 31, .var_02 = 0, .var_03 = 0, - .var_04 = 0, + .spacing = 0, .car_friction = 0, .tab_height = 0, .num_seats = 0, @@ -1265,8 +1269,8 @@ const rct_ride_type_vehicle CableLiftVehicle = { .sprite_height_negative = 0, .sprite_height_positive = 0, .var_11 = 0, - .var_12 = 0, - .var_14 = 0, + .flags_a = 0, + .flags_b = 0, .var_16 = 1, .base_image_id = 29110, .var_1C = 0, @@ -1286,7 +1290,9 @@ const rct_ride_type_vehicle CableLiftVehicle = { .no_seating_rows = 0, .spinning_inertia = 0, .spinning_friction = 255, - .pad_57 = { 0,0,0 }, + .friction_sound_id = 0, + .var_58 = 0, + .sound_range = 0, .var_5A = 0, .powered_acceleration = 0, .powered_max_speed = 0, @@ -1296,3 +1302,110 @@ const rct_ride_type_vehicle CableLiftVehicle = { .special_frames = 0, .peep_loading_positions = NULL }; + +/* rct2: 0x009A0AA0 */ +const uint16 RideFilmLength[3] = { + 5000, // MOUSE_TAILS + 6000, // STORM_CHASERS + 7000 // SPACE_RAIDERS +}; + +/* rct2: 0x009A0AC4 */ +const uint16 RideCrookedHouseLength[1] = { + 600 +}; + +/* rct2: 0x0097D7C8, 0x0097D7C9, 0x0097D7CA */ +const rct_ride_lift_data RideLiftData[] = { + { SOUND_LIFT_3, 7, 7 }, // Spiral Roller coaster + { SOUND_LIFT_1, 4, 6 }, // Stand Up Coaster + { SOUND_LIFT_1, 4, 6 }, // Suspended Swinging + { SOUND_LIFT_7, 5, 7 }, // Inverted + { SOUND_LIFT_3, 4, 6 }, // Steel Mini Coaster + { 255, 5, 5 }, // Mini Railroad + { 255, 5, 5 }, // Monorail + { SOUND_LIFT_3, 4, 5 }, // Mini Suspended Coaster + { 255, 5, 5 }, // Boat Ride + { SOUND_LIFT_1, 4, 5 }, // Wooden Wild Mine/Mouse + { SOUND_LIFT_1, 4, 5 }, // Steeplechase/Motorbike/Soap Box D + { 255, 5, 5 }, // Car Ride + { 255, 5, 5 }, // Launched Freefall + { SOUND_LIFT_3, 4, 5 }, // Bobsleigh Coaster + { 255, 5, 5 }, // Observation Tower + { SOUND_LIFT_1, 4, 6 }, // Looping Roller Coaster + { SOUND_LIFT_3, 4, 5 }, // Dinghy Slide + { SOUND_LIFT_4, 4, 6 }, // Mine Train Coaster + { 255, 5, 5 }, // Chairlift + { SOUND_LIFT_4, 4, 6 }, // Corkscrew Roller Coaster + { 255, 5, 5 }, // Maze + { 255, 5, 5 }, // Spiral Slide + { 255, 5, 5 }, // Go Karts + { 255, 5, 5 }, // Log Flume + { 255, 5, 5 }, // River Rapids + { 255, 5, 5 }, // Bumper Cars + { 255, 5, 5 }, // Pirate Ship + { 255, 5, 5 }, // Swinging Inverter Ship + { 255, 5, 5 }, // Food Stall + { 255, 5, 5 }, // (none) + { 255, 5, 5 }, // Drink Stall + { 255, 5, 5 }, // (none) + { 255, 5, 5 }, // Shop (all types) + { 255, 5, 5 }, // Merry Go Round + { 255, 5, 5 }, // Balloon Stall (maybe) + { 255, 5, 5 }, // Information Kiosk + { 255, 5, 5 }, // Bathroom + { 255, 5, 5 }, // Ferris Wheel + { 255, 5, 5 }, // Motion Simulator + { 255, 5, 5 }, // 3D Cinema + { 255, 5, 5 }, // Topspin + { 255, 5, 5 }, // Space Rings + { 255, 5, 5 }, // Reverse Freefall Coaster + { 255, 5, 5 }, // Elevator + { SOUND_LIFT_7, 4, 5 }, // Vertical Drop Roller Coaster + { 255, 5, 5 }, // ATM + { 255, 5, 5 }, // Twist + { 255, 5, 5 }, // Haunted House + { 255, 5, 5 }, // First Aid + { 255, 5, 5 }, // Circus Show + { 255, 5, 5 }, // Ghost Train + { SOUND_LIFT_7, 5, 8 }, // Twister Roller Coaster + { SOUND_LIFT_5, 5, 7 }, // Wooden Roller Coaster + { SOUND_LIFT_5, 3, 4 }, // Side-Friction Roller Coaster + { SOUND_LIFT_6, 4, 6 }, // Wild Mouse + { SOUND_LIFT_3, 4, 6 }, // Multi Dimension Coaster + { SOUND_LIFT_3, 4, 6 }, // (none) + { SOUND_LIFT_7, 4, 6 }, // Flying Roller Coaster + { SOUND_LIFT_7, 4, 6 }, // (none) + { SOUND_LIFT_1, 3, 4 }, // Virginia Reel + { 255, 5, 5 }, // Splash Boats + { 255, 5, 5 }, // Mini Helicopters + { SOUND_LIFT_1, 4, 6 }, // Lay-down Roller Coaster + { 255, 5, 5 }, // Suspended Monorail + { SOUND_LIFT_1, 4, 6 }, // (none) + { SOUND_LIFT_1, 3, 4 }, // Reverser Roller Coaster + { SOUND_LIFT_1, 4, 6 }, // Heartline Twister Roller Coaster + { 255, 5, 5 }, // Mini Golf + { SOUND_LIFT_1, 5, 8 }, // Giga Coaster + { 255, 5, 5 }, // Roto-Drop + { 255, 5, 5 }, // Flying Saucers + { 255, 5, 5 }, // Crooked House + { 255, 5, 5 }, // Monorail Cycles + { SOUND_LIFT_3, 4, 6 }, // Compact Inverted Coaster + { SOUND_LIFT_1, 4, 6 }, // Water Coaster + { 255, 5, 5 }, // Air Powered Vertical Coaster + { SOUND_LIFT_6, 4, 6 }, // Inverted Hairpin Coaster + { 255, 5, 5 }, // Magic Carpet + { 255, 5, 5 }, // Submarine Ride + { 255, 5, 5 }, // River Rafts + { 255, 5, 5 }, // (none) + { 255, 5, 5 }, // Enterprise + { 255, 5, 5 }, // (none) + { 255, 5, 5 }, // (none) + { 255, 5, 5 }, // (none) + { SOUND_LIFT_4, 4, 7 }, // (none) + { SOUND_LIFT_1, 4, 7 }, // Inverted Impulse Coaster + { SOUND_LIFT_1, 4, 6 }, // Mini Roller Coaster + { 255, 5, 5 }, // Mine Ride + { SOUND_LIFT_6, 4, 6 }, // (none) + { 255, 4, 6 } // LIM Launched Roller Coaster +}; diff --git a/src/ride/ride_data.h b/src/ride/ride_data.h index bd124525b5..0275dd3a06 100644 --- a/src/ride/ride_data.h +++ b/src/ride/ride_data.h @@ -54,6 +54,12 @@ typedef struct { uint8 pad[4]; } rct_ride_data_4; +typedef struct { + uint8 sound_id; + uint8 minimum_speed; + uint8 maximum_speed; +} rct_ride_lift_data; + enum { RIDE_TYPE_FLAG4_0 = (1 << 0), RIDE_TYPE_FLAG4_MUSIC_ON_DEFAULT = (1 << 1), @@ -80,6 +86,7 @@ extern const uint8 costPerTrackPiece[0x60]; extern const uint8 rideUnknownData1[0x60]; extern const bool rideUnknownData2[0x60]; extern const uint8 rideUnknownData3[0x60]; +extern const uint8 rideBonusValue[0x60]; extern const rct_ride_name_convention RideNameConvention[96]; extern const uint8 RideAvailableModes[]; @@ -87,7 +94,7 @@ extern const uint8 AllRideModesAvailable[]; extern const uint8 RideAvailableBreakdowns[]; extern const rct_ride_entrance_definition RideEntranceDefinitions[RIDE_ENTRANCE_STYLE_COUNT]; -extern const uint8 RideLiftHillAdjustments[0x60]; +extern const rct_ride_lift_data RideLiftData[91]; extern const rct_ride_data_4 RideData4[91]; @@ -95,6 +102,9 @@ extern const money8 DefaultShopItemPrice[SHOP_ITEM_COUNT]; extern const rct_shop_item_string_types ShopItemStringIds[SHOP_ITEM_COUNT]; extern const uint32 ShopItemImage[SHOP_ITEM_COUNT]; -extern const rct_ride_type_vehicle CableLiftVehicle; +extern const rct_ride_entry_vehicle CableLiftVehicle; + +extern const uint16 RideFilmLength[3]; +extern const uint16 RideCrookedHouseLength[1]; #endif diff --git a/src/ride/ride_ratings.c b/src/ride/ride_ratings.c index 5b04920885..a65ba6e349 100644 --- a/src/ride/ride_ratings.c +++ b/src/ride/ride_ratings.c @@ -137,7 +137,7 @@ static void ride_ratings_update_state_0() if (_rideRatingsCurrentRide == 255) _rideRatingsCurrentRide = 0; - ride = GET_RIDE(_rideRatingsCurrentRide); + ride = get_ride(_rideRatingsCurrentRide); if (ride->type != RIDE_TYPE_NULL && ride->status != RIDE_STATUS_CLOSED) _rideRatingsState = RIDE_RATINGS_STATE_INITIALISE; } @@ -170,7 +170,7 @@ static void ride_ratings_update_state_2() rct_xy_element trackElement, nextTrackElement; int x, y, z, trackType, entranceIndex; - ride = GET_RIDE(_rideRatingsCurrentRide); + ride = get_ride(_rideRatingsCurrentRide); if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; return; @@ -233,7 +233,7 @@ static void ride_ratings_update_state_3() { rct_ride *ride; - ride = GET_RIDE(_rideRatingsCurrentRide); + ride = get_ride(_rideRatingsCurrentRide); if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; return; @@ -267,7 +267,7 @@ static void ride_ratings_update_state_5() track_begin_end trackBeginEnd; int x, y, z, trackType; - ride = GET_RIDE(_rideRatingsCurrentRide); + ride = get_ride(_rideRatingsCurrentRide); if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; return; @@ -322,7 +322,7 @@ static void ride_ratings_begin_proximity_loop() rct_ride *ride; int i, x, y, z; - ride = GET_RIDE(_rideRatingsCurrentRide); + ride = get_ride(_rideRatingsCurrentRide); if (ride->type == RIDE_TYPE_NULL || ride->status == RIDE_STATUS_CLOSED) { _rideRatingsState = RIDE_RATINGS_STATE_FIND_NEXT_RIDE; return; @@ -632,10 +632,6 @@ static void ride_ratings_calculate(rct_ride *ride) ride->ratings.nausea = max(0, ride->ratings.nausea); } #endif - - // Original ride calculation - // calcFunc = RCT2_ADDRESS(0x0097E050, ride_ratings_calculation)[ride->type]; - // RCT2 CALLPROC X((int)calcFunc, 0, 0, 0, 0, 0, (int)ride, 0); } static void ride_ratings_calculate_value(rct_ride *ride) @@ -683,10 +679,8 @@ static void ride_ratings_calculate_value(rct_ride *ride) } /** - * rct2: sub_65E621 - * * I think this function computes ride upkeep? Though it is weird that the - * + * rct2: sub_65E621 * inputs * - edi: ride ptr */ @@ -771,11 +765,12 @@ static uint16 ride_compute_upkeep(rct_ride *ride) // multiply by 5/8 upkeep = upkeep * 10; upkeep = upkeep >> 4; - return upkeep; + return upkeep; } /** - * rct2: 0x0065E7FB + * + * rct2: 0x0065E7FB * * inputs * - bx: excitement @@ -785,9 +780,9 @@ static uint16 ride_compute_upkeep(rct_ride *ride) */ static void ride_ratings_apply_adjustments(rct_ride *ride, rating_tuple *ratings) { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; - rideEntry = gRideTypeList[ride->subtype]; + rideEntry = get_ride_entry(ride->subtype); // Apply ride entry multipliers ratings->excitement += ((ratings->excitement * rideEntry->excitement_multipler) >> 7); @@ -839,15 +834,13 @@ static void ride_ratings_apply_intensity_penalty(rating_tuple *ratings) } /** + * * rct2: 0x00655FD6 */ static void set_unreliability_factor(rct_ride *ride) { - // The higher the number, the lower the breakdown - // possibility. Range is [3, 7]. values are here: - // https://gist.github.com/kevinburke/123977c4884ccadbec70. Consider - // inlining this per ride - uint8 lift_speed_adjustment = RideLiftHillAdjustments[ride->type]; + // The bigger the difference in lift speed and minimum the higher the unreliability + uint8 lift_speed_adjustment = RideLiftData[ride->type].minimum_speed; ride->unreliability_factor += (ride->lift_hill_speed - lift_speed_adjustment) * 2; } @@ -923,103 +916,97 @@ static int sub_65E72D(rct_ride *ride) } int dh = numShelteredEighths; - rct_ride_type *rideType = GET_RIDE_ENTRY(ride->subtype); + rct_ride_entry *rideType = get_ride_entry(ride->subtype); if (rideType->flags & RIDE_ENTRY_FLAG_COVERED_RIDE) numShelteredEighths = 7; return (dh << 8) | numShelteredEighths; } -static rating_tuple get_var_10E_rating(rct_ride* ride) { - int var_10E_unk_1 = get_var_10E_unk_1(ride); - int var_10E_unk_2 = get_var_10E_unk_2(ride); - int var_10E_unk_3 = get_var_10E_unk_3(ride); +static rating_tuple get_flat_turns_rating(rct_ride* ride) { + rating_tuple rating; - int excitement = (var_10E_unk_1 * 0x28000) >> 16; - excitement += (var_10E_unk_2 * 0x30000) >> 16; - excitement += (var_10E_unk_3 * 63421) >> 16; + int no_3_plus_turns = get_turn_count_3_elements(ride, 0); + int no_2_turns = get_turn_count_2_elements(ride, 0); + int no_1_turns = get_turn_count_1_element(ride, 0); - int intensity = (var_10E_unk_1 * 81920) >> 16; - intensity += (var_10E_unk_2 * 49152) >> 16; - intensity += (var_10E_unk_3 * 21140) >> 16; + rating.excitement = (no_3_plus_turns * 0x28000) >> 16; + rating.excitement += (no_2_turns * 0x30000) >> 16; + rating.excitement += (no_1_turns * 63421) >> 16; - int nausea = (var_10E_unk_1 * 0x50000) >> 16; - nausea += (var_10E_unk_2 * 0x32000) >> 16; - nausea += (var_10E_unk_3 * 42281) >> 16; + rating.intensity = (no_3_plus_turns * 81920) >> 16; + rating.intensity += (no_2_turns * 49152) >> 16; + rating.intensity += (no_1_turns * 21140) >> 16; + + rating.nausea = (no_3_plus_turns * 0x50000) >> 16; + rating.nausea += (no_2_turns * 0x32000) >> 16; + rating.nausea += (no_1_turns * 42281) >> 16; - rating_tuple rating = { excitement, intensity, nausea }; return rating; } /** - * rct2: 0x0065DF72 + * + * rct2: 0x0065DF72 */ -static rating_tuple get_var_110_rating(rct_ride* ride) { - int var_110_unk_1 = get_var_110_unk_1(ride); - int var_110_unk_2 = get_var_110_unk_2(ride); - int var_110_unk_3 = get_var_110_unk_3(ride); +static rating_tuple get_banked_turns_rating(rct_ride* ride) { + rating_tuple rating; - int excitement = (var_110_unk_1 * 0x3C000) >> 16; - excitement += (var_110_unk_2 * 0x3C000) >> 16; - excitement += (var_110_unk_3 * 73992) >> 16; + int no_3_plus_turns = get_turn_count_3_elements(ride, 1); + int no_2_turns = get_turn_count_2_elements(ride, 1); + int no_1_turns = get_turn_count_1_element(ride, 1); - int intensity = (var_110_unk_1 * 0x14000) >> 16; - intensity += (var_110_unk_2 * 49152) >> 16; - intensity += (var_110_unk_3 * 21140) >> 16; + rating.excitement = (no_3_plus_turns * 0x3C000) >> 16; + rating.excitement += (no_2_turns * 0x3C000) >> 16; + rating.excitement += (no_1_turns * 73992) >> 16; - int nausea = (var_110_unk_1 * 0x50000) >> 16; - nausea += (var_110_unk_2 * 0x32000) >> 16; - nausea += (var_110_unk_3 * 48623) >> 16; + rating.intensity = (no_3_plus_turns * 0x14000) >> 16; + rating.intensity += (no_2_turns * 49152) >> 16; + rating.intensity += (no_1_turns * 21140) >> 16; + + rating.nausea = (no_3_plus_turns * 0x50000) >> 16; + rating.nausea += (no_2_turns * 0x32000) >> 16; + rating.nausea += (no_1_turns * 48623) >> 16; - rating_tuple rating = { excitement, intensity, nausea }; return rating; } /** - * rct2: 0x0065E047 + * + * rct2: 0x0065E047 */ -static rating_tuple get_var_112_rating(rct_ride *ride) { - int al; +static rating_tuple get_sloped_turns_rating(rct_ride* ride) { + rating_tuple rating; - al = get_var_112_unk_1(ride); - al = min(al, 4); - int excitement = (al * 0x78000) >> 16; + int no_4_plus_turns = get_turn_count_4_plus_elements(ride, 2); + int no_3_turns = get_turn_count_3_elements(ride, 2); + int no_2_turns = get_turn_count_2_elements(ride, 2); + int no_1_turns = get_turn_count_1_element(ride, 2); - al = get_var_112_unk_1(ride); - al = min(al, 8); - int nausea = (al * 0x78000) >> 16; + rating.excitement = (min(no_4_plus_turns, 4) * 0x78000) >> 16; + rating.excitement += (min(no_3_turns, 6) * 273066) >> 16; + rating.excitement += (min(no_2_turns, 6) * 0x3AAAA) >> 16; + rating.excitement += (min(no_1_turns, 7) * 187245) >> 16; + rating.intensity = 0; + rating.nausea = (min(no_4_plus_turns, 8) * 0x78000) >> 16; - al = get_var_112_unk_2(ride); - al = min(al, 6); - excitement += (al * 273066) >> 16; - - al = get_var_112_unk_3(ride); - al = min(al, 6); - excitement += (al * 0x3AAAA) >> 16; - - al = get_var_112_unk_4(ride); - al = min(al, 7); - excitement += (al * 187245) >> 16; - - rating_tuple rating = { excitement, 0, nausea }; return rating; } /** - * rct2: 0x0065E0F2 + * + * rct2: 0x0065E0F2 */ static rating_tuple get_inversions_ratings(uint8 inversions) { - int excitement = (min(inversions, 6) * 0x1AAAAA) >> 16; - int intensity = (inversions * 0x320000) >> 16; - int nausea = (inversions * 0x15AAAA) >> 16; + rating_tuple rating; + + rating.excitement = (min(inversions, 6) * 0x1AAAAA) >> 16; + rating.intensity = (inversions * 0x320000) >> 16; + rating.nausea = (inversions * 0x15AAAA) >> 16; - rating_tuple rating = { excitement, intensity, nausea }; return rating; } -/* - * - */ static rating_tuple get_special_track_elements_rating(uint8 type, rct_ride *ride) { int excitement = 0, intensity = 0, nausea = 0; if (type == RIDE_TYPE_GHOST_TRAIN) { @@ -1067,6 +1054,7 @@ static rating_tuple get_special_track_elements_rating(uint8 type, rct_ride *ride } /** + * * rct2: 0x0065DDD1 */ static rating_tuple sub_65DDD1(rct_ride *ride) @@ -1078,17 +1066,17 @@ static rating_tuple sub_65DDD1(rct_ride *ride) intensity += special_track_element_rating.intensity; nausea += special_track_element_rating.nausea; - rating_tuple var_10E_rating = get_var_10E_rating(ride); + rating_tuple var_10E_rating = get_flat_turns_rating(ride); excitement += var_10E_rating.excitement; intensity += var_10E_rating.intensity; nausea += var_10E_rating.nausea; - rating_tuple var_110_rating = get_var_110_rating(ride); + rating_tuple var_110_rating = get_banked_turns_rating(ride); excitement += var_110_rating.excitement; intensity += var_110_rating.intensity; nausea += var_110_rating.nausea; - rating_tuple var_112_rating = get_var_112_rating(ride); + rating_tuple var_112_rating = get_sloped_turns_rating(ride); excitement += var_112_rating.excitement; intensity += var_112_rating.intensity; nausea += var_112_rating.nausea; diff --git a/src/ride/ride_ratings.h b/src/ride/ride_ratings.h index 29c5c92fff..95ee0b8663 100644 --- a/src/ride/ride_ratings.h +++ b/src/ride/ride_ratings.h @@ -26,4 +26,4 @@ void ride_ratings_update_all(); -#endif \ No newline at end of file +#endif diff --git a/src/ride/station.c b/src/ride/station.c index 91f25949fb..2b584b214a 100644 --- a/src/ride/station.c +++ b/src/ride/station.c @@ -66,7 +66,7 @@ static void ride_update_station_blocksection(rct_ride *ride, int stationIndex) mapElement = ride_get_station_start_track_element(ride, stationIndex); - if ((ride->status == RIDE_STATUS_CLOSED && ride->num_riders == 0) || mapElement->flags & 0x20) { + if ((ride->status == RIDE_STATUS_CLOSED && ride->num_riders == 0) || (mapElement != NULL && mapElement->flags & 0x20)) { ride->station_depart[stationIndex] &= ~STATION_DEPART_FLAG; if ((ride->station_depart[stationIndex] & STATION_DEPART_FLAG) || (mapElement->properties.track.sequence & 0x80)) @@ -75,7 +75,7 @@ static void ride_update_station_blocksection(rct_ride *ride, int stationIndex) if (!(ride->station_depart[stationIndex] & STATION_DEPART_FLAG)) { ride->station_depart[stationIndex] |= STATION_DEPART_FLAG; ride_invalidate_station_start(ride, stationIndex, 1); - } else if (mapElement->properties.track.sequence & 0x80) { + } else if (mapElement != NULL && mapElement->properties.track.sequence & 0x80) { ride_invalidate_station_start(ride, stationIndex, 1); } } @@ -105,7 +105,7 @@ static void ride_update_station_bumpercar(rct_ride *ride, int stationIndex) dh = (dx >> 8) & 0xFF; for (i = 0; i < ride->num_vehicles; i++) { vehicle = &(g_sprite_list[ride->vehicles[i]].vehicle); - if (vehicle->var_CE < dh || (vehicle->var_CE < dh && vehicle->var_51 > dl)) + if (vehicle->var_CE < dh || (vehicle->var_CE < dh && vehicle->sub_state > dl)) continue; // End match @@ -242,7 +242,7 @@ static void ride_update_station_race(rct_ride *ride, int stationIndex) */ static void ride_race_init_vehicle_speeds(rct_ride *ride) { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_vehicle *vehicle; int i; @@ -250,7 +250,7 @@ static void ride_race_init_vehicle_speeds(rct_ride *ride) vehicle = &g_sprite_list[ride->vehicles[i]].vehicle; vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_6; - rideEntry = GET_RIDE_ENTRY(vehicle->ride_subtype); + rideEntry = get_ride_entry(vehicle->ride_subtype); vehicle->speed = (scenario_rand() & 16) - 8 + rideEntry->vehicles[vehicle->vehicle_type].powered_max_speed; diff --git a/src/ride/station.h b/src/ride/station.h index 8614e5b059..4fdd281fef 100644 --- a/src/ride/station.h +++ b/src/ride/station.h @@ -29,4 +29,4 @@ void ride_update_station(rct_ride *ride, int stationIndex); rct_map_element *ride_get_station_start_track_element(rct_ride *ride, int stationIndex); rct_map_element *ride_get_station_exit_element(rct_ride *ride, int x, int y, int z); -#endif \ No newline at end of file +#endif diff --git a/src/ride/track.c b/src/ride/track.c index ff7bf11948..a2e0c9ae79 100644 --- a/src/ride/track.c +++ b/src/ride/track.c @@ -26,6 +26,7 @@ #include "../interface/viewport.h" #include "../localisation/localisation.h" #include "../management/finance.h" +#include "../network/network.h" #include "../platform/platform.h" #include "../rct1.h" #include "../util/sawyercoding.h" @@ -50,194 +51,194 @@ const rct_trackdefinition *gFlatRideTrackDefinitions = (rct_trackdefinition*)0x0 // TODO This table is incorrect or at least missing 69 elements. There should be 256 in total! const rct_trackdefinition gTrackDefinitions_INCORRECT[] = { - // TYPE VANGLE END VANGLE START BANK END BANK START SPECIAL - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_END_STATION - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_BEGIN_STATION - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_MIDDLE_STATION - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_RIGHT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_RIGHT_BANK - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_RIGHT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN - { TRACK_S_BEND, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_LEFT - { TRACK_S_BEND, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_RIGHT - { TRACK_VERTICAL_LOOP, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_UNKNOWN_VERTICAL_LOOP }, // ELEM_LEFT_VERTICAL_LOOP - { TRACK_VERTICAL_LOOP, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_UNKNOWN_VERTICAL_LOOP }, // ELEM_RIGHT_VERTICAL_LOOP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_1_TILE - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_1_TILE - { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_TWIST_DOWN_TO_UP - { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_TWIST_DOWN_TO_UP - { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_LEFT_TWIST_UP_TO_DOWN - { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_RIGHT_TWIST_UP_TO_DOWN - { TRACK_HALF_LOOP, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_HALF_LOOP_UP }, // ELEM_HALF_LOOP_UP - { TRACK_HALF_LOOP, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_HALF_LOOP_DOWN - { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_CORKSCREW_UP - { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_CORKSCREW_UP - { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_CORKSCREW_DOWN }, // ELEM_LEFT_CORKSCREW_DOWN - { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_CORKSCREW_DOWN }, // ELEM_RIGHT_CORKSCREW_DOWN - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_FLAT - { TRACK_TOWER_BASE, TRACK_VANGLE_TOWER, TRACK_VANGLE_TOWER, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_TOWER_BASE - { TRACK_TOWER_BASE, TRACK_VANGLE_TOWER, TRACK_VANGLE_TOWER, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_TOWER_SECTION - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_COVERED - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_COVERED - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_COVERED - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_UP_COVERED - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_60_DEG_UP_COVERED - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_25_DEG_UP_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_FLAT_COVERED - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_COVERED - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_COVERED - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_DOWN_COVERED - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_60_DEG_DOWN_COVERED - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_25_DEG_DOWN_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_FLAT_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_LEFT_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_RIGHT_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_COVERED - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_UP_SMALL - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_UP_SMALL - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_DOWN_SMALL - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_SMALL - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_UP_LARGE - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_UP_LARGE - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_DOWN_LARGE - { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_LARGE - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN - { TRACK_BRAKES, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_BRAKES - { TRACK_ROTATION_CONTROL_TOGGLE,TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_ROTATION_CONTROL_TOGGLE - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP - { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_UP - { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_UP - { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_DOWN - { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_DOWN - { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_HELIX_LARGE_UP - { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_HELIX_LARGE_UP - { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_HELIX_LARGE_DOWN - { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_HELIX_LARGE_DOWN - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_25_DEG_UP_LEFT_BANKED - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_25_DEG_UP_RIGHT_BANKED - { TRACK_WATERFALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_WATERFALL - { TRACK_RAPIDS, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RAPIDS - { TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_ON_RIDE_PHOTO - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_25_DEG_DOWN_LEFT_BANKED - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_25_DEG_DOWN_RIGHT_BANKED - { TRACK_WATER_SPLASH, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_WATER_SPLASH - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_UP_LONG_BASE - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_FLAT_LONG_BASE - { TRACK_WHIRLPOOL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_WHIRLPOOL - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_FLAT_LONG_BASE - { TRACK_LIFT_HILL, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_CABLE_LIFT_HILL - { TRACK_WHOA_BELLY, TRACK_VANGLE_WHOA_BELLY, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_REVERSE_WHOA_BELLY_SLOPE - { TRACK_WHOA_BELLY, TRACK_VANGLE_WHOA_BELLY, TRACK_VANGLE_WHOA_BELLY, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_REVERSE_WHOA_BELLY_VERTICAL - { TRACK_FLAT, TRACK_SLOPE_UP_90, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_DOWN_90, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_UP_90, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_90_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_DOWN_TO_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_UP_TO_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_DOWN_90, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_90_DEG_DOWN - { TRACK_BRAKE_FOR_DROP, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_BRAKE_FOR_DROP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_EIGHTH_TO_DIAG - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_TO_DIAG - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_EIGHTH_TO_ORTHOGONAL - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_TO_ORTHOGONAL - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_EIGHTH_BANK_TO_DIAG - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_BANK_TO_DIAG - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_EIGHTH_BANK_TO_ORTHOGONAL - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_UP_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_DOWN_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_60_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_UP_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_60_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_DOWN_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_RIGHT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK_TO_FLAT - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK_TO_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_RIGHT_BANK - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK_TO_25_DEG_DOWN - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_RIGHT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK - { TRACK_LOG_FLUME_REVERSER, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LOG_FLUME_REVERSER - { TRACK_SPINNING_TUNNEL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_SPINNING_TUNNEL - { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_BARREL_ROLL_UP_TO_DOWN - { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_BARREL_ROLL_UP_TO_DOWN - { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_LEFT_BARREL_ROLL_DOWN_TO_UP - { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_RIGHT_BARREL_ROLL_DOWN_TO_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_LEFT_BANK - { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_RIGHT_BANK - { TRACK_POWERED_LIFT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_POWERED_LIFT - { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_HALF_LOOP_UP }, // ELEM_LEFT_LARGE_HALF_LOOP_UP - { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_HALF_LOOP_UP }, // ELEM_RIGHT_LARGE_HALF_LOOP_UP - { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_RIGHT_LARGE_HALF_LOOP_DOWN - { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_LEFT_LARGE_HALF_LOOP_DOWN + // TYPE VANGLE END VANGLE START BANK END BANK START SPECIAL + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_END_STATION + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_BEGIN_STATION + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_MIDDLE_STATION + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_RIGHT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_RIGHT_BANK + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_RIGHT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN + { TRACK_S_BEND, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_LEFT + { TRACK_S_BEND, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_RIGHT + { TRACK_VERTICAL_LOOP, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_UNKNOWN_VERTICAL_LOOP }, // ELEM_LEFT_VERTICAL_LOOP + { TRACK_VERTICAL_LOOP, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_UNKNOWN_VERTICAL_LOOP }, // ELEM_RIGHT_VERTICAL_LOOP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_1_TILE + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_1_TILE + { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_TWIST_DOWN_TO_UP + { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_TWIST_DOWN_TO_UP + { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_LEFT_TWIST_UP_TO_DOWN + { TRACK_TWIST, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_RIGHT_TWIST_UP_TO_DOWN + { TRACK_HALF_LOOP, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_HALF_LOOP_UP }, // ELEM_HALF_LOOP_UP + { TRACK_HALF_LOOP, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_HALF_LOOP_DOWN + { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_CORKSCREW_UP + { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_CORKSCREW_UP + { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_CORKSCREW_DOWN }, // ELEM_LEFT_CORKSCREW_DOWN + { TRACK_CORKSCREW, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_CORKSCREW_DOWN }, // ELEM_RIGHT_CORKSCREW_DOWN + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_FLAT + { TRACK_TOWER_BASE, TRACK_VANGLE_TOWER, TRACK_VANGLE_TOWER, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_TOWER_BASE + { TRACK_TOWER_BASE, TRACK_VANGLE_TOWER, TRACK_VANGLE_TOWER, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_TOWER_SECTION + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_COVERED + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_COVERED + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_COVERED + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_UP_COVERED + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_60_DEG_UP_COVERED + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_25_DEG_UP_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_UP_TO_FLAT_COVERED + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_COVERED + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_COVERED + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_25_DEG_DOWN_COVERED + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_60_DEG_DOWN_COVERED + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_25_DEG_DOWN_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_25_DEG_DOWN_TO_FLAT_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_LEFT_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_S_BEND_RIGHT_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_COVERED + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_UP_SMALL + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_UP_SMALL + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_DOWN_SMALL + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_SMALL + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_UP_LARGE + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_UP_LARGE + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_HALF_BANKED_HELIX_DOWN_LARGE + { TRACK_HELIX_SMALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_LARGE + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN + { TRACK_BRAKES, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_BRAKES + { TRACK_ROTATION_CONTROL_TOGGLE,TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_ROTATION_CONTROL_TOGGLE + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP + { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_UP + { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_UP + { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_DOWN + { TRACK_HELIX_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_DOWN + { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_HELIX_LARGE_UP + { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_HELIX_LARGE_UP + { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_HELIX_LARGE_DOWN + { TRACK_HELIX_LARGE_UNBANKED, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_HELIX_LARGE_DOWN + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_25_DEG_UP_LEFT_BANKED + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_25_DEG_UP_RIGHT_BANKED + { TRACK_WATERFALL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_WATERFALL + { TRACK_RAPIDS, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RAPIDS + { TRACK_ON_RIDE_PHOTO, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_ON_RIDE_PHOTO + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_25_DEG_DOWN_LEFT_BANKED + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_25_DEG_DOWN_RIGHT_BANKED + { TRACK_WATER_SPLASH, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_WATER_SPLASH + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_UP_LONG_BASE + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_FLAT_LONG_BASE + { TRACK_WHIRLPOOL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_WHIRLPOOL + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_FLAT_LONG_BASE + { TRACK_LIFT_HILL, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_CABLE_LIFT_HILL + { TRACK_WHOA_BELLY, TRACK_VANGLE_WHOA_BELLY, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_REVERSE_WHOA_BELLY_SLOPE + { TRACK_WHOA_BELLY, TRACK_VANGLE_WHOA_BELLY, TRACK_VANGLE_WHOA_BELLY, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_REVERSE_WHOA_BELLY_VERTICAL + { TRACK_FLAT, TRACK_SLOPE_UP_90, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_DOWN_90, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_UP_90, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_UP_TO_90_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_DOWN_TO_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_90_DEG_UP_TO_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_DOWN_90, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_60_DEG_DOWN_TO_90_DEG_DOWN + { TRACK_BRAKE_FOR_DROP, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_BRAKE_FOR_DROP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_EIGHTH_TO_DIAG + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_TO_DIAG + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_EIGHTH_TO_ORTHOGONAL + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_TO_ORTHOGONAL + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_EIGHTH_BANK_TO_DIAG + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_BANK_TO_DIAG + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_EIGHTH_BANK_TO_ORTHOGONAL + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_UP_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_DOWN_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_UP_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_60_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_UP_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_DOWN_60, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_60_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_60_DEG_DOWN_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_FLAT_TO_RIGHT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK_TO_FLAT + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK_TO_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_UP_TO_RIGHT_BANK + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK_TO_25_DEG_DOWN + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_DIAG_25_DEG_DOWN_TO_RIGHT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_DIAG_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_DIAG_RIGHT_BANK + { TRACK_LOG_FLUME_REVERSER, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LOG_FLUME_REVERSER + { TRACK_SPINNING_TUNNEL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_SPINNING_TUNNEL + { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_BARREL_ROLL_UP_TO_DOWN + { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_BARREL_ROLL_UP_TO_DOWN + { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_LEFT_BARREL_ROLL_DOWN_TO_UP + { TRACK_BARREL_ROLL, TRACK_SLOPE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_NONE }, // ELEM_RIGHT_BARREL_ROLL_DOWN_TO_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_LEFT, TRACK_NONE }, // ELEM_LEFT_BANK_TO_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_UP_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_RIGHT, TRACK_NONE }, // ELEM_RIGHT_BANK_TO_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_LEFT_BANK + { TRACK_FLAT, TRACK_SLOPE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_RIGHT_BANK + { TRACK_POWERED_LIFT, TRACK_SLOPE_UP_25, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_BANK_NONE, TRACK_NONE }, // ELEM_POWERED_LIFT + { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_HALF_LOOP_UP }, // ELEM_LEFT_LARGE_HALF_LOOP_UP + { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_UPSIDE_DOWN, TRACK_BANK_NONE, TRACK_HALF_LOOP_UP }, // ELEM_RIGHT_LARGE_HALF_LOOP_UP + { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_RIGHT_LARGE_HALF_LOOP_DOWN + { TRACK_HALF_LOOP_LARGE, TRACK_SLOPE_DOWN_25, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_BANK_UPSIDE_DOWN, TRACK_HALF_LOOP_DOWN }, // ELEM_LEFT_LARGE_HALF_LOOP_DOWN }; #define TRACK_MAX_SAVED_MAP_ELEMENTS 1500 @@ -339,7 +340,7 @@ static uint8* track_list_cache_load(int totalFiles) void track_list_populate(ride_list_item item, uint8* track_list_cache){ uint8* track_pointer = track_list_cache; - uint8 cur_track_entry_index = 0; + int cur_track_entry_index = 0; for (uint8 track_type = *track_pointer++; track_type != 0xFE; track_pointer += strlen((const char *)track_pointer) + 1, track_type = *track_pointer++){ @@ -359,8 +360,8 @@ void track_list_populate(ride_list_item item, uint8* track_list_cache){ } else{ if (find_object_in_entry_group(track_object, &entry_type, &entry_index)){ - if ((GET_RIDE_ENTRY(entry_index)->flags & (RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME | RIDE_ENTRY_FLAG_SEPARATE_RIDE)) && - !rideTypeShouldLoseSeparateFlag(GET_RIDE_ENTRY(entry_index))) + if ((get_ride_entry(entry_index)->flags & (RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME | RIDE_ENTRY_FLAG_SEPARATE_RIDE)) && + !rideTypeShouldLoseSeparateFlag(get_ride_entry(entry_index))) continue; } else{ @@ -376,7 +377,7 @@ void track_list_populate(ride_list_item item, uint8* track_list_cache){ break; } - uint8 track_entry_index = 0; + int track_entry_index = 0; uint8 isBelow = 0; for (; track_entry_index != cur_track_entry_index; track_entry_index++){ if (strcicmp((const char *)track_pointer, &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, const char)[track_entry_index * 128]) < 0){ @@ -408,7 +409,7 @@ void track_load_list(ride_list_item item) RCT2_GLOBAL(0xF635ED, uint8) = 0; if (item.type < 0x80){ - rct_ride_type* ride_type = gRideTypeList[item.entry_index]; + rct_ride_entry* ride_type = get_ride_entry(item.entry_index); if (!(ride_type->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE) || rideTypeShouldLoseSeparateFlag(ride_type)){ item.entry_index = 0xFF; } @@ -439,7 +440,7 @@ void track_load_list(ride_list_item item) if (new_file_pointer > new_track_file + 0x3FF00)break; char path[MAX_PATH]; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), enumFileInfo.path); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), enumFileInfo.path); rct_track_td6* loaded_track = load_track_design(path); if (loaded_track){ @@ -486,7 +487,9 @@ static void copy(void *dst, uint8 **src, int length) *src += length; } -/* rct2: 0x00677530 +/** + * + * rct2: 0x00677530 * Returns 1 if it has booster track elements */ uint8 td4_track_has_boosters(rct_track_td6* track_design, uint8* track_elements){ @@ -678,7 +681,10 @@ rct_track_td6* load_track_design(const char *path) return track_design; } -/* rct2: 0x006D1DCE*/ +/** + * + * rct2: 0x006D1DCE + */ void reset_track_list_cache(){ int* track_list_cache = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, int); for (int i = 0; i < 4; ++i){ @@ -687,7 +693,10 @@ void reset_track_list_cache(){ RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_NEXT_INDEX_CACHE, uint32) = 0; } -/* rct2: 0x006D1C68 */ +/** + * + * rct2: 0x006D1C68 + */ int backup_map(){ RCT2_GLOBAL(0xF440ED, uint8*) = malloc(0xED600); if (RCT2_GLOBAL(0xF440ED, uint32) == 0) return 0; @@ -712,7 +721,7 @@ int backup_map(){ memcpy(RCT2_GLOBAL(0xF440F1, uint32*), tile_map_pointers, 0x40000); uint8* backup_info = RCT2_GLOBAL(0xF440F5, uint8*); - *(uint32*)backup_info = RCT2_GLOBAL(0x0140E9A4, uint32); + *(uint32*)backup_info = RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, uint32); *(uint16*)(backup_info + 4) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16); *(uint16*)(backup_info + 6) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_MINUS_2, uint16); *(uint16*)(backup_info + 8) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16); @@ -720,7 +729,10 @@ int backup_map(){ return 1; } -/* rct2: 0x006D2378 */ +/** + * + * rct2: 0x006D2378 + */ void reload_map_backup(){ uint32* map_elements = RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, uint32); memcpy(map_elements, RCT2_GLOBAL(0xF440ED, uint32*), 0xED600); @@ -729,7 +741,7 @@ void reload_map_backup(){ memcpy(tile_map_pointers, RCT2_GLOBAL(0xF440F1, uint32*), 0x40000); uint8* backup_info = RCT2_GLOBAL(0xF440F5, uint8*); - RCT2_GLOBAL(0x0140E9A4, uint32) = *(uint32*)backup_info; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, uint32) = *(uint32*)backup_info; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint16) = *(uint16*)(backup_info + 4); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_MINUS_2, uint16) = *(uint16*)(backup_info + 6); RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) = *(uint16*)(backup_info + 8); @@ -740,7 +752,10 @@ void reload_map_backup(){ free(RCT2_GLOBAL(0xF440F5, uint8*)); } -/* rct2: 0x006D1D9A */ +/** + * + * rct2: 0x006D1D9A + */ void blank_map(){ // These values were previously allocated in backup map but @@ -764,7 +779,10 @@ void blank_map(){ map_update_tile_pointers(); } -/* rct2: 0x006ABDB0 */ +/** + * + * rct2: 0x006ABDB0 + */ void load_track_scenery_objects(){ uint8 entry_index = RCT2_GLOBAL(0xF44157, uint8); rct_object_entry_extended* object_entry = &object_entry_groups[0].entries[entry_index]; @@ -773,7 +791,7 @@ void load_track_scenery_objects(){ memcpy(copied_entry, object_entry, sizeof(rct_object_entry)); object_unload_all(); - object_load(-1, copied_entry, 0); + object_load_chunk(-1, copied_entry, 0); uint8 entry_type; find_object_in_entry_group(copied_entry, &entry_type, &entry_index); RCT2_GLOBAL(0xF44157, uint8) = entry_index; @@ -800,7 +818,7 @@ void load_track_scenery_objects(){ rct_track_scenery* scenery_entry = (rct_track_scenery*)track_elements; if (!find_object_in_entry_group(&scenery_entry->scenery_object, &entry_type, &entry_index)){ - object_load(-1, &scenery_entry->scenery_object, 0); + object_load_chunk(-1, &scenery_entry->scenery_object, 0); } // Skip object and location/direction/colour track_elements += sizeof(rct_track_scenery); @@ -809,7 +827,10 @@ void load_track_scenery_objects(){ reset_loaded_objects(); } -/* rct2: 0x006D247A */ +/** + * + * rct2: 0x006D247A + */ void track_mirror_scenery(uint8** track_elements){ rct_track_scenery* scenery = (rct_track_scenery*)*track_elements; for (; (scenery->scenery_object.flags & 0xFF) != 0xFF; scenery++){ @@ -898,7 +919,10 @@ void track_mirror_scenery(uint8** track_elements){ } } -/* rct2: 0x006D2443 */ +/** + * + * rct2: 0x006D2443 + */ void track_mirror_ride(uint8** track_elements){ rct_track_element* track = (rct_track_element*)*track_elements; for (; track->type != 0xFF; track++){ @@ -916,7 +940,10 @@ void track_mirror_ride(uint8** track_elements){ *track_elements = (uint8*)entrance + 1; } -/* rct2: 0x006D25FA */ +/** + * + * rct2: 0x006D25FA + */ void track_mirror_maze(uint8** track_elements){ rct_maze_element* maze = (rct_maze_element*)*track_elements; for (; maze->all != 0; maze++){ @@ -942,7 +969,10 @@ void track_mirror_maze(uint8** track_elements){ *track_elements = (uint8*)maze + 4; } -/* rct2: 0x006D2436 */ +/** + * + * rct2: 0x006D2436 + */ void track_mirror(){ uint8* track_elements = RCT2_ADDRESS(0x009D821B, uint8); @@ -984,7 +1014,10 @@ void track_update_max_min_coordinates(sint16 x, sint16 y, sint16 z){ } } -/* rct2: 0x006D0964 */ +/** + * + * rct2: 0x006D0964 + */ int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int originX, int originY, int originZ){ RCT2_GLOBAL(0x00F44050, rct_track_scenery*) = scenery_start; @@ -1197,7 +1230,7 @@ int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int o if (RCT2_GLOBAL(0x00F440D4, uint8) == 4)bl = 0xE9; if (RCT2_GLOBAL(0x00F440D4, uint8) == 1)bl = 0x80; - RCT2_GLOBAL(0x00141E9AE, rct_string_id) = STR_CANT_POSITION_THIS_HERE; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = STR_CANT_POSITION_THIS_HERE; cost = game_do_command( mapCoord.x, @@ -1256,7 +1289,7 @@ int track_place_scenery(rct_track_scenery* scenery_start, uint8 rideIndex, int o if (RCT2_GLOBAL(0x00F440D4, uint8) == 4)bl = 105; if (RCT2_GLOBAL(0x00F440D4, uint8) == 1)bl = 0; - RCT2_GLOBAL(0x00141E9AE, rct_string_id) = STR_CANT_BUILD_PARK_ENTRANCE_HERE; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = STR_CANT_BUILD_PARK_ENTRANCE_HERE; cost = game_do_command( mapCoord.x, @@ -1652,6 +1685,7 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac } if (RCT2_GLOBAL(0x00F440D4, uint8) == 3){ + int temp_z = z - TrackCoordinates[track_type].z_begin; for (const rct_preview_track* trackBlock = TrackBlocks[track_type]; trackBlock->index != 0xFF; trackBlock++){ @@ -1709,11 +1743,10 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac height = water_height; } } - int temp_z = z + RCT2_GLOBAL(0x00F440D5, sint16); - temp_z -= height; + int height_diff = temp_z + RCT2_GLOBAL(0x00F440D5, sint16) + trackBlock->z - height; - if (temp_z < 0){ - RCT2_GLOBAL(0x00F440D5, sint16) -= temp_z; + if (height_diff < 0){ + RCT2_GLOBAL(0x00F440D5, sint16) -= height_diff; } } } @@ -1748,8 +1781,8 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac rotation |= (1 << 2); if (!(rotation & (1 << 2))){ - x += RCT2_ADDRESS(0x00993CCC, sint16)[rotation * 2]; - y += RCT2_ADDRESS(0x00993CCE, sint16)[rotation * 2]; + x += TileDirectionDelta[rotation].x; + y += TileDirectionDelta[rotation].y; } } @@ -1827,8 +1860,8 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac if (RCT2_GLOBAL(0x00F440D4, uint8) != 1){ rct_xy16 tile; - tile.x = x + RCT2_ADDRESS(0x00993CCC, sint16)[rotation * 2]; - tile.y = y + RCT2_ADDRESS(0x00993CCE, sint16)[rotation * 2]; + tile.x = x + TileDirectionDelta[rotation].x; + tile.y = y + TileDirectionDelta[rotation].y; rct_map_element* map_element = map_get_first_element_at(tile.x / 32, tile.y / 32); z = RCT2_GLOBAL(0x00F44146, sint16) / 8; @@ -1881,7 +1914,7 @@ int track_place_ride(sint16 x, sint16 y, sint16 z, uint8 rideIndex, uint8** trac if (RCT2_GLOBAL(0x00F440D4, uint8) == 6){ sub_6CB945(RCT2_GLOBAL(0x00F440A7, uint8)); - rct_ride* ride = GET_RIDE(RCT2_GLOBAL(0x00F440A7, uint8)); + rct_ride* ride = get_ride(RCT2_GLOBAL(0x00F440A7, uint8)); user_string_free(ride->name); ride->type = RIDE_TYPE_NULL; } @@ -1956,22 +1989,11 @@ int sub_6D01B3(uint8 bl, uint8 rideIndex, int x, int y, int z) if (bl == 3) return RCT2_GLOBAL(0x00F440D5, sint16); return RCT2_GLOBAL(0x00F440D5, money32); - - int eax, ebx, ecx, edx, esi, edi, ebp; - eax = x; - ebx = bl; - ecx = y; - edx = z; - esi = 0; - edi = 0; - ebp = 0; - RCT2_CALLFUNC_X(0x006D01B3, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - if (bl == 3) - ebx &= 0xFFFF; - return ebx; } -/* rct2: 0x006D2189 +/** + * + * rct2: 0x006D2189 * ebx = ride_id * cost = edi */ @@ -1993,7 +2015,7 @@ int sub_6D2189(int* cost, uint8* ride_id){ // bh *ride_id = edi & 0xFF; - rct_ride* ride = GET_RIDE(*ride_id); + rct_ride* ride = get_ride(*ride_id); const utf8* ride_name = RCT2_ADDRESS(0x9E3504, const utf8); rct_string_id new_ride_name = user_string_allocate(132, ride_name); @@ -2065,14 +2087,20 @@ int sub_6D2189(int* cost, uint8* ride_id){ } } -/* rct2: 0x006D235B */ +/** + * + * rct2: 0x006D235B + */ void sub_6D235B(uint8 ride_id){ - rct_ride* ride = GET_RIDE(ride_id); + rct_ride* ride = get_ride(ride_id); user_string_free(ride->name); ride->type = RIDE_TYPE_NULL; } -/* rct2: 0x006D1EF0 */ +/** + * + * rct2: 0x006D1EF0 + */ void draw_track_preview(uint8** preview){ // Make a copy of the map if (!backup_map())return; @@ -2229,7 +2257,7 @@ rct_track_design *track_get_info(int index, uint8** preview) RCT2_ADDRESS(RCT2_ADDRESS_TRACK_DESIGN_INDEX_CACHE, uint32)[i] = index; char track_path[MAX_PATH] = { 0 }; - subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, (char *)trackDesignList + (index * 128)); + substitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, (char *)trackDesignList + (index * 128)); rct_track_td6* loaded_track = NULL; @@ -2284,13 +2312,13 @@ int track_rename(const char *text) } char new_path[MAX_PATH]; - subsitute_path(new_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), text); + substitute_path(new_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), text); strcat(new_path, ".TD6"); rct_window* w = window_find_by_class(WC_TRACK_DESIGN_LIST); char old_path[MAX_PATH]; - subsitute_path(old_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]); + substitute_path(old_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]); if (!platform_file_move(old_path, new_path)) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_ANOTHER_FILE_EXISTS_WITH_NAME_OR_FILE_IS_WRITE_PROTECTED; @@ -2319,7 +2347,7 @@ int track_delete() rct_window* w = window_find_by_class(WC_TRACK_DESIGN_LIST); char path[MAX_PATH]; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), &RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char)[128 * w->track_list.var_482]); if (!platform_file_delete(path)) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_FILE_IS_WRITE_PROTECTED_OR_LOCKED; @@ -2345,33 +2373,16 @@ int track_delete() int track_is_connected_by_shape(rct_map_element *a, rct_map_element *b) { int trackType, aBank, aAngle, bBank, bAngle; - rct_ride *ride; - ride = GET_RIDE(a->properties.track.ride_index); trackType = a->properties.track.type; aBank = gTrackDefinitions[trackType].bank_end; aAngle = gTrackDefinitions[trackType].vangle_end; - if (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_3) { - if (a->properties.track.colour & 4) { - if (aBank == TRACK_BANK_NONE) - aBank = TRACK_BANK_UPSIDE_DOWN; - else if (aBank == TRACK_BANK_UPSIDE_DOWN) - aBank = TRACK_BANK_NONE; - } - } + aBank = track_get_actual_bank(a, aBank); - ride = GET_RIDE(b->properties.track.ride_index); trackType = b->properties.track.type; bBank = gTrackDefinitions[trackType].bank_start; bAngle = gTrackDefinitions[trackType].vangle_start; - if (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_3) { - if (b->properties.track.colour & 4) { - if (bBank == TRACK_BANK_NONE) - bBank = TRACK_BANK_UPSIDE_DOWN; - else if (bBank == TRACK_BANK_UPSIDE_DOWN) - bBank = TRACK_BANK_NONE; - } - } + bBank = track_get_actual_bank(b, bBank); return aBank == bBank && aAngle == bAngle; } @@ -2480,7 +2491,10 @@ int copy_scenery_to_track(uint8** track_pointer){ return 1; } -/* rct2: 0x006CEAAE */ +/** + * + * rct2: 0x006CEAAE + */ int maze_ride_to_td6(uint8 rideIndex, rct_track_td6* track_design, uint8* track_elements){ rct_map_element* map_element = NULL; uint8 map_found = 0; @@ -2546,7 +2560,7 @@ int maze_ride_to_td6(uint8 rideIndex, rct_track_td6* track_design, uint8* track_ x = 0; } - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); uint16 location = ride->entrances[0]; if (location == 0xFFFF){ @@ -2617,9 +2631,12 @@ int maze_ride_to_td6(uint8 rideIndex, rct_track_td6* track_design, uint8* track_ RCT2_GLOBAL(0x00F44058, uint8*) = track_elements; - // Previously you had to save start_x, y, z but - // no need since global vars not used + // Save global vars as they are still used by scenery + sint16 start_z = RCT2_GLOBAL(0x00F44146, sint16); sub_6D01B3(0, 0, 4096, 4096, 0); + RCT2_GLOBAL(0x00F44142, sint16) = start_x; + RCT2_GLOBAL(0x00F44144, sint16) = start_y; + RCT2_GLOBAL(0x00F44146, sint16) = start_z; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, sint16) &= 0xFFF9; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, sint16) &= 0xFFF7; @@ -2641,14 +2658,17 @@ int maze_ride_to_td6(uint8 rideIndex, rct_track_td6* track_design, uint8* track_ return 1; } -/* rct2: 0x006CE68D */ +/** + * + * rct2: 0x006CE68D + */ int tracked_ride_to_td6(uint8 rideIndex, rct_track_td6* track_design, uint8* track_elements) { - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); rct_xy_element trackElement; track_begin_end trackBeginEnd; - if (sub_6CAF80(rideIndex, &trackElement) == 0){ + if (!ride_try_get_origin_element(rideIndex, &trackElement)) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_TRACK_TOO_LARGE_OR_TOO_MUCH_SCENERY; return 0; } @@ -2662,10 +2682,10 @@ int tracked_ride_to_td6(uint8 rideIndex, rct_track_td6* track_design, uint8* tra rct_xy_element lastGood = { .element = trackBeginEnd.begin_element, .x = trackBeginEnd.begin_x, - .y = trackBeginEnd.begin_y + .y = trackBeginEnd.begin_y }; - if (!track_block_get_previous(trackBeginEnd.begin_x, trackBeginEnd.begin_y, trackBeginEnd.begin_element, &trackBeginEnd)) { + if (!track_block_get_previous(trackBeginEnd.end_x, trackBeginEnd.end_y, trackBeginEnd.begin_element, &trackBeginEnd)) { trackElement = lastGood; break; } @@ -2899,9 +2919,12 @@ int tracked_ride_to_td6(uint8 rideIndex, rct_track_td6* track_design, uint8* tra return 1; } -/* rct2: 0x006CE44F */ +/** + * + * rct2: 0x006CE44F + */ int ride_to_td6(uint8 rideIndex){ - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); rct_track_td6* track_design = RCT2_ADDRESS(0x009D8178, rct_track_td6); track_design->type = ride->type; @@ -2972,8 +2995,10 @@ int ride_to_td6(uint8 rideIndex){ return tracked_ride_to_td6(rideIndex, track_design, track_elements); } -/* rct2: 0x006771DC but not really its branched from that - * quite far. +/** + * + * rct2: 0x006771DC but not really its branched from that + * quite far. */ int save_track_to_file(rct_track_td6* track_design, char* path) { @@ -3000,9 +3025,12 @@ int save_track_to_file(rct_track_td6* track_design, char* path) return 1; } -/* rct2: 0x006D2804 & 0x006D264D */ +/** + * + * rct2: 0x006D2804, 0x006D264D + */ int save_track_design(uint8 rideIndex){ - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)){ window_error_open(STR_CANT_SAVE_TRACK_DESIGN, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id)); @@ -3037,35 +3065,45 @@ int save_track_design(uint8 rideIndex){ format_string(track_name, ride->name, &ride->name_arguments); char path[MAX_PATH]; - subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); - - strcat(path, ".TD6"); + substitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); // Save track design - format_string(RCT2_ADDRESS(0x141ED68, char), 2306, NULL); + format_string(RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char), 2306, NULL); // Track design files format_string(RCT2_ADDRESS(0x141EE68, char), 2305, NULL); + // Show save dialog + utf8 initialDirectory[MAX_PATH]; + { + strcpy(initialDirectory, path); + utf8 *a = strrchr(initialDirectory, '/'); + utf8 *b = strrchr(initialDirectory, '\\'); + utf8 *c = max(a, b); + if (c != NULL) { + *c = '\0'; + } + } + + file_dialog_desc desc; + memset(&desc, 0, sizeof(desc)); + desc.type = FD_SAVE; + desc.title = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, utf8); + desc.initial_directory = initialDirectory; + desc.default_filename = path; + desc.filters[0].name = language_get_string(STR_OPENRCT2_TRACK_DESIGN_FILE); + desc.filters[0].pattern = "*.td6"; + audio_pause_sounds(); - - int result = platform_open_common_file_dialog( - 0, - RCT2_ADDRESS(0x141ED68, char), - path, - "*.TD?", - RCT2_ADDRESS(0x141EE68, char)); - + bool result = platform_open_common_file_dialog(path, &desc); audio_unpause_sounds(); - if (result == 0){ + if (!result) { ride_list_item item = { .type = 0xFD, .entry_index = 0 }; track_load_list(item); return 1; } - path_set_extension(path, "TD6"); - save_track_to_file(RCT2_ADDRESS(0x009D8178, rct_track_td6), path); ride_list_item item = { .type = 0xFC, .entry_index = 0 }; @@ -3121,7 +3159,7 @@ rct_track_design *temp_track_get_info(char* path, uint8** preview) return NULL; } - if (!object_load(0, &loaded_track->vehicle_object, NULL)){ + if (!object_load_chunk(0, &loaded_track->vehicle_object, NULL)){ if (preview != NULL) *preview = NULL; log_error("Failed to load track (vehicle load fail): %s", path); return NULL; @@ -3147,6 +3185,7 @@ void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool { const utf8 *ch; int codepoint; + char *lastDot = strrchr(src, '.'); if (colour != 0) { dst = utf8_write_codepoint(dst, colour); @@ -3155,8 +3194,8 @@ void window_track_list_format_name(utf8 *dst, const utf8 *src, int colour, bool if (quotes) dst = utf8_write_codepoint(dst, FORMAT_OPENQUOTES); ch = src; - while ((codepoint = utf8_get_next(ch, &ch)) != 0) { - if (codepoint == '.') break; + while (lastDot > ch) { + codepoint = utf8_get_next(ch, &ch); dst = utf8_write_codepoint(dst, codepoint); } @@ -3184,7 +3223,7 @@ int install_track(char* source_path, char* dest_name){ strcat(track_name, ".TD4"); char dest_path[MAX_PATH]; - subsitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); + substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); if (platform_file_exists(dest_path)) return 2; @@ -3195,18 +3234,21 @@ int install_track(char* source_path, char* dest_name){ // Check if .TD6 file exists under that name strcat(track_name, ".TD6"); - subsitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); + substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), track_name); if (platform_file_exists(dest_path)) return 2; // Set path for actual copy - subsitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), dest_name); + substitute_path(dest_path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), dest_name); return platform_file_copy(source_path, dest_path, false); } -/* rct2: 0x006D13FE */ +/** + * + * rct2: 0x006D13FE + */ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp){ int x = *eax; int y = *ecx; @@ -3218,7 +3260,7 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, sint16) = z; if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)){ - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -3233,7 +3275,7 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int entry_index = 0xFF; } - RCT2_GLOBAL(0x00141E9AE, rct_string_id) = 988; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = STR_CANT_CREATE_NEW_RIDE_ATTRACTION; int rideIndex = 0; { int _eax = 0, @@ -3253,6 +3295,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; @@ -3308,8 +3358,8 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int uint8 num_circuits = track_design->lift_hill_speed_num_circuits >> 5; 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_set_to_default_inspection_interval(rideIndex); ride->lifecycle_flags |= RIDE_LIFECYCLE_NOT_CUSTOM_DESIGN; @@ -3348,18 +3398,143 @@ void game_command_place_track_design(int* eax, int* ebx, int* ecx, int* edx, int *edi = rideIndex; } -/** - * - * rct2: 0x006CDEE4 - */ -void game_command_place_maze_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +money32 place_maze_design(uint8 flags, uint8 rideIndex, uint16 mazeEntry, sint16 x, sint16 y, sint16 z) { - RCT2_CALLFUNC_X(0x006CDEE4, eax, ebx, ecx, edx, esi, edi, ebp); + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, sint16) = x + 8; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, sint16) = y + 8; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, sint16) = z; + if (!sub_68B044()) { + return MONEY32_UNDEFINED; + } + + if ((z & 15) != 0) { + return MONEY32_UNDEFINED; + } + + if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32) != 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + return MONEY32_UNDEFINED; + } + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + if (!(flags & GAME_COMMAND_FLAG_GHOST)) { + footpath_remove_litter(x, y, z); + map_remove_walls_at(floor2(x, 32), floor2(y, 32), z, z + 32); + } + } + + if (!gCheatsSandboxMode) { + if (!map_is_location_owned(floor2(x, 32), floor2(y, 32), z)) { + return MONEY32_UNDEFINED; + } + } + + // Check support height + if (!gCheatsDisableSupportLimits) { + rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); + uint8 supportZ = (z + 32) >> 3; + if (supportZ > mapElement->base_height) { + uint8 supportHeight = (supportZ - mapElement->base_height) / 2; + uint8 maxSupportHeight = RCT2_GLOBAL(0x0097D218 + (RIDE_TYPE_MAZE * 8), uint8); + if (supportHeight > maxSupportHeight) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_HIGH_FOR_SUPPORTS; + return MONEY32_UNDEFINED; + } + } + } + + money32 cost = 0; + // Clearance checks + if (!gCheatsDisableClearanceChecks) { + int fx = floor2(x, 32); + int fy = floor2(y, 32); + int fz0 = z >> 3; + int fz1 = fz0 + 4; + + if (!map_can_construct_with_clear_at(fx, fy, fz0, fz1, &map_place_non_scenery_clear_func, 15, flags, &cost)) { + return MONEY32_UNDEFINED; + } + + uint8 elctgaw = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8); + if (elctgaw & ELEMENT_IS_UNDERWATER) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; + return MONEY32_UNDEFINED; + } + if (elctgaw & ELEMENT_IS_UNDERGROUND) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND; + return MONEY32_UNDEFINED; + } + } + + rct_ride *ride = get_ride(rideIndex); + + // Calculate price + money32 price = 0; + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { + price = RCT2_ADDRESS(0x0097DD78, money16)[ride->type * 2] * RCT2_GLOBAL(0x0099DBC8, money32); + price = (price >> 17) * 10; + } + + cost += price; + + if (flags & GAME_COMMAND_FLAG_APPLY) { + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 8; + coord.y = y + 8; + coord.z = z; + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + + // Place track element + int fx = floor2(x, 32); + int fy = floor2(y, 32); + int fz = z >> 3; + rct_map_element *mapElement = map_element_insert(fx >> 5, fy >> 5, fz, 15); + mapElement->clearance_height = fz + 4; + mapElement->type = MAP_ELEMENT_TYPE_TRACK; + mapElement->properties.track.type = 101; + mapElement->properties.track.ride_index = rideIndex; + mapElement->properties.track.maze_entry = mazeEntry; + if (flags & GAME_COMMAND_FLAG_GHOST) { + mapElement->flags |= MAP_ELEMENT_FLAG_GHOST; + } + + map_invalidate_element(fx, fy, mapElement); + + ride->maze_tiles++; + ride->station_heights[0] = mapElement->base_height; + ride->station_starts[0] = 0; + if (ride->maze_tiles == 1) { + ride->overall_view = (fx >> 5) | ((fy >> 5) << 8); + } + } + + return cost; } /** * - * rct2: 0x006D3026 + * rct2: 0x006CDEE4 + */ +void game_command_place_maze_design(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) +{ + *ebx = place_maze_design( + *ebx & 0xFF, + *edx & 0xFF, + ((*ebx >> 8) & 0xFF) | (((*edx >> 8) & 0xFF) << 8), + *eax & 0xFFFF, + *ecx & 0xFFFF, + *edi & 0xFFFF + ); +} + +/** + * + * rct2: 0x006D3026 */ void track_save_reset_scenery() { @@ -3429,7 +3604,7 @@ static rct_map_element **track_get_next_spare_saved_map_element() /** * - * rct2: 0x006D2ED2 + * rct2: 0x006D2ED2 */ static bool track_save_can_add_map_element(rct_map_element *mapElement) { @@ -3461,7 +3636,7 @@ static bool track_save_can_add_map_element(rct_map_element *mapElement) /** * - * rct2: 0x006D2F4C + * rct2: 0x006D2F4C */ static void track_save_push_map_element(int x, int y, rct_map_element *mapElement) { @@ -3475,7 +3650,7 @@ static void track_save_push_map_element(int x, int y, rct_map_element *mapElemen /** * - * rct2: 0x006D2FA7 + * rct2: 0x006D2FA7 */ static void track_save_push_map_element_desc(rct_object_entry *entry, int x, int y, int z, uint8 flags, uint8 primaryColour, uint8 secondaryColour) { @@ -3584,7 +3759,7 @@ static void track_save_add_footpath(int x, int y, rct_map_element *mapElement) /** * - * rct2: 0x006D2B3C + * rct2: 0x006D2B3C */ static bool track_save_add_map_element(int interactionType, int x, int y, rct_map_element *mapElement) { @@ -3612,7 +3787,7 @@ static bool track_save_add_map_element(int interactionType, int x, int y, rct_ma /** * - * rct2: 0x006D2F78 + * rct2: 0x006D2F78 */ static void track_save_pop_map_element(int x, int y, rct_map_element *mapElement) { @@ -3643,7 +3818,7 @@ static void track_save_pop_map_element(int x, int y, rct_map_element *mapElement /** * - * rct2: 0x006D2FDD + * rct2: 0x006D2FDD */ static void track_save_pop_map_element_desc(rct_object_entry *entry, int x, int y, int z, uint8 flags, uint8 primaryColour, uint8 secondaryColour) { @@ -3764,7 +3939,7 @@ static void track_save_remove_footpath(int x, int y, rct_map_element *mapElement /** * - * rct2: 0x006D2B3C + * rct2: 0x006D2B3C */ static void track_save_remove_map_element(int interactionType, int x, int y, rct_map_element *mapElement) { @@ -3786,7 +3961,7 @@ static void track_save_remove_map_element(int interactionType, int x, int y, rct /** * - * rct2: 0x006D2B07 + * rct2: 0x006D2B07 */ void track_save_toggle_map_element(int interactionType, int x, int y, rct_map_element *mapElement) { @@ -3804,7 +3979,7 @@ void track_save_toggle_map_element(int interactionType, int x, int y, rct_map_el /** * - * rct2: 0x006D303D + * rct2: 0x006D303D */ void track_save_select_nearby_scenery(int rideIndex) { @@ -3899,28 +4074,344 @@ const rct_track_coordinates *get_track_coord_from_ride(rct_ride *ride, int track const rct_preview_track *get_track_def_from_ride_index(int rideIndex, int trackType) { - return get_track_def_from_ride(GET_RIDE(rideIndex), trackType); + return get_track_def_from_ride(get_ride(rideIndex), trackType); +} + +static rct_map_element *find_station_element(int x, int y, int z, int direction, int rideIndex) +{ + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (z != mapElement->base_height) continue; + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (map_element_get_direction(mapElement) != direction) continue; + if (mapElement->properties.track.ride_index != rideIndex) continue; + if (!track_element_is_station(mapElement)) continue; + + return mapElement; + } while (!map_element_is_last_for_tile(mapElement++)); + return NULL; +} + +static void ride_remove_station(rct_ride *ride, int x, int y, int z) +{ + uint16 xy = (x >> 5) | ((y >> 5) << 8); + for (int i = 0; i < 4; i++) { + if (ride->station_starts[i] == xy && ride->station_heights[i] == z) { + ride->station_starts[i] = 0xFFFF; + ride->num_stations--; + break; + } + } } /** * * rct2: 0x006C4D89 */ -static bool sub_6C4D89(int x, int y, int z, int direction, int rideIndex, int flags) +static bool track_add_station_element(int x, int y, int z, int direction, int rideIndex, int flags) { - return !(RCT2_CALLPROC_X(0x006C4D89, x, flags | (rideIndex << 8), y, z | (direction << 8), 0, 0, 0) & 0x100); + int stationX0 = x; + int stationY0 = y; + int stationX1 = x; + int stationY1 = y; + int stationLength = 1; + + rct_ride *ride = get_ride(rideIndex); + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3)) { + if (ride->num_stations >= 4) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE; + return false; + } + if (flags & GAME_COMMAND_FLAG_APPLY) { + int stationIndex = -1; + for (int i = 0; i < 4; i++) { + if (ride->station_starts[i] == 0xFFFF) { + stationIndex = i; + break; + } + } + + assert(stationIndex != -1); + + ride->station_starts[stationIndex] = (x >> 5) | ((y >> 5) << 8); + ride->station_heights[stationIndex] = z; + ride->station_depart[stationIndex] = 1; + ride->station_length[stationIndex] = 0; + ride->num_stations++; + } + return true; + } + + rct_map_element *stationElement; + + // Search backwards for more station + x = stationX0; + y = stationY0; + do { + x -= TileDirectionDelta[direction].x; + y -= TileDirectionDelta[direction].y; + + stationElement = find_station_element(x, y, z, direction, rideIndex); + if (stationElement != NULL) { + if (stationElement->properties.track.type == TRACK_ELEM_END_STATION) { + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride_remove_station(ride, x, y, z); + } + } + + stationX0 = x; + stationY0 = y; + stationLength++; + } + } while (stationElement != NULL); + + // Search forwards for more station + x = stationX1; + y = stationY1; + do { + x += TileDirectionDelta[direction].x; + y += TileDirectionDelta[direction].y; + + stationElement = find_station_element(x, y, z, direction, rideIndex); + if (stationElement != NULL) { + if (stationElement->properties.track.type == TRACK_ELEM_END_STATION) { + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride_remove_station(ride, x, y, z); + } + } + + stationX1 = x; + stationY1 = y; + stationLength++; + } + } while (stationElement != NULL); + + if (stationX0 == stationX1 && stationY0 == stationY1 && ride->num_stations >= 4) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE; + return false; + } + + if (stationLength > 12) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_STATION_PLATFORM_TOO_LONG; + return false; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + x = stationX1; + y = stationY1; + + bool finaliseStationDone; + do { + finaliseStationDone = true; + + stationElement = find_station_element(x, y, z, direction, rideIndex); + if (stationElement != NULL) { + int targetTrackType; + if (x == stationX1 && y == stationY1) { + int stationIndex = -1; + for (int i = 0; i < 4; i++) { + if (ride->station_starts[i] == 0xFFFF) { + stationIndex = i; + break; + } + } + + assert(stationIndex != -1); + + uint16 xy = (x >> 5) | ((y >> 5) << 8); + ride->station_starts[stationIndex] = xy; + ride->station_heights[stationIndex] = z; + ride->station_depart[stationIndex] = 1; + ride->station_length[stationIndex] = stationLength; + ride->num_stations++; + + targetTrackType = TRACK_ELEM_END_STATION; + } else if (x == stationX0 && y == stationY0) { + targetTrackType = TRACK_ELEM_BEGIN_STATION; + } else { + targetTrackType = TRACK_ELEM_MIDDLE_STATION; + } + stationElement->properties.track.type = targetTrackType; + + map_invalidate_element(x, y, stationElement); + + if (x != stationX0 || y != stationY0) { + x -= TileDirectionDelta[direction].x; + y -= TileDirectionDelta[direction].y; + finaliseStationDone = false; + } + } + } while (!finaliseStationDone); + } + return true; +} + +/** + * + * rct2: 0x006C494B + */ +static bool track_remove_station_element(int x, int y, int z, int direction, int rideIndex, int flags) +{ + int removeX = x; + int removeY = y; + int stationX0 = x; + int stationY0 = y; + int stationX1 = x; + int stationY1 = y; + int stationLength = 0; + int byte_F441D1 = -1; + + rct_ride *ride = get_ride(rideIndex); + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_3)) { + rct_map_element *mapElement = map_get_track_element_at_with_direction_from_ride(x, y, z, direction, rideIndex); + if (mapElement != NULL) { + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride_remove_station(ride, x, y, z); + } + } + return true; + } + + rct_map_element *stationElement; + + // Search backwards for more station + x = stationX0; + y = stationY0; + while ((stationElement = find_station_element(x, y, z, direction, rideIndex)) != NULL) { + if (stationElement->properties.track.type == TRACK_ELEM_END_STATION) { + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride_remove_station(ride, x, y, z); + } + } + + stationX0 = x; + stationY0 = y; + byte_F441D1++; + + x -= TileDirectionDelta[direction].x; + y -= TileDirectionDelta[direction].y; + } + + // Search forwards for more station + x = stationX1; + y = stationY1; + do { + x += TileDirectionDelta[direction].x; + y += TileDirectionDelta[direction].y; + + stationElement = find_station_element(x, y, z, direction, rideIndex); + if (stationElement != NULL) { + if (stationElement->properties.track.type == TRACK_ELEM_END_STATION) { + if (flags & GAME_COMMAND_FLAG_APPLY) { + ride_remove_station(ride, x, y, z); + } + } + + stationX1 = x; + stationY1 = y; + stationLength++; + } + } while (stationElement != NULL); + + if (!(flags & GAME_COMMAND_FLAG_APPLY)) { + if ((removeX != stationX0 || removeY != stationY0) && + (removeX != stationX1 || removeY != stationY1) && + ride->num_stations >= 4 + ) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE; + return false; + } else { + return true; + } + } + + x = stationX1; + y = stationY1; + bool finaliseStationDone; + do { + finaliseStationDone = true; + + if (x != removeX || y != removeY) { + stationElement = find_station_element(x, y, z, direction, rideIndex); + if (stationElement != NULL) { + int targetTrackType; + if (x == stationX1 && y == stationY1) { + loc_6C4BF5:; + int stationIndex = -1; + for (int i = 0; i < 4; i++) { + if (ride->station_starts[i] == 0xFFFF) { + stationIndex = i; + break; + } + } + + assert(stationIndex != -1); + + uint16 xy = (x >> 5) | ((y >> 5) << 8); + ride->station_starts[stationIndex] = xy; + ride->station_heights[stationIndex] = z; + ride->station_depart[stationIndex] = 1; + ride->station_length[stationIndex] = stationLength != 0 ? stationLength : byte_F441D1; + ride->num_stations++; + + stationLength = 0; + targetTrackType = TRACK_ELEM_END_STATION; + } else { + if (x + TileDirectionDelta[direction].x == removeX && + y + TileDirectionDelta[direction].y == removeY + ) { + goto loc_6C4BF5; + } else { + if (x - TileDirectionDelta[direction].x == removeX && + y - TileDirectionDelta[direction].y == removeY + ) { + targetTrackType = TRACK_ELEM_BEGIN_STATION; + } else { + if (x == stationX0 && y == stationY0) { + targetTrackType = TRACK_ELEM_BEGIN_STATION; + } else { + targetTrackType = TRACK_ELEM_MIDDLE_STATION; + } + } + } + } + stationElement->properties.track.type = targetTrackType; + + map_invalidate_element(x, y, stationElement); + } + } + + if (x != stationX0 || y != stationY0) { + x -= TileDirectionDelta[direction].x; + y -= TileDirectionDelta[direction].y; + finaliseStationDone = false; + } + } while (!finaliseStationDone); + + return true; } static money32 track_place(int rideIndex, int type, int originX, int originY, int originZ, int direction, int properties_1, int properties_2, int properties_3, int edx_flags, int flags) { - rct_ride *ride = GET_RIDE(rideIndex); - rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride->subtype); + rct_ride *ride = get_ride(rideIndex); + if (ride == NULL) + { + log_warning("Invalid ride for track placement, rideIndex = %d", rideIndex); + return MONEY32_UNDEFINED; + } + rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); + if (rideEntry == (rct_ride_entry *)0xFFFFFFFF || rideEntry == NULL) + { + log_warning("Invalid ride type for track placement, rideIndex = %d", rideIndex); + return MONEY32_UNDEFINED; + } rct_map_element *mapElement; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION * 4; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = originX + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = originY + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = originZ; + sint16 trackpieceZ = originZ; direction &= 3; RCT2_GLOBAL(0x00F441D5, uint32) = properties_1; RCT2_GLOBAL(0x00F441D9, uint32) = properties_2; @@ -3931,7 +4422,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in enabledTrackPieces |= rideEntry->enabledTrackPiecesB & RCT2_ADDRESS(0x01357644, uint32)[ride->type]; enabledTrackPieces <<= 32; enabledTrackPieces |= rideEntry->enabledTrackPiecesA & RCT2_ADDRESS(0x01357444, uint32)[ride->type]; - uint32 rideTypeFlags = RCT2_GLOBAL(0x0097CF40 + (ride->type * 8), uint32); + uint32 rideTypeFlags = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8), uint32); RCT2_GLOBAL(0x00F44068, uint32) = rideTypeFlags; if ((ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) && type == 1) { @@ -3942,36 +4433,32 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in return MONEY32_UNDEFINED; } if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)) { - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } } - if (type == TRACK_ELEM_ON_RIDE_PHOTO) { - if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_ONLY_ONE_ON_RIDE_PHOTO_PER_RIDE; - return MONEY32_UNDEFINED; - } - } - else if (type == TRACK_ELEM_CABLE_LIFT_HILL) { - if (ride->lifecycle_flags & RIDE_LIFECYCLE_16) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_ONLY_ONE_CABLE_LIFT_HILL_PER_RIDE; - return MONEY32_UNDEFINED; - } - } - - if ((edx_flags & (1 << 0)) && !(enabledTrackPieces & (1ULL << TRACK_LIFT_HILL_STEEP))) { - if (RCT2_ADDRESS(0x0099423C, uint16)[type] & 0x400) { - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_STEEP_FOR_LIFT_HILL; - return MONEY32_UNDEFINED; - } - } - - if (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE){ + if (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE) { RCT2_GLOBAL(0x00F44054, uint8*) = &RCT2_ADDRESS(0x0099AA94, uint8)[type * 16]; - } - else{ + } else { + if (type == TRACK_ELEM_ON_RIDE_PHOTO) { + if (ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_ONLY_ONE_ON_RIDE_PHOTO_PER_RIDE; + return MONEY32_UNDEFINED; + } + } else if (type == TRACK_ELEM_CABLE_LIFT_HILL) { + if (ride->lifecycle_flags & RIDE_LIFECYCLE_16) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_ONLY_ONE_CABLE_LIFT_HILL_PER_RIDE; + return MONEY32_UNDEFINED; + } + } + if ((edx_flags & (1 << 0)) && !(enabledTrackPieces & (1ULL << TRACK_LIFT_HILL_STEEP))) { + if (RCT2_ADDRESS(0x0099423C, uint16)[type] & 0x400) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_STEEP_FOR_LIFT_HILL; + return MONEY32_UNDEFINED; + } + } RCT2_GLOBAL(0x00F44054, uint8*) = &RCT2_ADDRESS(0x00999A94, uint8)[type * 16]; } @@ -4010,7 +4497,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in return MONEY32_UNDEFINED; } } - + uint16 *trackFlags = (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE) ? RCT2_ADDRESS(0x0099443C, uint16) : RCT2_ADDRESS(0x0099423C, uint16); @@ -4073,6 +4560,8 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in y = originY + offsetY; z = originZ + trackBlock->z; + trackpieceZ = z; + if (z < 16) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_LOW; return MONEY32_UNDEFINED; @@ -4098,41 +4587,27 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in _currentTrackEndX = x; _currentTrackEndY = y; - // Until 0x006C5A5F is implemented use this hacky struct. - struct{ - money32 cost; //0 - uint8 pad[0x10];//4 - uint8 flags;//14 - } clearance_struct; - clearance_struct.cost = cost; - clearance_struct.flags = flags; - - RCT2_GLOBAL(0x00F44060, void*) = &clearance_struct; - if (!gCheatsDisableClearanceChecks || flags & GAME_COMMAND_FLAG_GHOST){ - if (!map_can_construct_with_clear_at(x, y, baseZ, clearanceZ, (void*)0x006C5A5F, bl)) + if (!map_can_construct_with_clear_at(x, y, baseZ, clearanceZ, &map_place_non_scenery_clear_func, bl, flags, &cost)) return MONEY32_UNDEFINED; } - // Again when 0x006C5A5F implemented remove this. - cost = clearance_struct.cost; //6c53dc // push baseZ and clearanceZ int cur_z = baseZ * 8; - if ((flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)) { + if ((flags & GAME_COMMAND_FLAG_APPLY) && !(flags & GAME_COMMAND_FLAG_GHOST)) { footpath_remove_litter(x, y, z); - // push bl bh?? if (rideTypeFlags & RIDE_TYPE_FLAG_18) { map_remove_walls_at(x, y, baseZ * 8, clearanceZ * 8); - } - else { - uint8 _bl = *RCT2_GLOBAL(0x00F44054, uint8*); - _bl ^= 0x0F; - - for (int dl = bitscanforward(_bl); dl != -1; dl = bitscanforward(_bl)){ - _bl &= ~(1 << dl); - map_remove_intersecting_walls(x, y, baseZ, clearanceZ, direction & 3); + } else { + // Remove walls in the directions this track intersects + uint8 intersectingDirections = *RCT2_GLOBAL(0x00F44054, uint8*); + intersectingDirections ^= 0x0F; + for (int i = 0; i < 4; i++) { + if (intersectingDirections & (1 << i)) { + map_remove_intersecting_walls(x, y, baseZ, clearanceZ, i); + } } } } @@ -4214,7 +4689,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in entranceDirections = RCT2_ADDRESS(0x0099BA64, uint8)[type * 16]; } if ((entranceDirections & 0x10) && trackBlock->index == 0) { - if (!sub_6C4D89(x, y, baseZ, direction, rideIndex, 0)) { + if (!track_add_station_element(x, y, baseZ, direction, rideIndex, 0)) { return MONEY32_UNDEFINED; } } @@ -4228,8 +4703,8 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in _bl &= ~(1 << dl); int temp_x = x, temp_y = y; int temp_direction = (direction + dl) & 3; - temp_x += RCT2_ADDRESS(0x00993CCC, sint16)[temp_direction * 2]; - temp_y += RCT2_ADDRESS(0x00993CCE, sint16)[temp_direction * 2]; + temp_x += TileDirectionDelta[temp_direction].x; + temp_y += TileDirectionDelta[temp_direction].y; temp_direction ^= (1 << 1); map_remove_intersecting_walls(temp_x, temp_y, baseZ, clearanceZ, temp_direction & 3); } @@ -4258,7 +4733,8 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in support_height = 10; } - cost += (support_height / 2) * RCT2_ADDRESS(0x0097DD7A, uint16)[ride->type * 2]; + cost += ((support_height / 2) * RCT2_ADDRESS(0x0097DD7A, uint16)[ride->type * 2]) * 5; + //6c56d3 if (!(flags & GAME_COMMAND_FLAG_APPLY)) @@ -4317,6 +4793,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in } mapElement = map_element_insert(x / 32, y / 32, baseZ, bl & 0xF); + assert(mapElement != NULL); mapElement->clearance_height = clearanceZ; uint8 map_type = direction; @@ -4370,7 +4847,7 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in if (entranceDirections & (1 << 4)) { if (trackBlock->index == 0) { - sub_6C4D89(x, y, baseZ, direction, rideIndex, GAME_COMMAND_FLAG_APPLY); + track_add_station_element(x, y, baseZ, direction, rideIndex, GAME_COMMAND_FLAG_APPLY); } sub_6CB945(rideIndex); ride_update_max_vehicles(rideIndex); @@ -4388,13 +4865,21 @@ static money32 track_place(int rideIndex, int type, int originX, int originY, in map_invalidate_tile_full(x, y); } + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1) { + rct_xyz16 coord; + coord.x = originX + 16; + coord.y = originY + 16; + coord.z = trackpieceZ; + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + money32 price = RCT2_ADDRESS(0x0097DD78, money16)[ride->type * 2]; price *= (rideTypeFlags & RIDE_TYPE_FLAG_FLAT_RIDE) ? RCT2_ADDRESS(0x0099DE34, money32)[type] : RCT2_ADDRESS(0x0099DA34, money32)[type]; price >>= 16; - price = ((cost + price) / 2) * 10; + price = cost + ((price / 2) * 10); if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) { return 0; @@ -4413,9 +4898,9 @@ void game_command_place_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, *ebx = track_place( *edx & 0xFF, (*edx >> 8) & 0xFF, - *eax & 0xFFFF, - *ecx & 0xFFFF, - *edi & 0xFFFF, + (sint16)(*eax & 0xFFFF), + (sint16)(*ecx & 0xFFFF), + (sint16)(*edi & 0xFFFF), (*ebx >> 8) & 0xFF, (*edi >> 16) & 0xFF, (*edi >> 24) & 0x0F, @@ -4425,20 +4910,12 @@ void game_command_place_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, ); } -/** - * - * rct2: 0x006C494B - */ -static bool sub_6C494B(int x, int y, int z, int direction, int rideIndex, int flags) -{ - return !(RCT2_CALLPROC_X(0x006C494B, x, flags | (rideIndex << 8), y, z | (direction << 8), 0, 0, 0) & 0x100); -} - money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, sint16 originZ, uint8 rotation, uint8 flags){ - RCT2_GLOBAL(0x00141F56C, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 0; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, sint16) = originX + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, sint16) = originY + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, sint16) = originZ; + sint16 trackpieceZ = originZ; RCT2_GLOBAL(0x00F440E1, uint8) = sequence; switch (type){ @@ -4448,13 +4925,18 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, break; } - if (!(flags & (1 << 3)) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + if (!(flags & (1 << 3)) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } 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; @@ -4500,7 +4982,7 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, RCT2_GLOBAL(0x00F44138, uint8) = rideIndex; RCT2_GLOBAL(0x00F4414C, uint8) = mapElement->type; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); const rct_preview_track* trackBlock = get_track_def_from_ride(ride, type); trackBlock += mapElement->properties.track.sequence & 0xF; @@ -4557,6 +5039,8 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, RCT2_GLOBAL(0x00F441C4, sint16) = x; RCT2_GLOBAL(0x00F441C6, sint16) = y; + trackpieceZ = z; + found = 0; mapElement = map_get_first_element_at(x / 32, y / 32); do{ @@ -4593,7 +5077,7 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, } if (entranceDirections & (1 << 4) && ((mapElement->properties.track.sequence & 0xF) == 0)){ - if (!sub_6C494B(x, y, z / 8, rotation, rideIndex, 0)) { + if (!track_remove_station_element(x, y, z / 8, rotation, rideIndex, 0)) { return MONEY32_UNDEFINED; } } @@ -4614,7 +5098,7 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, continue; if (entranceDirections & (1 << 4) && ((mapElement->properties.track.sequence & 0xF) == 0)){ - if (!sub_6C494B(x, y, z / 8, rotation, rideIndex, GAME_COMMAND_FLAG_APPLY)) { + if (!track_remove_station_element(x, y, z / 8, rotation, rideIndex, GAME_COMMAND_FLAG_APPLY)) { return MONEY32_UNDEFINED; } } @@ -4683,6 +5167,14 @@ money32 track_remove(uint8 type, uint8 sequence, sint16 originX, sint16 originY, else price *= -10; + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1) { + rct_xyz16 coord; + coord.x = originX + 16; + coord.y = originY + 16; + coord.z = trackpieceZ; + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) return 0; else @@ -4707,15 +5199,246 @@ void game_command_remove_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, return; } +uint8 maze_element_get_segment_bit(uint16 x, uint16 y) { + uint8 minorX = x & 0x1F; // 0 or 16 + uint8 minorY = y & 0x1F; // 0 or 16 + + if (minorX == 0 && minorY == 0) { + return 3; + } + + if (minorY == 16 && minorX == 16) { + return 11; + } + + if (minorY == 0) { + return 15; + } + + return 7; +} + +money32 set_maze_track(uint16 x, uint8 flags, uint8 direction, uint16 y, uint8 rideIndex, uint8 mode, uint16 z) { + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x + 8; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 8; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; + + RCT2_GLOBAL(0xF4413E, money32) = 0; + + if (!sub_68B044()) { + return MONEY32_UNDEFINED; + } + + if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && !gCheatsBuildInPauseMode && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, unsigned short) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + return MONEY32_UNDEFINED; + } + + if ((z & 0xF) != 0) { + // ‘Can't construct this here…’ + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, unsigned short) = 954; + return MONEY32_UNDEFINED; + } + + if ((flags & GAME_COMMAND_FLAG_APPLY) != 0) { + if (!(flags & GAME_COMMAND_FLAG_GHOST) && !(flags & GAME_COMMAND_FLAG_2)) { + footpath_remove_litter(x, y, z); + map_remove_walls_at(floor2(x, 32), floor2(y, 32), z, z + 32); + } + } + + if (!map_is_location_owned(floor2(x, 32), floor2(y, 32), z) && !gCheatsSandboxMode) { + return MONEY32_UNDEFINED; + } + + rct_map_element *mapElement = map_get_surface_element_at(x / 32, y / 32); + if (mapElement == NULL) { + return MONEY32_UNDEFINED; + } + + uint8 baseHeight = z >> 3; + uint8 clearanceHeight = (z + 32) >> 3; + + sint8 heightDifference = baseHeight - mapElement->base_height; + if (heightDifference >= 0 && !gCheatsDisableSupportLimits) { + heightDifference = heightDifference >> 1; + + if (heightDifference > RCT2_GLOBAL(0x0097D218 + (RIDE_TYPE_MAZE * 8), uint8)) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_TOO_HIGH_FOR_SUPPORTS; + return MONEY32_UNDEFINED; + } + } + + mapElement = map_get_track_element_at_of_type_from_ride(x, y, baseHeight, 0x65, rideIndex); + if (mapElement == NULL) { + if (mode != 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, unsigned short) = 0; + return MONEY32_UNDEFINED; + } + + if (!map_can_construct_at(floor2(x, 32), floor2(y, 32), baseHeight, clearanceHeight, 0x0F)) { + return MONEY32_UNDEFINED; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, unsigned short) = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; + return MONEY32_UNDEFINED; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 0x02) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, unsigned short) = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND; + return MONEY32_UNDEFINED; + } + + rct_ride *ride = get_ride(rideIndex); + + money32 price = (((RCT2_ADDRESS(0x0097DD78, money16)[ride->type * 2] * RCT2_GLOBAL(0x0099DBC8, money32)) >> 16)); + RCT2_GLOBAL(0x00F4413E, money32) = price / 2 * 10; + + if (!(flags & GAME_COMMAND_FLAG_APPLY)) { + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) { + return 0; + } + + return RCT2_GLOBAL(0xF4413E, money32); + } + + uint16 flooredX = floor2(x, 32); + uint16 flooredY = floor2(y, 32); + + mapElement = map_element_insert(x / 32, y / 32, baseHeight, 0xF); + assert(mapElement != NULL); + mapElement->clearance_height = clearanceHeight; + mapElement->type = MAP_ELEMENT_TYPE_TRACK; + mapElement->properties.track.type = 0x65; + mapElement->properties.track.ride_index = rideIndex; + mapElement->properties.track.maze_entry = 0xFFFF; + + if (flags & GAME_COMMAND_FLAG_GHOST) { + mapElement->flags |= MAP_ELEMENT_FLAG_GHOST; + } + + map_invalidate_tile_full(flooredX, flooredY); + + ride->maze_tiles++; + ride->station_heights[0] = mapElement->base_height; + ride->station_starts[0] = 0; + + if (direction == 4) { + if (!(flags & GAME_COMMAND_FLAG_GHOST)) { + ride->overall_view = (flooredX >> 5) | (flooredY << 3); + } + } + } + + if (!(flags & GAME_COMMAND_FLAG_APPLY)) { + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) { + return 0; + } + + return RCT2_GLOBAL(0xF4413E, money32); + } + + + if (mode == 0) { + // Build mode + uint8 segmentOffset = maze_element_get_segment_bit(x, y); + + mapElement->properties.track.maze_entry &= ~(1 << segmentOffset); + + if (direction != 4) { + segmentOffset = RCT2_GLOBAL(0x993ce9 + (direction + segmentOffset), uint8); + mapElement->properties.track.maze_entry &= ~(1 << segmentOffset); + + uint8 temp_edx = RCT2_GLOBAL(0x993cfc + segmentOffset, uint8); + if (temp_edx != 0xFF) { + uint16 previousElementX = floor2(x, 32) - TileDirectionDelta[direction].x; + uint16 previousElementY = floor2(y, 32) - TileDirectionDelta[direction].y; + + rct_map_element *previousMapElement = map_get_track_element_at_of_type_from_ride(previousElementX, previousElementY, baseHeight, 0x65, rideIndex); + if (previousMapElement != NULL) { + previousMapElement->properties.track.maze_entry &= ~(1 << temp_edx); + } else { + mapElement->properties.track.maze_entry |= (1 << segmentOffset); + } + } + } + } else if (mode == 1) { + // Move mode + } else { + // Fill-in mode + if (direction != 4) { + uint16 previousSegmentX = x - TileDirectionDelta[direction].x / 2; + uint16 previousSegmentY = y - TileDirectionDelta[direction].y / 2; + + mapElement = map_get_track_element_at_of_type_from_ride(previousSegmentX, previousSegmentY, baseHeight, 0x65, rideIndex); + map_invalidate_tile_full(floor2(previousSegmentX, 32), floor2(previousSegmentY, 32)); + if (mapElement == NULL) { + log_error("No surface found"); + return MONEY32_UNDEFINED; + } + + uint32 segmentBit = maze_element_get_segment_bit(previousSegmentX, previousSegmentY); + + mapElement->properties.track.maze_entry |= (1 << segmentBit); + segmentBit--; + mapElement->properties.track.maze_entry |= (1 << segmentBit); + segmentBit = (segmentBit - 4) & 0x0F; + mapElement->properties.track.maze_entry |= (1 << segmentBit); + segmentBit = (segmentBit + 3) & 0x0F; + + do { + mapElement->properties.track.maze_entry |= (1 << segmentBit); + + uint32 direction1 = RCT2_GLOBAL(0x00993D0C + segmentBit, uint8_t); + uint16 nextElementX = floor2(previousSegmentX, 32) + TileDirectionDelta[direction1].x; + uint16 nextElementY = floor2(previousSegmentY, 32) + TileDirectionDelta[direction1].y; + + rct_map_element *tmp_mapElement = map_get_track_element_at_of_type_from_ride(nextElementX, nextElementY, baseHeight, 0x65, rideIndex); + if (tmp_mapElement != NULL) { + uint8 edx11 = RCT2_GLOBAL(0x993CFC + segmentBit, uint8); + tmp_mapElement->properties.track.maze_entry |= 1 << (edx11); + } + + segmentBit--; + } while ((segmentBit & 0x3) != 0x3); + } + } + + map_invalidate_tile(floor2(x, 32), floor2(y, 32), mapElement->base_height * 8, mapElement->clearance_height * 8); + + if ((mapElement->properties.track.maze_entry & 0x8888) == 0x8888) { + map_element_remove(mapElement); + sub_6CB945(rideIndex); + get_ride(rideIndex)->maze_tiles--; + } + + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) { + return 0; + } + + return RCT2_GLOBAL(0xF4413E, money32); +} + /** * * rct2: 0x006CD8CE */ void game_command_set_maze_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { - RCT2_CALLFUNC_X(0x006CD8CE, eax, ebx, ecx, edx, esi, edi, ebp); + uint16 x = (*eax & 0xFFFF); // AX + uint8 flags = (*ebx & 0xFF); // BL + uint8 direction = ((*ebx & 0xFF00) >> 8); // BH + uint16 y = (*ecx & 0xFFFF); // CX + uint8 rideIndex = (*edx & 0xFF); // DL + uint8 mode = ((*edx & 0xFF00) >> 8); // DH + uint16 z = (*edi & 0xFFFF); // DI + + *ebx = set_maze_track(x, flags, direction, y, rideIndex, mode, z); } + /** * * rct2: 0x006C5AE9 @@ -4732,9 +5455,9 @@ void game_command_set_brakes_speed(int *eax, int *ebx, int *ecx, int *edx, int * brakesSpeed = ((*ebx >> 8) & 0xFF); RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION * 4; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint8) = x + 16; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint8) = y + 16; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint8) = z; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x + 16; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; if (*ebx & GAME_COMMAND_FLAG_APPLY) { *ebx = 0; @@ -4742,6 +5465,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; @@ -4865,6 +5594,30 @@ bool track_element_is_lift_hill(rct_map_element *trackElement) return trackElement->type & 0x80; } +/** + * Checks if a track element is recognised as the beginning of a block. + * A beginning of a block can be the end of a station, the end of a lift hill, + * or a block brake. + */ +bool track_element_is_block_start(rct_map_element *trackElement) +{ + switch (trackElement->properties.track.type) { + case TRACK_ELEM_END_STATION: + case TRACK_ELEM_CABLE_LIFT_HILL: + case 216: + return true; + case TRACK_ELEM_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_60_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT: + if (track_element_is_lift_hill(trackElement)) { + return true; + } + break; + } + return false; +} + bool track_element_is_cable_lift(rct_map_element *trackElement) { return trackElement->properties.track.colour & TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; } @@ -4876,3 +5629,74 @@ void track_element_set_cable_lift(rct_map_element *trackElement) { void track_element_clear_cable_lift(rct_map_element *trackElement) { trackElement->properties.track.colour &= ~TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT; } + +int track_get_actual_bank(rct_map_element *mapElement, int bank) +{ + rct_ride *ride = get_ride(mapElement->properties.track.ride_index); + int trackColour = mapElement->properties.track.colour; + return track_get_actual_bank_2(ride->type, trackColour, bank); +} + +int track_get_actual_bank_2(int rideType, int trackColour, int bank) +{ + if (RideData4[rideType].flags & RIDE_TYPE_FLAG4_3) { + if (trackColour & 4) { + if (bank == TRACK_BANK_NONE) { + bank = TRACK_BANK_UPSIDE_DOWN; + } else if (bank == TRACK_BANK_UPSIDE_DOWN) { + bank = TRACK_BANK_NONE; + } + } + } + return bank; +} + +int track_get_actual_bank_3(rct_vehicle *vehicle, rct_map_element *mapElement) +{ + uint8 colourThingToXor = (vehicle->update_flags >> 9) & 0xFF; + int trackType = mapElement->properties.track.type; + int rideType = get_ride(mapElement->properties.track.ride_index)->type; + int trackColour = mapElement->properties.track.colour ^ colourThingToXor; + int bankStart = gTrackDefinitions[trackType].bank_start; + return track_get_actual_bank_2(rideType, trackColour, bankStart); +} + +bool track_element_is_station(rct_map_element *trackElement) +{ + switch (trackElement->properties.track.type) { + case TRACK_ELEM_END_STATION: + case TRACK_ELEM_BEGIN_STATION: + case TRACK_ELEM_MIDDLE_STATION: + return true; + default: + return false; + } +} + +bool track_element_is_covered(int trackElementType) +{ + switch (trackElementType) { + case TRACK_ELEM_FLAT_COVERED: + case TRACK_ELEM_25_DEG_UP_COVERED: + case TRACK_ELEM_60_DEG_UP_COVERED: + case TRACK_ELEM_FLAT_TO_25_DEG_UP_COVERED: + case TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP_COVERED: + case TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP_COVERED: + case TRACK_ELEM_25_DEG_UP_TO_FLAT_COVERED: + case TRACK_ELEM_25_DEG_DOWN_COVERED: + case TRACK_ELEM_60_DEG_DOWN_COVERED: + case TRACK_ELEM_FLAT_TO_25_DEG_DOWN_COVERED: + case TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN_COVERED: + case TRACK_ELEM_60_DEG_DOWN_TO_25_DEG_DOWN_COVERED: + case TRACK_ELEM_25_DEG_DOWN_TO_FLAT_COVERED: + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED: + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED: + case TRACK_ELEM_S_BEND_LEFT_COVERED: + case TRACK_ELEM_S_BEND_RIGHT_COVERED: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_COVERED: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED: + return true; + default: + return false; + } +} diff --git a/src/ride/track.h b/src/ride/track.h index 5690767666..21e9421fbb 100644 --- a/src/ride/track.h +++ b/src/ride/track.h @@ -300,6 +300,17 @@ enum { TRACK_CORKSCREW_DOWN = 224 }; +enum { + TRACK_ELEM_FLAG_TURN_LEFT = (1 << 1), + TRACK_ELEM_FLAG_TURN_RIGHT = (1 << 2), + TRACK_ELEM_FLAG_TURN_BANKED = (1 << 3), + TRACK_ELEM_FLAG_TURN_SLOPED = (1 << 4), + TRACK_ELEM_FLAG_DOWN = (1 << 5), + TRACK_ELEM_FLAG_UP = (1 << 6), + TRACK_ELEM_FLAG_INVERSION = (1 << 7), + TRACK_ELEM_FLAG_HELIX = (1 << 11), +}; + enum { TRACK_ELEM_FLAT, TRACK_ELEM_END_STATION, @@ -311,7 +322,7 @@ enum { TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP, TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP, TRACK_ELEM_25_DEG_UP_TO_FLAT, - TRACK_ELEM_25_DEG_DOWN, + TRACK_ELEM_25_DEG_DOWN = 10, TRACK_ELEM_60_DEG_DOWN, TRACK_ELEM_FLAT_TO_25_DEG_DOWN, TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN, @@ -321,7 +332,7 @@ enum { TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES, TRACK_ELEM_FLAT_TO_LEFT_BANK, TRACK_ELEM_FLAT_TO_RIGHT_BANK, - TRACK_ELEM_LEFT_BANK_TO_FLAT, + TRACK_ELEM_LEFT_BANK_TO_FLAT = 20, TRACK_ELEM_RIGHT_BANK_TO_FLAT, TRACK_ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES, TRACK_ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES, @@ -331,7 +342,7 @@ enum { TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANK, TRACK_ELEM_LEFT_BANK_TO_25_DEG_DOWN, TRACK_ELEM_RIGHT_BANK_TO_25_DEG_DOWN, - TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANK, + TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANK = 30, TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANK, TRACK_ELEM_LEFT_BANK, TRACK_ELEM_RIGHT_BANK, @@ -341,7 +352,7 @@ enum { TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN, TRACK_ELEM_S_BEND_LEFT, TRACK_ELEM_S_BEND_RIGHT, - TRACK_ELEM_LEFT_VERTICAL_LOOP, + TRACK_ELEM_LEFT_VERTICAL_LOOP = 40, TRACK_ELEM_RIGHT_VERTICAL_LOOP, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES, @@ -351,7 +362,7 @@ enum { TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN, - TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE, + TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE = 50, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE, TRACK_ELEM_LEFT_TWIST_DOWN_TO_UP, TRACK_ELEM_RIGHT_TWIST_DOWN_TO_UP, @@ -361,7 +372,7 @@ enum { TRACK_ELEM_HALF_LOOP_DOWN, TRACK_ELEM_LEFT_CORKSCREW_UP, TRACK_ELEM_RIGHT_CORKSCREW_UP, - TRACK_ELEM_LEFT_CORKSCREW_DOWN, + TRACK_ELEM_LEFT_CORKSCREW_DOWN = 60, TRACK_ELEM_RIGHT_CORKSCREW_DOWN, TRACK_ELEM_FLAT_TO_60_DEG_UP, TRACK_ELEM_60_DEG_UP_TO_FLAT, @@ -371,7 +382,7 @@ enum { TRACK_ELEM_TOWER_SECTION, TRACK_ELEM_FLAT_COVERED, TRACK_ELEM_25_DEG_UP_COVERED, - TRACK_ELEM_60_DEG_UP_COVERED, + TRACK_ELEM_60_DEG_UP_COVERED = 70, TRACK_ELEM_FLAT_TO_25_DEG_UP_COVERED, TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP_COVERED, TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP_COVERED, @@ -381,7 +392,7 @@ enum { TRACK_ELEM_FLAT_TO_25_DEG_DOWN_COVERED, TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN_COVERED, TRACK_ELEM_60_DEG_DOWN_TO_25_DEG_DOWN_COVERED, - TRACK_ELEM_25_DEG_DOWN_TO_FLAT_COVERED, + TRACK_ELEM_25_DEG_DOWN_TO_FLAT_COVERED = 80, TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED, TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED, TRACK_ELEM_S_BEND_LEFT_COVERED, @@ -391,7 +402,7 @@ enum { TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_SMALL, TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_SMALL, TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_SMALL, - TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_SMALL, + TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_SMALL = 90, TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_LARGE, TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_LARGE, TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_LARGE, @@ -401,7 +412,7 @@ enum { TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_DOWN, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN, TRACK_ELEM_BRAKES, - TRACK_ELEM_ROTATION_CONTROL_TOGGLE, + TRACK_ELEM_ROTATION_CONTROL_TOGGLE = 100, TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP, TRACK_ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_UP, TRACK_ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_UP, @@ -411,7 +422,7 @@ enum { TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_UP, TRACK_ELEM_LEFT_QUARTER_HELIX_LARGE_DOWN, TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_DOWN, - TRACK_ELEM_25_DEG_UP_LEFT_BANKED, + TRACK_ELEM_25_DEG_UP_LEFT_BANKED = 110, TRACK_ELEM_25_DEG_UP_RIGHT_BANKED, TRACK_ELEM_WATERFALL, TRACK_ELEM_RAPIDS, @@ -421,7 +432,7 @@ enum { TRACK_ELEM_WATER_SPLASH, TRACK_ELEM_FLAT_TO_60_DEG_UP_LONG_BASE, TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE, - TRACK_ELEM_WHIRLPOOL, + TRACK_ELEM_WHIRLPOOL = 120, TRACK_ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE, TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE_122, TRACK_ELEM_CABLE_LIFT_HILL, @@ -431,7 +442,7 @@ enum { TRACK_ELEM_90_DEG_DOWN, TRACK_ELEM_60_DEG_UP_TO_90_DEG_UP, TRACK_ELEM_90_DEG_DOWN_TO_60_DEG_DOWN, - TRACK_ELEM_90_DEG_UP_TO_60_DEG_UP, + TRACK_ELEM_90_DEG_UP_TO_60_DEG_UP = 130, TRACK_ELEM_60_DEG_DOWN_TO_90_DEG_DOWN, TRACK_ELEM_BRAKE_FOR_DROP, TRACK_ELEM_LEFT_EIGHTH_TO_DIAG, @@ -441,7 +452,7 @@ enum { TRACK_ELEM_LEFT_EIGHTH_BANK_TO_DIAG, TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_DIAG, TRACK_ELEM_LEFT_EIGHTH_BANK_TO_ORTHOGONAL, - TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL, + TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL = 140, TRACK_ELEM_DIAG_FLAT, TRACK_ELEM_DIAG_25_DEG_UP, TRACK_ELEM_DIAG_60_DEG_UP, @@ -451,7 +462,7 @@ enum { TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT, TRACK_ELEM_DIAG_25_DEG_DOWN, TRACK_ELEM_DIAG_60_DEG_DOWN, - TRACK_ELEM_DIAG_FLAT_TO_25_DEG_DOWN, + TRACK_ELEM_DIAG_FLAT_TO_25_DEG_DOWN = 150, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_60_DEG_DOWN, TRACK_ELEM_DIAG_60_DEG_DOWN_TO_25_DEG_DOWN, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_FLAT, @@ -461,7 +472,7 @@ enum { TRACK_ELEM_DIAG_60_DEG_DOWN_TO_FLAT, TRACK_ELEM_DIAG_FLAT_TO_LEFT_BANK, TRACK_ELEM_DIAG_FLAT_TO_RIGHT_BANK, - TRACK_ELEM_DIAG_LEFT_BANK_TO_FLAT, + TRACK_ELEM_DIAG_LEFT_BANK_TO_FLAT = 160, TRACK_ELEM_DIAG_RIGHT_BANK_TO_FLAT, TRACK_ELEM_DIAG_LEFT_BANK_TO_25_DEG_UP, TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_UP, @@ -471,7 +482,7 @@ enum { TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_DOWN, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_LEFT_BANK, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_RIGHT_BANK, - TRACK_ELEM_DIAG_LEFT_BANK, + TRACK_ELEM_DIAG_LEFT_BANK = 170, TRACK_ELEM_DIAG_RIGHT_BANK, TRACK_ELEM_LOG_FLUME_REVERSER, TRACK_ELEM_SPINNING_TUNNEL, @@ -481,13 +492,81 @@ enum { TRACK_ELEM_RIGHT_BARREL_ROLL_DOWN_TO_UP, TRACK_ELEM_LEFT_BANK_TO_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP, TRACK_ELEM_RIGHT_BANK_TO_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP, - TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_LEFT_BANK, + TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_LEFT_BANK = 180, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_RIGHT_BANK, TRACK_ELEM_POWERED_LIFT, TRACK_ELEM_LEFT_LARGE_HALF_LOOP_UP, TRACK_ELEM_RIGHT_LARGE_HALF_LOOP_UP, TRACK_ELEM_RIGHT_LARGE_HALF_LOOP_DOWN, - TRACK_ELEM_LEFT_LARGE_HALF_LOOP_DOWN + TRACK_ELEM_LEFT_LARGE_HALF_LOOP_DOWN, + TRACK_ELEM_LEFT_FLYER_TWIST_UP, + TRACK_ELEM_RIGHT_FLYER_TWIST_UP, + TRACK_ELEM_LEFT_FLYER_TWIST_DOWN, + TRACK_ELEM_RIGHT_FLYER_TWIST_DOWN, + TRACK_ELEM_FLYER_HALF_LOOP_UP, + TRACK_ELEM_FLYER_HALF_LOOP_DOWN, + TRACK_ELEM_LEFT_FLYER_CORKSCREW_UP, + TRACK_ELEM_RIGHT_FLYER_CORKSCREW_UP, + TRACK_ELEM_LEFT_FLYER_CORKSCREW_DOWN, + TRACK_ELEM_RIGHT_FLYER_CORKSCREW_DOWN, + TRACK_ELEM_HEARTLINE_TRANSFER_UP, + TRACK_ELEM_HEARTLINE_TRANSFER_DOWN, + TRACK_ELEM_LEFT_HEARTLINE_ROLL, + TRACK_ELEM_RIGHT_HEARTLINE_ROLL, + TRACK_ELEM_MINI_GOLF_HOLE_A, + TRACK_ELEM_MINI_GOLF_HOLE_B, + TRACK_ELEM_MINI_GOLF_HOLE_C, + TRACK_ELEM_MINI_GOLF_HOLE_D, + TRACK_ELEM_MINI_GOLF_HOLE_E, + TRACK_ELEM_MULTIDIM_INVERTED_FLAT_TO_90_DEG_QUARTER_LOOP_DOWN, + TRACK_ELEM_90_DEG_TO_INVERTED_FLAT_QUARTER_LOOP_UP, + TRACK_ELEM_INVERTED_FLAT_TO_90_DEG_QUARTER_LOOP_DOWN, + TRACK_ELEM_LEFT_CURVED_LIFT_HILL, + TRACK_ELEM_RIGHT_CURVED_LIFT_HILL, + TRACK_ELEM_LEFT_REVERSER, + TRACK_ELEM_RIGHT_REVERSER, + TRACK_ELEM_AIR_THRUST_TOP_CAP, + TRACK_ELEM_AIR_THRUST_VERTICAL_DOWN, + TRACK_ELEM_AIR_THRUST_VERTICAL_DOWN_TO_LEVEL, + TRACK_ELEM_BLOCK_BRAKES, + TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP, + TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP, + TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN, + TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN, + TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP, + TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP, + TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN, + TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN, + TRACK_ELEM_25_DEG_UP_TO_LEFT_BANKED_25_DEG_UP, + TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANKED_25_DEG_UP, + TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_25_DEG_UP, + TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_25_DEG_UP, + TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANKED_25_DEG_DOWN, + TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANKED_25_DEG_DOWN, + TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_25_DEG_DOWN, + TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_25_DEG_DOWN, + TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_UP, + TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_UP, + TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_LEFT_BANKED_FLAT, + TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_RIGHT_BANKED_FLAT, + TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_DOWN, + TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN, + TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_LEFT_BANKED_FLAT, + TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_RIGHT_BANKED_FLAT, + TRACK_ELEM_FLAT_TO_LEFT_BANKED_25_DEG_UP, + TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_UP, + TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_FLAT, + TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_FLAT, + TRACK_ELEM_FLAT_TO_LEFT_BANKED_25_DEG_DOWN, + TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN, + TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_FLAT, + TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_FLAT, + TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_90_DEG_UP, + TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_90_DEG_UP, + TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_90_DEG_DOWN, + TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_90_DEG_DOWN, + TRACK_ELEM_MULTIDIM_90_DEG_UP_TO_INVERTED_FLAT_QUARTER_LOOP, + TRACK_ELEM_MULTIDIM_FLAT_TO_90_DEG_DOWN_QUARTER_LOOP, }; enum { @@ -547,9 +626,17 @@ void track_get_back(rct_xy_element *input, rct_xy_element *output); void track_get_front(rct_xy_element *input, rct_xy_element *output); bool track_element_is_lift_hill(rct_map_element *trackElement); +bool track_element_is_block_start(rct_map_element *trackElement); bool track_element_is_cable_lift(rct_map_element *trackElement); void track_element_set_cable_lift(rct_map_element *trackElement); void track_element_clear_cable_lift(rct_map_element *trackElement); +int track_get_actual_bank(rct_map_element *mapElement, int bank); +int track_get_actual_bank_2(int rideType, int trackColour, int bank); +int track_get_actual_bank_3(rct_vehicle *vehicle, rct_map_element *mapElement); + +bool track_element_is_station(rct_map_element *trackElement); +bool track_element_is_covered(int trackElementType); + #endif diff --git a/src/ride/track_data.c b/src/ride/track_data.c index 17efa05e0a..2a7d6ecec6 100644 --- a/src/ride/track_data.c +++ b/src/ride/track_data.c @@ -5507,7 +5507,7 @@ const uint32 RideTypeTrackPaintFunctionsOld[91] = { 0x0076190C, // RIDE_TYPE_MERRY_GO_ROUND 0, // RIDE_TYPE_22 0, // RIDE_TYPE_INFORMATION_KIOSK - 0x00762D44, // RIDE_TYPE_TOILETS + 0, // RIDE_TYPE_TOILETS 0x008A8CC8, // RIDE_TYPE_FERRIS_WHEEL 0x00763520, // RIDE_TYPE_MOTION_SIMULATOR 0x0076554C, // RIDE_TYPE_3D_CINEMA @@ -5519,7 +5519,7 @@ const uint32 RideTypeTrackPaintFunctionsOld[91] = { 0, // RIDE_TYPE_CASH_MACHINE 0x0076D658, // RIDE_TYPE_TWIST 0x0076E7B0, // RIDE_TYPE_HAUNTED_HOUSE - 0x00762D44, // RIDE_TYPE_FIRST_AID + 0, // RIDE_TYPE_FIRST_AID 0x0076F8D4, // RIDE_TYPE_CIRCUS_SHOW 0x00770924, // RIDE_TYPE_GHOST_TRAIN 0x008AB2A0, // RIDE_TYPE_TWISTER_ROLLER_COASTER @@ -5565,7 +5565,7 @@ const uint32 RideTypeTrackPaintFunctionsOld[91] = { }; -const uint32 RideTypeTrackPaintFunctions[91] = { +const TRACK_PAINT_FUNCTION_GETTER RideTypeTrackPaintFunctions[91] = { 0, // RIDE_TYPE_SPIRAL_ROLLER_COASTER 0, // RIDE_TYPE_STAND_UP_ROLLER_COASTER 0, // RIDE_TYPE_SUSPENDED_SWINGING_COASTER @@ -5594,27 +5594,27 @@ const uint32 RideTypeTrackPaintFunctions[91] = { 0, // RIDE_TYPE_DODGEMS 0, // RIDE_TYPE_PIRATE_SHIP 0, // RIDE_TYPE_SWINGING_INVERTER_SHIP - (uint32)shop_track_paint_functions, // RIDE_TYPE_FOOD_STALL - (uint32)shop_track_paint_functions, // RIDE_TYPE_1D - (uint32)shop_track_paint_functions, // RIDE_TYPE_DRINK_STALL - (uint32)shop_track_paint_functions, // RIDE_TYPE_1F - (uint32)shop_track_paint_functions, // RIDE_TYPE_SHOP + get_track_paint_function_shop, // RIDE_TYPE_FOOD_STALL + get_track_paint_function_shop, // RIDE_TYPE_1D + get_track_paint_function_shop, // RIDE_TYPE_DRINK_STALL + get_track_paint_function_shop, // RIDE_TYPE_1F + get_track_paint_function_shop, // RIDE_TYPE_SHOP 0, // RIDE_TYPE_MERRY_GO_ROUND - (uint32)shop_track_paint_functions, // RIDE_TYPE_22 - (uint32)shop_track_paint_functions, // RIDE_TYPE_INFORMATION_KIOSK - (uint32)shop_track_paint_functions, // RIDE_TYPE_TOILETS + get_track_paint_function_shop, // RIDE_TYPE_22 + get_track_paint_function_shop, // RIDE_TYPE_INFORMATION_KIOSK + get_track_paint_function_facility, // RIDE_TYPE_TOILETS 0, // RIDE_TYPE_FERRIS_WHEEL 0, // RIDE_TYPE_MOTION_SIMULATOR 0, // RIDE_TYPE_3D_CINEMA - (uint32)top_spin_track_paint_functions, // RIDE_TYPE_TOP_SPIN + get_track_paint_function_topspin, // RIDE_TYPE_TOP_SPIN 0, // RIDE_TYPE_SPACE_RINGS 0, // RIDE_TYPE_REVERSE_FREEFALL_COASTER 0, // RIDE_TYPE_LIFT 0, // RIDE_TYPE_VERTICAL_DROP_ROLLER_COASTER - (uint32)shop_track_paint_functions, // RIDE_TYPE_CASH_MACHINE + get_track_paint_function_shop, // RIDE_TYPE_CASH_MACHINE 0, // RIDE_TYPE_TWIST 0, // RIDE_TYPE_HAUNTED_HOUSE - 0, // RIDE_TYPE_FIRST_AID + get_track_paint_function_facility, // RIDE_TYPE_FIRST_AID 0, // RIDE_TYPE_CIRCUS_SHOW 0, // RIDE_TYPE_GHOST_TRAIN 0, // RIDE_TYPE_TWISTER_ROLLER_COASTER @@ -5658,3 +5658,146 @@ const uint32 RideTypeTrackPaintFunctions[91] = { 0, // RIDE_TYPE_59 0, // RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER }; + +const track_descriptor gTrackDescriptors[140] = { + { true, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_DIAG_60_DEG_DOWN }, + { true, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_60_DEG_DOWN_TO_25_DEG_DOWN }, + { true, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_DIAG_60_DEG_DOWN_TO_FLAT }, + { true, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_60_DEG_DOWN }, + { true, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_25_DEG_DOWN }, + { true, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_LEFT_BANK }, + { true, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_FLAT }, + { true, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_DIAG_25_DEG_DOWN_TO_RIGHT_BANK }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_LEFT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_EIGHTH_BANK_TO_ORTHOGONAL }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_LEFT_BANK_TO_25_DEG_DOWN }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_DIAG_LEFT_BANK }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_DIAG_LEFT_BANK_TO_FLAT }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_LEFT_BANK_TO_25_DEG_UP }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_LEFT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_EIGHTH_TO_ORTHOGONAL }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_DIAG_FLAT_TO_60_DEG_DOWN }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_FLAT_TO_25_DEG_DOWN }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_DIAG_FLAT_TO_LEFT_BANK }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_DIAG_FLAT }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_DIAG_FLAT_TO_RIGHT_BANK }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_FLAT_TO_25_DEG_UP }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_DIAG_FLAT_TO_60_DEG_UP }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_EIGHTH_TO_ORTHOGONAL }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_DOWN }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_DIAG_RIGHT_BANK_TO_FLAT }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_DIAG_RIGHT_BANK }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_UP }, + { true, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL }, + { true, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_DIAG_25_DEG_UP_TO_LEFT_BANK }, + { true, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT }, + { true, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_DIAG_25_DEG_UP_TO_RIGHT_BANK }, + { true, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_25_DEG_UP }, + { true, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_DIAG_25_DEG_UP_TO_60_DEG_UP }, + { true, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT }, + { true, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_DIAG_60_DEG_UP_TO_25_DEG_UP }, + { true, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_DIAG_60_DEG_UP }, + { false, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_90_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_ELEM_90_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_90_DEG_DOWN_TO_60_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_90_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_90, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_DOWN_TO_90_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_DOWN_TO_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_DOWN_TO_FLAT }, + { false, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_CURVE_LEFT, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_ELEM_25_DEG_DOWN_LEFT_BANKED }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_LEFT_BANKED_FLAT }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_FLAT }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_LEFT, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANKED_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANKED_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANK }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_25_DEG_DOWN_TO_FLAT }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANK }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_RIGHT, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_ELEM_25_DEG_DOWN_RIGHT_BANKED }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_FLAT }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_RIGHT_BANKED_FLAT }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN }, + { false, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_BANK }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANK_TO_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_LEFT, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_LEFT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_EIGHTH_BANK_TO_DIAG }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANK_TO_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANK }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANK_TO_FLAT }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANK_TO_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_LEFT, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_LEFT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_EIGHTH_TO_DIAG }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_60, TRACK_BANK_NONE, TRACK_ELEM_FLAT_TO_60_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_LEFT, TRACK_ELEM_FLAT_TO_LEFT_BANKED_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_FLAT_TO_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_FLAT_TO_LEFT_BANK }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_FLAT }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_LEFT_VERY_SMALL, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_VERY_SMALL, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_FLAT_TO_RIGHT_BANK }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_ELEM_FLAT_TO_LEFT_BANKED_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_FLAT_TO_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_FLAT_TO_60_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_EIGHTH_TO_DIAG }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_RIGHT, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANK_TO_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_DOWN_25, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANK_TO_FLAT }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANK }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANK_TO_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_UP }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT_LARGE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_DIAG }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK }, + { false, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANK_TO_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_CURVE_LEFT, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_LEFT_BANKED_FLAT }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_FLAT }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_ELEM_25_DEG_UP_LEFT_BANKED }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_LEFT, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_LEFT, TRACK_ELEM_25_DEG_UP_TO_LEFT_BANK }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_25_DEG_UP_TO_FLAT }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANK }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_LEFT, TRACK_ELEM_25_DEG_UP_TO_LEFT_BANKED_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANKED_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_RIGHT, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_FLAT }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_RIGHT_BANKED_FLAT }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_ELEM_25_DEG_UP_RIGHT_BANKED }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP }, + { false, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_UP_25, TRACK_BANK_RIGHT, TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP }, + { false, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP }, + { false, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_NONE, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_UP_TO_FLAT }, + { false, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_25, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP }, + { false, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_UP }, + { false, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_ELEM_60_DEG_UP_TO_90_DEG_UP }, + { false, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_UP }, + { false, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_CURVE_LEFT_SMALL, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_90_DEG_UP }, + { false, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_60, TRACK_BANK_NONE, TRACK_ELEM_90_DEG_UP_TO_60_DEG_UP }, + { false, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_CURVE_NONE, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_ELEM_90_DEG_UP }, + { false, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_CURVE_RIGHT_SMALL, TRACK_SLOPE_UP_90, TRACK_BANK_NONE, TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_90_DEG_UP }, +}; diff --git a/src/ride/track_data.h b/src/ride/track_data.h index 366e642589..41e8c37d15 100644 --- a/src/ride/track_data.h +++ b/src/ride/track_data.h @@ -20,6 +20,7 @@ #include "../common.h" #include "track.h" +#include "track_paint.h" // 0x009968BB, 0x009968BC, 0x009968BD, 0x009968BF, 0x009968C1, 0x009968C3 extern const rct_track_coordinates TrackCoordinates[256]; @@ -40,5 +41,17 @@ typedef struct { extern const track_curve_chain gTrackCurveChain[256]; extern const track_curve_chain gFlatRideTrackCurveChain[256]; -extern const uint32 RideTypeTrackPaintFunctions[91]; +extern const TRACK_PAINT_FUNCTION_GETTER RideTypeTrackPaintFunctions[91]; extern const uint32 RideTypeTrackPaintFunctionsOld[91]; + +typedef struct { + bool starts_diagonal; + uint8 slope_start; + uint8 bank_start; + uint8 track_curve; + uint8 slope_end; + uint8 bank_end; + uint8 track_element; +} track_descriptor; + +extern const track_descriptor gTrackDescriptors[140]; diff --git a/src/ride/track_paint.c b/src/ride/track_paint.c index 44d14d0a8d..a356391eb1 100644 --- a/src/ride/track_paint.c +++ b/src/ride/track_paint.c @@ -18,171 +18,34 @@ * along with this program. If not, see . *****************************************************************************/ - #include "../addresses.h" #include "../config.h" #include "../drawing/drawing.h" +#include "../drawing/supports.h" +#include "../interface/viewport.h" +#include "../interface/window.h" #include "../localisation/localisation.h" -#include "ride_data.h" -#include "track_data.h" #include "../sprites.h" #include "../world/map.h" #include "../world/sprite.h" -#include "../interface/viewport.h" -#include "../interface/window.h" +#include "ride_data.h" +#include "track_data.h" #include "track_paint.h" -void top_spin_paint_setup_rot_0(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement); -void top_spin_paint_setup_rot_1(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement); -void top_spin_paint_setup_rot_2(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement); -void top_spin_paint_setup_rot_3(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement); - -/* 0x0076679C */ -TRACK_PAINT_FUNCTION top_spin_base_functions[] = { - top_spin_paint_setup_rot_0, - top_spin_paint_setup_rot_1, - top_spin_paint_setup_rot_2, - top_spin_paint_setup_rot_3, -}; - -TRACK_PAINT_FUNCTION* top_spin_track_paint_functions[] = { - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - top_spin_base_functions // 123 -}; - -/* rct2: 0x0076687C */ -void top_spin_paint_tile_0(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x0076687C + */ +static void top_spin_paint_tile_0(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22137 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); RCT2_GLOBAL(0x141E9B4, uint16) = 0xFFFF; RCT2_GLOBAL(0x141E9B8, uint16) = 0xFFFF; @@ -195,29 +58,31 @@ void top_spin_paint_tile_0(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 112; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2:0x007667AE */ -rct_xy16 loc_7667AE[] = { +/* rct2: 0x007667AE */ +static rct_xy16 loc_7667AE[] = { { .x = 0, .y = -1 }, { .x = 1, .y = 0 }, { .x = 0, .y = 1}, { .x = -1, .y = 0 }, }; -/* rct2:0x007667AC */ -rct_xy16 loc_7667AC[] = { +/* rct2: 0x007667AC */ +static rct_xy16 loc_7667AC[] = { { .x = -1, .y = 0 }, { .x = 0, .y = -1 }, { .x = 1, .y = 0 }, { .x = 0, .y = 1 }, }; -/* rct2: 0x0142811C +/** + * + * rct2: 0x0142811C * Can be calculated as Rounddown(34*sin(x)+0.5) * where x is in 7.5 deg segments. */ @@ -228,16 +93,19 @@ static sint8 TopSpinSeatPositionOffset[] = { 0 }; -/* rct2: 0x0076750D */ -void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x0076750D + */ +static void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction, int height, rct_map_element* mapElement) { // As we will be drawing a vehicle we need to backup the mapElement that // is assigned to the drawings. rct_map_element* curMapElement = RCT2_GLOBAL(0x009DE578, rct_map_element*); height += 3; - rct_ride* ride = GET_RIDE(rideIndex); - rct_ride_type* rideEntry = GET_RIDE_ENTRY(ride->subtype); + rct_ride* ride = get_ride(rideIndex); + rct_ride_entry* rideEntry = get_ride_entry(ride->subtype); rct_vehicle* vehicle = NULL; uint8 seatRotation = 0; @@ -250,8 +118,8 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8) = VIEWPORT_INTERACTION_ITEM_SPRITE; RCT2_GLOBAL(0x009DE578, rct_vehicle*) = vehicle; - armRotation = vehicle->var_1F; - seatRotation = vehicle->var_20; + armRotation = vehicle->vehicle_sprite_type; + seatRotation = vehicle->bank_rotation; } RCT2_GLOBAL(0x009DEA52, sint16) = al + 16; @@ -276,7 +144,7 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction // Left back bottom support image_id += 572; - sub_98197C(al, 90, image_id, cl, height, lengthY, lengthX, get_current_rotation()); + sub_98197C(image_id, al, cl, lengthX, lengthY, 90, height, get_current_rotation()); image_id = RCT2_GLOBAL(0x00F441A0, uint32); if (image_id == 0x20000000) { @@ -299,20 +167,20 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction image_id += 380; sub_98199C( - al, - 90, image_id, + al, cl, - height, - lengthY, lengthX, + lengthY, + 90, + height, 0); uint32 seatImageId; - if (vehicle != NULL && vehicle->var_B5 >= 64) { + if (vehicle != NULL && vehicle->restraints_position >= 64) { // Open Restraints - image_id = (vehicle->var_B5 - 64) >> 6; + image_id = (vehicle->restraints_position - 64) >> 6; image_id += direction * 3; image_id += rideEntry->vehicles[0].base_image_id; image_id += 64; @@ -363,13 +231,13 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction RCT2_GLOBAL(0x014280BA, sint16) = seatCoords.z; sub_98199C( - (sint8)seatCoords.x, - 90, image_id, + (sint8)seatCoords.x, (sint8)seatCoords.y, - seatCoords.z, - lengthY, lengthX, + lengthY, + 90, + seatCoords.z, 0); rct_drawpixelinfo* dpi = RCT2_GLOBAL(0x140E9A8, rct_drawpixelinfo*); @@ -381,7 +249,7 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction image_id += 0xA0000000; image_id += 76; - sub_98199C((sint8)seatCoords.x, 90, image_id, (sint8)seatCoords.y, seatCoords.z, lengthY, lengthX, 0); + sub_98199C(image_id, (sint8)seatCoords.x, (sint8)seatCoords.y, lengthX, lengthY, 90, seatCoords.z, 0); if (vehicle->num_peeps > 2) { image_id = @@ -391,7 +259,7 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction image_id += 0xA0000000; image_id += 152; - sub_98199C((sint8)seatCoords.x, 90, image_id, (sint8)seatCoords.y, seatCoords.z, lengthY, lengthX, 0); + sub_98199C(image_id, (sint8)seatCoords.x, (sint8)seatCoords.y, lengthX, lengthY, 90, seatCoords.z, 0); } if (vehicle->num_peeps > 4) { @@ -402,7 +270,7 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction image_id += 0xA0000000; image_id += 228; - sub_98199C((sint8)seatCoords.x, 90, image_id, (sint8)seatCoords.y, seatCoords.z, lengthY, lengthX, 0); + sub_98199C(image_id, (sint8)seatCoords.x, (sint8)seatCoords.y, lengthX, lengthY, 90, seatCoords.z, 0); } if (vehicle->num_peeps > 6) { @@ -413,7 +281,7 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction image_id += 0xA0000000; image_id += 304; - sub_98199C((sint8)seatCoords.x, 90, image_id, (sint8)seatCoords.y, seatCoords.z, lengthY, lengthX, 0); + sub_98199C(image_id, (sint8)seatCoords.x, (sint8)seatCoords.y, lengthX, lengthY, 90, seatCoords.z, 0); } } @@ -432,13 +300,13 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction image_id += 476; sub_98199C( - al, - 90, image_id, + al, cl, - height, - lengthY, lengthX, + lengthY, + 90, + height, 0); image_id = RCT2_GLOBAL(0x00F441A0, uint32); @@ -455,30 +323,33 @@ void top_spin_paint_vehicle(sint8 al, sint8 cl, uint8 rideIndex, uint8 direction image_id += 573; sub_98199C( - al, - 90, image_id, + al, cl, - height, - lengthY, lengthX, + lengthY, + 90, + height, 0); RCT2_GLOBAL(0x009DE578, rct_map_element*) = curMapElement; RCT2_GLOBAL(RCT2_ADDRESS_PAINT_SETUP_CURRENT_TYPE, uint8) = VIEWPORT_INTERACTION_ITEM_RIDE; } -/* rct2: 0x0076693F */ -void top_spin_paint_tile_1(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x0076693F + */ +static void top_spin_paint_tile_1(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22137 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint16 entranceLoc = @@ -486,7 +357,7 @@ void top_spin_paint_tile_1(uint8 rideIndex, uint8 trackSequence, uint8 direction (((y / 32) + loc_7667AE[get_current_rotation()].y) << 8); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride->entrances[entranceId] != entranceLoc && ride->exits[entranceId] != entranceLoc) { @@ -495,7 +366,7 @@ void top_spin_paint_tile_1(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98199C(0, 7, image_id, 0, height, 1, 32, 0); + sub_98199C(image_id, 0, 0, 32, 1, 7, height, 0); } entranceLoc = @@ -509,7 +380,7 @@ void top_spin_paint_tile_1(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98199C(0, 7, image_id, 0, height, 32, 1, 0); + sub_98199C(image_id, 0, 0, 1, 32, 7, height, 0); } top_spin_paint_vehicle(32, 32, rideIndex, direction, height, mapElement); @@ -528,23 +399,26 @@ void top_spin_paint_tile_1(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 110; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x00767033 */ -void top_spin_paint_tile_2(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x00767033 + */ +static void top_spin_paint_tile_2(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22137 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint16 entranceLoc = @@ -552,7 +426,7 @@ void top_spin_paint_tile_2(uint8 rideIndex, uint8 trackSequence, uint8 direction (((y / 32) + loc_7667AC[get_current_rotation()].y) << 8); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride->entrances[entranceId] != entranceLoc && ride->exits[entranceId] != entranceLoc) { @@ -561,7 +435,7 @@ void top_spin_paint_tile_2(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98199C(0, 7, image_id, 0, height, 32, 1, 0); + sub_98199C(image_id, 0, 0, 1, 32, 7, height, 0); } RCT2_GLOBAL(0x141E9B4, uint16) = 0xFFFF; @@ -575,23 +449,26 @@ void top_spin_paint_tile_2(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 110; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x0076718D */ -void top_spin_paint_tile_4(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x0076718D + */ +static void top_spin_paint_tile_4(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22137 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint16 entranceLoc = @@ -599,7 +476,7 @@ void top_spin_paint_tile_4(uint8 rideIndex, uint8 trackSequence, uint8 direction (((y / 32) + loc_7667AE[get_current_rotation()].y) << 8); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride->entrances[entranceId] != entranceLoc && ride->exits[entranceId] != entranceLoc) { @@ -608,7 +485,7 @@ void top_spin_paint_tile_4(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98199C(0, 7, image_id, 0, height, 1, 32, 0); + sub_98199C(image_id, 0, 0, 32, 1, 7, height, 0); } RCT2_GLOBAL(0x141E9B4, uint16) = 0xFFFF; @@ -622,23 +499,26 @@ void top_spin_paint_tile_4(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 110; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x00766B4C */ -void top_spin_paint_tile_3(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x00766B4C + */ +static void top_spin_paint_tile_3(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22136 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint16 entranceLoc = @@ -646,7 +526,7 @@ void top_spin_paint_tile_3(uint8 rideIndex, uint8 trackSequence, uint8 direction (((y / 32) + loc_7667AC[get_current_rotation()].y) << 8); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride->entrances[entranceId] != entranceLoc && ride->exits[entranceId] != entranceLoc) { @@ -655,7 +535,7 @@ void top_spin_paint_tile_3(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98199C(0, 7, image_id, 0, height, 32, 1, 0); + sub_98199C(image_id, 0, 0, 1, 32, 7, height, 0); } entranceLoc = @@ -669,7 +549,7 @@ void top_spin_paint_tile_3(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 30; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98197C(0, 7, image_id, 0, height, 1, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 1, 7, height, get_current_rotation()); } top_spin_paint_vehicle(32, -32, rideIndex, direction, height, mapElement); @@ -688,27 +568,30 @@ void top_spin_paint_tile_3(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D6, uint16) = 32; height += 110; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x007672E7 */ -void top_spin_paint_tile_5(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x007672E7 + */ +static void top_spin_paint_tile_5(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22136 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); uint16 entranceLoc = ((x / 32) + loc_7667AC[(get_current_rotation() + 3) & 3].x) | @@ -720,7 +603,7 @@ void top_spin_paint_tile_5(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 30; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98197C(0, 7, image_id, 0, height, 1, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 1, 7, height, get_current_rotation()); } top_spin_paint_vehicle(0, -32, rideIndex, direction, height, mapElement); @@ -736,23 +619,26 @@ void top_spin_paint_tile_5(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 112; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x00766D09 */ -void top_spin_paint_tile_6(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x00766D09 + */ +static void top_spin_paint_tile_6(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22135 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint16 entranceLoc = @@ -760,7 +646,7 @@ void top_spin_paint_tile_6(uint8 rideIndex, uint8 trackSequence, uint8 direction (((y / 32) + loc_7667AE[get_current_rotation()].y) << 8); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride->entrances[entranceId] != entranceLoc && ride->exits[entranceId] != entranceLoc) { @@ -769,7 +655,7 @@ void top_spin_paint_tile_6(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98199C(0, 7, image_id, 0, height, 1, 32, 0); + sub_98199C(image_id, 0, 0, 32, 1, 7, height, 0); } entranceLoc = @@ -783,7 +669,7 @@ void top_spin_paint_tile_6(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98197C(0, 7, image_id, 0, height, 32, 1, get_current_rotation()); + sub_98197C(image_id, 0, 0, 1, 32, 7, height, get_current_rotation()); } top_spin_paint_vehicle(-32, 32, rideIndex, direction, height, mapElement); @@ -798,31 +684,34 @@ void top_spin_paint_tile_6(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9CA, uint16) = 32; RCT2_GLOBAL(0x141E9CC, uint16) = 0xFFFF; RCT2_GLOBAL(0x141E9D0, uint16) = height + 2; - RCT2_GLOBAL(0x141E9D0, uint16) = 32; + RCT2_GLOBAL(0x141E9D2, uint16) = 32; RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 110; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x00766EC6 */ -void top_spin_paint_tile_7(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x00766EC6 + */ +static void top_spin_paint_tile_7(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22134 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); uint16 entranceLoc = ((x / 32) + loc_7667AE[(get_current_rotation() + 1) & 3].x) | @@ -835,7 +724,7 @@ void top_spin_paint_tile_7(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA52, uint16) = 29; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height + 3; - sub_98197C(0, 7, image_id, 0, height, 28, 1, get_current_rotation()); + sub_98197C(image_id, 0, 0, 1, 28, 7, height, get_current_rotation()); } entranceLoc = @@ -849,7 +738,7 @@ void top_spin_paint_tile_7(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 29; RCT2_GLOBAL(0x009DEA56, uint16) = height + 3; - sub_98197C(0, 7, image_id, 0, height, 1, 28, get_current_rotation()); + sub_98197C(image_id, 0, 0, 28, 1, 7, height, get_current_rotation()); } top_spin_paint_vehicle(-32, -32, rideIndex, direction, height, mapElement); @@ -868,27 +757,30 @@ void top_spin_paint_tile_7(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D6, uint16) = 32; height += 110; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x007673FA */ -void top_spin_paint_tile_8(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +/** + * + * rct2: 0x007673FA + */ +static void top_spin_paint_tile_8(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { uint32 image_id = RCT2_GLOBAL(0x00F441A0, uint32); - sub_6629BC(height, 0, image_id, direction & 1); + wooden_a_supports_paint_setup(direction & 1, 0, height, image_id, NULL); image_id = 22135 | RCT2_GLOBAL(0x00F44198, uint32); RCT2_GLOBAL(0x009DEA52, uint16) = 0; RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height; - sub_98197C(0, 1, image_id, 0, height, 32, 32, get_current_rotation()); + sub_98197C(image_id, 0, 0, 32, 32, 1, height, get_current_rotation()); sint16 x = RCT2_GLOBAL(0x009DE56A, sint16), y = RCT2_GLOBAL(0x009DE56E, sint16); uint8 entranceId = (mapElement->properties.track.sequence & 0x70) >> 4; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); uint16 entranceLoc = ((x / 32) + loc_7667AE[(get_current_rotation() + 1) & 3].x) | @@ -901,7 +793,7 @@ void top_spin_paint_tile_8(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x009DEA54, uint16) = 0; RCT2_GLOBAL(0x009DEA56, uint16) = height + 2; - sub_98197C(0, 7, image_id, 0, height, 32, 1, get_current_rotation()); + sub_98197C(image_id, 0, 0, 1, 32, 7, height, get_current_rotation()); } top_spin_paint_vehicle(-32, 0, rideIndex, direction, height, mapElement); @@ -916,15 +808,17 @@ void top_spin_paint_tile_8(uint8 rideIndex, uint8 trackSequence, uint8 direction RCT2_GLOBAL(0x141E9D4, uint16) = 0xFFFF; height += 112; - if (RCT2_GLOBAL(0x141E9D8, sint16) < height) { - RCT2_GLOBAL(0x141E9D8, sint16) = height; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height; RCT2_GLOBAL(0x141E9DA, uint8) = 32; } } -/* rct2: 0x007667BC +/** + * + * rct2: 0x007667BC */ -void top_spin_paint_setup_rot_0(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +static void top_spin_paint_setup_rot_0(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { switch (trackSequence) { case 0: @@ -958,9 +852,11 @@ void top_spin_paint_setup_rot_0(uint8 rideIndex, uint8 trackSequence, uint8 dire return; } -/* rct2: 0x007667EC +/** + * + * rct2: 0x007667EC */ -void top_spin_paint_setup_rot_1(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +static void top_spin_paint_setup_rot_1(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { switch (trackSequence) { case 0: @@ -994,9 +890,11 @@ void top_spin_paint_setup_rot_1(uint8 rideIndex, uint8 trackSequence, uint8 dire return; } -/* rct2: 0x0076681C +/** + * + * rct2: 0x0076681C */ -void top_spin_paint_setup_rot_2(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +static void top_spin_paint_setup_rot_2(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { switch (trackSequence) { case 0: @@ -1030,9 +928,11 @@ void top_spin_paint_setup_rot_2(uint8 rideIndex, uint8 trackSequence, uint8 dire return; } -/* rct2: 0x0076684C +/** + * + * rct2: 0x0076684C */ -void top_spin_paint_setup_rot_3(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { +static void top_spin_paint_setup_rot_3(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { switch (trackSequence) { case 0: @@ -1066,141 +966,21 @@ void top_spin_paint_setup_rot_3(uint8 rideIndex, uint8 trackSequence, uint8 dire return; } -void shop_paint_setup(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement); - -/* 0x00761358 */ -TRACK_PAINT_FUNCTION shop_base_functions[] = { - shop_paint_setup, - shop_paint_setup, - shop_paint_setup, - shop_paint_setup, -}; - -/* 0x00761160 */ -TRACK_PAINT_FUNCTION* shop_track_paint_functions[] = { - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - shop_base_functions, // 118 - NULL, - NULL, - shop_base_functions // 121 -}; +/* 0x0076659C */ +TRACK_PAINT_FUNCTION get_track_paint_function_topspin(int trackType, int direction) +{ + switch (trackType) { + case 123: + switch (direction) { + case 0: return top_spin_paint_setup_rot_0; + case 1: return top_spin_paint_setup_rot_1; + case 2: return top_spin_paint_setup_rot_2; + case 3: return top_spin_paint_setup_rot_3; + } + break; + } + return NULL; +} /** * @@ -1209,9 +989,9 @@ TRACK_PAINT_FUNCTION* shop_track_paint_functions[] = { * rct2: 0x0076163F * rct2: 0x007617A5 */ -void shop_paint_setup(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) +static void shop_paint_setup(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) { - bool hasSupports = sub_6629BC(height, 0, RCT2_GLOBAL(0x00F441A4, uint32), direction & 1); + bool hasSupports = wooden_a_supports_paint_setup(direction & 1, 0, height, RCT2_GLOBAL(0x00F441A4, uint32), NULL); RCT2_GLOBAL(0x0141E9D0, sint16) = -1; RCT2_GLOBAL(0x0141E9C4, sint16) = -1; @@ -1223,9 +1003,9 @@ void shop_paint_setup(uint8 rideIndex, uint8 trackSequence, uint8 direction, int RCT2_GLOBAL(0x0141E9C8, sint16) = -1; RCT2_GLOBAL(0x0141E9D4, sint16) = -1; - rct_ride *ride = GET_RIDE(rideIndex); - rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride->subtype); - rct_ride_type_vehicle *firstVehicleEntry = &rideEntry->vehicles[0]; + rct_ride *ride = get_ride(rideIndex); + rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); + rct_ride_entry_vehicle *firstVehicleEntry = &rideEntry->vehicles[0]; uint32 imageId = RCT2_GLOBAL(0x00F44198, uint32); if (imageId & 0x80000000) { @@ -1243,22 +1023,119 @@ void shop_paint_setup(uint8 rideIndex, uint8 trackSequence, uint8 direction, int RCT2_GLOBAL(0x009DEA52, uint16) = 2; RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, sint16) = height16; - sub_98197C(0, 45, foundationImageId, 0, height, 28, 28, rotation); + sub_98197C(foundationImageId, 0, 0, 28, 28, 45, height, rotation); RCT2_GLOBAL(0x009DEA52, uint16) = 2; RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, sint16) = height16; - sub_98199C(0, 45, imageId, 0, height, 28, 28, rotation); + sub_98199C(imageId, 0, 0, 28, 28, 45, height, rotation); } else { RCT2_GLOBAL(0x009DEA52, uint16) = 2; RCT2_GLOBAL(0x009DEA54, uint16) = 2; RCT2_GLOBAL(0x009DEA56, sint16) = height16; - sub_98197C(0, 45, imageId, 0, height, 28, 28, rotation); + sub_98197C(imageId, 0, 0, 28, 28, 45, height, rotation); } height16 += 48; - if (RCT2_GLOBAL(0x00141E9D8, sint16) < height16) { - RCT2_GLOBAL(0x00141E9D8, sint16) = height16; - RCT2_GLOBAL(0x00141E9DA, sint16) = 32; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height16) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height16; + RCT2_GLOBAL(0x00141E9DA, uint8) = 32; } } + +/* 0x00761160 */ +TRACK_PAINT_FUNCTION get_track_paint_function_shop(int trackType, int direction) +{ + switch (trackType) { + case 118: + case 121: return shop_paint_setup; + } + return NULL; +} + +/** + * + * rct2: 0x00763234 + * rct2: 0x0076338C + * rct2: 0x00762F50 + * rct2: 0x007630DE + */ +static void facility_paint_setup(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement) +{ + bool hasSupports = wooden_a_supports_paint_setup(direction & 1, 0, height, RCT2_GLOBAL(0x00F441A4, uint32), NULL); + + RCT2_GLOBAL(0x0141E9D0, sint16) = -1; + RCT2_GLOBAL(0x0141E9C4, sint16) = -1; + RCT2_GLOBAL(0x0141E9CC, sint16) = -1; + RCT2_GLOBAL(0x0141E9B8, sint16) = -1; + RCT2_GLOBAL(0x0141E9BC, sint16) = -1; + RCT2_GLOBAL(0x0141E9B4, sint16) = -1; + RCT2_GLOBAL(0x0141E9C0, sint16) = -1; + RCT2_GLOBAL(0x0141E9C8, sint16) = -1; + RCT2_GLOBAL(0x0141E9D4, sint16) = -1; + + rct_ride *ride = get_ride(rideIndex); + rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); + rct_ride_entry_vehicle *firstVehicleEntry = &rideEntry->vehicles[0]; + + uint32 imageId = RCT2_GLOBAL(0x00F44198, uint32); + imageId |= firstVehicleEntry->base_image_id; + imageId += (direction + 2) & 3; + + sint16 height16 = (sint16)height; + int rotation = get_current_rotation(); + int lengthX = (direction & 1) == 0 ? 28 : 2; + int lengthY = (direction & 1) == 0 ? 2 : 28; + if (hasSupports) { + uint32 foundationImageId = RCT2_GLOBAL(0x00F441A4, uint32); + foundationImageId |= 3395; + + RCT2_GLOBAL(0x009DEA52, uint16) = direction == 3 ? 28 : 2; + RCT2_GLOBAL(0x009DEA54, uint16) = direction == 0 ? 28 : 2; + RCT2_GLOBAL(0x009DEA56, sint16) = height16; + sub_98197C(foundationImageId, 0, 0, lengthX, lengthY, 29, height, rotation); + + // Door image or base + RCT2_GLOBAL(0x009DEA52, uint16) = direction == 3 ? 28 : 2; + RCT2_GLOBAL(0x009DEA54, uint16) = direction == 0 ? 28 : 2; + RCT2_GLOBAL(0x009DEA56, sint16) = height16; + sub_98199C(imageId, 0, 0, lengthX, lengthY, 29, height, rotation); + } else { + // Door image or base + RCT2_GLOBAL(0x009DEA52, uint16) = direction == 3 ? 28 : 2; + RCT2_GLOBAL(0x009DEA54, uint16) = direction == 0 ? 28 : 2; + RCT2_GLOBAL(0x009DEA56, sint16) = height16; + + sub_98197C(imageId, 0, 0, lengthX, lengthY, 29, height, rotation); + } + + // Base image if door was drawn + if (direction == 1) { + imageId += 2; + RCT2_GLOBAL(0x009DEA52, uint16) = 28; + RCT2_GLOBAL(0x009DEA54, uint16) = 2; + RCT2_GLOBAL(0x009DEA56, sint16) = height16; + sub_98197C(imageId, 0, 0, 2, 28, 29, height, rotation); + } else if (direction == 2) { + imageId += 4; + RCT2_GLOBAL(0x009DEA52, uint16) = 2; + RCT2_GLOBAL(0x009DEA54, uint16) = 28; + RCT2_GLOBAL(0x009DEA56, sint16) = height16; + sub_98197C(imageId, 0, 0, 28, 2, 29, height, rotation); + } + + height16 += 32; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) < height16) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PAINT_TILE_MAX_HEIGHT, sint16) = height16; + RCT2_GLOBAL(0x00141E9DA, uint8) = 32; + } +} + +/* 0x00762D44 */ +TRACK_PAINT_FUNCTION get_track_paint_function_facility(int trackType, int direction) +{ + switch (trackType) { + case 118: return facility_paint_setup; + } + return NULL; +} diff --git a/src/ride/track_paint.h b/src/ride/track_paint.h index cea5f99250..410a85ce1d 100644 --- a/src/ride/track_paint.h +++ b/src/ride/track_paint.h @@ -4,8 +4,10 @@ #include "../common.h" typedef void (*TRACK_PAINT_FUNCTION)(uint8 rideIndex, uint8 trackSequence, uint8 direction, int height, rct_map_element* mapElement); +typedef TRACK_PAINT_FUNCTION (*TRACK_PAINT_FUNCTION_GETTER)(int trackType, int direction); -extern TRACK_PAINT_FUNCTION* top_spin_track_paint_functions[]; -extern TRACK_PAINT_FUNCTION* shop_track_paint_functions[]; +TRACK_PAINT_FUNCTION get_track_paint_function_topspin(int trackType, int direction); +TRACK_PAINT_FUNCTION get_track_paint_function_shop(int trackType, int direction); +TRACK_PAINT_FUNCTION get_track_paint_function_facility(int trackType, int direction); -#endif \ No newline at end of file +#endif diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index 4f66083e0b..90188e8542 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -19,24 +19,153 @@ *****************************************************************************/ #include "../addresses.h" +#include "../game.h" #include "../audio/audio.h" #include "../audio/mixer.h" #include "../config.h" #include "../hook.h" #include "../interface/viewport.h" +#include "../localisation/localisation.h" #include "../openrct2.h" +#include "../scenario.h" +#include "../world/map_animation.h" #include "../world/sprite.h" +#include "../world/scenery.h" +#include "cable_lift.h" +#include "track.h" #include "ride.h" #include "ride_data.h" #include "track.h" +#include "track_data.h" #include "vehicle.h" static void vehicle_update(rct_vehicle *vehicle); +static void vehicle_update_showing_film(rct_vehicle *vehicle); +static void vehicle_update_doing_circus_show(rct_vehicle *vehicle); +static void vehicle_update_moving_to_end_of_station(rct_vehicle *vehicle); +static void vehicle_update_waiting_for_passengers(rct_vehicle* vehicle); +static void vehicle_update_waiting_to_depart(rct_vehicle* vehicle); +static void vehicle_update_departing(rct_vehicle* vehicle); +static void vehicle_finish_departing(rct_vehicle* vehicle); +static void vehicle_update_travelling(rct_vehicle* vehicle); +static void vehicle_update_ferris_wheel_rotating(rct_vehicle* vehicle); +static void vehicle_update_rotating(rct_vehicle* vehicle); +static void vehicle_update_space_rings_operating(rct_vehicle* vehicle); +static void vehicle_update_haunted_house_operating(rct_vehicle* vehicle); +static void vehicle_update_crooked_house_operating(rct_vehicle* vehicle); +static void vehicle_update_bumpcar_mode(rct_vehicle* vehicle); +static void vehicle_update_swinging(rct_vehicle* vehicle); +static void vehicle_update_simulator_operating(rct_vehicle* vehicle); +static void vehicle_update_top_spin_operating(rct_vehicle* vehicle); +static void vehicle_update_crash(rct_vehicle *vehicle); +static void vehicle_update_travelling_boat(rct_vehicle* vehicle); +static void vehicle_update_motion_boat_hire(rct_vehicle *vehicle); +static void sub_6DA280(rct_vehicle *vehicle); +static bool vehicle_is_boat_on_water(rct_vehicle *vehicle, int x, int y); +static void vehicle_update_arriving(rct_vehicle* vehicle); +static void vehicle_update_unloading_passengers(rct_vehicle* vehicle); +static void vehicle_update_waiting_for_cable_lift(rct_vehicle *vehicle); +static void vehicle_update_travelling_cable_lift(rct_vehicle* vehicle); +static void vehicle_update_crash_setup(rct_vehicle* vehicle); +static void vehicle_update_collision_setup(rct_vehicle* vehicle); +static int vehicle_update_motion_bumper_car(rct_vehicle* vehicle); +static void sub_6D63D4(rct_vehicle *vehicle); +static bool vehicle_update_motion_collision_detection(rct_vehicle *vehicle, sint16 x, sint16 y, sint16 z, uint16 *otherVehicleIndex); +static void vehicle_update_sound(rct_vehicle *vehicle); +static int vehicle_update_scream_sound(rct_vehicle *vehicle); + +static void vehicle_kill_all_passengers(rct_vehicle* vehicle); +static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle); + +#define NO_SCREAM 254 + +rct_xyz16 *unk_F64E20 = (rct_xyz16*)0x00F64E20; + +const uint8 byte_9A3A14[] = { SOUND_SCREAM_8, SOUND_SCREAM_1 }; +const uint8 byte_9A3A16[] = { SOUND_SCREAM_1, SOUND_SCREAM_6 }; +const uint8 byte_9A3A18[] = { + SOUND_SCREAM_3, SOUND_SCREAM_1, SOUND_SCREAM_5, SOUND_SCREAM_6, + SOUND_SCREAM_7, SOUND_SCREAM_2, SOUND_SCREAM_4 +}; + +const rct_vehicle_info *vehicle_get_move_info(int cd, int typeAndDirection, int offset) +{ + const rct_vehicle_info **infoListList = RCT2_ADDRESS(0x008B8F30, const rct_vehicle_info**)[cd]; + const rct_vehicle_info *infoList = infoListList[typeAndDirection]; + return &infoList[offset]; +} + +const uint8 DoorOpenSoundIds[] = { + SOUND_DOOR_OPEN, + SOUND_62 +}; + +const uint8 DoorCloseSoundIds[] = { + SOUND_DOOR_CLOSE, + SOUND_62 +}; + +static const struct { sint8 x, y, z; } SteamParticleOffsets[] = { + { -11, 0, 22 }, + { -10, 4, 22 }, + { -8, 8, 22 }, + { -4, 10, 22 }, + { 0, 11, 22 }, + { 4, 10, 22 }, + { 8, 8, 22 }, + { 10, 4, 22 }, + { 11, 0, 22 }, + { 10, -4, 22 }, + { 8, -8, 22 }, + { 4, -10, 22 }, + { 0, -11, 22 }, + { -4, -10, 22 }, + { -8, -8, 22 }, + { -10, -4, 22 }, + { -9, 0, 27 }, + { -8, 4, 27 }, + { -6, 6, 27 }, + { -4, 8, 27 }, + { 0, 9, 27 }, + { 4, 8, 27 }, + { 6, 6, 27 }, + { 8, 4, 27 }, + { 9, 0, 27 }, + { 8, -4, 27 }, + { 6, -6, 27 }, + { 4, -8, 27 }, + { 0, -9, 27 }, + { -4, -8, 27 }, + { -6, -6, 27 }, + { -8, -4, 27 }, + { -13, 0, 18 }, + { -12, 4, 17 }, + { -9, 9, 17 }, + { -4, 8, 17 }, + { 0, 13, 18 }, + { 4, 8, 17 }, + { 6, 6, 17 }, + { 8, 4, 17 }, + { 13, 0, 18 }, + { 8, -4, 17 }, + { 6, -6, 17 }, + { 4, -8, 17 }, + { 0, -13, 18 }, + { -4, -8, 17 }, + { -6, -6, 17 }, + { -8, -4, 17 } +}; + +void vehicle_invalidate(rct_vehicle *vehicle) +{ + invalidate_sprite_2((rct_sprite*)vehicle); +} + /** -* -* rct2: 0x006BB9FF -*/ + * + * rct2: 0x006BB9FF + */ void vehicle_update_sound_params(rct_vehicle* vehicle) { if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) || RCT2_GLOBAL(0x0141F570, uint8) == 6)) { @@ -97,7 +226,7 @@ void vehicle_update_sound_params(rct_vehicle* vehicle) sint32 v19 = vehicle->velocity; - rct_ride_type* ride_type = GET_RIDE_ENTRY(vehicle->ride_subtype); + rct_ride_entry* ride_type = get_ride_entry(vehicle->ride_subtype); uint8 test = ride_type->vehicles[vehicle->vehicle_type].var_5A; if (test & 1) { @@ -131,9 +260,9 @@ void vehicle_update_sound_params(rct_vehicle* vehicle) } /** -* -* rct2: 0x006BC2F3 -*/ + * + * rct2: 0x006BC2F3 + */ int sub_6BC2F3(rct_vehicle* vehicle) { int result = 0; @@ -159,12 +288,12 @@ int sub_6BC2F3(rct_vehicle* vehicle) } /** -* -* rct2: 0x006BBC6B -*/ + * + * rct2: 0x006BBC6B + */ void vehicle_sounds_update() { - if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1 && !gGameSoundsOff && gConfigSound.sound && !gOpenRCT2Headless) { + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1 && !gGameSoundsOff && gConfigSound.sound_enabled && !gOpenRCT2Headless) { RCT2_GLOBAL(0x00F438A4, rct_viewport*) = (rct_viewport*)-1; rct_viewport* viewport = (rct_viewport*)-1; rct_window* window = RCT2_GLOBAL(RCT2_ADDRESS_NEW_WINDOW_PTR, rct_window*); @@ -449,13 +578,3834 @@ void vehicle_update_all() } } +/** + * + * rct2: 0x006D6956 + * @returns 0 when all closed + */ +static int vehicle_close_restraints(rct_vehicle* vehicle){ + rct_ride* ride = get_ride(vehicle->ride); + int ebp = 0; + uint16 vehicle_id = vehicle->sprite_index; + + do { + vehicle = GET_VEHICLE(vehicle_id); + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_BROKEN_CAR && + vehicle->restraints_position != 0 && + ( + ride->breakdown_reason_pending == BREAKDOWN_RESTRAINTS_STUCK_OPEN || + ride->breakdown_reason_pending == BREAKDOWN_DOORS_STUCK_OPEN) + ){ + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)){ + + ride->lifecycle_flags |= RIDE_LIFECYCLE_BROKEN_DOWN; + + ride_breakdown_add_news_item(vehicle->ride); + + ride->window_invalidate_flags |= + RIDE_INVALIDATE_RIDE_MAIN | + RIDE_INVALIDATE_RIDE_LIST | + RIDE_INVALIDATE_RIDE_MAINTENANCE; + + ride->mechanic_status = RIDE_MECHANIC_STATUS_CALLING; + + rct_vehicle* broken_vehicle = GET_VEHICLE(ride->vehicles[ride->broken_vehicle]); + ride->inspection_station = broken_vehicle->current_station; + + ride->breakdown_reason = ride->breakdown_reason_pending; + } + } + else{ + if (vehicle->restraints_position - 20 < 0){ + vehicle->restraints_position = 0; + continue; + } + vehicle->restraints_position -= 20; + } + vehicle_invalidate(vehicle); + ebp++; + } while ((vehicle_id = vehicle->next_vehicle_on_train) != 0xFFFF); + + return ebp; +} + +/** + * + * rct2: 0x006D6A2C + * @returns 0 when all open + */ +static int vehicle_open_restraints(rct_vehicle* vehicle){ + int ebp = 0; + uint16 vehicle_id = vehicle->sprite_index; + + do { + vehicle = GET_VEHICLE(vehicle_id); + + vehicle->swinging_car_var_0 = 0; + vehicle->var_4E = 0; + vehicle->var_4A = 0; + + rct_ride* ride = get_ride(vehicle->ride); + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SPINNING) { + if (abs(vehicle->var_B6) <= 700 && + !(vehicle->var_BA & 0x30) && + ( + !(vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_14) || + !(vehicle->var_BA & 0xF8)) + ){ + vehicle->var_B6 = 0; + } + else { + ebp++; + + if (abs(vehicle->var_B6) < 600) { + vehicle->var_B6 = 600; + } + sint16 value = vehicle->var_B6 / 256; + vehicle->var_BA += value; + vehicle->var_B6 -= value; + + vehicle_invalidate(vehicle); + continue; + } + } + if (vehicleEntry->var_11 == 6 && + vehicle->var_C5 != 0){ + + if (vehicle->var_C8 + 0x3333 < 0xFFFF){ + vehicle->var_C8 = vehicle->var_C8 + 0x3333 - 0xFFFF; + vehicle->var_C5++; + vehicle->var_C5 &= 7; + vehicle_invalidate(vehicle); + } + else{ + vehicle->var_C8 += 0x3333; + } + ebp++; + continue; + } + + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_BROKEN_CAR && + vehicle->restraints_position != 0xFF && + ( + ride->breakdown_reason_pending == BREAKDOWN_RESTRAINTS_STUCK_CLOSED || + ride->breakdown_reason_pending == BREAKDOWN_DOORS_STUCK_CLOSED) + ){ + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)){ + + ride->lifecycle_flags |= RIDE_LIFECYCLE_BROKEN_DOWN; + + ride_breakdown_add_news_item(vehicle->ride); + + ride->window_invalidate_flags |= + RIDE_INVALIDATE_RIDE_MAIN | + RIDE_INVALIDATE_RIDE_LIST | + RIDE_INVALIDATE_RIDE_MAINTENANCE; + + ride->mechanic_status = RIDE_MECHANIC_STATUS_CALLING; + + rct_vehicle* broken_vehicle = GET_VEHICLE(ride->vehicles[ride->broken_vehicle]); + ride->inspection_station = broken_vehicle->current_station; + + ride->breakdown_reason = ride->breakdown_reason_pending; + } + } + else{ + if (vehicle->restraints_position + 20 > 0xFF){ + vehicle->restraints_position = 255; + continue; + } + vehicle->restraints_position += 20; + } + vehicle_invalidate(vehicle); + ebp++; + } while ((vehicle_id = vehicle->next_vehicle_on_train) != 0xFFFF); + + return ebp; +} + +/** + * + * rct2: 0x006D6D1F + */ +static void vehicle_update_measurements(rct_vehicle *vehicle) +{ + rct_ride *ride; + + ride = get_ride(vehicle->ride); + + if (vehicle->status == VEHICLE_STATUS_TRAVELLING_BOAT){ + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + ride->lifecycle_flags |= RIDE_LIFECYCLE_NO_RAW_STATS; + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_TEST_IN_PROGRESS; + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_TESTING; + window_invalidate_by_number(WC_RIDE, vehicle->ride); + return; + } + + uint8 stationId = ride->current_test_station; + if (ride->entrances[stationId] != 0xFFFF){ + uint8 test_segment = ride->current_test_segment; + + ride->average_speed_test_timeout++; + if (ride->average_speed_test_timeout >= 32)ride->average_speed_test_timeout = 0; + + sint32 velocity = abs(vehicle->velocity); + if (velocity > ride->max_speed){ + ride->max_speed = velocity; + } + + if (ride->average_speed_test_timeout == 0 && velocity > 0x8000){ + ride->average_speed += velocity; + ride->time[test_segment]++; + } + + sint32 distance = abs(((vehicle->velocity + vehicle->acceleration) >> 10) * 42); + if (vehicle->var_CE == 0){ + ride->length[test_segment] += distance; + } + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES)){ + int vertical_g, lateral_g; + vehicle_get_g_forces(vehicle, &vertical_g, &lateral_g); + + vertical_g += ride->previous_vertical_g; + lateral_g += ride->previous_lateral_g; + vertical_g >>= 1; + lateral_g >>= 1; + + ride->previous_vertical_g = vertical_g; + ride->previous_lateral_g = lateral_g; + + if (vertical_g <= 0){ + ride->total_air_time++; + } + + if (vertical_g > ride->max_positive_vertical_g) + ride->max_positive_vertical_g = vertical_g; + + if (vertical_g < ride->max_negative_vertical_g) + ride->max_negative_vertical_g = vertical_g; + + lateral_g = abs(lateral_g); + + if (lateral_g > ride->max_lateral_g) + ride->max_lateral_g = lateral_g; + } + } + + // If we have already evaluated this track piece skip to next section + uint16 map_location = (vehicle->track_x / 32) | ((vehicle->track_y / 32) << 8); + if (vehicle->track_z / 8 != ride->cur_test_track_z || map_location != ride->cur_test_track_location.xy){ + ride->cur_test_track_z = vehicle->track_z / 8; + ride->cur_test_track_location.xy = map_location; + + if (ride->entrances[ride->current_test_station] == 0xFFFF) + return; + + uint16 track_elem_type = vehicle->track_type / 4; + if (track_elem_type == TRACK_ELEM_POWERED_LIFT || (vehicle->update_flags & VEHICLE_UPDATE_FLAG_0)){ + if (!(ride->testing_flags & RIDE_TESTING_POWERED_LIFT)){ + ride->testing_flags |= RIDE_TESTING_POWERED_LIFT; + if (ride->drops + 64 < 0xFF){ + ride->drops += 64; + } + } + } + else{ + ride->testing_flags &= ~RIDE_TESTING_POWERED_LIFT; + } + + if (ride->type == RIDE_TYPE_WATER_COASTER){ + if (track_elem_type >= TRACK_ELEM_FLAT_COVERED && track_elem_type <= TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED){ + ride->special_track_elements |= RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + } + } + + switch (track_elem_type) + { + case TRACK_ELEM_RAPIDS: + case TRACK_ELEM_SPINNING_TUNNEL: + ride->special_track_elements |= RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + break; + case TRACK_ELEM_WATERFALL: + case TRACK_ELEM_LOG_FLUME_REVERSER: + ride->special_track_elements |= RIDE_ELEMENT_REVERSER_OR_WATERFALL; + break; + case TRACK_ELEM_WHIRLPOOL: + ride->special_track_elements |= RIDE_ELEMENT_WHIRLPOOL; + break; + case TRACK_ELEM_WATER_SPLASH: + if (vehicle->velocity >= 0xB0000){ + ride->special_track_elements |= RIDE_ELEMENT_TUNNEL_SPLASH_OR_RAPIDS; + } + } + + // ax + uint16 track_flags = RCT2_ADDRESS(0x0099423C, uint16)[track_elem_type]; + + uint32 testing_flags = ride->testing_flags; + if (testing_flags & RIDE_TESTING_TURN_LEFT && + track_flags & TRACK_ELEM_FLAG_TURN_LEFT){ + // 0x800 as this is masked to CURRENT_TURN_COUNT_MASK + ride->turn_count_default += 0x800; + } + else if (testing_flags & RIDE_TESTING_TURN_RIGHT && + track_flags & TRACK_ELEM_FLAG_TURN_RIGHT){ + // 0x800 as this is masked to CURRENT_TURN_COUNT_MASK + ride->turn_count_default += 0x800; + } + else if (testing_flags & RIDE_TESTING_TURN_RIGHT || + testing_flags & RIDE_TESTING_TURN_LEFT){ + + ride->testing_flags &= ~( + RIDE_TESTING_TURN_LEFT | + RIDE_TESTING_TURN_RIGHT | + RIDE_TESTING_TURN_BANKED | + RIDE_TESTING_TURN_SLOPED); + + uint8 turn_type = 1; + if (!(testing_flags & RIDE_TESTING_TURN_BANKED)){ + turn_type = 2; + if (!(testing_flags & RIDE_TESTING_TURN_SLOPED)){ + turn_type = 0; + } + } + switch (ride->turn_count_default >> 11){ + case 0: + increment_turn_count_1_element(ride, turn_type); + break; + case 1: + increment_turn_count_2_elements(ride, turn_type); + break; + case 2: + increment_turn_count_3_elements(ride, turn_type); + break; + default: + increment_turn_count_4_plus_elements(ride, turn_type); + break; + } + } + else { + if (track_flags & TRACK_ELEM_FLAG_TURN_LEFT){ + ride->testing_flags |= RIDE_TESTING_TURN_LEFT; + ride->turn_count_default &= ~CURRENT_TURN_COUNT_MASK; + + if (track_flags & TRACK_ELEM_FLAG_TURN_BANKED){ + ride->testing_flags |= RIDE_TESTING_TURN_BANKED; + } + if (track_flags & TRACK_ELEM_FLAG_TURN_SLOPED){ + ride->testing_flags |= RIDE_TESTING_TURN_SLOPED; + } + } + + if (track_flags & TRACK_ELEM_FLAG_TURN_RIGHT){ + ride->testing_flags |= RIDE_TESTING_TURN_RIGHT; + ride->turn_count_default &= ~CURRENT_TURN_COUNT_MASK; + + if (track_flags & TRACK_ELEM_FLAG_TURN_BANKED){ + ride->testing_flags |= RIDE_TESTING_TURN_BANKED; + } + if (track_flags & TRACK_ELEM_FLAG_TURN_SLOPED){ + ride->testing_flags |= RIDE_TESTING_TURN_SLOPED; + } + } + } + + if (testing_flags & RIDE_TESTING_DROP_DOWN){ + if (vehicle->velocity < 0 || !(track_flags & TRACK_ELEM_FLAG_DOWN)){ + ride->testing_flags &= ~RIDE_TESTING_DROP_DOWN; + + sint16 z = vehicle->z / 8 - ride->start_drop_height; + if (z < 0){ + z = abs(z); + if (z > ride->highest_drop_height){ + ride->highest_drop_height = (uint8)z; + } + } + } + } + else if (track_flags & TRACK_ELEM_FLAG_DOWN && vehicle->velocity >= 0){ + ride->testing_flags &= ~RIDE_TESTING_DROP_UP; + ride->testing_flags |= RIDE_TESTING_DROP_DOWN; + + uint8 drops = ride->drops & 0x3F; + if (drops != 0x3F) + drops++; + ride->drops &= ~0x3F; + ride->drops |= drops; + + ride->start_drop_height = vehicle->z / 8; + testing_flags &= ~RIDE_TESTING_DROP_UP; + } + + if (testing_flags & RIDE_TESTING_DROP_UP){ + if (vehicle->velocity > 0 || !(track_flags & TRACK_ELEM_FLAG_UP)){ + ride->testing_flags &= ~RIDE_TESTING_DROP_UP; + + sint16 z = vehicle->z / 8 - ride->start_drop_height; + if (z < 0){ + z = abs(z); + if (z > ride->highest_drop_height){ + ride->highest_drop_height = (uint8)z; + } + } + } + } + else if (track_flags & TRACK_ELEM_FLAG_UP && vehicle->velocity <= 0){ + ride->testing_flags &= ~RIDE_TESTING_DROP_DOWN; + ride->testing_flags |= RIDE_TESTING_DROP_UP; + + uint8 drops = ride->drops & 0x3F; + if (drops != 0x3F) + drops++; + ride->drops &= ~0x3F; + ride->drops |= drops; + + ride->start_drop_height = vehicle->z / 8; + } + + if (track_flags & TRACK_ELEM_FLAG_INVERSION){ + uint8 inversions = ride->inversions & 0x1F; + if (inversions != 0x1F) + inversions++; + + ride->inversions &= ~0x1F; + ride->inversions |= inversions; + } + + if (track_flags & TRACK_ELEM_FLAG_HELIX){ + uint8 helixes = ride_get_helix_sections(ride); + if (helixes != 0x1F) + helixes++; + + ride->special_track_elements &= ~0x1F; + ride->special_track_elements |= helixes; + } + + } + + if (ride->entrances[ride->current_test_station] == 0xFFFF) + return; + + sint16 x, y; + x = vehicle->x; + y = vehicle->y; + + if (x == SPRITE_LOCATION_NULL){ + ride->testing_flags &= ~RIDE_TESTING_SHELTERED; + return; + } + + rct_map_element* map_element = map_get_surface_element_at(x / 32, y / 32); + if (map_element->base_height * 8 <= vehicle->z){ + + bool cover_found = false; + do{ + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) { + cover_found = true; + break; + } + + if (map_element_get_type(map_element) == MAP_ELEMENT_TYPE_PATH) { + cover_found = true; + break; + } + + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY) + continue; + + rct_scenery_entry* scenery = g_smallSceneryEntries[map_element->properties.scenery.type]; + if (scenery->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE) { + cover_found = true; + break; + } + } while (!map_element_is_last_for_tile(map_element++)); + + if (cover_found == false) { + ride->testing_flags &= ~RIDE_TESTING_SHELTERED; + return; + } + } + + if (!(ride->testing_flags & RIDE_TESTING_SHELTERED)){ + ride->testing_flags |= RIDE_TESTING_SHELTERED; + + uint8 num_sheltered_sections = ride->num_sheltered_sections & 0x1F; + if (num_sheltered_sections != 0x1F) + num_sheltered_sections++; + ride->num_sheltered_sections &= ~0x1F; + ride->num_sheltered_sections |= num_sheltered_sections; + + if (vehicle->vehicle_sprite_type != 0){ + ride->num_sheltered_sections |= (1 << 5); + } + + if (vehicle->bank_rotation != 0){ + ride->num_sheltered_sections |= (1 << 6); + } + } + + sint32 distance = ((vehicle->velocity + vehicle->acceleration) >> 10) * 42; + if (distance < 0)return; + + ride->sheltered_length += distance; +} + +static uint16 sub_6D7AC0(int currentSoundId, int currentVolume, int targetSoundId, int targetVolume) +{ + if (currentSoundId != 255) { + if (currentSoundId == targetSoundId) { + currentVolume = min(currentVolume + 15, targetVolume); + return (currentVolume << 8) | currentSoundId; + } else { + currentVolume -= 9; + if (currentVolume >= 80) + return (currentVolume << 8) | currentSoundId; + } + } + + // Begin sound at quarter volume + currentSoundId = targetSoundId; + currentVolume = targetVolume == 255 ? 255 : targetVolume / 4; + + return (currentVolume << 8) | currentSoundId; +} + /** * * rct2: 0x006D77F2 */ static void vehicle_update(rct_vehicle *vehicle) { - RCT2_CALLPROC_X(0x006D77F2, 0, 0, 0, 0, (int)vehicle, 0, 0); + rct_ride *ride; + rct_ride_entry *rideEntry; + + // The cable lift uses the ride type of NULL + if (vehicle->ride_subtype == RIDE_TYPE_NULL) { + cable_lift_update(vehicle); + return; + } + + rideEntry = get_ride_entry(vehicle->ride_subtype); + + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + ride = get_ride(vehicle->ride); + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_TESTING) + vehicle_update_measurements(vehicle); + + RCT2_GLOBAL(0x00F64E34, uint8) = 255; + if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN)) { + RCT2_GLOBAL(0x00F64E34, uint8) = ride->breakdown_reason_pending; + if ((vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3) && ride->breakdown_reason_pending == BREAKDOWN_SAFETY_CUT_OUT) { + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_13) || + ( + vehicle->vehicle_sprite_type == 2 && + vehicle->velocity <= 0x20000 + ) + ) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_7; + } + } + } + + switch (vehicle->status) { + case VEHICLE_STATUS_MOVING_TO_END_OF_STATION: + vehicle_update_moving_to_end_of_station(vehicle); + break; + case VEHICLE_STATUS_WAITING_FOR_PASSENGERS: + vehicle_update_waiting_for_passengers(vehicle); + break; + case VEHICLE_STATUS_WAITING_TO_DEPART: + vehicle_update_waiting_to_depart(vehicle); + break; + case VEHICLE_STATUS_CRASHING: + case VEHICLE_STATUS_CRASHED: + vehicle_update_crash(vehicle); + break; + case VEHICLE_STATUS_TRAVELLING_BUMPER_CARS: + vehicle_update_bumpcar_mode(vehicle); + break; + case VEHICLE_STATUS_SWINGING: + vehicle_update_swinging(vehicle); + break; + case VEHICLE_STATUS_SIMULATOR_OPERATING: + vehicle_update_simulator_operating(vehicle); + break; + case VEHICLE_STATUS_TOP_SPIN_OPERATING: + vehicle_update_top_spin_operating(vehicle); + break; + case VEHICLE_STATUS_FERRIS_WHEEL_ROTATING: + vehicle_update_ferris_wheel_rotating(vehicle); + break; + case VEHICLE_STATUS_SPACE_RINGS_OPERATING: + vehicle_update_space_rings_operating(vehicle); + break; + case VEHICLE_STATUS_HAUNTED_HOUSE_OPERATING: + vehicle_update_haunted_house_operating(vehicle); + break; + case VEHICLE_STATUS_CROOKED_HOUSE_OPERATING: + vehicle_update_crooked_house_operating(vehicle); + break; + case VEHICLE_STATUS_ROTATING: + vehicle_update_rotating(vehicle); + break; + case VEHICLE_STATUS_DEPARTING: + vehicle_update_departing(vehicle); + break; + case VEHICLE_STATUS_TRAVELLING: + vehicle_update_travelling(vehicle); + break; + case VEHICLE_STATUS_TRAVELLING_CABLE_LIFT: + vehicle_update_travelling_cable_lift(vehicle); + break; + case VEHICLE_STATUS_TRAVELLING_BOAT: + vehicle_update_travelling_boat(vehicle); + break; + case VEHICLE_STATUS_ARRIVING: + vehicle_update_arriving(vehicle); + break; + case VEHICLE_STATUS_UNLOADING_PASSENGERS: + vehicle_update_unloading_passengers(vehicle); + break; + case VEHICLE_STATUS_WAITING_FOR_CABLE_LIFT: + vehicle_update_waiting_for_cable_lift(vehicle); + break; + case VEHICLE_STATUS_SHOWING_FILM: + vehicle_update_showing_film(vehicle); + break; + case VEHICLE_STATUS_DOING_CIRCUS_SHOW: + vehicle_update_doing_circus_show(vehicle); + } + + vehicle_update_sound(vehicle); +} + +/** + * + * rct2: 0x006D7BCC + */ +static void vehicle_update_moving_to_end_of_station(rct_vehicle *vehicle){ + rct_ride* ride = get_ride(vehicle->ride); + int eax, ebx; + + switch (ride->mode){ + case RIDE_MODE_UPWARD_LAUNCH: + case RIDE_MODE_ROTATING_LIFT: + case RIDE_MODE_DOWNWARD_LAUNCH: + case RIDE_MODE_FREEFALL_DROP: + if (vehicle->velocity >= -131940){ + vehicle->acceleration = -3298; + } + if (vehicle->velocity < -131940){ + vehicle->velocity = vehicle->velocity / 16; + vehicle->acceleration = 0; + } + + eax = vehicle_update_track_motion(vehicle, &ebx); + if (!(eax&(1 << 5))) + break; + //Fall through to next case + case RIDE_MODE_BUMPERCAR: + case RIDE_MODE_SWING: + case RIDE_MODE_ROTATION: + case RIDE_MODE_FORWARD_ROTATION: + case RIDE_MODE_BACKWARD_ROTATION: + case RIDE_MODE_FILM_AVENGING_AVIATORS: + case RIDE_MODE_FILM_THRILL_RIDERS: + case RIDE_MODE_BEGINNERS: + case RIDE_MODE_INTENSE: + case RIDE_MODE_BERSERK: + case RIDE_MODE_3D_FILM_MOUSE_TAILS: + case RIDE_MODE_3D_FILM_STORM_CHASERS: + case RIDE_MODE_3D_FILM_SPACE_RAIDERS: + case RIDE_MODE_SPACE_RINGS: + case RIDE_MODE_HAUNTED_HOUSE: + case RIDE_MODE_CROOKED_HOUSE: + case RIDE_MODE_CIRCUS_SHOW: + vehicle->current_station = 0; + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_WAITING_FOR_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + break; + default: + { + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3)){ + if (vehicle->velocity <= 131940){ + vehicle->acceleration = 3298; + } + } + if (vehicle->velocity > 131940){ + vehicle->velocity -= vehicle->velocity / 16; + vehicle->acceleration = 0; + } + + int station; + eax = vehicle_update_track_motion(vehicle, &station); + + if (eax & (1 << 1)){ + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->sub_state++; + + if (ride->mode == RIDE_MODE_RACE && + vehicle->sub_state >= 40){ + vehicle->status = VEHICLE_STATUS_WAITING_FOR_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + break; + } + } + else{ + if (vehicle->velocity > 98955){ + vehicle->sub_state = 0; + } + } + + if (!(eax & (1 << 0))) + break; + + vehicle->current_station = station; + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_WAITING_FOR_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + break; + } + } +} + +/** + * + * rct2: 0x006D7FB4 + */ +static void train_ready_to_depart(rct_vehicle* vehicle, uint8 num_peeps_on_train, uint8 num_used_seats){ + + if (num_peeps_on_train != num_used_seats) + return; + + rct_ride* ride = get_ride(vehicle->ride); + + if (ride->status == RIDE_STATUS_OPEN && + !(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) && + !(vehicle->update_flags & VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART)){ + return; + } + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)){ + // Original code did not check if the ride was a boat hire, causing empty boats to leave the platform when closing a Boat Ride with passengers on it. + if (ride->status != RIDE_STATUS_CLOSED || + (ride->num_riders != 0 && ride->type != RIDE_TYPE_BOAT_RIDE)){ + ride->train_at_station[vehicle->current_station] = 0xFF; + vehicle->sub_state = 2; + return; + } + } + + if (ride->mode == RIDE_MODE_FORWARD_ROTATION || + ride->mode == RIDE_MODE_BACKWARD_ROTATION){ + + uint8 peep = ((-vehicle->vehicle_sprite_type) / 8) & 0xF; + if (vehicle->peep[peep] != 0xFFFF){ + ride->train_at_station[vehicle->current_station] = 0xFF; + vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + return; + } + + if (vehicle->num_peeps == 0) + return; + + ride->train_at_station[vehicle->current_station] = 0xFF; + vehicle->sub_state = 2; + return; + } + + if (num_peeps_on_train == 0) + return; + + ride->train_at_station[vehicle->current_station] = 0xFF; + vehicle->status = VEHICLE_STATUS_WAITING_FOR_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); +} + +/** + * + * rct2: 0x006D7DA1 + */ +static void vehicle_update_waiting_for_passengers(rct_vehicle* vehicle){ + vehicle->velocity = 0; + + rct_ride* ride = get_ride(vehicle->ride); + + if (vehicle->sub_state == 0){ + if (vehicle_open_restraints(vehicle)) + return; + + if (ride->entrances[vehicle->current_station] == 0xFFFF){ + ride->train_at_station[vehicle->current_station] = 0xFF; + vehicle->sub_state = 2; + return; + } + + uint8 train_index = 0; + while (ride->vehicles[train_index] != vehicle->sprite_index)train_index++; + + if (ride->train_at_station[vehicle->current_station] != 0xFF) + return; + + ride->train_at_station[vehicle->current_station] = train_index; + vehicle->sub_state = 1; + vehicle->time_waiting = 0; + + vehicle_invalidate(vehicle); + return; + } + else if (vehicle->sub_state == 1){ + if (vehicle->time_waiting != 0xFFFF) + vehicle->time_waiting++; + + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + + // 0xF64E31, 0xF64E32, 0xF64E33 + uint8 num_peeps_on_train = 0, num_used_seats_on_train = 0, num_seats_on_train = 0; + + for (uint16 sprite_id = vehicle->sprite_index; sprite_id != 0xFFFF;){ + rct_vehicle* train_vehicle = GET_VEHICLE(sprite_id); + + num_peeps_on_train += train_vehicle->num_peeps; + num_used_seats_on_train += train_vehicle->next_free_seat; + num_seats_on_train += train_vehicle->num_seats; + + sprite_id = train_vehicle->next_vehicle_on_train; + } + + num_seats_on_train &= 0x7F; + + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE)){ + if (vehicle->time_waiting < 20){ + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + } + else{ + if (num_peeps_on_train == 0){ + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + } + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS)){ + if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH){ + if (ride->min_waiting_time * 32 > vehicle->time_waiting){ + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + } + if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH){ + if (ride->max_waiting_time * 32 < vehicle->time_waiting){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + } + } + + if (ride->depart_flags & RIDE_DEPART_LEAVE_WHEN_ANOTHER_ARRIVES){ + + for (int i = 0; i < 32; ++i){ + uint16 train_id = ride->vehicles[i]; + if (train_id == 0xFFFF) + continue; + + if (train_id == vehicle->sprite_index) + continue; + + rct_vehicle* train = GET_VEHICLE(train_id); + + if (train->status == VEHICLE_STATUS_UNLOADING_PASSENGERS || + train->status == VEHICLE_STATUS_MOVING_TO_END_OF_STATION){ + if (train->current_station == vehicle->current_station){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + } + } + } + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS) && + ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD){ + + if (num_peeps_on_train == num_seats_on_train){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + uint8 load = ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD_MASK; + if (load == 3){ + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + uint8 three_quater_seats = (3 * num_seats_on_train) / 4; + if (three_quater_seats != 0 && num_peeps_on_train >= three_quater_seats){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + if (load == 2){ + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + if (num_seats_on_train / 2 != 0 && num_peeps_on_train >= num_seats_on_train / 2){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + if (load == 1){ + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + if (num_seats_on_train / 4 != 0 && num_peeps_on_train >= num_seats_on_train / 4){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + if (load == 0){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + if (num_peeps_on_train != 0){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + } + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TRAIN_READY_DEPART; + train_ready_to_depart(vehicle, num_peeps_on_train, num_used_seats_on_train); + return; + } + + if (vehicle_close_restraints(vehicle)) + return; + + vehicle->velocity = 0; + vehicle->status = VEHICLE_STATUS_WAITING_TO_DEPART; + vehicle->sub_state = 0; + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; + + if (ride->depart_flags & RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS){ + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; + } + + vehicle_invalidate_window(vehicle); +} + +/** + * + * rct2: 0x006D91BF + */ +static void vehicle_update_bumpcar_mode(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_7 && vehicle->var_C5 != 1) { + vehicle->var_C5 = 1; + vehicle_invalidate(vehicle); + } + + vehicle_update_motion_bumper_car(vehicle); + + // Update the length of time vehicle has been in bumper mode + if (vehicle->sub_state++ == 0xFF) { + vehicle->var_CE++; + } + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) + return; + + vehicle->var_C5 = 0; + vehicle_invalidate(vehicle); + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); +} + +/** + * + * rct2: 0x006D80BE + */ +static void vehicle_update_waiting_to_depart(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + bool shouldBreak = false; + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) { + switch (ride->breakdown_reason_pending) { + case BREAKDOWN_RESTRAINTS_STUCK_CLOSED: + case BREAKDOWN_RESTRAINTS_STUCK_OPEN: + case BREAKDOWN_DOORS_STUCK_CLOSED: + case BREAKDOWN_DOORS_STUCK_OPEN: + break; + default: + shouldBreak = true; + break; + } + } + + bool skipCheck = false; + if (shouldBreak == true || ride->status != RIDE_STATUS_OPEN) { + if (ride->mode == RIDE_MODE_FORWARD_ROTATION || + ride->mode == RIDE_MODE_BACKWARD_ROTATION) { + uint8 bl = ((-vehicle->vehicle_sprite_type) >> 3) & 0xF; + if (vehicle->peep[bl] == 0xFFFF) { + if (vehicle->num_peeps == 0) { + skipCheck = true; + } + } + else { + if (ride->exits[vehicle->current_station] != 0xFFFF) { + vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + return; + } + } + } + else { + uint16 spriteId = vehicle->sprite_index; + for (rct_vehicle* curVehicle; spriteId != 0xFFFF; spriteId = curVehicle->next_vehicle_on_train) { + curVehicle = GET_VEHICLE(spriteId); + + if (curVehicle->num_peeps != 0) { + if (ride->exits[vehicle->current_station] != 0xFFFF) { + vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + return; + } + break; + } + } + } + } + + if (skipCheck == false) { + if (!(ride->station_depart[vehicle->current_station] & STATION_DEPART_FLAG)) + return; + } + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_CAN_SYNCHRONISE_ADJACENT_STATIONS)) { + if (ride->depart_flags & RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS) { + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT) { + if (vehicle_can_depart_synchronised(vehicle)) { + return; + } + } + } + } + + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 0; + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_CABLE_LIFT) { + rct_xy_element track; + int z; + int direction; + + if (track_block_get_next_from_zero( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z, + vehicle->ride, + (uint8)(vehicle->track_direction & 0x3), + &track, + &z, + &direction)) { + + if (track_element_is_cable_lift(track.element)) { + vehicle->status = VEHICLE_STATUS_WAITING_FOR_CABLE_LIFT; + } + } + } + + switch (ride->mode) { + case RIDE_MODE_BUMPERCAR: + vehicle->status = VEHICLE_STATUS_TRAVELLING_BUMPER_CARS; + vehicle_invalidate_window(vehicle); + // Bumper mode uses sub_state / var_CE to tell how long + // the vehicle has been ridden. + vehicle->sub_state = 0; + vehicle->var_CE = 0; + vehicle_update_bumpcar_mode(vehicle); + break; + case RIDE_MODE_SWING: + vehicle->status = VEHICLE_STATUS_SWINGING; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + vehicle->var_CE = 0; + vehicle->current_time = -1; + vehicle_update_swinging(vehicle); + break; + case RIDE_MODE_ROTATION: + vehicle->status = VEHICLE_STATUS_ROTATING; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + vehicle->var_CE = 0; + vehicle->current_time = -1; + vehicle_update_rotating(vehicle); + break; + case RIDE_MODE_FILM_AVENGING_AVIATORS: + case RIDE_MODE_FILM_THRILL_RIDERS: + vehicle->status = VEHICLE_STATUS_SIMULATOR_OPERATING; + vehicle->sub_state = 0; + if (ride->mode == RIDE_MODE_FILM_THRILL_RIDERS) + vehicle->sub_state = 1; + vehicle_invalidate_window(vehicle); + vehicle->current_time = -1; + vehicle_update_simulator_operating(vehicle); + break; + case RIDE_MODE_BEGINNERS: + case RIDE_MODE_INTENSE: + case RIDE_MODE_BERSERK: + vehicle->status = VEHICLE_STATUS_TOP_SPIN_OPERATING; + vehicle_invalidate_window(vehicle); + + switch (ride->mode) { + case RIDE_MODE_BEGINNERS: + vehicle->sub_state = 0; + break; + case RIDE_MODE_INTENSE: + vehicle->sub_state = 1; + break; + case RIDE_MODE_BERSERK: + vehicle->sub_state = 2; + break; + } + vehicle->current_time = -1; + vehicle->vehicle_sprite_type = 0; + vehicle->bank_rotation = 0; + vehicle_update_top_spin_operating(vehicle); + break; + case RIDE_MODE_FORWARD_ROTATION: + case RIDE_MODE_BACKWARD_ROTATION: + vehicle->status = VEHICLE_STATUS_FERRIS_WHEEL_ROTATING; + vehicle->sub_state = vehicle->vehicle_sprite_type; + vehicle_invalidate_window(vehicle); + vehicle->var_CE = 0; + vehicle->ferris_wheel_var_0 = 8; + vehicle->ferris_wheel_var_1 = 8; + vehicle_update_ferris_wheel_rotating(vehicle); + break; + case RIDE_MODE_3D_FILM_MOUSE_TAILS: + case RIDE_MODE_3D_FILM_STORM_CHASERS: + case RIDE_MODE_3D_FILM_SPACE_RAIDERS: + vehicle->status = VEHICLE_STATUS_SHOWING_FILM; + vehicle_invalidate_window(vehicle); + switch (ride->mode) { + case RIDE_MODE_3D_FILM_MOUSE_TAILS: + vehicle->sub_state = 0; + break; + case RIDE_MODE_3D_FILM_STORM_CHASERS: + vehicle->sub_state = 1; + break; + case RIDE_MODE_3D_FILM_SPACE_RAIDERS: + vehicle->sub_state = 2; + break; + } + vehicle->current_time = -1; + vehicle_update_showing_film(vehicle); + break; + case RIDE_MODE_CIRCUS_SHOW: + vehicle->status = VEHICLE_STATUS_DOING_CIRCUS_SHOW; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + vehicle->current_time = -1; + vehicle_update_doing_circus_show(vehicle); + break; + case RIDE_MODE_SPACE_RINGS: + vehicle->status = VEHICLE_STATUS_SPACE_RINGS_OPERATING; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + vehicle->vehicle_sprite_type = 0; + vehicle->current_time = -1; + vehicle_update_space_rings_operating(vehicle); + break; + case RIDE_MODE_HAUNTED_HOUSE: + vehicle->status = VEHICLE_STATUS_HAUNTED_HOUSE_OPERATING; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + vehicle->vehicle_sprite_type = 0; + vehicle->current_time = -1; + vehicle_update_haunted_house_operating(vehicle); + break; + case RIDE_MODE_CROOKED_HOUSE: + vehicle->status = VEHICLE_STATUS_CROOKED_HOUSE_OPERATING; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + vehicle->vehicle_sprite_type = 0; + vehicle->current_time = -1; + vehicle_update_crooked_house_operating(vehicle); + break; + default: + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + vehicle->var_CE = 0; + break; + } +} + +typedef struct { + uint8 ride_id; + uint8 station_id; + uint16 vehicle_id; +} rct_synchrnoised_vehicle; + +// 8 synchrnoised vehicle info +rct_synchrnoised_vehicle *_synchrnoisedVehicles = (rct_synchrnoised_vehicle*)0x00F64E4C; + +#define _lastSynchrnoisedVehicle RCT2_GLOBAL(0x00F64E48, rct_synchrnoised_vehicle*) +#define MaxSynchrnoisedVehicle ((rct_synchrnoised_vehicle*)0x00F64E6C) + +/** + * Checks if a map position contains a synchrnoised ride station and adds the vehicle + * to synchrnoise to the vehicle synchronisation list. + * rct2: 0x006DE1A4 + */ +static bool try_add_synchronised_station(int x, int y, int z) +{ + bool foundMapElement = false; + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + if (mapElement != NULL) { + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (z != mapElement->base_height && + z != mapElement->base_height - 2 && + z != mapElement->base_height + 2 + ) { + continue; + } + + foundMapElement = true; + break; + } while (!map_element_is_last_for_tile(mapElement++)); + } + if (!foundMapElement) { + return false; + } + + int rideIndex = mapElement->properties.track.ride_index; + rct_ride *ride = get_ride(rideIndex); + if (!(ride->depart_flags & RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS)) { + return false; + } + + int stationIndex = map_get_station(mapElement); + + rct_synchrnoised_vehicle *sv = _lastSynchrnoisedVehicle; + sv->ride_id = rideIndex; + sv->station_id = stationIndex; + sv->vehicle_id = SPRITE_INDEX_NULL; + _lastSynchrnoisedVehicle++; + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) { + return false; + } + + for (int i = 0; i < ride->num_vehicles; i++) { + uint16 spriteIndex = ride->vehicles[i]; + if (spriteIndex == SPRITE_INDEX_NULL) continue; + + rct_vehicle *vehicle = GET_VEHICLE(spriteIndex); + if (vehicle->status != VEHICLE_STATUS_WAITING_TO_DEPART) continue; + if (vehicle->sub_state != 0) continue; + if (!(vehicle->update_flags & VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT)) continue; + if (vehicle->current_station != stationIndex) continue; + + sv->vehicle_id = spriteIndex; + return true; + } + return false; +} + +/** + * Checks whether a vehicle can depart a station when set to synchrnoise with adjacent stations. + * rct2: 0x006DE287 + * @param vehicle The vehicle waiting to depart. + * @returns true if the vehicle can depart (all adjacent trains are ready or broken down), otherwise false. + */ +static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) +{ + rct_ride *ride = get_ride(vehicle->ride); + int station = vehicle->current_station; + uint16 xy = ride->station_starts[station]; + int x = (xy & 0xFF) * 32; + int y = (xy >> 8) * 32; + int z = ride->station_heights[station]; + + rct_map_element *mapElement = map_get_track_element_at(x, y, z); + int direction = (mapElement->type + 1) & 3; + _lastSynchrnoisedVehicle = _synchrnoisedVehicles; + + while (_lastSynchrnoisedVehicle < MaxSynchrnoisedVehicle) { + x += TileDirectionDelta[direction].x; + y += TileDirectionDelta[direction].y; + if (!try_add_synchronised_station(x, y, z)) { + break; + } + } + + while (_lastSynchrnoisedVehicle < MaxSynchrnoisedVehicle) { + x += TileDirectionDelta[direction].x; + y += TileDirectionDelta[direction].y; + if (!try_add_synchronised_station(x, y, z)) { + break; + } + } + + if (_lastSynchrnoisedVehicle == _synchrnoisedVehicles) { + // No adjacent stations, allow depart + return true; + } + + for (rct_synchrnoised_vehicle *sv = _synchrnoisedVehicles; sv < _lastSynchrnoisedVehicle; sv++) { + if (ride_is_block_sectioned(ride)) { + if (!(ride->station_depart[sv->station_id] & 0x80)) { + sv = _synchrnoisedVehicles; + uint8 rideId = 0xFF; + for (; sv < _lastSynchrnoisedVehicle; sv++) { + if (rideId == 0xFF) { + rideId = sv->ride_id; + } + if (rideId != sv->ride_id) { + return true; + } + } + + ride = get_ride(rideId); + for (int i = 0; i < ride->num_vehicles; i++) { + rct_vehicle *v = GET_VEHICLE(ride->vehicles[i]); + if (v->status != VEHICLE_STATUS_WAITING_TO_DEPART && v->velocity != 0) { + return true; + } + } + + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; + return false; + } + } + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)) { + if (ride->status != RIDE_STATUS_CLOSED) { + if (sv->vehicle_id == SPRITE_INDEX_NULL) { + if (_lastSynchrnoisedVehicle > &_synchrnoisedVehicles[1]) { + return true; + } + uint8 someRideIndex = _synchrnoisedVehicles[0].ride_id; + // uint8 currentStation = _synchrnoisedVehicles[0].station_id + if (someRideIndex != vehicle->ride) { + return true; + } + + ride = get_ride(someRideIndex); + int numAdjacentTrainsAtStation = 0; + int numTravelingTrains = 0; + int currentStation = vehicle->current_station; + for (int i = 0; i < ride->num_vehicles; i++) { + uint16 spriteIndex = ride->vehicles[i]; + if (spriteIndex != SPRITE_INDEX_NULL) { + rct_vehicle *otherVehicle = GET_VEHICLE(spriteIndex); + if (otherVehicle->status != VEHICLE_STATUS_TRAVELLING) { + if (currentStation == otherVehicle->current_station) { + if (otherVehicle->status == VEHICLE_STATUS_WAITING_TO_DEPART || + otherVehicle->status == VEHICLE_STATUS_MOVING_TO_END_OF_STATION + ) { + numAdjacentTrainsAtStation++; + } + } + } else { + numTravelingTrains++; + } + } + } + + int totalTrains = numAdjacentTrainsAtStation + numTravelingTrains; + if (totalTrains != ride->num_vehicles || numTravelingTrains >= ride->num_vehicles / 2) { + return true; + } else { + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; + return false; + } + } + } + } + } + + for (rct_synchrnoised_vehicle *sv = _synchrnoisedVehicles; sv < _lastSynchrnoisedVehicle; sv++) { + if (sv->vehicle_id != SPRITE_INDEX_NULL) { + rct_vehicle *v = GET_VEHICLE(sv->vehicle_id); + v->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; + } + } + + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; + return false; +} + +/** + * + * rct2: 0x006D9EB0 + */ +void vehicle_peep_easteregg_here_we_are(rct_vehicle* vehicle) { + uint16 spriteId = vehicle->sprite_index; + do { + vehicle = GET_VEHICLE(spriteId); + for (int i = 0; i < vehicle->num_peeps; ++i) { + rct_peep* peep = GET_PEEP(vehicle->peep[i]); + if (peep->peep_flags & PEEP_FLAGS_HERE_WE_ARE) { + peep_insert_new_thought(peep, PEEP_THOUGHT_HERE_WE_ARE, peep->current_ride); + } + } + } while ((spriteId = vehicle->next_vehicle_on_train) != 0xFFFF); +} + +/** + * Performed when vehicle has completed a full circuit + * rct2: 0x006D7338 + */ +void vehicle_update_test_finish(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_TEST_IN_PROGRESS; + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_TESTING; + ride->lifecycle_flags |= RIDE_LIFECYCLE_TESTED; + + for (int i = ride->num_stations - 1; i >= 1; i--) { + if (ride->time[i - 1] != 0) + continue; + + uint16 oldTime = ride->time[i - 1]; + ride->time[i - 1] = ride->time[i]; + ride->time[i] = oldTime; + + sint32 oldLength = ride->length[i - 1]; + ride->length[i - 1] = ride->length[i]; + ride->length[i] = oldLength; + } + + uint32 totalTime = 0; + for (uint8 i = 0; i < ride->num_stations; ++i) { + totalTime += ride->time[i]; + } + + totalTime = max(totalTime, 1); + ride->average_speed = ride->average_speed / totalTime; + + window_invalidate_by_number(WC_RIDE, vehicle->ride); +} + +/** + * + * rct2: 0x006D6BE7 + */ +void vehicle_test_reset(rct_vehicle* vehicle) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_TESTING; + + rct_ride* ride = get_ride(vehicle->ride); + ride->lifecycle_flags |= RIDE_LIFECYCLE_TEST_IN_PROGRESS; + ride->lifecycle_flags &= ~RIDE_LIFECYCLE_NO_RAW_STATS; + ride->max_speed = 0; + ride->average_speed = 0; + ride->current_test_segment = 0; + ride->average_speed_test_timeout = 0; + ride->max_positive_vertical_g = FIXED_2DP(1, 0); + ride->max_negative_vertical_g = FIXED_2DP(1, 0); + ride->max_lateral_g = 0; + ride->previous_vertical_g = 0; + ride->previous_lateral_g = 0; + ride->testing_flags = 0; + ride->cur_test_track_location.xy = 0xFFFF; + ride->cur_test_track_z = 0xFF; + ride->turn_count_default = 0; + ride->turn_count_banked = 0; + ride->turn_count_sloped = 0; + ride->inversions = 0; + ride->drops = 0; + ride->sheltered_length = 0; + ride->var_11C = 0; + ride->num_sheltered_sections = 0; + ride->highest_drop_height = 0; + ride->special_track_elements = 0; + memset(&ride->length, 0, 4 * 4); + memset(&ride->time, 0, 4 * 2); + ride->total_air_time = 0; + ride->current_test_station = vehicle->current_station; + window_invalidate_by_number(WC_RIDE, vehicle->ride); +} + +static bool vehicle_next_tower_element_is_top(rct_vehicle* vehicle) { + rct_map_element* mapElement = map_get_track_element_at_of_type( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z / 8, + vehicle->track_type >> 2); + + if (mapElement->flags & MAP_ELEMENT_FLAG_LAST_TILE) { + return true; + } + + if (mapElement->clearance_height == (mapElement + 1)->base_height) { + if ((mapElement + 1)->properties.track.type == TRACK_ELEM_TOWER_SECTION) { + return false; + } + } + + if ((mapElement + 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE) { + return true; + } + + if (mapElement->clearance_height != (mapElement + 2)->base_height) { + return true; + } + + if ((mapElement + 2)->properties.track.type == TRACK_ELEM_TOWER_SECTION) { + return false; + } + return true; +} + +/** + * + * rct2: 0x006D986C + */ +static void vehicle_update_travelling_boat_hire_setup(rct_vehicle* vehicle) { + vehicle->var_34 = vehicle->sprite_direction; + vehicle->track_x = vehicle->x & 0xFFE0; + vehicle->track_y = vehicle->y & 0xFFE0; + + rct_xy8 location = { + .x = (vehicle->track_x + TileDirectionDelta[vehicle->sprite_direction >> 3].x) / 32, + .y = (vehicle->track_y + TileDirectionDelta[vehicle->sprite_direction >> 3].y) / 32 + }; + + vehicle->boat_location = location; + vehicle->var_35 = 0; + vehicle->status = VEHICLE_STATUS_TRAVELLING_BOAT; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->remaining_distance += 27924; + + vehicle_update_travelling_boat(vehicle); +} + +/** + * + * rct2: 0x006D982F + */ +static void vehicle_update_departing_boat_hire(rct_vehicle* vehicle) { + vehicle->lost_time_out = 0; + rct_ride* ride = get_ride(vehicle->ride); + + ride->station_depart[vehicle->current_station] &= STATION_DEPART_FLAG; + uint8 waitingTime = max(ride->min_waiting_time, 3); + waitingTime = min(waitingTime, 127); + ride->station_depart[vehicle->current_station] |= waitingTime; + vehicle_update_travelling_boat_hire_setup(vehicle); +} + +/** + * + * rct2: 0x006D845B + */ +static void vehicle_update_departing(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + + if (vehicle->sub_state == 0) { + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_BROKEN_TRAIN) { + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) + return; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_BROKEN_DOWN; + ride_breakdown_add_news_item(vehicle->ride); + + ride->window_invalidate_flags |= + RIDE_INVALIDATE_RIDE_MAIN | + RIDE_INVALIDATE_RIDE_LIST | + RIDE_INVALIDATE_RIDE_MAINTENANCE; + ride->mechanic_status = RIDE_MECHANIC_STATUS_CALLING; + ride->inspection_station = vehicle->current_station; + ride->breakdown_reason = ride->breakdown_reason_pending; + vehicle->velocity = 0; + return; + } + + vehicle->sub_state = 1; + vehicle_peep_easteregg_here_we_are(vehicle); + + if (rideEntry->flags & RIDE_ENTRY_FLAG_3) { + uint8 soundId = (rideEntry->vehicles[0].sound_range == 4) ? + SOUND_TRAM : + SOUND_TRAIN_CHUGGING; + + audio_play_sound_at_location( + soundId, + vehicle->x, + vehicle->y, + vehicle->z); + } + + if (ride->mode == RIDE_MODE_UPWARD_LAUNCH || + (ride->mode == RIDE_MODE_DOWNWARD_LAUNCH && vehicle->var_CE > 1)) { + + audio_play_sound_at_location( + SOUND_RIDE_LAUNCH_2, + vehicle->x, + vehicle->y, + vehicle->z + ); + } + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) { + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_TESTING) { + if (ride->current_test_segment + 1 < ride->num_stations) { + ride->current_test_segment++; + ride->current_test_station = vehicle->current_station; + } + else { + vehicle_update_test_finish(vehicle); + } + } + else if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TEST_IN_PROGRESS)) { + vehicle_test_reset(vehicle); + } + } + } + + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + switch (ride->mode) { + case RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE: + if (vehicle->velocity >= -131940) + vehicle->acceleration = -3298; + break; + case RIDE_MODE_POWERED_LAUNCH_PASSTROUGH: + case RIDE_MODE_POWERED_LAUNCH: + case RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED: + case RIDE_MODE_LIM_POWERED_LAUNCH: + case RIDE_MODE_UPWARD_LAUNCH: + if (ride->type == RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER) { + if ((ride->launch_speed << 16) > vehicle->velocity) { + vehicle->acceleration = ride->launch_speed << 13; + } + break; + } + + if ((ride->launch_speed << 16) > vehicle->velocity) + vehicle->acceleration = ride->launch_speed << 12; + break; + case RIDE_MODE_DOWNWARD_LAUNCH: + if (vehicle->var_CE >= 1) { + if ((14 << 16) > vehicle->velocity) + vehicle->acceleration = 14 << 12; + break; + } + // Fall through + case RIDE_MODE_CONTINUOUS_CIRCUIT: + case RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED: + case RIDE_MODE_ROTATING_LIFT: + case RIDE_MODE_FREEFALL_DROP: + case RIDE_MODE_BOAT_HIRE: + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3) + break; + + if (vehicle->velocity <= 131940) + vehicle->acceleration = 3298; + break; + } + + uint32 flags = vehicle_update_track_motion(vehicle, NULL); + + if (flags & (1 << 8)) { + if (ride->mode == RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE) { + vehicle->velocity = -vehicle->velocity; + vehicle_finish_departing(vehicle); + return; + } + } + + if (flags & ((1 << 5) | (1 << 12))) { + if (ride->mode == RIDE_MODE_BOAT_HIRE) { + vehicle_update_departing_boat_hire(vehicle); + return; + } + else if (ride->mode == RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE) { + vehicle->velocity = -vehicle->velocity; + vehicle_finish_departing(vehicle); + return; + } + else if (ride->mode == RIDE_MODE_SHUTTLE) { + vehicle->update_flags ^= VEHICLE_UPDATE_FLAG_3; + vehicle->velocity = 0; + } + } + + if (flags & VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_ON_LIFT_HILL) { + vehicle->var_B8 |= (1 << 1); + if (ride->mode != RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE) { + sint32 speed = ride->lift_hill_speed * 31079; + if (vehicle->velocity <= speed) { + vehicle->acceleration = 15539; + if (vehicle->velocity != 0) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == BREAKDOWN_SAFETY_CUT_OUT) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_7; + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_1; + } + } + else + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_1; + } + } + else { + sint32 speed = ride->lift_hill_speed * -31079; + if (vehicle->velocity >= speed) { + vehicle->acceleration = -15539; + if (vehicle->velocity != 0) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == BREAKDOWN_SAFETY_CUT_OUT) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_7; + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_1; + } + } + else + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_1; + } + } + } + + if (ride->mode == RIDE_MODE_FREEFALL_DROP) { + vehicle->var_C5++; + }else{ + bool shouldLaunch = true; + if (ride->mode == RIDE_MODE_DOWNWARD_LAUNCH) { + if (vehicle->var_CE < 1) + shouldLaunch = false; + } + + if (shouldLaunch) { + if (!(flags & (1 << 3)) || (RCT2_GLOBAL(0x00F64E1C, uint8) != vehicle->current_station)) { + vehicle_finish_departing(vehicle); + return; + } + + if (!(flags & (1 << 5))) + return; + if (ride->mode == RIDE_MODE_BOAT_HIRE || + ride->mode == RIDE_MODE_ROTATING_LIFT || + ride->mode == RIDE_MODE_SHUTTLE) + return; + + vehicle_update_crash_setup(vehicle); + return; + } + } + + if (vehicle_next_tower_element_is_top(vehicle) == false) { + if (ride->mode == RIDE_MODE_FREEFALL_DROP) + vehicle_invalidate(vehicle); + return; + } + + vehicle_finish_departing(vehicle); +} + +/** + * Part of vehicle_update_departing + * Called after finishing departing sequence to enter + * traveling state. + * Vertical rides class the lift to the top of the tower + * as the departing sequence. After this point station + * boosters do not affect the ride. + * rct2: 0x006D8858 + */ +static void vehicle_finish_departing(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + + if (ride->mode == RIDE_MODE_DOWNWARD_LAUNCH ) { + if (vehicle->var_CE >= 1 && (14 << 16) > vehicle->velocity) + return; + + audio_play_sound_at_location( + SOUND_RIDE_LAUNCH_1, + vehicle->x, + vehicle->y, + vehicle->z); + } + + if (ride->mode == RIDE_MODE_UPWARD_LAUNCH) { + if ((ride->launch_speed << 16) > vehicle->velocity) + return; + + audio_play_sound_at_location( + SOUND_RIDE_LAUNCH_1, + vehicle->x, + vehicle->y, + vehicle->z); + } + + if (ride->mode != RIDE_MODE_RACE && + ride->mode != RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED && + ride->mode != RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED) { + + ride->station_depart[vehicle->current_station] &= STATION_DEPART_FLAG; + uint8 waitingTime = 3; + if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH) { + waitingTime = max(ride->min_waiting_time, 3); + waitingTime = min(waitingTime, 127); + } + + ride->station_depart[vehicle->current_station] |= waitingTime; + } + + vehicle->status = VEHICLE_STATUS_TRAVELLING; + vehicle_invalidate_window(vehicle); + vehicle->lost_time_out = 0; + + vehicle->sub_state = 1; + if (vehicle->velocity < 0) + vehicle->sub_state = 0; +} + +/** + * + * rct2: 0x006DE5CB + */ +static void vehicle_check_if_missing(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + + if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BROKEN_DOWN | RIDE_LIFECYCLE_CRASHED)) + return; + + if (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED || + ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED) + return; + + if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_27)) + return; + + vehicle->lost_time_out++; + if (ride->lifecycle_flags & RIDE_LIFECYCLE_11) + return; + + uint16 limit = ride->type == RIDE_TYPE_BOAT_RIDE ? 15360 : 9600; + + if (vehicle->lost_time_out <= limit) + return; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_11; + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) + = RCT2_ADDRESS(0x0097C98E, rct_string_id)[ride->type * 4] + 6; + + uint8 vehicleIndex = 0; + for (; vehicleIndex < ride->num_vehicles; ++vehicleIndex) + if (ride->vehicles[vehicleIndex] == vehicle->sprite_index) break; + + vehicleIndex++; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = vehicleIndex; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, rct_string_id) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 10, rct_string_id) = + RCT2_ADDRESS(0x0097C98E, rct_string_id)[ride->type * 4 + 2]; + + news_item_add_to_queue(NEWS_ITEM_RIDE, 2218, vehicle->ride); +} + +/** + * Setup function for a vehicle colliding with + * another vehicle. + * + * rct2: 0x006DA059 + */ +static void vehicle_update_collision_setup(rct_vehicle* vehicle) { + vehicle->status = VEHICLE_STATUS_CRASHED; + vehicle_invalidate_window(vehicle); + + rct_ride* ride = get_ride(vehicle->ride); + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)) { + rct_vehicle* frontVehicle = vehicle; + while (frontVehicle->is_child != 0)frontVehicle = GET_VEHICLE(frontVehicle->prev_vehicle_on_ride); + + uint8 trainIndex = 0; + while (ride->vehicles[trainIndex] != frontVehicle->sprite_index) + trainIndex++; + + ride_crash(vehicle->ride, trainIndex); + + if (ride->status != RIDE_STATUS_CLOSED) { + ride_set_status(vehicle->ride, RIDE_STATUS_CLOSED); + } + } + + ride->lifecycle_flags |= RIDE_LIFECYCLE_CRASHED; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; + vehicle_kill_all_passengers(vehicle); + + rct_vehicle* lastVehicle = vehicle; + uint16 spriteId = vehicle->sprite_index; + for (rct_vehicle* train; spriteId != 0xFFFF; spriteId = train->next_vehicle_on_train) { + train = GET_VEHICLE(spriteId); + lastVehicle = train; + + train->sub_state = 2; + + audio_play_sound_at_location( + SOUND_CRASH, + train->x, + train->y, + train->z + ); + + sprite_misc_3_create( + train->x, + train->y, + train->z + ); + + for (int i = 0; i < 10; i++) { + crashed_vehicle_particle_create( + train->colours, + train->x, + train->y, + train->z + ); + } + + train->flags |= SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE; + train->var_C8 = scenario_rand(); + train->var_CA = scenario_rand(); + + train->var_C5 = train->var_CA & 0x7; + train->sprite_width = 13; + train->sprite_height_negative = 45; + train->sprite_height_positive = 5; + + sprite_move(train->x, train->y, train->z, (rct_sprite*)train); + invalidate_sprite_2((rct_sprite*)train); + + train->var_4E = 0; + } + + (GET_VEHICLE(vehicle->prev_vehicle_on_ride))->next_vehicle_on_ride = lastVehicle->next_vehicle_on_ride; + (GET_VEHICLE(lastVehicle->next_vehicle_on_ride))->prev_vehicle_on_ride = vehicle->prev_vehicle_on_ride; + vehicle->velocity = 0; +} + +/** + * + * rct2: 0x006D9EFE + */ +static void vehicle_update_crash_setup(rct_vehicle* vehicle) { + vehicle->status = VEHICLE_STATUS_CRASHING; + vehicle_invalidate_window(vehicle); + + int num_peeps = vehicle_get_total_num_peeps(vehicle); + if (num_peeps != 0) { + audio_play_sound_at_location( + SOUND_HAUNTED_HOUSE_SCREAM_2, + vehicle->x, + vehicle->y, + vehicle->z + ); + } + + int edx = vehicle->velocity >> 10; + + rct_vehicle* lastVehicle = vehicle; + uint16 spriteId = vehicle->sprite_index; + for (rct_vehicle* trainVehicle; spriteId != 0xFFFF; spriteId = trainVehicle->next_vehicle_on_train) { + trainVehicle = GET_VEHICLE(spriteId); + lastVehicle = trainVehicle; + + trainVehicle->sub_state = 0; + int x = RCT2_ADDRESS(0x009A3AC4, sint16)[trainVehicle->sprite_direction & 0xFE]; + int y = RCT2_ADDRESS(0x009A3AC6, sint16)[trainVehicle->sprite_direction & 0xFE]; + + int ecx = RCT2_ADDRESS(0x009A37E4, sint32)[trainVehicle->vehicle_sprite_type] >> 15; + x *= ecx; + y *= ecx; + x >>= 16; + y >>= 16; + ecx = RCT2_ADDRESS(0x009A38D4, sint32)[trainVehicle->vehicle_sprite_type] >> 23; + x *= edx; + y *= edx; + ecx *= edx; + x >>= 8; + y >>= 8; + ecx >>= 8; + + trainVehicle->var_B6 = x; + trainVehicle->var_C0 = y; + trainVehicle->var_4E = ecx; + trainVehicle->var_B6 += (scenario_rand() & 0xF) - 8; + trainVehicle->var_C0 += (scenario_rand() & 0xF) - 8; + trainVehicle->var_4E += (scenario_rand() & 0xF) - 8; + + trainVehicle->track_x = 0; + trainVehicle->track_y = 0; + trainVehicle->track_z = 0; + } + + (GET_VEHICLE(vehicle->prev_vehicle_on_ride))->next_vehicle_on_ride = lastVehicle->next_vehicle_on_ride; + (GET_VEHICLE(lastVehicle->next_vehicle_on_ride))->prev_vehicle_on_ride = vehicle->prev_vehicle_on_ride; + vehicle->velocity = 0; +} + +/** + * + * rct2: 0x006D8937 + */ +static void vehicle_update_travelling(rct_vehicle* vehicle) { + vehicle_check_if_missing(vehicle); + + rct_ride* ride = get_ride(vehicle->ride); + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0 && ride->mode == RIDE_MODE_ROTATING_LIFT) + return; + + if (vehicle->sub_state == 2) { + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->var_C0--; + if (vehicle->var_C0 == 0) + vehicle->sub_state = 0; + } + + if (ride->mode == RIDE_MODE_FREEFALL_DROP && + vehicle->var_C5 != 0) { + + vehicle->var_C5++; + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle_invalidate(vehicle); + return; + } + + uint32 flags = vehicle_update_track_motion(vehicle, NULL); + + bool skipCheck = false; + if (flags & ((1 << 8) | (1 << 9)) && + ride->mode == RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE && + vehicle->sub_state == 0) { + vehicle->sub_state = 1; + vehicle->velocity = 0; + skipCheck = true; + } + + if (!skipCheck) { + if (flags & (1 << 6)) { + vehicle_update_crash_setup(vehicle); + return; + } + + if (flags & (1 << 7)) { + vehicle_update_collision_setup(vehicle); + return; + } + + if (flags & ((1 << 5) | (1 << 12))) { + if (ride->mode == RIDE_MODE_ROTATING_LIFT) { + if (vehicle->sub_state <= 1) { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 1; + vehicle->var_C0 = 0; + return; + } + } + else if (ride->mode == RIDE_MODE_BOAT_HIRE) { + vehicle_update_travelling_boat_hire_setup(vehicle); + return; + } + else if (ride->mode == RIDE_MODE_SHUTTLE) { + vehicle->update_flags ^= VEHICLE_UPDATE_FLAG_3; + vehicle->velocity = 0; + } + else { + if (vehicle->sub_state != 0) { + vehicle_update_crash_setup(vehicle); + return; + } + vehicle->sub_state = 1; + vehicle->velocity = 0; + } + } + } + + if (ride->mode == RIDE_MODE_ROTATING_LIFT && + vehicle->sub_state <= 1) { + + if (vehicle->sub_state == 0) { + if (vehicle->velocity >= -131940) + vehicle->acceleration = -3298; + vehicle->velocity = max(vehicle->velocity, -131940); + } + else { + if (vehicle_next_tower_element_is_top(vehicle) == true) { + vehicle->velocity = 0; + vehicle->sub_state = 2; + vehicle->var_C0 = 150; + } + else { + if (vehicle->velocity <= 131940) + vehicle->acceleration = 3298; + } + } + } + + if (flags & VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_ON_LIFT_HILL) { + if (ride->mode == RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE) { + if (vehicle->sub_state == 0) { + if (vehicle->velocity != 0) + vehicle->var_B8 |= (1 << 1); + + if (!(vehicle->update_flags & VEHICLE_UPDATE_FLAG_12)) { + if (vehicle->velocity >= ride->lift_hill_speed * -31079) { + vehicle->acceleration = -15539; + + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) { + vehicle->var_B8 &= ~(1 << 1); + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_7; + } + } + } + } + } + else { + vehicle->var_B8 |= (1 << 1); + if (vehicle->velocity <= ride->lift_hill_speed * 31079) { + vehicle->acceleration = 15539; + if (vehicle->velocity != 0) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_7; + vehicle->var_B8 &= ~(1 << 1); + } + } + else { + vehicle->var_B8 &= ~(1 << 1); + } + } + } + } + + if (!(flags & (1 << 3))) + return; + + if (ride->mode == RIDE_MODE_REVERSE_INCLINE_LAUNCHED_SHUTTLE && + vehicle->velocity >= 0 && + !(vehicle->update_flags & VEHICLE_UPDATE_FLAG_12)) { + return; + } + + if (ride->mode == RIDE_MODE_POWERED_LAUNCH_PASSTROUGH && + vehicle->velocity < 0) + return; + + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle->current_station = RCT2_GLOBAL(0x00F64E1C, uint8); + vehicle_invalidate_window(vehicle); + vehicle->var_C0 = 0; + + vehicle->sub_state = 0; + if (vehicle->velocity < 0) + vehicle->sub_state = 1; +} + +/** + * + * rct2: 0x006D8C36 + */ +static void vehicle_update_arriving(rct_vehicle* vehicle) { + RCT2_GLOBAL(0x00F64E35, uint8) = 1; + rct_ride* ride = get_ride(vehicle->ride); + + switch (ride->mode) { + case RIDE_MODE_SWING: + case RIDE_MODE_ROTATION: + case RIDE_MODE_FORWARD_ROTATION: + case RIDE_MODE_BACKWARD_ROTATION: + case RIDE_MODE_FILM_AVENGING_AVIATORS: + case RIDE_MODE_FILM_THRILL_RIDERS: + case RIDE_MODE_BEGINNERS: + case RIDE_MODE_INTENSE: + case RIDE_MODE_BERSERK: + case RIDE_MODE_3D_FILM_MOUSE_TAILS: + case RIDE_MODE_3D_FILM_STORM_CHASERS: + case RIDE_MODE_3D_FILM_SPACE_RAIDERS: + case RIDE_MODE_CIRCUS_SHOW: + case RIDE_MODE_SPACE_RINGS: + case RIDE_MODE_HAUNTED_HOUSE: + case RIDE_MODE_CROOKED_HOUSE: + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_12; + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + return; + } + + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN && + ride->breakdown_reason_pending == BREAKDOWN_BRAKES_FAILURE && + ride->inspection_station == vehicle->current_station && + ride->mechanic_status != RIDE_MECHANIC_STATUS_4) + RCT2_GLOBAL(0x00F64E35, uint8) = 0; + + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + if (vehicle->sub_state == 0) { + if (ride->mode == RIDE_MODE_RACE && + ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) { + goto loc_6D8E36; + } + + if (vehicle->velocity <= 131940) { + vehicle->acceleration = 3298; + goto loc_6D8E36; + } + + sint32 velocity_diff = vehicle->velocity; + if (velocity_diff >= 1572864) + velocity_diff /= 8; + else + velocity_diff /= 16; + + if (RCT2_GLOBAL(0x00F64E35, uint8) == 0) { + goto loc_6D8E36; + } + + if (ride->num_circuits != 1) { + if (vehicle->num_laps + 1 < ride->num_circuits) { + goto loc_6D8E36; + } + } + vehicle->velocity -= velocity_diff; + vehicle->acceleration = 0; + } + else { + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3) && + vehicle->velocity >= -131940) { + vehicle->acceleration = -3298; + } + + if (vehicle->velocity >= -131940) { + goto loc_6D8E36; + } + + sint32 velocity_diff = vehicle->velocity; + if (velocity_diff < -1572864) + velocity_diff /= 8; + else + velocity_diff /= 16; + + if (RCT2_GLOBAL(0x00F64E35, uint8) == 0) { + goto loc_6D8E36; + } + + if (vehicle->num_laps + 1 < ride->num_circuits) { + goto loc_6D8E36; + } + + if (vehicle->num_laps + 1 != ride->num_circuits) { + vehicle->velocity -= velocity_diff; + vehicle->acceleration = 0; + goto loc_6D8E36; + } + + if (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_ALLOW_MULTIPLE_CIRCUITS && + ride->mode != RIDE_MODE_SHUTTLE && + ride->mode != RIDE_MODE_POWERED_LAUNCH) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_12; + } + else{ + vehicle->velocity -= velocity_diff; + vehicle->acceleration = 0; + } + } + + uint32 flags; + loc_6D8E36: + flags = vehicle_update_track_motion(vehicle, NULL); + if (flags & (1 << 7) && + RCT2_GLOBAL(0x00F64E35, uint8) == 0) { + vehicle_update_collision_setup(vehicle); + return; + } + + if (flags & (1 << 0) && + RCT2_GLOBAL(0x00F64E35, uint8) == 0) { + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 1; + vehicle_invalidate_window(vehicle); + return; + } + + if (!(flags & ((1 << 0) | (1 << 1) | (1 << 5)))) { + if (vehicle->velocity > 98955) + vehicle->var_C0 = 0; + return; + } + + vehicle->var_C0++; + if (flags & (1 << 1) && + vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_14 && + vehicle->var_C0 < 40){ + return; + } + + rct_map_element* mapElement = map_get_track_element_at( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z / 8 + ); + + vehicle->current_station = map_get_station(mapElement); + vehicle->num_laps++; + + if (vehicle->sub_state != 0) { + if (vehicle->num_laps < ride->num_circuits) { + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 1; + vehicle_invalidate_window(vehicle); + return; + } + + if (vehicle->num_laps == ride->num_circuits && + vehicle->update_flags & VEHICLE_UPDATE_FLAG_12) { + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 1; + vehicle_invalidate_window(vehicle); + return; + } + } + + if (ride->num_circuits != 1 && + vehicle->num_laps < ride->num_circuits) { + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 1; + vehicle_invalidate_window(vehicle); + return; + } + + if ((ride->mode == RIDE_MODE_UPWARD_LAUNCH || + ride->mode == RIDE_MODE_DOWNWARD_LAUNCH) && + vehicle->var_CE < 2) { + audio_play_sound_at_location( + SOUND_RIDE_LAUNCH_2, + vehicle->x, + vehicle->y, + vehicle->z); + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 1; + vehicle_invalidate_window(vehicle); + return; + } + + if (ride->mode == RIDE_MODE_RACE && + ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) { + vehicle->status = VEHICLE_STATUS_DEPARTING; + vehicle->sub_state = 1; + vehicle_invalidate_window(vehicle); + return; + } + + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_12; + vehicle->velocity = 0; + vehicle->acceleration = 0; + vehicle->status = VEHICLE_STATUS_UNLOADING_PASSENGERS; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); +} + +/** + * + * rct2: 0x006D9002 + */ +static void vehicle_update_unloading_passengers(rct_vehicle* vehicle) { + if (vehicle->sub_state == 0) { + if (!vehicle_open_restraints(vehicle)) { + vehicle->sub_state = 1; + } + } + + rct_ride* ride = get_ride(vehicle->ride); + if (ride->mode == RIDE_MODE_FORWARD_ROTATION || + ride->mode == RIDE_MODE_BACKWARD_ROTATION) { + uint8 seat = ((-vehicle->vehicle_sprite_type) >> 3) & 0xF; + if (vehicle->restraints_position == 255 && + (vehicle->peep[seat * 2] != 0xFFFF)) { + vehicle->next_free_seat -= 2; + + rct_peep* peep = GET_PEEP(vehicle->peep[seat * 2]); + vehicle->peep[seat * 2] = 0xFFFF; + + peep_decrement_num_riders(peep); + peep->sub_state = 7; + peep->state = PEEP_STATE_LEAVING_RIDE; + peep_window_state_update(peep); + + peep = GET_PEEP(vehicle->peep[seat * 2 + 1]); + vehicle->peep[seat * 2 + 1] = 0xFFFF; + + peep_decrement_num_riders(peep); + peep->sub_state = 7; + peep->state = PEEP_STATE_LEAVING_RIDE; + peep_window_state_update(peep); + } + } + else { + if (ride->exits[vehicle->current_station] == 0xFFFF) { + if (vehicle->sub_state != 1) + return; + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) && + vehicle->update_flags & VEHICLE_UPDATE_FLAG_TESTING && + ride->current_test_segment + 1 >= ride->num_stations) { + vehicle_update_test_finish(vehicle); + } + vehicle->status = VEHICLE_STATUS_MOVING_TO_END_OF_STATION; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); + return; + } + + uint16 spriteId = vehicle->sprite_index; + for (rct_vehicle* train; spriteId != 0xFFFF; spriteId = train->next_vehicle_on_train) { + train = GET_VEHICLE(spriteId); + if (train->restraints_position != 255) + continue; + + if (train->next_free_seat == 0) + continue; + + train->next_free_seat = 0; + for (uint8 peepIndex = 0; peepIndex < train->num_peeps; peepIndex++) { + rct_peep* peep = GET_PEEP(train->peep[peepIndex]); + peep_decrement_num_riders(peep); + peep->sub_state = 7; + peep->state = PEEP_STATE_LEAVING_RIDE; + peep_window_state_update(peep); + } + } + } + + if (vehicle->sub_state != 1) + return; + + uint16 spriteId = vehicle->sprite_index; + for (rct_vehicle* train; spriteId != 0xFFFF; spriteId = train->next_vehicle_on_train) { + train = GET_VEHICLE(spriteId); + if (train->num_peeps != train->next_free_seat) + return; + } + + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) && + vehicle->update_flags & VEHICLE_UPDATE_FLAG_TESTING && + ride->current_test_segment + 1 >= ride->num_stations) { + vehicle_update_test_finish(vehicle); + } + vehicle->status = VEHICLE_STATUS_MOVING_TO_END_OF_STATION; + vehicle->sub_state = 0; + vehicle_invalidate_window(vehicle); +} + +/** + * + * rct2: 0x006D9CE9 + */ +static void vehicle_update_waiting_for_cable_lift(rct_vehicle *vehicle) +{ + rct_ride* ride = get_ride(vehicle->ride); + + rct_vehicle* cableLift = GET_VEHICLE(ride->cable_lift); + + if (cableLift->status != VEHICLE_STATUS_WAITING_FOR_PASSENGERS) + return; + + cableLift->status = VEHICLE_STATUS_WAITING_TO_DEPART; + cableLift->cable_lift_target = vehicle->sprite_index; +} + +/** + * + * rct2: 0x006D9D21 + */ +static void vehicle_update_travelling_cable_lift(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + + if (vehicle->sub_state == 0) { + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_BROKEN_TRAIN) { + if (ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN) + return; + + ride->lifecycle_flags |= RIDE_LIFECYCLE_BROKEN_DOWN; + ride_breakdown_add_news_item(vehicle->ride); + ride->window_invalidate_flags |= + RIDE_INVALIDATE_RIDE_MAIN | + RIDE_INVALIDATE_RIDE_LIST | + RIDE_INVALIDATE_RIDE_MAINTENANCE; + + ride->mechanic_status = RIDE_MECHANIC_STATUS_CALLING; + ride->inspection_station = vehicle->current_station; + ride->breakdown_reason = ride->breakdown_reason_pending; + vehicle->velocity = 0; + return; + } + + vehicle->sub_state = 1; + vehicle_peep_easteregg_here_we_are(vehicle); + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED)) { + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_TESTING) { + if (ride->current_test_segment + 1 < ride->num_stations) { + ride->current_test_segment++; + ride->current_test_station = vehicle->current_station; + } + else { + vehicle_update_test_finish(vehicle); + } + } + else if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_TEST_IN_PROGRESS)) { + vehicle_test_reset(vehicle); + } + } + } + + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + if (vehicle->velocity <= 439800) { + vehicle->acceleration = 4398; + } + int flags = vehicle_update_track_motion(vehicle, NULL); + + if (flags & VEHICLE_UPDATE_MOTION_TRACK_FLAG_11) { + vehicle->status = VEHICLE_STATUS_TRAVELLING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 1; + vehicle->lost_time_out = 0; + return; + } + + if (vehicle->sub_state == 2) + return; + + if (flags & VEHICLE_UPDATE_MOTION_TRACK_FLAG_3 && vehicle->current_station == RCT2_GLOBAL(0x00F64E1C, uint8)) + return; + + vehicle->sub_state = 2; + + if (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT_BLOCK_SECTIONED || + ride->mode == RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED) + return; + + // This is slightly different to the vanilla function + ride->station_depart[vehicle->current_station] &= STATION_DEPART_FLAG; + uint8 waitingTime = 3; + if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH) { + waitingTime = max(ride->min_waiting_time, 3); + waitingTime = min(waitingTime, 127); + } + + ride->station_depart[vehicle->current_station] |= waitingTime; +} + +/** + * + * rct2: 0x006D9820 + */ +static void vehicle_update_travelling_boat(rct_vehicle* vehicle) +{ + vehicle_check_if_missing(vehicle); + vehicle_update_motion_boat_hire(vehicle); +} + +static void loc_6DA9F9(rct_vehicle *vehicle, int x, int y, int bx, int dx) +{ + vehicle->remaining_distance = 0; + if (!vehicle_update_motion_collision_detection(vehicle, x, y, vehicle->z, NULL)) { + vehicle->track_x = bx; + vehicle->track_y = dx; + + rct_map_element *mapElement = map_get_track_element_at( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z >> 3 + ); + + rct_ride *ride = get_ride(vehicle->ride); + vehicle->track_type = + (mapElement->properties.track.type << 2) | + (ride->boat_hire_return_direction & 3); + + vehicle->track_progress = 0; + vehicle->status = VEHICLE_STATUS_TRAVELLING; + unk_F64E20->x = x; + unk_F64E20->y = y; + } +} + +/** + * + * rct2: 0x006DA717 + */ +static void vehicle_update_motion_boat_hire(rct_vehicle *vehicle) +{ + RCT2_GLOBAL(0x00F64E18, uint32) = 0; + vehicle->velocity += vehicle->acceleration; + RCT2_GLOBAL(0x00F64E08, sint32) = vehicle->velocity; + RCT2_GLOBAL(0x00F64E0C, sint32) = (vehicle->velocity >> 10) * 42; + + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + if (vehicleEntry->flags_b & (VEHICLE_ENTRY_FLAG_B_7 | VEHICLE_ENTRY_FLAG_B_8)) { + sub_6D63D4(vehicle); + } + + RCT2_GLOBAL(0x00F64E10, uint32) = 1; + vehicle->acceleration = 0; + vehicle->remaining_distance += RCT2_GLOBAL(0x00F64E0C, sint32); + if (vehicle->remaining_distance >= 0x368A) { + vehicle->var_B8 &= ~(1 << 1); + unk_F64E20->x = vehicle->x; + unk_F64E20->y = vehicle->y; + unk_F64E20->z = vehicle->z; + vehicle_invalidate(vehicle); + + for (;;) { + // loc_6DA7A5 + vehicle->var_35++; + int x = (vehicle->boat_location.x * 32) + 16; + int y = (vehicle->boat_location.y * 32) + 16; + int z; + uint8 bl; + + x -= vehicle->x; + if (x >= 0) { + y -= vehicle->y; + if (y < 0) { + // loc_6DA81A: + y = -y; + bl = 24; + if (y <= x * 4) { + bl = 16; + if (x <= y * 4) { + bl = 20; + } + } + } else { + bl = 8; + if (y <= x * 4) { + bl = 16; + if (x <= y * 4) { + bl = 12; + } + } + } + } else { + y -= vehicle->y; + if (y < 0) { + // loc_6DA83D: + x = -x; + y = -y; + bl = 24; + if (y <= x * 4) { + bl = 0; + if (x <= y * 4) { + bl = 28; + } + } + } else { + x = -x; + bl = 8; + if (y <= x * 4) { + bl = 0; + if (x <= y * 4) { + bl = 4; + } + } + } + } + + // loc_6DA861: + vehicle->var_34 = bl; + x += y; + if (x <= 12) { + sub_6DA280(vehicle); + } + + if (!(vehicle->var_35 & (1 << 0))) { + uint8 spriteDirection = vehicle->sprite_direction; + if (spriteDirection != vehicle->var_34) { + uint8 dl = (vehicle->var_34 + 16 - spriteDirection) & 0x1E; + if (dl >= 16) { + spriteDirection += 2; + if (dl > 24) { + vehicle->var_35--; + } + } else { + spriteDirection -= 2; + if (dl < 8) { + vehicle->var_35--; + } + } + + vehicle->sprite_direction = spriteDirection & 0x1E; + } + } + + int edi = (vehicle->sprite_direction | (vehicle->var_35 & 1)) & 0x1F; + x = vehicle->x + RCT2_ADDRESS(0x009A36C4, sint16)[edi * 4]; + y = vehicle->y + RCT2_ADDRESS(0x009A36C6, sint16)[edi * 4]; + z = vehicle->z; + if (vehicle_update_motion_collision_detection(vehicle, x, y, z, NULL)) { + vehicle->remaining_distance = 0; + if (vehicle->sprite_direction == vehicle->var_34) { + vehicle->sprite_direction ^= (1 << 4); + sub_6DA280(vehicle); + vehicle->sprite_direction ^= (1 << 4); + } + break; + } + + int bx = floor2(x, 32); + int dx = floor2(y, 32); + if (bx != vehicle->track_x || dx != vehicle->track_y) { + if (vehicle_is_boat_on_water(vehicle, x, y)) { + // loc_6DA939: + rct_ride *ride = get_ride(vehicle->ride); + + bool do_loc_6DAA97 = false; + if (vehicle->sub_state != 1) { + do_loc_6DAA97 = true; + } else { + uint16 xy = (((dx >> 5) << 8) | (bx >> 5)); + if (xy != ride->boat_hire_return_position) { + do_loc_6DAA97 = true; + } + } + + // loc_6DAA97: + if (do_loc_6DAA97) { + vehicle->remaining_distance = 0; + if (vehicle->sprite_direction == vehicle->var_34) { + sub_6DA280(vehicle); + } + break; + } + + if (!(ride->boat_hire_return_direction & 1)) { + uint16 bp = y & 0x1F; + if (bp == 16) { + loc_6DA9F9(vehicle, x, y, bx, dx); + break; + } + if (bp <= 16) { + x = unk_F64E20->x; + y = unk_F64E20->y + 1; + } else { + x = unk_F64E20->x; + y = unk_F64E20->y - 1; + } + } else { + // loc_6DA9A2: + uint16 bp = x & 0x1F; + if (bp == 16) { + loc_6DA9F9(vehicle, x, y, bx, dx); + break; + } + if (bp <= 16) { + x = unk_F64E20->x + 1; + y = unk_F64E20->y; + } else { + x = unk_F64E20->x - 1; + y = unk_F64E20->y; + } + } + + // loc_6DA9D1: + vehicle->remaining_distance = 0; + if (!vehicle_update_motion_collision_detection(vehicle, x, y, vehicle->z, NULL)) { + unk_F64E20->x = x; + unk_F64E20->y = y; + } + break; + } + vehicle->track_x = bx; + vehicle->track_y = dx; + } + + vehicle->remaining_distance -= RCT2_ADDRESS(0x009A36C8, uint32)[edi * 2]; + unk_F64E20->x = x; + unk_F64E20->y = y; + if (vehicle->remaining_distance < 0x368A) { + break; + } + RCT2_GLOBAL(0x00F64E10, uint32)++; + } + + sprite_move( + unk_F64E20->x, + unk_F64E20->y, + unk_F64E20->z, + (rct_sprite*)vehicle + ); + vehicle_invalidate(vehicle); + } + +// loc_6DAAC9: + { + int edx = vehicle->velocity >> 8; + edx = (edx * edx); + if (vehicle->velocity < 0) { + edx = -edx; + } + edx >>= 5; + + // Hack to fix people messing with boat hire + int friction = vehicle->friction == 0 ? 1 : vehicle->friction; + + int eax = ((vehicle->velocity >> 1) + edx) / friction; + int ecx = -eax; + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3) { + eax = vehicle->speed << 14; + int ebx = (vehicle->speed * friction) >> 2; + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_3) { + eax = -eax; + } + eax -= vehicle->velocity; + edx = vehicle->powered_acceleration * 2; + ecx += (eax * edx) / ebx; + } + vehicle->acceleration = ecx; + } + // eax = RCT2_GLOBAL(0x00F64E18, uint32); + // ebx = RCT2_GLOBAL(0x00F64E1C, uint32); +} + + /** + * + * rct2: 0x006DA280 + */ +static void sub_6DA280(rct_vehicle *vehicle) +{ + rct_ride* ride = get_ride(vehicle->ride); + + rct_xy8 location = { + .x = (vehicle->x + TileDirectionDelta[ride->boat_hire_return_direction & 3].x) / 32, + .y = (vehicle->y + TileDirectionDelta[ride->boat_hire_return_direction & 3].y) / 32 + }; + + if (*((uint16*)&location) == ride->boat_hire_return_position) { + vehicle->sub_state = 1; + vehicle->boat_location = location; + return; + } + + vehicle->sub_state = 0; + uint8 curDirection = ((vehicle->sprite_direction + 19) >> 3) & 3; + uint8 randDirection = scenario_rand() & 3; + + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + if (scenario_rand() & 1 && (!(rideEntry->flags & RIDE_ENTRY_FLAG_7) || vehicle->lost_time_out > 1920)) { + location = *((rct_xy8*)&ride->boat_hire_return_position); + rct_xy16 destLocation = { + .x = location.x * 32 - TileDirectionDelta[ride->boat_hire_return_direction & 3].x + 16, + .y = location.y * 32 - TileDirectionDelta[ride->boat_hire_return_direction & 3].y + 16 + }; + + destLocation.x -= vehicle->x; + destLocation.y -= vehicle->y; + + if (abs(destLocation.x) <= abs(destLocation.y)) { + randDirection = destLocation.y < 0 ? 3 : 1; + } else { + randDirection = destLocation.x < 0 ? 0 : 2; + } + } + + static const sint8 rotations[] = { 0, 1, -1, 2 }; + for (int i = 0; i < 4; i++) { + if (randDirection + rotations[i] == curDirection) { + continue; + } + + sint16 x = vehicle->track_x + TileDirectionDelta[(randDirection + rotations[i]) & 3].x; + sint16 y = vehicle->track_y + TileDirectionDelta[(randDirection + rotations[i]) & 3].y; + + if (vehicle_is_boat_on_water(vehicle, x, y)) { + continue; + } + vehicle->boat_location.x = x / 32; + vehicle->boat_location.y = y / 32; + return; + } + + sint16 x = vehicle->track_x + TileDirectionDelta[curDirection & 3].x; + sint16 y = vehicle->track_y + TileDirectionDelta[curDirection & 3].y; + vehicle->boat_location.x = x / 32; + vehicle->boat_location.y = y / 32; +} + + /** + * + * rct2: 0x006DA22A + */ +static bool vehicle_is_boat_on_water(rct_vehicle *vehicle, int x, int y) +{ + int z = vehicle->track_z >> 3; + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SURFACE) { + int waterZ = (mapElement->properties.surface.terrain & 0x1F) * 2; + if (z != waterZ) { + return true; + } + } else { + if (z > mapElement->base_height - 2 && z < mapElement->clearance_height + 2) { + return true; + } + } + } while (!map_element_is_last_for_tile(mapElement++)); + return false; +} + + /** + * + * rct2: 0x006D9249 + */ +static void vehicle_update_swinging(rct_vehicle* vehicle) { + rct_ride* ride = get_ride(vehicle->ride); + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + + // SubState for this ride means swinging state + // 0 == first swing + // 3 == full swing + uint8 swingState = vehicle->sub_state; + if (rideEntry->flags & RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_1) { + swingState += 4; + if (rideEntry->flags & RIDE_ENTRY_FLAG_ALTERNATIVE_SWING_MODE_2) + swingState += 4; + } + uint8* edi = RCT2_ADDRESS(0x0099F9D0, uint8*)[swingState]; + uint8 al = edi[(uint16)(vehicle->current_time + 1)]; + + // 0x80 indicates that a complete swing has been + // completed and the next swing can start + if (al != 0x80) { + vehicle->current_time++; + if (al == vehicle->vehicle_sprite_type) + return; + // Used to know which sprite to draw + vehicle->vehicle_sprite_type = al; + vehicle_invalidate(vehicle); + return; + } + + vehicle->current_time = -1; + vehicle->var_CE++; + if (ride->status != RIDE_STATUS_CLOSED) { + // It takes 3 swings to get into full swing + // ride->rotations already takes this into account + if (vehicle->var_CE + 3 < ride->rotations) { + // Go to the next swing state until we + // are at full swing. + if (vehicle->sub_state != 3) { + vehicle->sub_state++; + } + vehicle_update_swinging(vehicle); + return; + } + } + + // To get to this part of the code the + // swing has to be in slowing down phase + if (vehicle->sub_state == 0) { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; + return; + } + // Go towards first swing state + vehicle->sub_state--; + vehicle_update_swinging(vehicle); +} + +/** + * + * rct2: 0x006D9413 + */ +static void vehicle_update_ferris_wheel_rotating(rct_vehicle* vehicle) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + rct_ride* ride = get_ride(vehicle->ride); + if ((vehicle->ferris_wheel_var_1 -= 1) != 0) + return; + + sint8 ferris_wheel_var_0 = vehicle->ferris_wheel_var_0; + + if (ferris_wheel_var_0 == 3) { + vehicle->ferris_wheel_var_0 = ferris_wheel_var_0; + vehicle->ferris_wheel_var_1 = ferris_wheel_var_0; + } + else if (ferris_wheel_var_0 < 3) { + if (ferris_wheel_var_0 != -8) + ferris_wheel_var_0--; + vehicle->ferris_wheel_var_0 = ferris_wheel_var_0; + vehicle->ferris_wheel_var_1 = -ferris_wheel_var_0; + } + else { + ferris_wheel_var_0--; + vehicle->ferris_wheel_var_0 = ferris_wheel_var_0; + vehicle->ferris_wheel_var_1 = ferris_wheel_var_0; + } + + uint8 rotation = vehicle->vehicle_sprite_type; + if (ride->mode == RIDE_MODE_FORWARD_ROTATION) + rotation++; + else + rotation--; + + rotation &= 0x7F; + vehicle->vehicle_sprite_type = rotation; + + if (rotation == vehicle->sub_state) + vehicle->var_CE++; + + vehicle_invalidate(vehicle); + + uint8 subState = vehicle->sub_state; + if (ride->mode == RIDE_MODE_FORWARD_ROTATION) + subState++; + else + subState--; + subState &= 0x7F; + + if (subState == vehicle->vehicle_sprite_type) { + bool shouldStop = true; + if (ride->status != RIDE_STATUS_CLOSED) { + if (vehicle->var_CE < ride->rotations) + shouldStop = false; + } + + if (shouldStop) { + ferris_wheel_var_0 = vehicle->ferris_wheel_var_0; + vehicle->ferris_wheel_var_0 = -abs(ferris_wheel_var_0); + vehicle->ferris_wheel_var_1 = abs(ferris_wheel_var_0); + } + } + + if (vehicle->ferris_wheel_var_0 != -8) + return; + + subState = vehicle->sub_state; + if (ride->mode == RIDE_MODE_FORWARD_ROTATION) + subState += 8; + else + subState -= 8; + subState &= 0x7F; + + if (subState != vehicle->vehicle_sprite_type) + return; + + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; +} + +/** + * + * rct2: 0x006D94F2 + */ +static void vehicle_update_simulator_operating(rct_vehicle* vehicle) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + uint8* edi = RCT2_ADDRESS(0x009A042C, uint8*)[vehicle->sub_state]; + + uint8 al = edi[(uint16)(vehicle->current_time + 1)]; + if (al != 0xFF) { + vehicle->current_time++; + if (al == vehicle->vehicle_sprite_type) + return; + vehicle->vehicle_sprite_type = al; + vehicle_invalidate(vehicle); + return; + } + + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; +} + +/** + * + * rct2: 0x006D92FF + */ +static void vehicle_update_rotating(rct_vehicle* vehicle) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + rct_ride* ride = get_ride(vehicle->ride); + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + + uint8* edi; + if (rideEntry->flags & RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_1) { + edi = RCT2_ADDRESS(0x0099F0F4, uint8*)[vehicle->sub_state]; + } + else if (rideEntry->flags & RIDE_ENTRY_FLAG_ALTERNATIVE_ROTATION_MODE_2) { + edi = RCT2_ADDRESS(0x009A2428, uint8*)[vehicle->sub_state]; + } + else { + edi = RCT2_ADDRESS(0x0099EB1C, uint8*)[vehicle->sub_state]; + } + + sint32 var_4C = (sint16)vehicle->current_time; + if (RCT2_GLOBAL(0x00F64E34, uint8) == BREAKDOWN_CONTROL_FAILURE) { + var_4C += (ride->breakdown_sound_modifier >> 6) + 1; + } + var_4C++; + + uint8 al = edi[(uint32)var_4C]; + if (al != 0xFF) { + vehicle->current_time = (uint16)var_4C; + if (al == vehicle->vehicle_sprite_type) + return; + vehicle->vehicle_sprite_type = al; + vehicle_invalidate(vehicle); + return; + } + + vehicle->current_time = -1; + vehicle->var_CE++; + if (RCT2_GLOBAL(0x00F64E34, uint8) != BREAKDOWN_CONTROL_FAILURE) { + bool shouldStop = true; + if (ride->status != RIDE_STATUS_CLOSED) { + al = vehicle->var_CE + 1; + if (ride->type == RIDE_TYPE_ENTERPRISE) + al += 9; + + if (al < ride->rotations) + shouldStop = false; + } + + if (shouldStop == true) { + if (vehicle->sub_state == 2) { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; + return; + } + vehicle->sub_state++; + vehicle_update_rotating(vehicle); + return; + } + } + + if (ride->type == RIDE_TYPE_ENTERPRISE && + vehicle->sub_state == 2) { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; + return; + } + + vehicle->sub_state = 1; + vehicle_update_rotating(vehicle); +} + +/** + * + * rct2: 0x006D97CB + */ +static void vehicle_update_space_rings_operating(rct_vehicle* vehicle) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + uint8* edi = RCT2_ADDRESS(0x009A0ACC, uint8*)[vehicle->sub_state]; + + uint8 al = edi[(uint16)(vehicle->current_time + 1)]; + if (al != 0xFF) { + vehicle->current_time++; + if (al == vehicle->vehicle_sprite_type) + return; + vehicle->vehicle_sprite_type = al; + vehicle_invalidate(vehicle); + return; + } + + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; +} + +/** + * + * rct2: 0x006D9641 + */ +static void vehicle_update_haunted_house_operating(rct_vehicle* vehicle) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + if (vehicle->vehicle_sprite_type != 0) { + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 1) { + vehicle->vehicle_sprite_type++; + vehicle_invalidate(vehicle); + + if (vehicle->vehicle_sprite_type == 19) + vehicle->vehicle_sprite_type = 0; + } + } + + uint16* edi = RCT2_ADDRESS(0x009A0ABC, uint16*)[vehicle->sub_state]; + + uint16 ax = *edi; + if ((uint16)(vehicle->current_time + 1) > ax) { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; + return; + } + + vehicle->current_time++; + switch (vehicle->current_time) { + case 45: + audio_play_sound_at_location( + SOUND_HAUNTED_HOUSE_SCARE, + vehicle->x, + vehicle->y, + vehicle->z); + break; + case 75: + vehicle->vehicle_sprite_type = 1; + vehicle_invalidate(vehicle); + break; + case 400: + audio_play_sound_at_location( + SOUND_HAUNTED_HOUSE_SCREAM_1, + vehicle->x, + vehicle->y, + vehicle->z); + break; + case 745: + audio_play_sound_at_location( + SOUND_HAUNTED_HOUSE_SCARE, + vehicle->x, + vehicle->y, + vehicle->z); + break; + case 775: + vehicle->vehicle_sprite_type = 1; + vehicle_invalidate(vehicle); + break; + case 1100: + audio_play_sound_at_location( + SOUND_HAUNTED_HOUSE_SCREAM_2, + vehicle->x, + vehicle->y, + vehicle->z); + break; + } +} + +/** + * + * rct2: 0x006d9781 + */ +static void vehicle_update_crooked_house_operating(rct_vehicle* vehicle) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + if ((uint16)(vehicle->current_time + 1) > RideCrookedHouseLength[vehicle->sub_state]) { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; + return; + } + + vehicle->current_time++; +} + +/** + * + * rct2: 0x006D9547 + */ +static void vehicle_update_top_spin_operating(rct_vehicle* vehicle) { + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + uint8* edi = RCT2_ADDRESS(0x009A12E0, uint8*)[vehicle->sub_state]; + + uint8 al = edi[(vehicle->current_time + 1) * 2]; + if (al != 0xFF) { + vehicle->current_time = vehicle->current_time + 1; + if (al != vehicle->vehicle_sprite_type) { + vehicle->vehicle_sprite_type = al; + vehicle_invalidate(vehicle); + } + al = edi[vehicle->current_time * 2 + 1]; + if (al != vehicle->bank_rotation) { + vehicle->bank_rotation = al; + vehicle_invalidate(vehicle); + } + return; + } + + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; +} + +/** + * + * rct2: 0x006D95AD + */ +static void vehicle_update_showing_film(rct_vehicle *vehicle) +{ + int currentTime, totalTime; + + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + totalTime = RideFilmLength[vehicle->sub_state]; + currentTime = vehicle->current_time + 1; + if (currentTime <= totalTime) { + vehicle->current_time = currentTime; + } + else { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; + } +} + +/** + * + * rct2: 0x006D95F7 + */ +static void vehicle_update_doing_circus_show(rct_vehicle *vehicle) +{ + int currentTime, totalTime; + + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) + return; + + totalTime = *(RCT2_ADDRESS(0x009A0AB4, uint16*)[vehicle->sub_state]); + currentTime = vehicle->current_time + 1; + if (currentTime <= totalTime) { + vehicle->current_time = currentTime; + } else { + vehicle->status = VEHICLE_STATUS_ARRIVING; + vehicle_invalidate_window(vehicle); + vehicle->sub_state = 0; + vehicle->var_C0 = 0; + } +} + +/** + * + * rct2: 0x0068B8BD + * @returns the map element that the vehicle will collide with or NULL if no collisions. + */ +static rct_map_element* vehicle_check_collision(sint16 x, sint16 y, sint16 z) { + rct_map_element* mapElement = map_get_first_element_at(x / 32, y / 32); + if (mapElement == NULL) + // Can't return null as that implies no collision, + // but should still cause a crash when dereferenced. + return (rct_map_element *) -1; + + uint8 bl; + if ((x & 0x1F) >= 16) { + bl = 1; + if ((y & 0x1F) < 16) + bl = 2; + } + else { + bl = 4; + if ((y & 0x1F) >= 16) + bl = 8; + } + + do { + if (z / 8 < mapElement->base_height) + continue; + + if (z / 8 >= mapElement->clearance_height) + continue; + + if (mapElement->flags & bl) + return mapElement; + } while (!map_element_is_last_for_tile(mapElement++)); + + return NULL; +} + +/** + * + * rct2: 0x006DE6C6 + */ +static void vehicle_kill_all_passengers(rct_vehicle* vehicle) { + uint16 numFatalities = 0; + + uint16 spriteId = vehicle->sprite_index; + for (rct_vehicle* curVehicle; spriteId != 0xFFFF; spriteId = curVehicle->next_vehicle_on_train) { + curVehicle = GET_VEHICLE(spriteId); + numFatalities += curVehicle->num_peeps; + } + + rct_ride* ride = get_ride(vehicle->ride); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = numFatalities; + + uint8 crashType = numFatalities == 0 ? + RIDE_CRASH_TYPE_NO_FATALITIES : + RIDE_CRASH_TYPE_FATALITIES; + + if (crashType >= ride->last_crash_type) + ride->last_crash_type = crashType; + + if (numFatalities != 0) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = ride->name_arguments; + news_item_add_to_queue(NEWS_ITEM_RIDE, STR_X_PEOPLE_DIED_ON_X, vehicle->ride); + + if (RCT2_GLOBAL(0x135882E, uint16) < 500) { + RCT2_GLOBAL(0x135882E, uint16) += 200; + } + } + + spriteId = vehicle->sprite_index; + for (rct_vehicle* curVehicle; spriteId != 0xFFFF; spriteId = curVehicle->next_vehicle_on_train) { + curVehicle = GET_VEHICLE(spriteId); + + if (curVehicle->num_peeps != curVehicle->next_free_seat) + continue; + + if (curVehicle->num_peeps == 0) + continue; + + for (uint8 i = 0; i < curVehicle->num_peeps; i++) { + rct_peep* peep = GET_PEEP(curVehicle->peep[i]); + if (peep->outside_of_park == 0) { + RCT2_GLOBAL(RCT2_ADDRESS_GUESTS_IN_PARK, uint16)--; + RCT2_GLOBAL(RCT2_ADDRESS_BTM_TOOLBAR_DIRTY_FLAGS, uint16) |= + BTM_TB_DIRTY_FLAG_PEEP_COUNT; + } + ride->num_riders--; + peep_sprite_remove(peep); + } + + curVehicle->num_peeps = 0; + curVehicle->next_free_seat = 0; + } +} + +static void vehicle_crash_on_land(rct_vehicle* vehicle) { + vehicle->status = VEHICLE_STATUS_CRASHED; + vehicle_invalidate_window(vehicle); + + rct_ride* ride = get_ride(vehicle->ride); + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)) { + + rct_vehicle* frontVehicle = vehicle; + while (frontVehicle->is_child != 0)frontVehicle = GET_VEHICLE(frontVehicle->prev_vehicle_on_ride); + + uint8 trainIndex = 0; + while (ride->vehicles[trainIndex] != frontVehicle->sprite_index) + trainIndex++; + + ride_crash(vehicle->ride, trainIndex); + + if (ride->status != RIDE_STATUS_CLOSED) { + ride_set_status(vehicle->ride, RIDE_STATUS_CLOSED); + } + } + ride->lifecycle_flags |= RIDE_LIFECYCLE_CRASHED; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; + + if (vehicle->is_child == 0) { + vehicle_kill_all_passengers(vehicle); + } + + vehicle->sub_state = 2; + audio_play_sound_at_location(SOUND_CRASH, vehicle->x, vehicle->y, vehicle->z); + + sprite_misc_3_create(vehicle->x, vehicle->y, vehicle->z); + sprite_misc_5_create(vehicle->x, vehicle->y, vehicle->z); + + uint8 numParticles = min(vehicle->sprite_width, 7); + + while (numParticles-- != 0) + crashed_vehicle_particle_create(vehicle->colours, vehicle->x, vehicle->y, vehicle->z); + + vehicle->flags |= SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE; + vehicle->var_C5 = 0; + vehicle->var_C8 = 0; + vehicle->sprite_width = 13; + vehicle->sprite_height_negative = 45; + vehicle->sprite_height_positive = 5; + + sprite_move(vehicle->x, vehicle->y, vehicle->z, (rct_sprite*)vehicle); + vehicle_invalidate(vehicle); + + vehicle->var_4E = 0; +} + +static void vehicle_crash_on_water(rct_vehicle* vehicle) { + vehicle->status = VEHICLE_STATUS_CRASHED; + vehicle_invalidate_window(vehicle); + + rct_ride* ride = get_ride(vehicle->ride); + if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED)) { + + rct_vehicle* frontVehicle = vehicle; + while (frontVehicle->is_child != 0)frontVehicle = GET_VEHICLE(frontVehicle->prev_vehicle_on_ride); + + uint8 trainIndex = 0; + while (ride->vehicles[trainIndex] != frontVehicle->sprite_index) + trainIndex++; + + ride_crash(vehicle->ride, trainIndex); + + if (ride->status != RIDE_STATUS_CLOSED) { + ride_set_status(vehicle->ride, RIDE_STATUS_CLOSED); + } + } + ride->lifecycle_flags |= RIDE_LIFECYCLE_CRASHED; + ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; + + if (vehicle->is_child == 0) { + vehicle_kill_all_passengers(vehicle); + } + + vehicle->sub_state = 2; + audio_play_sound_at_location(SOUND_WATER_1, vehicle->x, vehicle->y, vehicle->z); + + crash_splash_create(vehicle->x, vehicle->y, vehicle->z); + crash_splash_create(vehicle->x - 8, vehicle->y - 9, vehicle->z); + crash_splash_create(vehicle->x + 11, vehicle->y - 9, vehicle->z); + crash_splash_create(vehicle->x + 11, vehicle->y + 8, vehicle->z); + crash_splash_create(vehicle->x - 4, vehicle->y + 8, vehicle->z); + + for (int i = 0; i < 10; ++i) + crashed_vehicle_particle_create(vehicle->colours, vehicle->x - 4, vehicle->y + 8, vehicle->z); + + vehicle->flags |= SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE; + vehicle->var_C5 = 0; + vehicle->var_C8 = 0; + vehicle->sprite_width = 13; + vehicle->sprite_height_negative = 45; + vehicle->sprite_height_positive = 5; + + sprite_move(vehicle->x, vehicle->y, vehicle->z, (rct_sprite*)vehicle); + vehicle_invalidate(vehicle); + + vehicle->var_4E = 0xFFFF; +} + +/** + * + * rct2: 0x006D98CA + */ +static void vehicle_update_crash(rct_vehicle *vehicle){ + uint16 spriteId = vehicle->sprite_index; + rct_vehicle* curVehicle; + do { + curVehicle = GET_VEHICLE(spriteId); + if (curVehicle->sub_state > 1) { + if (curVehicle->var_4E <= 96) { + curVehicle->var_4E++; + if ((scenario_rand() & 0xFFFF) <= 0x1555) { + sprite_misc_3_create( + curVehicle->x + ((scenario_rand() & 2) - 1), + curVehicle->y + ((scenario_rand() & 2) - 1), + curVehicle->z + ); + } + } + if (curVehicle->var_C8 + 7281 > 0xFFFF) { + curVehicle->var_C5++; + if (curVehicle->var_C5 >= 8) + curVehicle->var_C5 = 0; + invalidate_sprite_2((rct_sprite*)curVehicle); + } + curVehicle->var_C8 += 7281; + continue; + } + + rct_map_element* collideElement = vehicle_check_collision(curVehicle->x, curVehicle->y, curVehicle->z); + if (collideElement == NULL) { + curVehicle->sub_state = 1; + } + else if (curVehicle->sub_state == 1){ + vehicle_crash_on_land(curVehicle); + continue; + } + + int z = map_element_height(curVehicle->x, curVehicle->y); + sint16 waterHeight = (z >> 16) & 0xFFFF; + z = (sint16)(z & 0xFFFF); + sint16 zDiff; + if (waterHeight != 0) { + zDiff = curVehicle->z - waterHeight; + if (zDiff <= 0 && zDiff >= -20) { + vehicle_crash_on_water(curVehicle); + continue; + } + } + + zDiff = curVehicle->z - z; + if ((zDiff <= 0 && zDiff >= -20) || curVehicle->z < 16){ + vehicle_crash_on_land(curVehicle); + continue; + } + + invalidate_sprite_2((rct_sprite*)curVehicle); + + rct_xyz16 curPosition = { + .x = curVehicle->x, + .y = curVehicle->y, + .z = curVehicle->z + }; + + curPosition.x += (sint8)(curVehicle->var_B6 >> 8); + curPosition.y += (sint8)(curVehicle->var_C0 >> 8); + curPosition.z += (sint8)(curVehicle->var_4E >> 8); + curVehicle->track_x = (sint16)(curVehicle->var_B6 << 8); + curVehicle->track_y = (sint16)(curVehicle->var_C0 << 8); + curVehicle->track_z = (sint16)(curVehicle->var_4E << 8); + + if (curPosition.x > 0x1FFF || + curPosition.y > 0x1FFF) { + vehicle_crash_on_land(curVehicle); + continue; + } + + sprite_move(curPosition.x, curPosition.y, curPosition.z, (rct_sprite*)curVehicle); + invalidate_sprite_2((rct_sprite*)curVehicle); + + if (curVehicle->sub_state == 1) { + curVehicle->var_4E += 0xFFEC; + } + } while ((spriteId = curVehicle->next_vehicle_on_train) != 0xFFFF); +} +/** + * + * rct2: 0x006D7888 + */ +static void vehicle_update_sound(rct_vehicle *vehicle) +{ + rct_ride *ride; + rct_ride_entry *rideEntry; + // frictionVolume (bl) should be set before hand + uint8 frictionVolume = 255, frictionId = 255; + // bh screamVolume should be set before hand + uint8 screamId, screamVolume = 255; + uint16 soundIdVolume; + + ride = get_ride(vehicle->ride); + rideEntry = get_ride_entry(vehicle->ride_subtype); + + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + int ecx = abs(vehicle->velocity) - 0x10000; + if (ecx >= 0) { + frictionId = vehicleEntry->friction_sound_id; + ecx >>= 15; + frictionVolume = min(208 + (ecx & 0xFF), 255); + } + + switch (vehicleEntry->sound_range) { + case 3: + screamId = vehicle->scream_sound_id; + if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x7F)) { + if (vehicle->velocity < 0x40000 || vehicle->scream_sound_id != 255) + goto loc_6D7A97; + + if ((scenario_rand() & 0xFFFF) <= 0x5555) { + vehicle->scream_sound_id = SOUND_TRAIN_WHISTLE; + screamVolume = 255; + break; + } + } + if (screamId == NO_SCREAM) screamId = 255; + screamVolume = 255; + break; + + case 4: + screamId = vehicle->scream_sound_id; + if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x7F)) { + if (vehicle->velocity < 0x40000 || vehicle->scream_sound_id != 255) + goto loc_6D7A97; + + if ((scenario_rand() & 0xFFFF) <= 0x5555) { + vehicle->scream_sound_id = SOUND_TRAM; + screamVolume = 255; + break; + } + } + if (screamId == NO_SCREAM) screamId = 255; + screamVolume = 255; + break; + + default: + if ((vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_4)) { + screamId = vehicle_update_scream_sound(vehicle); + if (screamId == NO_SCREAM) + screamId = 255; + if (screamId == 255) + goto loc_6D7A97; + break; + } + + loc_6D7A97: + vehicle->scream_sound_id = 255; + assert(ride->type < countof(RideLiftData)); + // Get lift hill sound + screamId = RideLiftData[ride->type].sound_id; + screamVolume = 243; + if (!(vehicle->var_B8 & 2)) + screamId = 255; + } + + // Friction sound + soundIdVolume = sub_6D7AC0(vehicle->sound1_id, vehicle->sound1_volume, frictionId, frictionVolume); + vehicle->sound1_id = soundIdVolume & 0xFF; + vehicle->sound1_volume = (soundIdVolume >> 8) & 0xFF; + + // Scream sound + soundIdVolume = sub_6D7AC0(vehicle->sound2_id, vehicle->sound2_volume, screamId, screamVolume); + vehicle->sound2_id = soundIdVolume & 0xFF; + vehicle->sound2_volume = (soundIdVolume >> 8) & 0xFF; + + { + int ebx = RCT2_ADDRESS(0x009A3684, sint16)[vehicle->sprite_direction]; + int eax = ((vehicle->velocity >> 14) * ebx) >> 14; + eax = clamp(-127, eax, 127); + + vehicle->var_BF = eax & 0xFF; + } +} + +/** + * + * rct2: 0x006D796B + */ +static int vehicle_update_scream_sound(rct_vehicle *vehicle) +{ + uint32 r; + uint16 spriteIndex; + rct_ride_entry *rideEntry; + rct_vehicle *vehicle2; + + rideEntry = get_ride_entry(vehicle->ride_subtype); + + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + int totalNumPeeps = vehicle_get_total_num_peeps(vehicle); + if (totalNumPeeps == 0) + return 255; + + if (vehicle->velocity < 0) { + if (vehicle->velocity > -0x2C000) + return 255; + + spriteIndex = vehicle->sprite_index; + do { + vehicle2 = &(g_sprite_list[spriteIndex].vehicle); + if (vehicle2->vehicle_sprite_type < 1) + continue; + if (vehicle2->vehicle_sprite_type <= 4) + goto produceScream; + if (vehicle2->vehicle_sprite_type < 9) + continue; + if (vehicle2->vehicle_sprite_type <= 15) + goto produceScream; + } while ((spriteIndex = vehicle2->next_vehicle_on_train) != SPRITE_INDEX_NULL); + return 255; + } + + if (vehicle->velocity < 0x2C000) + return 255; + + spriteIndex = vehicle->sprite_index; + do { + vehicle2 = &(g_sprite_list[spriteIndex].vehicle); + if (vehicle2->vehicle_sprite_type < 5) + continue; + if (vehicle2->vehicle_sprite_type <= 8) + goto produceScream; + if (vehicle2->vehicle_sprite_type < 17) + continue; + if (vehicle2->vehicle_sprite_type <= 23) + goto produceScream; + } while ((spriteIndex = vehicle2->next_vehicle_on_train) != SPRITE_INDEX_NULL); + return 255; + +produceScream: + if (vehicle->scream_sound_id == 255) { + r = scenario_rand(); + if (totalNumPeeps >= (int)(r % 16)) { + switch (vehicleEntry->sound_range) { + case 0: + vehicle->scream_sound_id = byte_9A3A14[r % 2]; + break; + case 1: + vehicle->scream_sound_id = byte_9A3A18[r % 7]; + break; + case 2: + vehicle->scream_sound_id = byte_9A3A16[r % 2]; + break; + default: + vehicle->scream_sound_id = NO_SCREAM; + break; + } + } else { + vehicle->scream_sound_id = NO_SCREAM; + } + } + return vehicle->scream_sound_id; } /** @@ -467,13 +4417,519 @@ static void vehicle_update(rct_vehicle *vehicle) */ void vehicle_get_g_forces(rct_vehicle *vehicle, int *verticalG, int *lateralG) { - int eax, ebx, ecx, edx, esi, edi, ebp; + int gForceVert = (((sint64)0x280000) * RCT2_ADDRESS(0x009A37E4, sint32)[vehicle->vehicle_sprite_type]) >> 32; + gForceVert = (((sint64)gForceVert) * RCT2_ADDRESS(0x009A39C4, sint32)[vehicle->bank_rotation]) >> 32; + int lateralFactor = 0, vertFactor = 0; - esi = (int)vehicle; - RCT2_CALLFUNC_X(0x006D73D0, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); + // Note shr has meant some of the below functions cast a known negative number to + // unsigned. Possibly an original bug but will be left implemented. + switch (vehicle->track_type >> 2) { + case TRACK_ELEM_FLAT: + case TRACK_ELEM_END_STATION: + case TRACK_ELEM_BEGIN_STATION: + case TRACK_ELEM_MIDDLE_STATION: + case TRACK_ELEM_25_DEG_UP: + case TRACK_ELEM_60_DEG_UP: // + case TRACK_ELEM_25_DEG_DOWN: + case TRACK_ELEM_60_DEG_DOWN: // + case TRACK_ELEM_FLAT_TO_LEFT_BANK: + case TRACK_ELEM_FLAT_TO_RIGHT_BANK: + case TRACK_ELEM_LEFT_BANK_TO_FLAT: + case TRACK_ELEM_RIGHT_BANK_TO_FLAT:// + case TRACK_ELEM_LEFT_BANK: + case TRACK_ELEM_RIGHT_BANK: + case TRACK_ELEM_TOWER_BASE: + case TRACK_ELEM_TOWER_SECTION: + case TRACK_ELEM_FLAT_COVERED: + case TRACK_ELEM_25_DEG_UP_COVERED: + case TRACK_ELEM_60_DEG_UP_COVERED: + case TRACK_ELEM_25_DEG_DOWN_COVERED: + case TRACK_ELEM_60_DEG_DOWN_COVERED: + case TRACK_ELEM_BRAKES: + case TRACK_ELEM_ROTATION_CONTROL_TOGGLE: + case TRACK_ELEM_INVERTED_90_DEG_UP_TO_FLAT_QUARTER_LOOP: + case TRACK_ELEM_25_DEG_UP_LEFT_BANKED: + case TRACK_ELEM_25_DEG_UP_RIGHT_BANKED: + case TRACK_ELEM_WATERFALL: + case TRACK_ELEM_RAPIDS: + case TRACK_ELEM_ON_RIDE_PHOTO: + case TRACK_ELEM_25_DEG_DOWN_LEFT_BANKED: + case TRACK_ELEM_25_DEG_DOWN_RIGHT_BANKED: + case TRACK_ELEM_WHIRLPOOL: + case TRACK_ELEM_REVERSE_WHOA_BELLY_VERTICAL: + case TRACK_ELEM_90_DEG_UP: + case TRACK_ELEM_90_DEG_DOWN: + case TRACK_ELEM_DIAG_FLAT: + case TRACK_ELEM_DIAG_25_DEG_UP: + case TRACK_ELEM_DIAG_60_DEG_UP: + case TRACK_ELEM_DIAG_25_DEG_DOWN: + case TRACK_ELEM_DIAG_60_DEG_DOWN: + case TRACK_ELEM_DIAG_FLAT_TO_LEFT_BANK: + case TRACK_ELEM_DIAG_FLAT_TO_RIGHT_BANK: + case TRACK_ELEM_DIAG_LEFT_BANK_TO_FLAT: + case TRACK_ELEM_DIAG_RIGHT_BANK_TO_FLAT: + case TRACK_ELEM_DIAG_LEFT_BANK: + case TRACK_ELEM_DIAG_RIGHT_BANK: + case TRACK_ELEM_LOG_FLUME_REVERSER: + case TRACK_ELEM_SPINNING_TUNNEL: + case TRACK_ELEM_POWERED_LIFT: + case TRACK_ELEM_MINI_GOLF_HOLE_A: + case TRACK_ELEM_MINI_GOLF_HOLE_B: + case TRACK_ELEM_MINI_GOLF_HOLE_C: + case TRACK_ELEM_MINI_GOLF_HOLE_D: + case TRACK_ELEM_MINI_GOLF_HOLE_E: + case TRACK_ELEM_LEFT_REVERSER: + case TRACK_ELEM_RIGHT_REVERSER: + case TRACK_ELEM_AIR_THRUST_VERTICAL_DOWN: + case TRACK_ELEM_BLOCK_BRAKES: + case TRACK_ELEM_25_DEG_UP_TO_LEFT_BANKED_25_DEG_UP: + case TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANKED_25_DEG_UP: + case TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_25_DEG_UP: + case TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_25_DEG_UP: + case TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANKED_25_DEG_DOWN: + case TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANKED_25_DEG_DOWN: + case TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_25_DEG_DOWN: + case TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_25_DEG_DOWN: + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_90_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_90_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_90_DEG_DOWN: + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_90_DEG_DOWN: + //6d73FF + // Do nothing + break; + case TRACK_ELEM_FLAT_TO_25_DEG_UP:// + case TRACK_ELEM_25_DEG_DOWN_TO_FLAT:// + case TRACK_ELEM_LEFT_BANK_TO_25_DEG_UP: + case TRACK_ELEM_RIGHT_BANK_TO_25_DEG_UP: + case TRACK_ELEM_25_DEG_DOWN_TO_LEFT_BANK: + case TRACK_ELEM_25_DEG_DOWN_TO_RIGHT_BANK: + case TRACK_ELEM_FLAT_TO_25_DEG_UP_COVERED: + case TRACK_ELEM_25_DEG_DOWN_TO_FLAT_COVERED: + case TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_UP: + case TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_UP: + case TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_LEFT_BANKED_FLAT: + case TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_RIGHT_BANKED_FLAT: + case TRACK_ELEM_FLAT_TO_LEFT_BANKED_25_DEG_UP: + case TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_UP: + case TRACK_ELEM_LEFT_BANKED_25_DEG_DOWN_TO_FLAT: + case TRACK_ELEM_RIGHT_BANKED_25_DEG_DOWN_TO_FLAT: + vertFactor = 103; + //6d7509 + break; + case TRACK_ELEM_25_DEG_UP_TO_FLAT:// + case TRACK_ELEM_FLAT_TO_25_DEG_DOWN:// + case TRACK_ELEM_25_DEG_UP_TO_LEFT_BANK: + case TRACK_ELEM_25_DEG_UP_TO_RIGHT_BANK: + case TRACK_ELEM_LEFT_BANK_TO_25_DEG_DOWN: + case TRACK_ELEM_RIGHT_BANK_TO_25_DEG_DOWN: + case TRACK_ELEM_25_DEG_UP_TO_FLAT_COVERED: + case TRACK_ELEM_FLAT_TO_25_DEG_DOWN_COVERED: + case TRACK_ELEM_CABLE_LIFT_HILL: + case TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_LEFT_BANKED_FLAT: + case TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_RIGHT_BANKED_FLAT: + case TRACK_ELEM_LEFT_BANKED_FLAT_TO_LEFT_BANKED_25_DEG_DOWN: + case TRACK_ELEM_RIGHT_BANKED_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN: + case TRACK_ELEM_LEFT_BANKED_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_RIGHT_BANKED_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_FLAT_TO_LEFT_BANKED_25_DEG_DOWN: + case TRACK_ELEM_FLAT_TO_RIGHT_BANKED_25_DEG_DOWN: + vertFactor = -103; + //6d7569 + break; + case TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP:// + case TRACK_ELEM_60_DEG_DOWN_TO_25_DEG_DOWN:// + case TRACK_ELEM_25_DEG_UP_TO_60_DEG_UP_COVERED: + case TRACK_ELEM_60_DEG_DOWN_TO_25_DEG_DOWN_COVERED: + vertFactor = 82; + //6d7545 + break; + case TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP:// + case TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN:// + case TRACK_ELEM_60_DEG_UP_TO_25_DEG_UP_COVERED: + case TRACK_ELEM_25_DEG_DOWN_TO_60_DEG_DOWN_COVERED: + vertFactor = -82; + //6d7551 + break; + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES:// + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_DOWN: + case TRACK_ELEM_LEFT_TWIST_DOWN_TO_UP: + case TRACK_ELEM_LEFT_TWIST_UP_TO_DOWN: + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED: + case TRACK_ELEM_LEFT_QUARTER_HELIX_LARGE_UP: + case TRACK_ELEM_LEFT_QUARTER_HELIX_LARGE_DOWN: + case TRACK_ELEM_LEFT_FLYER_TWIST_UP: + case TRACK_ELEM_LEFT_FLYER_TWIST_DOWN: + case TRACK_ELEM_LEFT_HEARTLINE_ROLL: + lateralFactor = 98; + //6d7590 + break; + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES:// + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN: + case TRACK_ELEM_RIGHT_TWIST_DOWN_TO_UP: + case TRACK_ELEM_RIGHT_TWIST_UP_TO_DOWN: + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED: + case TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_UP: + case TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_DOWN: + case TRACK_ELEM_RIGHT_FLYER_TWIST_UP: + case TRACK_ELEM_RIGHT_FLYER_TWIST_DOWN: + case TRACK_ELEM_RIGHT_HEARTLINE_ROLL: + lateralFactor = -98; + //6d75B7 + break; + case TRACK_ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_LARGE: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_LARGE: + case TRACK_ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_UP: + case TRACK_ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_DOWN: + vertFactor = 200; + lateralFactor = 160; + //6d75E1 + break; + case TRACK_ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_LARGE: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_LARGE: + case TRACK_ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_UP: + case TRACK_ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_DOWN: + vertFactor = 200; + lateralFactor = -160; + //6d75F0 + break; + case TRACK_ELEM_S_BEND_LEFT: + case TRACK_ELEM_S_BEND_LEFT_COVERED: + lateralFactor = (vehicle->track_progress < 48) ? 98 : -98; + //6d75FF + break; + case TRACK_ELEM_S_BEND_RIGHT: + case TRACK_ELEM_S_BEND_RIGHT_COVERED: + lateralFactor = (vehicle->track_progress < 48) ? -98 : 98; + //6d7608 + break; + case TRACK_ELEM_LEFT_VERTICAL_LOOP: + case TRACK_ELEM_RIGHT_VERTICAL_LOOP: + vertFactor = (abs(vehicle->track_progress - 155) / 2) + 28; + //6d7690 + break; + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_COVERED: + case TRACK_ELEM_LEFT_CURVED_LIFT_HILL: + lateralFactor = 59; + //6d7704 + break; + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED: + case TRACK_ELEM_RIGHT_CURVED_LIFT_HILL: + lateralFactor = -59; + //6d7710 + break; + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_BANK: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_SMALL: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_SMALL: + vertFactor = 100; + lateralFactor = 100; + //6d7782 + break; + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_SMALL: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_SMALL: + vertFactor = 100; + lateralFactor = -100; + //6d778E + break; + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE: + lateralFactor = 45; + //6d779A + break; + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE: + lateralFactor = -45; + //6d77A3 + break; + case TRACK_ELEM_HALF_LOOP_UP: + case TRACK_ELEM_FLYER_HALF_LOOP_UP: + vertFactor = (((uint16)(-(vehicle->track_progress - 155))) / 2) + 28; + //6d763E + break; + case TRACK_ELEM_HALF_LOOP_DOWN: + case TRACK_ELEM_FLYER_HALF_LOOP_DOWN: + vertFactor = (vehicle->track_progress / 2) + 28; + //6d7656 + break; + case TRACK_ELEM_LEFT_CORKSCREW_UP: + case TRACK_ELEM_RIGHT_CORKSCREW_DOWN: + case TRACK_ELEM_LEFT_FLYER_CORKSCREW_UP: + case TRACK_ELEM_RIGHT_FLYER_CORKSCREW_DOWN: + vertFactor = 52; + lateralFactor = 70; + //6d76AA + break; + case TRACK_ELEM_RIGHT_CORKSCREW_UP: + case TRACK_ELEM_LEFT_CORKSCREW_DOWN: + case TRACK_ELEM_RIGHT_FLYER_CORKSCREW_UP: + case TRACK_ELEM_LEFT_FLYER_CORKSCREW_DOWN: + vertFactor = 52; + lateralFactor = -70; + //6d76B9 + break; + case TRACK_ELEM_FLAT_TO_60_DEG_UP: + case TRACK_ELEM_60_DEG_DOWN_TO_FLAT: + vertFactor = 56; + //6d747C + break; + case TRACK_ELEM_60_DEG_UP_TO_FLAT: + case TRACK_ELEM_FLAT_TO_60_DEG_DOWN: + case TRACK_ELEM_BRAKE_FOR_DROP: + vertFactor = -56; + //6d7488 + break; + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_DOWN: + lateralFactor = 88; + //6d7770 + break; + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN: + lateralFactor = -88; + //6d7779 + break; + case TRACK_ELEM_WATER_SPLASH: + vertFactor = -150; + if (vehicle->track_progress < 32) + break; + vertFactor = 150; + if (vehicle->track_progress < 64) + break; + vertFactor = 0; + if (vehicle->track_progress < 96) + break; + vertFactor = 150; + if (vehicle->track_progress < 128) + break; + vertFactor = -150; + //6d7408 + break; + case TRACK_ELEM_FLAT_TO_60_DEG_UP_LONG_BASE: + case TRACK_ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE: + vertFactor = 160; + //6d74F1 + break; + case TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE: + case TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE_122: + vertFactor = -160; + //6d74FD + break; + case TRACK_ELEM_REVERSE_WHOA_BELLY_SLOPE: + case TRACK_ELEM_AIR_THRUST_VERTICAL_DOWN_TO_LEVEL: + vertFactor = 120; + //6d7458 + break; + case TRACK_ELEM_60_DEG_UP_TO_90_DEG_UP: + case TRACK_ELEM_90_DEG_DOWN_TO_60_DEG_DOWN: + vertFactor = 110; + //6d7515 + break; + case TRACK_ELEM_90_DEG_UP_TO_60_DEG_UP: + case TRACK_ELEM_60_DEG_DOWN_TO_90_DEG_DOWN: + vertFactor = -110; + //6d7521 + break; + case TRACK_ELEM_LEFT_EIGHTH_TO_DIAG: + case TRACK_ELEM_LEFT_EIGHTH_TO_ORTHOGONAL: + lateralFactor = 137; + //6d7575 + break; + case TRACK_ELEM_RIGHT_EIGHTH_TO_DIAG: + case TRACK_ELEM_RIGHT_EIGHTH_TO_ORTHOGONAL: + lateralFactor = -137; + //6d759C + break; + case TRACK_ELEM_LEFT_EIGHTH_BANK_TO_DIAG: + case TRACK_ELEM_LEFT_EIGHTH_BANK_TO_ORTHOGONAL: + vertFactor = 270; + lateralFactor = 200; + //6d75C3 + break; + case TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_DIAG: + case TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL: + vertFactor = 270; + lateralFactor = -200; + //6d75D2 + break; + case TRACK_ELEM_DIAG_FLAT_TO_25_DEG_UP: + case TRACK_ELEM_DIAG_25_DEG_DOWN_TO_FLAT: + case TRACK_ELEM_DIAG_LEFT_BANK_TO_25_DEG_UP: + case TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_UP: + case TRACK_ELEM_DIAG_25_DEG_DOWN_TO_LEFT_BANK: + case TRACK_ELEM_DIAG_25_DEG_DOWN_TO_RIGHT_BANK: + vertFactor = 113; + //6d7494 + break; + case TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_FLAT_TO_25_DEG_DOWN: + case TRACK_ELEM_DIAG_25_DEG_UP_TO_LEFT_BANK: + case TRACK_ELEM_DIAG_25_DEG_UP_TO_RIGHT_BANK: + case TRACK_ELEM_DIAG_LEFT_BANK_TO_25_DEG_DOWN: + case TRACK_ELEM_DIAG_RIGHT_BANK_TO_25_DEG_DOWN: + vertFactor = -113; + //6d755D + break; + case TRACK_ELEM_DIAG_25_DEG_UP_TO_60_DEG_UP: + case TRACK_ELEM_DIAG_60_DEG_DOWN_TO_25_DEG_DOWN: + vertFactor = 95; + //6D752D + break; + case TRACK_ELEM_DIAG_60_DEG_UP_TO_25_DEG_UP: + case TRACK_ELEM_DIAG_25_DEG_DOWN_TO_60_DEG_DOWN: + vertFactor = -95; + //6D7539 + break; + case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_UP: + case TRACK_ELEM_DIAG_60_DEG_DOWN_TO_FLAT: + vertFactor = 60; + //6D7464 + break; + case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_DOWN: + vertFactor = -60; + //6d7470 + break; + case TRACK_ELEM_LEFT_BARREL_ROLL_UP_TO_DOWN: + case TRACK_ELEM_LEFT_BARREL_ROLL_DOWN_TO_UP: + vertFactor = 170; + lateralFactor = 115; + //6d7581 + break; + case TRACK_ELEM_RIGHT_BARREL_ROLL_UP_TO_DOWN: + case TRACK_ELEM_RIGHT_BARREL_ROLL_DOWN_TO_UP: + vertFactor = 170; + lateralFactor = -115; + //6d75A8 + break; + case TRACK_ELEM_LEFT_BANK_TO_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP: + vertFactor = -(vehicle->track_progress / 2) + 134; + lateralFactor = 90; + //6d771C + break; + case TRACK_ELEM_RIGHT_BANK_TO_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP: + vertFactor = -(vehicle->track_progress / 2) + 134; + lateralFactor = -90; + //6D7746 + break; + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_LEFT_BANK: + vertFactor = -(vehicle->track_progress / 2) + 134; + lateralFactor = 90; + //6D7731 identical to 6d771c + break; + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_RIGHT_BANK: + vertFactor = -(vehicle->track_progress / 2) + 134; + lateralFactor = -90; + //6D775B identical to 6d7746 + break; + case TRACK_ELEM_LEFT_LARGE_HALF_LOOP_UP: + case TRACK_ELEM_RIGHT_LARGE_HALF_LOOP_UP: + vertFactor = (((uint16)(-(vehicle->track_progress - 311))) / 4) + 46; + //6d7666 + break; + case TRACK_ELEM_RIGHT_LARGE_HALF_LOOP_DOWN: + case TRACK_ELEM_LEFT_LARGE_HALF_LOOP_DOWN: + vertFactor = (vehicle->track_progress / 4) + 46; + //6d767F + break; + case TRACK_ELEM_HEARTLINE_TRANSFER_UP: + vertFactor = 103; + if (vehicle->track_progress < 32) + break; + vertFactor = -103; + if (vehicle->track_progress < 64) + break; + vertFactor = 0; + if (vehicle->track_progress < 96) + break; + vertFactor = 103; + if (vehicle->track_progress < 128) + break; + vertFactor = -103; + //6d74A0 + break; + case TRACK_ELEM_HEARTLINE_TRANSFER_DOWN: + vertFactor = -103; + if (vehicle->track_progress < 32) + break; + vertFactor = 103; + if (vehicle->track_progress < 64) + break; + vertFactor = 0; + if (vehicle->track_progress < 96) + break; + vertFactor = -103; + if (vehicle->track_progress < 128) + break; + vertFactor = 103; + //6D74CA + break; + case TRACK_ELEM_MULTIDIM_INVERTED_FLAT_TO_90_DEG_QUARTER_LOOP_DOWN: + case TRACK_ELEM_INVERTED_FLAT_TO_90_DEG_QUARTER_LOOP_DOWN: + case TRACK_ELEM_MULTIDIM_FLAT_TO_90_DEG_DOWN_QUARTER_LOOP: + vertFactor = (vehicle->track_progress / 4) + 55; + //6d762D + break; + case TRACK_ELEM_90_DEG_TO_INVERTED_FLAT_QUARTER_LOOP_UP: + case TRACK_ELEM_MULTIDIM_90_DEG_UP_TO_INVERTED_FLAT_QUARTER_LOOP: + case 255: + vertFactor = (((uint16)(-(vehicle->track_progress - 137))) / 4) + 55; + //6D7614 + break; + case TRACK_ELEM_AIR_THRUST_TOP_CAP: + vertFactor = -60; + //6D744C + break; + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP: + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN: + vertFactor = 200; + lateralFactor = 100; + //6d76C8 + break; + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP: + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN: + vertFactor = 200; + lateralFactor = -100; + //6d76d7 + break; + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP: + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN: + vertFactor = 200; + lateralFactor = 160; + //6D76E6 + break; + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP: + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN: + vertFactor = 200; + lateralFactor = -160; + //6d76F5 + break; + } - if (verticalG != NULL) *verticalG = (sint16)(eax & 0xFFFF); - if (lateralG != NULL) *lateralG = (sint16)(edx & 0xFFFF); + int gForceLateral = 0; + + if (vertFactor != 0) { + gForceVert += abs(vehicle->velocity) * 98 / vertFactor; + } + + if (lateralFactor != 0) { + gForceLateral += abs(vehicle->velocity) * 98 / lateralFactor; + } + + gForceVert *= 10; + gForceLateral *= 10; + gForceVert >>= 16; + gForceLateral >>= 16; + + if (verticalG != NULL) *verticalG = (sint16)(gForceVert & 0xFFFF); + if (lateralG != NULL) *lateralG = (sint16)(gForceLateral & 0xFFFF); } void vehicle_set_map_toolbar(rct_vehicle *vehicle) @@ -481,7 +4937,7 @@ void vehicle_set_map_toolbar(rct_vehicle *vehicle) rct_ride *ride; int vehicleIndex; - ride = GET_RIDE(vehicle->ride); + ride = get_ride(vehicle->ride); while (vehicle->is_child) { vehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride); @@ -536,103 +4992,3308 @@ int vehicle_is_used_in_pairs(rct_vehicle *vehicle) /** * - * rct2: 0x006DEF56 + * rct2: 0x006DA44E */ -void sub_6DEF56(rct_vehicle *cableLift) -{ - RCT2_CALLPROC_X(0x006DEF56, 0, 0, 0, 0, (int)cableLift, 0, 0); +static int vehicle_update_motion_bumper_car(rct_vehicle* vehicle) { + RCT2_GLOBAL(0x00F64E18, uint32) = 0; + rct_ride* ride = get_ride(vehicle->ride); + + sint32 nextVelocity = vehicle->velocity + vehicle->acceleration; + if (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN) && + ride->breakdown_reason_pending == BREAKDOWN_SAFETY_CUT_OUT) { + nextVelocity = 0; + } + vehicle->velocity = nextVelocity; + + RCT2_GLOBAL(0x00F64E08, sint32) = nextVelocity; + RCT2_GLOBAL(0x00F64E0C, sint32) = (nextVelocity / 1024) * 42; + RCT2_GLOBAL(0x00F64E10, uint32) = 1; + + vehicle->acceleration = 0; + if (!(ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN)) || + ride->breakdown_reason_pending != BREAKDOWN_SAFETY_CUT_OUT) { + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 1 && + vehicle->var_34 != 0) { + + if (vehicle->var_34 > 0) { + vehicle->var_34--; + vehicle->sprite_direction += 2; + } + else { + vehicle->var_34++; + vehicle->sprite_direction -= 2; + } + vehicle->sprite_direction &= 0x1E; + vehicle_invalidate(vehicle); + } + else if ((scenario_rand() & 0xFFFF) <= 2849) { + if (vehicle->var_35 & (1 << 6)) + vehicle->sprite_direction -= 2; + else + vehicle->sprite_direction += 2; + vehicle->sprite_direction &= 0x1E; + vehicle_invalidate(vehicle); + } + } + + uint16 collideSprite = 0xFFFF; + + if (vehicle->var_C4 != 0) { + uint8 oldC4 = vehicle->var_C4 & 0x1E; + vehicle->var_C4 = 0; + + rct_xyz16 location = { + .x = vehicle->x, + .y = vehicle->y, + .z = vehicle->z + }; + + location.x += RCT2_ADDRESS(0x009A36C4, sint16)[oldC4 * 4]; + location.y += RCT2_ADDRESS(0x009A36C6, sint16)[oldC4 * 4]; + location.x += RCT2_ADDRESS(0x009A36CC, sint16)[oldC4 * 4]; + location.y += RCT2_ADDRESS(0x009A36CE, sint16)[oldC4 * 4]; + + if (!vehicle_update_bumper_car_collision(vehicle, location.x, location.y, &collideSprite)) { + vehicle_invalidate(vehicle); + sprite_move( + location.x, + location.y, + location.z, + (rct_sprite*)vehicle + ); + vehicle_invalidate(vehicle); + } + } + + vehicle->remaining_distance += RCT2_GLOBAL(0x00F64E0C, sint32); + + if (vehicle->remaining_distance >= 13962) { + vehicle->var_B8 &= ~(1 << 1); + rct_xyz16 *unk_F64E20 = RCT2_ADDRESS(0x00F64E20, rct_xyz16); + unk_F64E20->x = vehicle->x; + unk_F64E20->y = vehicle->y; + unk_F64E20->z = vehicle->z; + + vehicle_invalidate(vehicle); + + while (1) { + vehicle->var_35++; + uint8 direction = vehicle->sprite_direction; + direction |= vehicle->var_35 & 1; + + rct_xyz16 location = *unk_F64E20; + location.x += RCT2_ADDRESS(0x009A36C4, sint16)[direction * 4]; + location.y += RCT2_ADDRESS(0x009A36C6, sint16)[direction * 4]; + + if (vehicle_update_bumper_car_collision(vehicle, location.x, location.y, &collideSprite)) + break; + + vehicle->remaining_distance -= RCT2_ADDRESS(0x009A36C8, sint16)[direction * 4]; + unk_F64E20->x = location.x; + unk_F64E20->y = location.y; + if (vehicle->remaining_distance < 13962) { + break; + } + RCT2_GLOBAL(0x00F64E10, uint32)++; + } + + if (vehicle->remaining_distance >= 13962) { + sint32 oldVelocity = vehicle->velocity; + vehicle->remaining_distance = 0; + vehicle->velocity = 0; + uint8 direction = vehicle->sprite_direction | 1; + + if (collideSprite != 0xFFFF) { + vehicle->var_34 = scenario_rand() & 1 ? 1 : -1; + + if (oldVelocity >= 131072) { + rct_vehicle* collideVehicle = GET_VEHICLE(collideSprite); + collideVehicle->var_C4 = direction; + vehicle->var_C4 = direction ^ (1 << 4); + } + } + else { + vehicle->var_34 = scenario_rand() & 1 ? 6 : -6; + + if (oldVelocity >= 131072) { + vehicle->var_C4 = direction ^ (1 << 4); + } + } + } + + sprite_move( + unk_F64E20->x, + unk_F64E20->y, + unk_F64E20->z, + (rct_sprite*)vehicle + ); + vehicle_invalidate(vehicle); + } + + sint32 eax = vehicle->velocity / 2; + sint32 edx = vehicle->velocity >> 8; + edx *= edx; + if (vehicle->velocity < 0) + edx = -edx; + edx >>= 5; + eax += edx; + eax /= vehicle->friction; + rct_ride_entry* rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle* vehicleEntry = &rideEntry->vehicles[vehicle->vehicle_type]; + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3)) { + vehicle->acceleration = -eax; + return RCT2_GLOBAL(0x00F64E18, uint32); + } + + sint32 ebx = (vehicle->speed * vehicle->friction) >> 2; + sint32 _eax = vehicle->speed << 14; + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_3) { + _eax = -_eax; + } + _eax -= vehicle->velocity; + _eax *= vehicle->powered_acceleration * 2; + _eax /= ebx; + + vehicle->acceleration = _eax - eax; + return RCT2_GLOBAL(0x00F64E18, uint32); } -rct_vehicle *cable_lift_segment_create(int rideIndex, int x, int y, int z, int direction, uint16 var_44, uint32 var_24, bool head) -{ - rct_ride *ride = GET_RIDE(rideIndex); - rct_vehicle *current = &(create_sprite(1)->vehicle); - current->sprite_identifier = SPRITE_IDENTIFIER_VEHICLE; - current->ride = rideIndex; - current->ride_subtype = 0xFF; - if (head) { - move_sprite_to_list((rct_sprite*)current, SPRITE_LINKEDLIST_OFFSET_VEHICLE); - ride->cable_lift = current->sprite_index; - } - current->is_child = head ? 0 : 1; - current->var_44 = var_44; - current->var_24 = var_24; - current->sprite_width = 10; - current->sprite_height_negative = 10; - current->sprite_height_positive = 10; - current->friction = 100; - current->num_seats = 0; - current->speed = 20; - current->acceleration = 80; - current->velocity = 0; - current->var_2C = 0; - current->var_4A = 0; - current->var_4C = 0; - current->var_4E = 0; - current->var_B5 = 0; - current->var_BA = 0; - current->var_B6 = 0; - current->var_B8 = 0; - current->sound1_id = 0xFF; - current->sound2_id = 0xFF; - current->var_C4 = 0; - current->var_C5 = 0; - current->var_C8 = 0; - current->scream_sound_id = 0xFF; - current->var_1F = 0; - current->var_20 = 0; - for (int j = 0; j < 32; j++) { - current->peep[j] = SPRITE_INDEX_NULL; - } - current->var_CD = 0; - current->sprite_direction = direction << 3; - current->track_x = x; - current->track_y = y; - z = z * 8; - current->track_z = z; - z += RCT2_GLOBAL(0x0097D21A + (ride->type * 8), uint8); - - sprite_move(16, 16, z, (rct_sprite*)current); - current->track_type = (TRACK_ELEM_CABLE_LIFT_HILL << 2) | (current->sprite_direction >> 3); - current->var_34 = 164; - current->update_flags = VEHICLE_UPDATE_FLAG_1; - current->status = VEHICLE_STATUS_MOVING_TO_END_OF_STATION; - current->var_51 = 0; - current->num_peeps = 0; - current->next_free_seat = 0; - return current; -} /** * * rct2: 0x006DD365 */ -bool sub_6DD365(rct_vehicle *vehicle) +bool vehicle_update_bumper_car_collision(rct_vehicle *vehicle, sint16 x, sint16 y, uint16 *spriteId) { - registers regs; - regs.esi = (int)vehicle; + uint16 bp = (vehicle->var_44 * 30) >> 9; + uint32 trackType = vehicle->track_type >> 2; - return RCT2_CALLFUNC_Y(0x006DD365, ®s) & 0x100; + sint16 rideLeft = vehicle->track_x + RCT2_ADDRESS(0x0099E228, uint8)[trackType * 4]; + sint16 rideRight = vehicle->track_x + RCT2_ADDRESS(0x0099E22A, uint8)[trackType * 4]; + sint16 rideTop = vehicle->track_y + RCT2_ADDRESS(0x0099E229, uint8)[trackType * 4]; + sint16 rideBottom = vehicle->track_y + RCT2_ADDRESS(0x0099E22B, uint8)[trackType * 4]; + + if (x - bp < rideLeft || + y - bp < rideTop || + x + bp > rideRight || + y + bp > rideBottom) { + if (spriteId != NULL) + *spriteId = 0xFFFF; + return true; + } + + uint16 location = (y / 32) | ((x / 32) << 8); + + + uint8 rideIndex = vehicle->ride; + for (sint32* ebp = RCT2_ADDRESS(0x009A37C4, sint32); ebp <= RCT2_ADDRESS(0x009A37E4, sint32); ebp++) { + uint16 spriteIdx = RCT2_ADDRESS(0xF1EF60, uint16)[location]; + for (rct_vehicle* vehicle2 = GET_VEHICLE(spriteIdx); spriteIdx != 0xFFFF; spriteIdx = vehicle2->next_in_quadrant) { + vehicle2 = GET_VEHICLE(spriteIdx); + + if (vehicle2 == vehicle) + continue; + + if (vehicle2->sprite_identifier != SPRITE_IDENTIFIER_VEHICLE) + continue; + + if (vehicle2->ride != rideIndex) + continue; + + int distX = abs(x - vehicle2->x); + if (distX > 32768) + continue; + + int distY = abs(y - vehicle2->y); + if (distY > 32768) + continue; + + int ecx = (vehicle->var_44 + vehicle2->var_44) / 2; + ecx *= 30; + ecx >>= 8; + if (max(distX, distY) < ecx) { + if (spriteId != NULL) + *spriteId = vehicle2->sprite_index; + return true; + } + } + location += *ebp; + } + + return false; +} + +// rct2: 0x009A2970 +const sint32 *dword_9A2970 = (sint32*)0x009A2970; + +/** + * + * rct2: 0x006DAB90 + */ +static void vehicle_update_track_motion_up_stop_check(rct_vehicle *vehicle) +{ + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + int verticalG, lateralG; + + // No up stops (coaster types) + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_1) { + int trackType = vehicle->track_type >> 2; + if (!track_element_is_covered(trackType)) { + vehicle_get_g_forces(vehicle, &verticalG, &lateralG); + lateralG = abs(lateralG); + if (lateralG <= 150) { + if (dword_9A2970[vehicle->vehicle_sprite_type] < 0) { + if (verticalG > -40) { + return; + } + } else if (verticalG > -80) { + return; + } + } + + if (vehicle->vehicle_sprite_type != 8) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_DERAILED; + } + } + } else if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_2) { + // No up stops bobsleigh type + int trackType = vehicle->track_type >> 2; + if (!track_element_is_covered(trackType)) { + vehicle_get_g_forces(vehicle, &verticalG, &lateralG); + + if (dword_9A2970[vehicle->vehicle_sprite_type] < 0) { + if (verticalG > -45) { + return; + } + } else { + if (verticalG > -80) { + return; + } + } + + if (vehicle->vehicle_sprite_type != 8 && vehicle->vehicle_sprite_type != 55) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_DERAILED; + } + } + } +} + +/** + * + * rct2: 0x006DAC43 + */ +static void sub_6DAB4C_chunk_2(rct_vehicle *vehicle) +{ + rct_ride *ride = get_ride(vehicle->ride); + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + + // Is chair lift type + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_12) { + sint32 velocity = ride->speed << 16; + if (RCT2_GLOBAL(0x00F64E34, uint8) == 0) { + velocity = 0; + } + vehicle->velocity = velocity; + vehicle->acceleration = 0; + } + + int trackType = vehicle->track_type >> 2; + switch (trackType) { + case TRACK_ELEM_END_STATION: + case TRACK_ELEM_BLOCK_BRAKES: + if (ride->mode == RIDE_MODE_CONTINUOUS_CIRCUIT || ride_is_block_sectioned(ride)) { + break; + } + return; + case TRACK_ELEM_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_60_DEG_UP_TO_FLAT: + case TRACK_ELEM_CABLE_LIFT_HILL: + case TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT: + if (ride_is_block_sectioned(ride)) { + break; + } + return; + default: + return; + } + + rct_map_element *trackElement = map_get_track_element_at_of_type( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z >> 3, + trackType + ); + if (trackType == TRACK_ELEM_END_STATION) { + if (trackElement->flags & (1 << 5)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_10; + } + } else if (trackType == TRACK_ELEM_CABLE_LIFT_HILL || trackType == TRACK_ELEM_BLOCK_BRAKES || track_element_is_lift_hill(trackElement)) { + if (!(trackElement->flags & (1 << 5))) { + if (trackType == TRACK_ELEM_BLOCK_BRAKES && vehicle->velocity >= 0) { + if (vehicle->velocity <= 0x20364) { + vehicle->velocity = 0x20364; + vehicle->acceleration = 0; + } else { + vehicle->velocity -= vehicle->velocity >> 4; + vehicle->acceleration = 0; + } + } + return; + } + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_10; + vehicle->acceleration = 0; + if (vehicle->velocity <= 0x20000) { + vehicle->velocity = 0; + } + vehicle->velocity -= vehicle->velocity >> 3; + } +} + +/** + * + * rct2: 0x006DADAE + */ +static void sub_6DAB4C_chunk_3(rct_vehicle *vehicle) +{ + sint32 nextVelocity = vehicle->acceleration + vehicle->velocity; + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_7) { + nextVelocity = 0; + } + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_ON_BREAK_FOR_DROP) { + vehicle->vertical_drop_countdown--; + if (vehicle->vertical_drop_countdown == -70) { + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_ON_BREAK_FOR_DROP; + } + if (vehicle->vertical_drop_countdown >= 0) { + nextVelocity = 0; + vehicle->acceleration = 0; + } + } + vehicle->velocity = nextVelocity; + + RCT2_GLOBAL(0x00F64E08, sint32) = nextVelocity; + RCT2_GLOBAL(0x00F64E0C, sint32) = (nextVelocity >> 10) * 42; +} + +static void vehicle_update_block_breaks_open_previous_section(rct_vehicle *vehicle, rct_map_element *mapElement) +{ + int x = vehicle->track_x; + int y = vehicle->track_y; + int z = vehicle->track_z; + track_begin_end trackBeginEnd; + do { + if (!track_block_get_previous(x, y, mapElement, &trackBeginEnd)) { + return; + } + if (trackBeginEnd.begin_x == vehicle->track_x && + trackBeginEnd.begin_y == vehicle->track_y && + mapElement == trackBeginEnd.begin_element) { + return; + } + + x = trackBeginEnd.end_x; + y = trackBeginEnd.end_y; + z = trackBeginEnd.begin_z; + mapElement = trackBeginEnd.begin_element; + } while (!track_element_is_block_start(trackBeginEnd.begin_element)); + + // Get the start of the track block instead of the end + x = trackBeginEnd.begin_x; + y = trackBeginEnd.begin_y; + z = trackBeginEnd.begin_z; + mapElement = map_get_track_element_at(x, y, z >> 3); + if (mapElement == NULL) { + return; + } + mapElement->flags &= ~MAP_ELEMENT_FLAG_BLOCK_BREAK_CLOSED; + map_invalidate_element(x, y, mapElement); + + int trackType = mapElement->properties.track.type; + if (trackType == TRACK_ELEM_BLOCK_BRAKES || trackType == TRACK_ELEM_END_STATION) { + rct_ride *ride = get_ride(vehicle->ride); + if (ride_is_block_sectioned(ride)) { + audio_play_sound_at_location(SOUND_48, x, y, z); + } + } +} + +static int vehicle_get_swing_amount(rct_vehicle *vehicle) +{ + int trackType = vehicle->track_type >> 2; + switch (trackType) { + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_25_DEG_DOWN: + case TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES_COVERED: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_LARGE: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_LARGE: + case TRACK_ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_UP: + case TRACK_ELEM_LEFT_QUARTER_BANKED_HELIX_LARGE_DOWN: + case TRACK_ELEM_LEFT_QUARTER_HELIX_LARGE_UP: + case TRACK_ELEM_LEFT_QUARTER_HELIX_LARGE_DOWN: + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP: + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN: + // loc_6D67E1 + return 14; + + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_25_DEG_DOWN: + case TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES_COVERED: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_LARGE: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_LARGE: + case TRACK_ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_UP: + case TRACK_ELEM_RIGHT_QUARTER_BANKED_HELIX_LARGE_DOWN: + case TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_UP: + case TRACK_ELEM_RIGHT_QUARTER_HELIX_LARGE_DOWN: + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_UP: + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_5_TILE_25_DEG_DOWN: + // loc_6D6804 + return -14; + + case TRACK_ELEM_S_BEND_LEFT: + case TRACK_ELEM_S_BEND_LEFT_COVERED: + // loc_6D67EF + if (vehicle->track_progress < 48) { + return 14; + } else { + return -15; + } + + case TRACK_ELEM_S_BEND_RIGHT: + case TRACK_ELEM_S_BEND_RIGHT_COVERED: + // loc_6D67CC + if (vehicle->track_progress < 48) { + return -14; + } else { + return 15; + } + + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_BANK: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_COVERED: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_UP_SMALL: + case TRACK_ELEM_LEFT_HALF_BANKED_HELIX_DOWN_SMALL: + case TRACK_ELEM_LEFT_BANK_TO_LEFT_QUARTER_TURN_3_TILES_25_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_LEFT_BANK: + case TRACK_ELEM_LEFT_CURVED_LIFT_HILL: + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP: + case TRACK_ELEM_LEFT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN: + // loc_6D67BE + return 13; + + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_COVERED: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_UP_SMALL: + case TRACK_ELEM_RIGHT_HALF_BANKED_HELIX_DOWN_SMALL: + case TRACK_ELEM_RIGHT_BANK_TO_RIGHT_QUARTER_TURN_3_TILES_25_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_25_DEG_DOWN_TO_RIGHT_BANK: + case TRACK_ELEM_RIGHT_CURVED_LIFT_HILL: + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_UP: + case TRACK_ELEM_RIGHT_BANKED_QUARTER_TURN_3_TILE_25_DEG_DOWN: + // loc_6D67B0 + return -13; + + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE: + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_UP: + case TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE_60_DEG_DOWN: + // loc_6D67A2 + return 12; + + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE: + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_UP: + case TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE_60_DEG_DOWN: + // loc_6D6794 + return -12; + + case TRACK_ELEM_LEFT_EIGHTH_TO_DIAG: + case TRACK_ELEM_LEFT_EIGHTH_TO_ORTHOGONAL: + case TRACK_ELEM_LEFT_EIGHTH_BANK_TO_DIAG: + case TRACK_ELEM_LEFT_EIGHTH_BANK_TO_ORTHOGONAL: + // loc_6D67D3 + return 15; + + case TRACK_ELEM_RIGHT_EIGHTH_TO_DIAG: + case TRACK_ELEM_RIGHT_EIGHTH_TO_ORTHOGONAL: + case TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_DIAG: + case TRACK_ELEM_RIGHT_EIGHTH_BANK_TO_ORTHOGONAL: + // loc_6D67F6 + return -15; + } + return 0; +} + +/** + * + * rct2: 0x006D6776 + */ +static void vehicle_update_swinging_car(rct_vehicle *vehicle) +{ + sint32 dword_F64E08 = RCT2_GLOBAL(0x00F64E08, sint32); + vehicle->var_4E += (-vehicle->swinging_car_var_0) >> 6; + int swingAmount = vehicle_get_swing_amount(vehicle); + if (swingAmount < 0) { + vehicle->var_4E -= dword_F64E08 >> (-swingAmount); + } + else if (swingAmount > 0){ + vehicle->var_4E += dword_F64E08 >> swingAmount; + } + + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + sint16 dx = 3185; + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_5) { + dx = 5006; + } + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_9) { + dx = 1820; + } + sint16 cx = -dx; + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_11) { + dx = 5370; + cx = -5370; + + int trackType = vehicle->track_type >> 2; + switch (trackType) { + case TRACK_ELEM_BANKED_LEFT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_LEFT_BANK: + case TRACK_ELEM_LEFT_QUARTER_TURN_3_TILES_BANK: + dx = 10831; + cx = -819; + break; + case TRACK_ELEM_BANKED_RIGHT_QUARTER_TURN_5_TILES: + case TRACK_ELEM_RIGHT_BANK: + case TRACK_ELEM_RIGHT_QUARTER_TURN_3_TILES_BANK: + dx = 819; + cx = -10831; + break; + } + + switch (trackType) { + case TRACK_ELEM_END_STATION: + case TRACK_ELEM_BEGIN_STATION: + case TRACK_ELEM_MIDDLE_STATION: + case TRACK_ELEM_BRAKES: + case TRACK_ELEM_BLOCK_BRAKES: + dx = 0; + cx = 0; + break; + } + + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_0) { + dx = 0; + cx = 0; + } + } + + vehicle->swinging_car_var_0 += vehicle->var_4E; + vehicle->var_4E -= vehicle->var_4E >> 5; + sint16 ax = vehicle->swinging_car_var_0; + if (ax > dx) { + ax = dx; + vehicle->var_4E = 0; + } + if (ax < cx) { + ax = cx; + vehicle->var_4E = 0; + } + + vehicle->swinging_car_var_0 = ax; + uint8 bl = 11; + if (ax >= -10012) { + bl = 12; + if (ax <= 10012) { + bl = 9; + if (ax >= -8191) { + bl = 10; + if (ax <= 8191) { + bl = 7; + if (ax >= -6371) { + bl = 8; + if (ax <= 6371) { + bl = 5; + if (ax >= -4550) { + bl = 6; + if (ax <= 4550) { + bl = 3; + if (ax >= -2730) { + bl = 4; + if (ax <= 2730) { + ax = 1; + if (ax >= -910) { + bl = 2; + if (ax <= 910) { + bl = 0; + } + } + } + } + } + } + } + } + } + } + } + } + if (bl != vehicle->var_4A) { + vehicle->var_4A = bl; + vehicle_invalidate(vehicle); + } +} + +#pragma region off_9A2E84 + +enum { + loc_6D673C, + loc_6D66F0, + loc_6D672B, + loc_6D6711, + loc_6D66D6, + loc_6D66C3, + loc_6D66B0, + loc_6D669A, + loc_6D6684, + loc_6D665A, + loc_6D6708, + loc_6D6703, + loc_6D66DD, + loc_6D6718 +}; + +static const uint8 off_9A2E84[256] = { + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66F0, + loc_6D672B, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66F0, + loc_6D672B, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66F0, + loc_6D672B, + loc_6D66F0, + loc_6D672B, + loc_6D6711, + loc_6D66D6, + loc_6D673C, + loc_6D673C, + loc_6D66C3, + loc_6D66B0, + loc_6D66C3, + loc_6D66B0, + loc_6D66C3, + loc_6D66B0, + loc_6D66C3, + loc_6D66B0, + loc_6D669A, + loc_6D6684, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66F0, + loc_6D672B, + loc_6D6711, + loc_6D66D6, + loc_6D66C3, + loc_6D66B0, + loc_6D66C3, + loc_6D66B0, + loc_6D66C3, + loc_6D66B0, + loc_6D66F0, + loc_6D672B, + loc_6D66F0, + loc_6D672B, + loc_6D669A, + loc_6D6684, + loc_6D669A, + loc_6D6684, + loc_6D673C, + loc_6D665A, + loc_6D673C, + loc_6D66F0, + loc_6D672B, + loc_6D66F0, + loc_6D672B, + loc_6D66F0, + loc_6D672B, + loc_6D66F0, + loc_6D672B, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D6708, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D6703, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66DD, + loc_6D6718, + loc_6D66DD, + loc_6D6718, + loc_6D66DD, + loc_6D6718, + loc_6D66DD, + loc_6D6718, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66C3, + loc_6D66B0, + loc_6D66C3, + loc_6D66B0, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66C3, + loc_6D66B0, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D66C3, + loc_6D66B0, + loc_6D66C3, + loc_6D66B0, + loc_6D66F0, + loc_6D672B, + loc_6D66F0, + loc_6D672B, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C, + loc_6D673C +}; + +#pragma endregion + +/** + * + * rct2: 0x006D661F + */ +static void vehicle_update_spinning_car(rct_vehicle *vehicle) +{ + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_13) { + vehicle->var_B6 = 0; + return; + } + + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + int spinningInertia = vehicleEntry->spinning_inertia; + int trackType = vehicle->track_type >> 2; + sint32 dword_F64E08 = RCT2_GLOBAL(0x00F64E08, sint32); + int unk; + switch (off_9A2E84[trackType]) { + case loc_6D665A: + spinningInertia += 6; + unk = dword_F64E08 >> spinningInertia; + if (vehicle->sprite_index & 1) { + vehicle->var_B6 -= unk; + } else { + vehicle->var_B6 += unk; + } + break; + case loc_6D6684: + case loc_6D6703: + spinningInertia += 5; + vehicle->var_B6 -= dword_F64E08 >> spinningInertia; + break; + case loc_6D669A: + spinningInertia += 5; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + break; + case loc_6D66B0: + spinningInertia += 7; + vehicle->var_B6 -= dword_F64E08 >> spinningInertia; + break; + case loc_6D66C3: + spinningInertia += 7; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + break; + case loc_6D66D6: + if (vehicle->track_progress < 48) { + spinningInertia += 8; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + break; + } + case loc_6D66DD: + spinningInertia += 9; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + break; + case loc_6D66F0: + spinningInertia += 8; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + break; + case loc_6D6708: + if (vehicle->track_progress > 22) { + spinningInertia += 5; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + } + break; + case loc_6D6711: + if (vehicle->track_progress < 48) { + spinningInertia += 8; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + break; + } + case loc_6D6718: + spinningInertia += 9; + vehicle->var_B6 -= dword_F64E08 >> spinningInertia; + break; + case loc_6D672B: + spinningInertia += 8; + vehicle->var_B6 += dword_F64E08 >> spinningInertia; + break; + } + + unk = clamp(-0x600, vehicle->var_B6, 0x600); + vehicle->var_B6 = unk; + vehicle->var_BA += unk >> 8; + vehicle->var_B6 -= unk >> vehicleEntry->spinning_friction; + vehicle_invalidate(vehicle); +} + +/** + * + * rct2: 0x006734B2 + */ +static void steam_particle_create(sint16 x, sint16 y, sint16 z) +{ + rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); + if (mapElement != NULL && z > mapElement->base_height * 8) { + rct_steam_particle *steam = (rct_steam_particle*)create_sprite(2); + steam->sprite_width = 20; + steam->sprite_height_negative = 18; + steam->sprite_height_positive = 16; + steam->sprite_identifier = SPRITE_IDENTIFIER_MISC; + steam->misc_identifier = SPRITE_MISC_STEAM_PARTICLE; + steam->var_26 = 256; + steam->var_24 = 0; + sprite_move(x, y, z, (rct_sprite*)steam); + } +} + +/** + * + * rct2: 0x006D63D4 + */ +static void sub_6D63D4(rct_vehicle *vehicle) +{ + uint8 al, ah; + uint32 eax; + + uint32 *var_C8 = (uint32*)&vehicle->var_C8; + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + switch (vehicleEntry->var_11) { + case 1: // loc_6D652B + *var_C8 += RCT2_GLOBAL(0x00F64E08, uint32); + al = (*var_C8 >> 20) & 3; + if (vehicle->var_C5 != al) { + ah = al; + al = vehicle->var_C5; + vehicle->var_C5 = ah; + al &= 0x02; + ah &= 0x02; + if (al != ah) { + rct_ride *ride = get_ride(vehicle->ride); + if (ride->entrance_style == RIDE_ENTRANCE_STYLE_PLAIN || + (vehicle->status != VEHICLE_STATUS_MOVING_TO_END_OF_STATION && + vehicle->status != VEHICLE_STATUS_ARRIVING) + ) { + int index = vehicle->sprite_direction >> 1; + if (vehicle->vehicle_sprite_type == 2) { + index += 16; + } + if (vehicle->vehicle_sprite_type == 6) { + index += 32; + } + steam_particle_create( + vehicle->x + SteamParticleOffsets[index].x, + vehicle->y + SteamParticleOffsets[index].y, + vehicle->z + SteamParticleOffsets[index].z + ); + } + } + vehicle_invalidate(vehicle); + } + break; + case 2: // loc_6D6424 + *var_C8 += RCT2_GLOBAL(0x00F64E08, uint32); + al = (*var_C8 >> 18) & 2; + if (vehicle->var_C5 != al) { + vehicle->var_C5 = al; + vehicle_invalidate(vehicle); + } + break; + case 3: // loc_6D6482 + *var_C8 += RCT2_GLOBAL(0x00F64E08, uint32); + eax = ((*var_C8 >> 13) & 0xFF) * 6; + ah = (eax >> 8) & 0xFF; + if (vehicle->var_C5 != ah) { + vehicle->var_C5 = ah; + vehicle_invalidate(vehicle); + } + break; + case 4: // loc_6D64F7 + *var_C8 += RCT2_GLOBAL(0x00F64E08, uint32); + eax = ((*var_C8 >> 13) & 0xFF) * 7; + ah = (eax >> 8) & 0xFF; + if (vehicle->var_C5 != ah) { + vehicle->var_C5 = ah; + vehicle_invalidate(vehicle); + } + break; + case 5: // loc_6D6453 + *var_C8 += RCT2_GLOBAL(0x00F64E08, uint32); + al = (*var_C8 >> 19) & 1; + if (vehicle->var_C5 != al) { + vehicle->var_C5 = al; + vehicle_invalidate(vehicle); + } + break; + case 6: // loc_6D65C3 + if (vehicle->var_C8 <= 0xCCCC) { + vehicle->var_C8 += 0x3333; + } else { + vehicle->var_C8 += 0x3333; + vehicle->var_C5 += 1; + vehicle->var_C5 &= 7; + vehicle_invalidate(vehicle); + } + break; + case 7: // loc_6D63F5 + *var_C8 += RCT2_GLOBAL(0x00F64E08, uint32); + al = (*var_C8 >> 18) & 3; + if (vehicle->var_C5 != al) { + vehicle->var_C5 = al; + vehicle_invalidate(vehicle); + } + break; + case 8: // loc_6D64B6 + if (vehicle->num_peeps != 0) { + *var_C8 += RCT2_GLOBAL(0x00F64E08, uint32); + eax = ((*var_C8 >> 13) & 0xFF) << 2; + ah = (eax >> 8) & 0xFF; + if (vehicle->var_C5 != ah) { + vehicle->var_C5 = ah; + vehicle_invalidate(vehicle); + } + } + break; + case 9: // loc_6D65E1 + if (vehicle->seat_rotation != vehicle->target_seat_rotation) { + if (vehicle->var_C8 <= 0xCCCC) { + vehicle->var_C8 += 0x3333; + } else { + vehicle->var_C8 += 0x3333; + + if (vehicle->seat_rotation >= vehicle->target_seat_rotation) + vehicle->seat_rotation--; + + else + vehicle->seat_rotation++; + + vehicle->var_C5 = (vehicle->seat_rotation - 4) & 7; + vehicle_invalidate(vehicle); + } + } + break; + } +} + +/** + * + * rct2: 0x006DEDB1 + */ +static void vehicle_play_scenery_door_open_sound(rct_vehicle *vehicle, rct_map_element *mapElement) +{ + rct_scenery_entry *wallEntry = g_wallSceneryEntries[mapElement->properties.fence.type]; + int doorSoundType = (wallEntry->wall.flags2 >> 1) & 3; + if (doorSoundType != 0) { + int soundId = DoorOpenSoundIds[doorSoundType - 1]; + if (soundId != 255) { + audio_play_sound_at_location(soundId, vehicle->x, vehicle->track_y, vehicle->track_z); + } + } +} + +/** + * + * rct2: 0x006DED7A + */ +static void vehicle_play_scenery_door_close_sound(rct_vehicle *vehicle, rct_map_element *mapElement) +{ + rct_scenery_entry *wallEntry = g_wallSceneryEntries[mapElement->properties.fence.type]; + int doorSoundType = (wallEntry->wall.flags2 >> 1) & 3; + if (doorSoundType != 0) { + int soundId = DoorCloseSoundIds[doorSoundType - 1]; + if (soundId != 255) { + audio_play_sound_at_location(soundId, vehicle->x, vehicle->track_y, vehicle->track_z); + } + } +} + +/** + * + * rct2: 0x006DEE93 + */ +static void vehicle_update_scenery_door(rct_vehicle *vehicle) +{ + int trackType = vehicle->track_type >> 2; + const rct_preview_track *trackBlock = TrackBlocks[trackType]; + while ((trackBlock + 1)->index != 255) { + trackBlock++; + } + const rct_track_coordinates *trackCoordinates = &TrackCoordinates[trackType]; + int x = floor2(vehicle->x, 32); + int y = floor2(vehicle->y, 32); + int z = (vehicle->track_z - trackBlock->z + trackCoordinates->z_end) >> 3; + int direction = (vehicle->track_direction + trackCoordinates->rotation_end) & 3; + + rct_map_element *mapElement = map_get_fence_element_at(x, y, z, direction); + if (mapElement == NULL) { + return; + } + + if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL) { + mapElement->properties.fence.item[2] &= 7; + mapElement->properties.fence.item[2] |= 8; + map_animation_create(MAP_ANIMATION_TYPE_WALL_UNKNOWN, x, y, z); + vehicle_play_scenery_door_open_sound(vehicle, mapElement); + } else { + mapElement->properties.fence.item[2] &= 7; + mapElement->properties.fence.item[2] |= 0x30; + vehicle_play_scenery_door_close_sound(vehicle, mapElement); + } +} + +/** + * + * rct2: 0x006DB38B + */ +static bool loc_6DB38B(rct_vehicle *vehicle, rct_map_element *mapElement) +{ + // Get bank + int bankStart = track_get_actual_bank_3(vehicle, mapElement); + + // Get vangle + int trackType = mapElement->properties.track.type; + int vangleStart = gTrackDefinitions[trackType].vangle_start; + + // ? + uint16 angleAndBank = vangleStart | (bankStart << 8); + if (angleAndBank != RCT2_GLOBAL(0x00F64E36, uint16)) { + return false; + } + + return true; +} + +void loc_6DB481(rct_vehicle *vehicle) +{ + uint16 probability = 0x8000; + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_6) { + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_6; + } else { + probability = 0x0A3D; + } + if ((scenario_rand() & 0xFFFF) <= probability) { + vehicle->var_CD += 2; + } +} + +/** + * + * rct2: 0x006DB545 + */ +static void vehicle_trigger_on_ride_photo(rct_vehicle *vehicle, rct_map_element *mapElement) +{ + mapElement->properties.track.sequence &= 0x0F; + mapElement->properties.track.sequence |= 0x30; + map_animation_create( + MAP_ANIMATION_TYPE_TRACK_ONRIDEPHOTO, + vehicle->track_x, + vehicle->track_y, + mapElement->base_height + ); +} + +/** + * + * rct2: 0x006DEDE8 + */ +static void sub_6DEDE8(rct_vehicle *vehicle) +{ + int trackType = vehicle->track_type >> 2; + const rct_preview_track *trackBlock = TrackBlocks[trackType]; + const rct_track_coordinates *trackCoordinates = &TrackCoordinates[trackType]; + int x = vehicle->track_x; + int y = vehicle->track_y; + int z = (vehicle->track_z - trackBlock->z + trackCoordinates->z_begin) >> 3; + int direction = (vehicle->track_direction + trackCoordinates->rotation_begin) & 3; + direction ^= 2; + + rct_map_element *mapElement = map_get_fence_element_at(x, y, z, direction); + if (mapElement == NULL) { + return; + } + + if (vehicle->next_vehicle_on_train != SPRITE_INDEX_NULL) { + mapElement->properties.fence.item[2] &= 7; + mapElement->properties.fence.item[2] |= 0x88; + map_animation_create(MAP_ANIMATION_TYPE_WALL_UNKNOWN, x, y, z); + vehicle_play_scenery_door_open_sound(vehicle, mapElement); + } else { + mapElement->properties.fence.item[2] &= 7; + mapElement->properties.fence.item[2] |= 0xB0; + vehicle_play_scenery_door_close_sound(vehicle, mapElement); + } +} + +static void vehicle_update_play_water_splash_sound() +{ + if (RCT2_GLOBAL(0x00F64E08, sint32) <= 0x20364) { + return; + } + + audio_play_sound_at_location( + SOUND_WATER_SPLASH, + unk_F64E20->x, + unk_F64E20->y, + unk_F64E20->z + ); +} + +/** + * + * rct2: 0x006DB59E + */ +static void vehicle_update_handle_water_splash(rct_vehicle *vehicle) +{ + rct_ride_entry *rideEntry = get_ride_entry(vehicle->ride_subtype); + int trackType = vehicle->track_type >> 2; + + if (!(rideEntry->flags & RIDE_ENTRY_FLAG_8)) { + if (rideEntry->flags & RIDE_ENTRY_FLAG_9) { + if (!vehicle->is_child) { + if (track_element_is_covered(trackType)) { + rct_vehicle *nextVehicle = GET_VEHICLE(vehicle->next_vehicle_on_ride); + rct_vehicle *nextNextVehicle = GET_VEHICLE(nextVehicle->next_vehicle_on_ride); + if (!track_element_is_covered(nextNextVehicle->track_type >> 2)) { + if (vehicle->track_progress == 4) { + vehicle_update_play_water_splash_sound(); + } + } + } + } + } + } else { + if (trackType == TRACK_ELEM_25_DEG_DOWN_TO_FLAT) { + if (vehicle->track_progress == 12) { + vehicle_update_play_water_splash_sound(); + } + } + } + if (!vehicle->is_child) { + if (trackType == TRACK_ELEM_WATER_SPLASH) { + if (vehicle->track_progress == 48) { + vehicle_update_play_water_splash_sound(); + } + } + } +} + +/** + * + * rct2: 0x006DB807 + */ +static void sub_6DB807(rct_vehicle *vehicle) +{ + const rct_vehicle_info *moveInfo = vehicle_get_move_info( + vehicle->var_CD, + vehicle->track_type, + vehicle->track_progress + ); + int x = vehicle->track_x + moveInfo->x; + int y = vehicle->track_y + moveInfo->y; + int z = vehicle->z; + sprite_move(x, y, z, (rct_sprite*)vehicle); +} + +/** + * Collision Detection + * rct2: 0x006DD078 + * @param vehicle (esi) + * @param x (ax) + * @param y (cx) + * @param z (dx) + * @param otherVehicleIndex (bp) + */ +static bool vehicle_update_motion_collision_detection( + rct_vehicle *vehicle, sint16 x, sint16 y, sint16 z, uint16* otherVehicleIndex +) { + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_1) return false; + + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_6)){ + vehicle->var_C4 = 0; + + // If hacking boat hire rides you can end up here + if (otherVehicleIndex == NULL) return false; + + rct_vehicle* collideVehicle = GET_VEHICLE(*otherVehicleIndex); + + if (vehicle == collideVehicle) return false; + + sint32 x_diff = abs(x - collideVehicle->x); + if (x_diff > 0x7FFF) return false; + + sint32 y_diff = abs(y - collideVehicle->y); + if (y_diff > 0x7FFF) return false; + + if (x_diff + y_diff > 0xFFFF) return false; + + sint32 z_diff = abs(z - collideVehicle->z); + if (x_diff + y_diff + z_diff > 0xFFFF) return false; + + uint16 ecx = min(vehicle->var_44 + collideVehicle->var_44, 560); + ecx = ((ecx >> 1) * 30) >> 8; + + if (x_diff + y_diff + z_diff >= ecx) return false; + + uint8 direction = (vehicle->sprite_direction - collideVehicle->sprite_direction + 7) & 0x1F; + if (direction >= 0xF) return false; + + return true; + } + + uint16 eax = ((x / 32) << 8) + (y / 32); + // TODO change to using a better technique + uint32* ebp = RCT2_ADDRESS(0x009A37C4, uint32); + bool mayCollide = false; + uint16 collideId = 0xFFFF; + rct_vehicle* collideVehicle = NULL; + for(; ebp <= RCT2_ADDRESS(0x009A37E4, uint32); ebp++){ + collideId = RCT2_ADDRESS(0x00F1EF60, uint16)[eax]; + for(; collideId != 0xFFFF; collideId = collideVehicle->next_in_quadrant){ + collideVehicle = GET_VEHICLE(collideId); + if (collideVehicle == vehicle) continue; + + if (collideVehicle->sprite_identifier != SPRITE_IDENTIFIER_VEHICLE) continue; + + sint32 z_diff = abs(collideVehicle->z - z); + + if (z_diff > 16) continue; + + rct_ride_entry_vehicle* collideType = vehicle_get_vehicle_entry(collideVehicle); + + if (!(collideType->flags_b & VEHICLE_ENTRY_FLAG_B_6)) continue; + + uint32 x_diff = abs(collideVehicle->x - x); + if (x_diff > 0x7FFF) continue; + + uint32 y_diff = abs(collideVehicle->y - y); + if (y_diff > 0x7FFF) continue; + + if (x_diff + y_diff > 0xFFFF) continue; + + uint8 cl = min(vehicle->var_CD, collideVehicle->var_CD); + uint8 ch = max(vehicle->var_CD, collideVehicle->var_CD); + if (cl != ch){ + if (cl == 5 && ch == 6) continue; + } + + uint32 ecx = vehicle->var_44 + collideVehicle->var_44; + ecx = ((ecx >> 1) * 30) >> 8; + + if (x_diff + y_diff >= ecx) continue; + + if (!(collideType->flags_b & VEHICLE_ENTRY_FLAG_B_14)){ + mayCollide = true; + break; + } + + uint8 direction = (vehicle->sprite_direction - collideVehicle->sprite_direction - 6) & 0x1F; + + if (direction < 0x14) continue; + + uint32 next_x_diff = abs(x + RCT2_ADDRESS(0x009A3B04, sint16)[((4 + vehicle->sprite_direction) >> 3) * 2] - collideVehicle->x); + uint32 next_y_diff = abs(y + RCT2_ADDRESS(0x009A3B06, sint16)[((4 + vehicle->sprite_direction) >> 3) * 2] - collideVehicle->y); + + if (next_x_diff + next_y_diff < x_diff + y_diff){ + mayCollide = true; + break; + } + + } + if (mayCollide == true) { + break; + } + + // TODO change this + eax += *ebp; + } + + if (mayCollide == false) { + vehicle->var_C4 = 0; + return false; + } + + vehicle->var_C4++; + if (vehicle->var_C4 < 200) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_6; + if (otherVehicleIndex != NULL) + *otherVehicleIndex = collideId; + return true; + } + + // TODO Is it possible for collideVehicle to be NULL? + + if (vehicle->status == VEHICLE_STATUS_MOVING_TO_END_OF_STATION){ + if (vehicle->sprite_direction == 0) { + if (vehicle->x <= collideVehicle->x) { + return false; + } + } + else if (vehicle->sprite_direction == 8) { + if (vehicle->y >= collideVehicle->y) { + return false; + } + } + else if (vehicle->sprite_direction == 16) { + if (vehicle->x >= collideVehicle->x) { + return false; + } + } + else if (vehicle->sprite_direction == 24) { + if (vehicle->y <= collideVehicle->y) { + return false; + } + } + } + + if (collideVehicle->status == VEHICLE_STATUS_TRAVELLING_BOAT && + vehicle->status != VEHICLE_STATUS_ARRIVING && + vehicle->status != VEHICLE_STATUS_TRAVELLING + ) { + return false; + } + + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_6; + if (otherVehicleIndex != NULL) + *otherVehicleIndex = collideId; + return true; +} + +/** + * + * rct2: 0x006DB7D6 + */ +static void sub_6DB7D6(rct_vehicle *vehicle) +{ + rct_vehicle *previousVehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride); + rct_vehicle *nextVehicle = GET_VEHICLE(vehicle->next_vehicle_on_ride); + + vehicle->track_progress = 168; + vehicle->vehicle_type ^= 1; + + previousVehicle->track_progress = 86; + nextVehicle->track_progress = 158; + + sub_6DB807(nextVehicle); + sub_6DB807(previousVehicle); +} + +/** + * + * rct2: 0x006DBF3E + */ +void sub_6DBF3E(rct_vehicle *vehicle) +{ + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + + vehicle->acceleration = (uint32)((sint32)vehicle->acceleration / RCT2_GLOBAL(0x00F64E10, sint32)); + if (vehicle->var_CD == 2) { + return; + } + + int trackType = vehicle->track_type >> 2; + if (!(RCT2_GLOBAL(0x0099BA64 + (trackType * 16), uint32) & 0x10)) { + return; + } + + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_3; + + rct_map_element *mapElement = map_get_track_element_at_of_type_seq( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z >> 3, + trackType, + 0 + ); + if (RCT2_GLOBAL(0x00F64E1C, uint32) == 0xFFFFFFFF) { + RCT2_GLOBAL(0x00F64E1C, uint32) = (mapElement->properties.track.sequence >> 4) & 7; + } + + if (trackType == TRACK_ELEM_TOWER_BASE && + vehicle == RCT2_GLOBAL(0x00F64E04, rct_vehicle*) + ) { + if (vehicle->track_progress > 3 && !(vehicle->update_flags & VEHICLE_UPDATE_FLAG_3)) { + rct_xy_element input, output; + int outputZ, outputDirection; + + input.x = vehicle->track_x; + input.y = vehicle->track_y; + input.element = mapElement; + if (!track_block_get_next(&input, &output, &outputZ, &outputDirection)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_12; + } + } + + if (vehicle->track_progress <= 3) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_STATION; + } + } + + if (trackType != TRACK_ELEM_END_STATION || + vehicle != RCT2_GLOBAL(0x00F64E04, rct_vehicle*) + ) { + return; + } + + uint16 ax = vehicle->track_progress; + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + if (ax <= 22) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_STATION; + } + } else { + uint16 cx = 17; + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_12) { + cx = 6; + } + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_14) { + cx = vehicle->var_CD == 6 ? 18 : 20; + } + + if (ax > cx) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_STATION; + } + } +} + +/** + * + * rct2: 0x006DB08C + */ +bool vehicle_update_track_motion_forwards_get_new_track(rct_vehicle *vehicle, uint16 trackType, rct_ride* ride, rct_ride_entry* rideEntry) { + registers regs = { 0 }; + + RCT2_GLOBAL(0x00F64E36, uint8) = gTrackDefinitions[trackType].vangle_end; + RCT2_GLOBAL(0x00F64E37, uint8) = gTrackDefinitions[trackType].bank_end; + rct_map_element *mapElement = map_get_track_element_at_of_type_seq( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z >> 3, + trackType, + 0 + ); + if (trackType == TRACK_ELEM_CABLE_LIFT_HILL && vehicle == RCT2_GLOBAL(0x00F64E04, rct_vehicle*)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_11; + } + + if (track_element_is_block_start(mapElement)) { + if (vehicle->next_vehicle_on_train == SPRITE_INDEX_NULL) { + mapElement->flags |= MAP_ELEMENT_FLAG_BLOCK_BREAK_CLOSED; + if (trackType == TRACK_ELEM_BLOCK_BRAKES || trackType == TRACK_ELEM_END_STATION) { + if (!(rideEntry->vehicles[0].flags_b & VEHICLE_ENTRY_FLAG_B_3)) { + audio_play_sound_at_location(SOUND_49, vehicle->track_x, vehicle->track_y, vehicle->track_z); + } + } + map_invalidate_element(vehicle->track_x, vehicle->track_z, mapElement); + vehicle_update_block_breaks_open_previous_section(vehicle, mapElement); + } + } + + // TODO check if getting the vehicle entry again is necessary + rct_ride_entry_vehicle* vehicleEntry = vehicle_get_vehicle_entry(vehicle); + + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_8) { + vehicle_update_scenery_door(vehicle); + } + + switch (vehicle->var_CD) { + default: + goto loc_6DB358; + case 2: + case 3: + vehicle->var_CD = 2; + goto loc_6DB32A; + case 4: + vehicle->var_CD = 1; + goto loc_6DB358; + case 7: + vehicle->var_CD = 6; + goto loc_6DB358; + case 8: + vehicle->var_CD = 5; + goto loc_6DB358; + } + +loc_6DB32A: + { + track_begin_end trackBeginEnd; + if (!track_block_get_previous(vehicle->track_x, vehicle->track_y, mapElement, &trackBeginEnd)) { + return false; + } + regs.eax = trackBeginEnd.begin_x; + regs.ecx = trackBeginEnd.begin_y; + regs.edx = trackBeginEnd.begin_z; + regs.bl = trackBeginEnd.begin_direction; + mapElement = trackBeginEnd.begin_element; + } + goto loc_6DB41D; + +loc_6DB358: + { + rct_xy_element xyElement; + int z, direction; + xyElement.x = vehicle->track_x; + xyElement.y = vehicle->track_y; + xyElement.element = mapElement; + if (!track_block_get_next(&xyElement, &xyElement, &z, &direction)) { + return false; + } + mapElement = xyElement.element; + regs.eax = xyElement.x; + regs.ecx = xyElement.y; + regs.edx = z; + regs.bl = direction; + } + if (mapElement->properties.track.type == 211 || + mapElement->properties.track.type == 212 + ) { + if (!vehicle->is_child && vehicle->velocity <= 0x30000) { + vehicle->velocity = 0; + } + } + + if (!loc_6DB38B(vehicle, mapElement)) { + return false; + } + + // Update VEHICLE_UPDATE_FLAG_11 flag + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_11; + int rideType = get_ride(mapElement->properties.track.ride_index)->type; + if (RideData4[rideType].flags & RIDE_TYPE_FLAG4_3) { + if (mapElement->properties.track.colour & 4) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_11; + } + } + +loc_6DB41D: + vehicle->track_x = regs.ax; + vehicle->track_y = regs.cx; + vehicle->track_z = regs.dx; + + // TODO check if getting the vehicle entry again is necessary + vehicleEntry = vehicle_get_vehicle_entry(vehicle); + + if ((vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_14) && vehicle->var_CD < 7) { + trackType = mapElement->properties.track.type; + if (trackType == TRACK_ELEM_FLAT) { + loc_6DB481(vehicle); + } + else if (ride->lifecycle_flags & RIDE_LIFECYCLE_PASS_STATION_NO_STOPPING) { + if (track_element_is_station(mapElement)) { + loc_6DB481(vehicle); + } + } + } + + if (vehicle->var_CD != 0 && vehicle->var_CD < 5) { + rct_xy8 curLocation = { + .x = regs.ax >> 5, + .y = regs.cx >> 5 + }; + + regs.dx >>= 3; + if (curLocation.xy == ride->chairlift_bullwheel_location[1].xy && regs.dl == ride->chairlift_bullwheel_z[1]) { + vehicle->var_CD = 3; + } + else if (curLocation.xy == ride->chairlift_bullwheel_location[0].xy && regs.dl == ride->chairlift_bullwheel_z[0]) { + vehicle->var_CD = 4; + } + } + + // loc_6DB500 + // Update VEHICLE_UPDATE_FLAG_0 + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_0; + if (track_element_is_lift_hill(mapElement)) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_0; + } + + trackType = mapElement->properties.track.type; + if (trackType != TRACK_ELEM_BRAKES) { + vehicle->target_seat_rotation = mapElement->properties.track.colour >> 4; + } + vehicle->track_direction = regs.bl & 3; + vehicle->track_type |= trackType << 2; + vehicle->break_speed = (mapElement->properties.track.sequence >> 4) << 1; + if (trackType == TRACK_ELEM_ON_RIDE_PHOTO) { + vehicle_trigger_on_ride_photo(vehicle, mapElement); + } + if (trackType == TRACK_ELEM_ROTATION_CONTROL_TOGGLE) { + vehicle->update_flags ^= VEHICLE_UPDATE_FLAG_13; + } + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_8) { + sub_6DEDE8(vehicle); + } + return true; +} + +/** + * + * rct2: 0x006DAEB9 + */ +bool vehicle_update_track_motion_forwards(rct_vehicle *vehicle, rct_ride_entry_vehicle* vehicleEntry, rct_ride* ride, rct_ride_entry* rideEntry) { + registers regs = { 0 }; +loc_6DAEB9: + regs.edi = vehicle->track_type; + regs.cx = vehicle->track_type >> 2; + + int trackType = vehicle->track_type >> 2; + if (trackType == TRACK_ELEM_HEARTLINE_TRANSFER_UP || trackType == TRACK_ELEM_HEARTLINE_TRANSFER_DOWN) { + if (vehicle->track_progress == 80) { + vehicle->vehicle_type ^= 1; + vehicleEntry = vehicle_get_vehicle_entry(vehicle); + } + if (RCT2_GLOBAL(0x00F64E08, sint32) >= 0x40000) { + vehicle->acceleration = -RCT2_GLOBAL(0x00F64E08, sint32) * 8; + } + else if (RCT2_GLOBAL(0x00F64E08, sint32) < 0x20000) { + vehicle->acceleration = 0x50000; + } + } + else if (trackType == TRACK_ELEM_BRAKES) { + if (!( + ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN && + ride->breakdown_reason_pending == BREAKDOWN_BRAKES_FAILURE && + ride->mechanic_status == RIDE_MECHANIC_STATUS_4 + )) { + regs.eax = vehicle->break_speed << 16; + if (regs.eax < RCT2_GLOBAL(0x00F64E08, sint32)) { + vehicle->acceleration = -RCT2_GLOBAL(0x00F64E08, sint32) * 16; + } + else if (!(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 0x0F)) { + if (RCT2_GLOBAL(0x00F64E2C, uint8) == 0) { + RCT2_GLOBAL(0x00F64E2C, uint8)++; + audio_play_sound_at_location(SOUND_51, vehicle->x, vehicle->y, vehicle->z); + } + } + } + } + + if ((trackType == TRACK_ELEM_FLAT && ride->type == RIDE_TYPE_REVERSE_FREEFALL_COASTER) || + (trackType == TRACK_ELEM_POWERED_LIFT) + ) { + vehicle->acceleration = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 7, uint8) << 16; + } + if (trackType == TRACK_ELEM_BRAKE_FOR_DROP) { + if (!vehicle->is_child) { + if (!(vehicle->update_flags & VEHICLE_UPDATE_FLAG_ON_BREAK_FOR_DROP)) { + if (vehicle->track_progress >= 8) { + vehicle->acceleration = -RCT2_GLOBAL(0x00F64E08, sint32) * 16; + if (vehicle->track_progress >= 24) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_ON_BREAK_FOR_DROP; + vehicle->vertical_drop_countdown = 90; + } + } + } + } + } + if (trackType == TRACK_ELEM_LOG_FLUME_REVERSER) { + if (vehicle->track_progress != 16 || vehicle->velocity < 0x40000) { + if (vehicle->track_progress == 32) { + vehicle->vehicle_type = vehicleEntry->var_58; + vehicleEntry = vehicle_get_vehicle_entry(vehicle); + } + } + else { + vehicle->track_progress += 17; + } + } + + regs.ax = vehicle->track_progress + 1; + + const rct_vehicle_info *moveInfo = vehicle_get_move_info( + vehicle->var_CD, + vehicle->track_type, + 0 + ); + + // Track Total Progress is in the two bytes before the move info list + uint16 trackTotalProgress = *((uint16*)((int)moveInfo - 2)); + if (regs.ax >= trackTotalProgress) { + if (!vehicle_update_track_motion_forwards_get_new_track(vehicle, trackType, ride, rideEntry)) { + goto loc_6DB94A; + } + regs.ax = 0; + } + + vehicle->track_progress = regs.ax; + vehicle_update_handle_water_splash(vehicle); + + // loc_6DB706 + moveInfo = vehicle_get_move_info( + vehicle->var_CD, + vehicle->track_type, + vehicle->track_progress + ); + sint16 x = vehicle->track_x + moveInfo->x; + sint16 y = vehicle->track_y + moveInfo->y; + sint16 z = vehicle->track_z + moveInfo->z + RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + + trackType = vehicle->track_type >> 2; + regs.ebx = 0; + if (x != unk_F64E20->x) { regs.ebx |= 1; } + if (y != unk_F64E20->y) { regs.ebx |= 2; } + if (z != unk_F64E20->z) { regs.ebx |= 4; } + if (vehicle->var_CD == 15 && + (trackType == TRACK_ELEM_LEFT_REVERSER || + trackType == TRACK_ELEM_RIGHT_REVERSER) && + vehicle->track_progress >= 30 && + vehicle->track_progress <= 66 + ) { + regs.ebx |= 8; + } + + if (vehicle->var_CD == 16 && + (trackType == TRACK_ELEM_LEFT_REVERSER || + trackType == TRACK_ELEM_RIGHT_REVERSER) && + vehicle->track_progress == 96 + ) { + sub_6DB7D6(vehicle); + + const rct_vehicle_info *moveInfo2 = vehicle_get_move_info( + vehicle->var_CD, + vehicle->track_type, + vehicle->track_progress + ); + x = vehicle->x + moveInfo2->x; + y = vehicle->y + moveInfo2->y; + } + + // loc_6DB8A5 + regs.ebx = RCT2_ADDRESS(0x009A2930, sint32)[regs.ebx]; + vehicle->remaining_distance -= regs.ebx; + unk_F64E20->x = x; + unk_F64E20->y = y; + unk_F64E20->z = z; + vehicle->sprite_direction = moveInfo->direction; + vehicle->bank_rotation = moveInfo->bank_rotation; + vehicle->vehicle_sprite_type = moveInfo->vehicle_sprite_type; + + regs.ebx = moveInfo->vehicle_sprite_type; + + if ((vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_9) && moveInfo->vehicle_sprite_type != 0) { + vehicle->var_4A = 0; + vehicle->swinging_car_var_0 = 0; + vehicle->var_4E = 0; + } + + // vehicle == frontVehicle + if (vehicle == RCT2_GLOBAL(0x00F64E00, rct_vehicle*)) { + if (RCT2_GLOBAL(0x00F64E08, sint32) >= 0) { + regs.bp = vehicle->prev_vehicle_on_ride; + if (vehicle_update_motion_collision_detection(vehicle, x, y, z, (uint16 *)®s.bp)) { + goto loc_6DB967; + } + } + } + + // loc_6DB928 + if (vehicle->remaining_distance < 0x368A) { + return true; + } + + regs.ebx = dword_9A2970[regs.ebx]; + vehicle->acceleration += regs.ebx; + RCT2_GLOBAL(0x00F64E10, uint32)++; + goto loc_6DAEB9; + +loc_6DB94A: + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; + regs.eax = vehicle->remaining_distance + 1; + RCT2_GLOBAL(0x00F64E0C, sint32) -= regs.eax; + vehicle->remaining_distance = 0xFFFFFFFF; + regs.ebx = vehicle->vehicle_sprite_type; + return false; + +loc_6DB967: + regs.eax = vehicle->remaining_distance + 1; + RCT2_GLOBAL(0x00F64E0C, sint32) -= regs.eax; + vehicle->remaining_distance -= regs.eax; + + // Might need to be bp rather than vehicle, but hopefully not + rct_vehicle *head = vehicle_get_head(GET_VEHICLE(regs.bp)); + + regs.eax = abs(vehicle->velocity - head->velocity); + if (!(rideEntry->flags & RIDE_ENTRY_FLAG_18)) { + if (regs.eax > 0xE0000) { + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_6)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_COLLISION; + } + } + } + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_14) { + vehicle->velocity -= vehicle->velocity >> 2; + } + else { + sint32 newHeadVelocity = vehicle->velocity >> 1; + vehicle->velocity = head->velocity >> 1; + head->velocity = newHeadVelocity; + } + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_1; + return false; +} + +/** + * + * rct2: 0x006DBAA6 + */ +bool vehicle_update_track_motion_backwards_get_new_track(rct_vehicle *vehicle, uint16 trackType, rct_ride* ride, rct_ride_entry* rideEntry, uint16* progress) { + RCT2_GLOBAL(0x00F64E36, uint8) = gTrackDefinitions[trackType].vangle_start; + RCT2_GLOBAL(0x00F64E37, uint8) = gTrackDefinitions[trackType].bank_start; + rct_map_element* mapElement = map_get_track_element_at_of_type_seq( + vehicle->track_x, + vehicle->track_y, + vehicle->track_z >> 3, + trackType, + 0 + ); + + bool nextTileBackwards = true; + int direction; +//loc_6DBB08:; + sint16 x = vehicle->track_x; + sint16 y = vehicle->track_y; + sint16 z = 0; + + switch (vehicle->var_CD) { + case 3: + vehicle->var_CD = 1; + break; + case 7: + vehicle->var_CD = 5; + break; + case 8: + vehicle->var_CD = 6; + break; + case 2: + case 4: + vehicle->var_CD = 2; + nextTileBackwards = false; + break; + } + + + if (nextTileBackwards == true) { + //loc_6DBB7E:; + track_begin_end trackBeginEnd; + if (!track_block_get_previous(x, y, mapElement, &trackBeginEnd)) { + return false; + } + mapElement = trackBeginEnd.begin_element; + + trackType = mapElement->properties.track.type; + if (trackType == TRACK_ELEM_LEFT_REVERSER || + trackType == TRACK_ELEM_RIGHT_REVERSER) { + return false; + } + + int trackColour = ((vehicle->update_flags >> 9) ^ mapElement->properties.track.colour) & 4; + int bank = gTrackDefinitions[trackType].bank_end; + bank = track_get_actual_bank_2(ride->type, trackColour, bank); + int vAngle = gTrackDefinitions[trackType].vangle_end; + if (RCT2_GLOBAL(0x00F64E36, uint8) != vAngle || + RCT2_GLOBAL(0x00F64E37, uint8) != bank + ) { + return false; + } + + // Update VEHICLE_UPDATE_FLAG_11 + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_11; + if (RideData4[ride->type].flags & RIDE_TYPE_FLAG4_3) { + if (mapElement->properties.track.colour & 4) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_11; + } + } + + x = trackBeginEnd.begin_x; + y = trackBeginEnd.begin_y; + z = trackBeginEnd.begin_z; + direction = trackBeginEnd.begin_direction; + } + else { + //loc_6DBB4F:; + rct_xy_element input; + rct_xy_element output; + int outputZ; + + input.x = x; + input.y = y; + input.element = mapElement; + if (!track_block_get_next(&input, &output, &outputZ, &direction)) { + return false; + } + mapElement = output.element; + x = output.x; + y = output.y; + z = outputZ; + } + +//loc_6DBC3B: + vehicle->track_x = x; + vehicle->track_y = y; + vehicle->track_z = z; + + if (vehicle->var_CD != 0 && + vehicle->var_CD < 5 + ) { + uint16 xy = (x >> 5) | ((y >> 5) << 8); + if (ride->chairlift_bullwheel_location[1].xy == xy && + ride->chairlift_bullwheel_z[1] == (z >> 3) + ) { + vehicle->var_CD = 3; + } + else if ( + ride->chairlift_bullwheel_location[0].xy == xy && + ride->chairlift_bullwheel_z[1] == (z >> 3) + ) { + vehicle->var_CD = 4; + } + } + + if (track_element_is_lift_hill(mapElement)) { + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + if (vehicle->next_vehicle_on_train == SPRITE_INDEX_NULL) { + trackType = mapElement->properties.track.type; + if (!(RCT2_ADDRESS(0x0099423C, uint16)[trackType] & 0x20)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_9; + } + } + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_0; + } + } + else { + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_0) { + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_0; + if (vehicle->next_vehicle_on_train == SPRITE_INDEX_NULL) { + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_8; + } + } + } + } + + trackType = mapElement->properties.track.type; + if (trackType != TRACK_ELEM_BRAKES) { + vehicle->target_seat_rotation = mapElement->properties.track.colour >> 4; + } + direction &= 3; + vehicle->track_type = trackType << 2; + vehicle->track_direction |= direction; + vehicle->break_speed = (mapElement->properties.track.sequence >> 4) << 1; + + const rct_vehicle_info* moveInfo = vehicle_get_move_info( + vehicle->var_CD, + vehicle->track_type, + 0 + ); + + // There are two bytes before the move info list + uint16 trackTotalProgress = *((uint16*)((int)moveInfo - 2)); + *progress = trackTotalProgress - 1; + return true; +} + +/** + * + * rct2: 0x006DBA33 + */ +bool vehicle_update_track_motion_backwards(rct_vehicle *vehicle, rct_ride_entry_vehicle* vehicleEntry, rct_ride* ride, rct_ride_entry* rideEntry) { + registers regs = { 0 }; + +loc_6DBA33:; + uint16 trackType = vehicle->track_type >> 2; + if (trackType == TRACK_ELEM_FLAT && ride->type == RIDE_TYPE_REVERSE_FREEFALL_COASTER) { + sint32 unkVelocity = RCT2_GLOBAL(0x00F64E08, sint32); + if (unkVelocity < -524288) { + unkVelocity = abs(unkVelocity); + vehicle->acceleration = unkVelocity * 2; + } + } + + if (trackType == TRACK_ELEM_BRAKES) { + regs.eax = -(vehicle->break_speed << 16); + if (regs.eax > RCT2_GLOBAL(0x00F64E08, sint32)) { + regs.eax = RCT2_GLOBAL(0x00F64E08, sint32) * -16; + vehicle->acceleration = regs.eax; + } + } + + regs.ax = vehicle->track_progress - 1; + if (regs.ax == -1) { + if (!vehicle_update_track_motion_backwards_get_new_track(vehicle, trackType, ride, rideEntry, (uint16 *)®s.ax)) { + goto loc_6DBE5E; + } + } + + // loc_6DBD42 + vehicle->track_progress = regs.ax; + const rct_vehicle_info* moveInfo = vehicle_get_move_info( + vehicle->var_CD, + vehicle->track_type, + vehicle->track_progress + ); + + sint16 x = vehicle->track_x + moveInfo->x; + sint16 y = vehicle->track_y + moveInfo->y; + sint16 z = vehicle->track_z + moveInfo->z + RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + + regs.ebx = 0; + if (x != unk_F64E20->x) { regs.ebx |= 1; } + if (y != unk_F64E20->y) { regs.ebx |= 2; } + if (z != unk_F64E20->z) { regs.ebx |= 4; } + vehicle->remaining_distance += RCT2_ADDRESS(0x009A2930, sint32)[regs.ebx]; + + unk_F64E20->x = x; + unk_F64E20->y = y; + unk_F64E20->z = z; + vehicle->sprite_direction = moveInfo->direction; + vehicle->bank_rotation = moveInfo->bank_rotation; + regs.ebx = moveInfo->vehicle_sprite_type; + vehicle->vehicle_sprite_type = regs.bl; + + if ((vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_9) && regs.bl != 0) { + vehicle->var_4A = 0; + vehicle->swinging_car_var_0 = 0; + vehicle->var_4E = 0; + } + + if (vehicle == RCT2_GLOBAL(0x00F64E00, rct_vehicle*)) { + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + regs.bp = vehicle->next_vehicle_on_ride; + if (vehicle_update_motion_collision_detection(vehicle, x, y, z, (uint16*)®s.bp)) { + goto loc_6DBE7F; + } + } + } + + // loc_6DBE3F + if ((sint32)vehicle->remaining_distance >= 0) { + return true; + } + regs.ebx = dword_9A2970[regs.ebx]; + vehicle->acceleration += regs.ebx; + RCT2_GLOBAL(0x00F64E10, uint32)++; + goto loc_6DBA33; + +loc_6DBE5E: + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; + regs.eax = vehicle->remaining_distance - 0x368A; + RCT2_GLOBAL(0x00F64E0C, sint32) -= regs.eax; + vehicle->remaining_distance -= regs.eax; + regs.ebx = vehicle->vehicle_sprite_type; + return false; + +loc_6DBE7F: + regs.eax = vehicle->remaining_distance - 0x368A; + RCT2_GLOBAL(0x00F64E0C, sint32) -= regs.eax; + vehicle->remaining_distance -= regs.eax; + + rct_vehicle *v3 = GET_VEHICLE(regs.bp); + rct_vehicle *v4 = RCT2_GLOBAL(0x00F64E04, rct_vehicle*); + regs.eax = abs(v4->velocity - v3->velocity); + + if (!(rideEntry->flags & RIDE_ENTRY_FLAG_18)) { + if (regs.eax > 0xE0000) { + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_6)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_COLLISION; + } + } + } + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_14) { + vehicle->velocity -= vehicle->velocity >> 2; + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_2; + } + else { + sint32 v3Velocity = v3->velocity; + v3->velocity = v4->velocity >> 1; + v4->velocity = v3Velocity >> 1; + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_2; + } + + return false; +} + +/** + * rct2: 0x006DC3A7 + * + * + */ +int vehicle_update_track_motion_mini_golf(rct_vehicle *vehicle, int* outStation) { + registers regs = { 0 }; + + rct_ride *ride = get_ride(vehicle->ride); + rct_ride_entry *rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + + rct_map_element *mapElement = NULL; + + RCT2_GLOBAL(0x00F64E04, rct_vehicle*) = vehicle; + RCT2_GLOBAL(0x00F64E18, uint32) = 0; + vehicle->velocity += vehicle->acceleration; + RCT2_GLOBAL(0x00F64E08, sint32) = vehicle->velocity; + RCT2_GLOBAL(0x00F64E0C, sint32) = (vehicle->velocity >> 10) * 42; + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + vehicle = vehicle_get_tail(vehicle); + } + RCT2_GLOBAL(0x00F64E00, rct_vehicle*) = vehicle; + +loc_6DC40E: + regs.ebx = vehicle->vehicle_sprite_type; + RCT2_GLOBAL(0x00F64E10, uint32) = 1; + vehicle->acceleration = dword_9A2970[vehicle->vehicle_sprite_type]; + vehicle->remaining_distance = RCT2_GLOBAL(0x00F64E0C, sint32) + vehicle->remaining_distance; + if ((sint32)vehicle->remaining_distance < 0) { + goto loc_6DCA7A; + } + if ((sint32)vehicle->remaining_distance < 0x368A) { + goto loc_6DCE02; + } + vehicle->var_B8 &= ~(1 << 1); + unk_F64E20->x = vehicle->x; + unk_F64E20->y = vehicle->y; + unk_F64E20->z = vehicle->z; + vehicle_invalidate(vehicle); + +loc_6DC462: + if (vehicle->var_D3 == 0) { + goto loc_6DC476; + } + vehicle->var_D3--; + goto loc_6DC985; + +loc_6DC476: + if (vehicle->mini_golf_flags & (1 << 2)) { + regs.edi = RCT2_ADDRESS(0x008B8F74, uint32)[vehicle->var_D4]; + regs.al = vehicle->var_C5 + 1; + if ((uint8)regs.al < ((uint8*)regs.edi)[-1]) { + vehicle->var_C5 = regs.al; + goto loc_6DC985; + } + vehicle->mini_golf_flags &= ~(1 << 2); + } + + if (vehicle->mini_golf_flags & (1 << 0)) { + regs.di = vehicle->is_child ? vehicle->prev_vehicle_on_ride : vehicle->next_vehicle_on_ride; + rct_vehicle *vEDI = GET_VEHICLE(regs.di); + if (!(vEDI->mini_golf_flags & (1 << 0)) || (vEDI->mini_golf_flags & (1 << 2))) { + goto loc_6DC985; + } + if (vEDI->var_D3 != 0) { + goto loc_6DC985; + } + vEDI->mini_golf_flags &= ~(1 << 0); + vehicle->mini_golf_flags &= ~(1 << 0); + } + + if (vehicle->mini_golf_flags & (1 << 1)) { + regs.di = vehicle->is_child ? vehicle->prev_vehicle_on_ride : vehicle->next_vehicle_on_ride; + rct_vehicle *vEDI = GET_VEHICLE(regs.di); + if (!(vEDI->mini_golf_flags & (1 << 1)) || (vEDI->mini_golf_flags & (1 << 2))) { + goto loc_6DC985; + } + if (vEDI->var_D3 != 0) { + goto loc_6DC985; + } + vEDI->mini_golf_flags &= ~(1 << 1); + vehicle->mini_golf_flags &= ~(1 << 1); + } + + if (vehicle->mini_golf_flags & (1 << 3)) { + rct_vehicle *vEDI = vehicle; + + for (;;) { + vEDI = GET_VEHICLE(vEDI->prev_vehicle_on_ride); + if (vEDI == vehicle) { + break; + } + if (!vEDI->is_child) continue; + if (!(vEDI->mini_golf_flags & (1 << 4))) continue; + if (vEDI->track_x != vehicle->track_x) continue; + if (vEDI->track_y != vehicle->track_y) continue; + if (vEDI->track_z != vehicle->track_z) continue; + goto loc_6DC985; + } + + vehicle->mini_golf_flags |= (1 << 4); + vehicle->mini_golf_flags &= ~(1 << 3); + } + + // loc_6DC5B8 + const rct_vehicle_info* moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, 0); + + // There are two bytes before the move info list + { + uint16 unk16_v34 = vehicle->track_progress + 1; + uint16 unk16 = *((uint16*)((int)moveInfo - 2)); + if (unk16_v34 < unk16) { + regs.ax = unk16_v34; + goto loc_6DC743; + } + } + + uint16 trackType = vehicle->track_type >> 2; + RCT2_GLOBAL(0x00F64E36, uint8) = gTrackDefinitions[trackType].vangle_end; + RCT2_GLOBAL(0x00F64E37, uint8) = gTrackDefinitions[trackType].bank_end; + mapElement = map_get_track_element_at_of_type_seq( + vehicle->track_x, vehicle->track_y, vehicle->track_z >> 3, + trackType, 0 + ); + sint16 x, y, z; + int direction; + { + rct_xy_element input, output; + int outZ, outDirection; + input.x = vehicle->track_x; + input.y = vehicle->track_y; + input.element = mapElement; + if (!track_block_get_next(&input, &output, &outZ, &outDirection)) { + goto loc_6DC9BC; + } + mapElement = output.element; + x = output.x; + y = output.y; + z = outZ; + direction = outDirection; + } + + if (!loc_6DB38B(vehicle, mapElement)) { + goto loc_6DC9BC; + } + + int rideType = get_ride(mapElement->properties.track.ride_index)->type; + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_11; + if (RideData4[rideType].flags & RIDE_TYPE_FLAG4_3) { + if (mapElement->properties.track.colour & (1 << 2)) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_11; + } + } + + vehicle->track_x = x; + vehicle->track_y = y; + vehicle->track_z = z; + + if (vehicle->is_child) { + rct_vehicle *prevVehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride); + regs.al = prevVehicle->var_CD; + if (regs.al != 9) { + regs.al--; + } + vehicle->var_CD = regs.al; + } + + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_0; + vehicle->track_type = (mapElement->properties.track.type << 2) | (direction & 3); + vehicle->var_CF = (mapElement->properties.track.sequence >> 4) << 1; + regs.ax = 0; + +loc_6DC743: + vehicle->track_progress = regs.ax; + if (vehicle->is_child) { + vehicle->var_C5++; + if (vehicle->var_C5 >= 6) { + vehicle->var_C5 = 0; + } + } + + for (;;) { + moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, vehicle->track_progress); + if (moveInfo->x != (uint16)0x8000) { + break; + } + switch (moveInfo->y) { + case 0: // loc_6DC7B4 + if (vehicle->is_child) { + vehicle->mini_golf_flags |= (1 << 3); + } + else { + uint16 rand16 = scenario_rand() & 0xFFFF; + regs.bl = 14; + if (rand16 <= 0xA000) { + regs.bl = 12; + if (rand16 <= 0x900) { + regs.bl = 10; + } + } + vehicle->var_CD = regs.bl; + } + vehicle->track_progress++; + break; + case 1: // loc_6DC7ED + vehicle->var_D3 = (uint8)moveInfo->z; + vehicle->track_progress++; + break; + case 2: // loc_6DC800 + vehicle->mini_golf_flags |= (1 << 0); + vehicle->track_progress++; + break; + case 3: // loc_6DC810 + vehicle->mini_golf_flags |= (1 << 1); + vehicle->track_progress++; + break; + case 4: // loc_6DC820 + z = moveInfo->z; + if (z == 2) { + rct_peep *peep = GET_PEEP(vehicle->peep[0]); + if (peep->id & 7) { + z = 7; + } + } + if (z == 6) { + rct_peep *peep = GET_PEEP(vehicle->peep[0]); + if (peep->id & 7) { + z = 8; + } + } + vehicle->var_D4 = (uint8)z; + vehicle->var_C5 = 0; + vehicle->track_progress++; + break; + case 5: // loc_6DC87A + vehicle->mini_golf_flags |= (1 << 2); + vehicle->track_progress++; + break; + case 6: // loc_6DC88A + vehicle->mini_golf_flags &= ~(1 << 4); + vehicle->mini_golf_flags |= (1 << 5); + vehicle->track_progress++; + break; + default: + log_error("Invalid move info..."); + assert(false); + break; + } + } + + // loc_6DC8A1 + x = vehicle->track_x + moveInfo->x; + y = vehicle->track_y + moveInfo->y; + z = vehicle->track_z + moveInfo->z + RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + + // Investigate redundant code + regs.ebx = 0; + if (regs.ax != unk_F64E20->x) { + regs.ebx |= 1; + } + if (regs.cx == unk_F64E20->y) { + regs.ebx |= 2; + } + if (regs.dx == unk_F64E20->z) { + regs.ebx |= 4; + } + regs.ebx = 0x368A; + vehicle->remaining_distance -= regs.ebx; + if ((sint32)vehicle->remaining_distance < 0) { + vehicle->remaining_distance = 0; + } + + unk_F64E20->x = x; + unk_F64E20->y = y; + unk_F64E20->z = z; + vehicle->sprite_direction = moveInfo->direction; + vehicle->bank_rotation = moveInfo->bank_rotation; + vehicle->vehicle_sprite_type = moveInfo->vehicle_sprite_type; + + if (rideEntry->vehicles[0].flags_b & VEHICLE_ENTRY_FLAG_B_9) { + if (vehicle->vehicle_sprite_type != 0) { + vehicle->var_4A = 0; + vehicle->swinging_car_var_0 = 0; + vehicle->var_4E = 0; + } + } + + if (vehicle == RCT2_GLOBAL(0x00F64E00, rct_vehicle*)) { + if (RCT2_GLOBAL(0x00F64E08, sint32) >= 0) { + regs.bp = vehicle->prev_vehicle_on_ride; + vehicle_update_motion_collision_detection(vehicle, x, y, z, (uint16*)®s.bp); + } + } + goto loc_6DC99A; + +loc_6DC985: + regs.ebx = 0; + vehicle->remaining_distance -= 0x368A; + if ((sint32)vehicle->remaining_distance < 0) { + vehicle->remaining_distance = 0; + } + +loc_6DC99A: + if ((sint32)vehicle->remaining_distance < 0x368A) { + goto loc_6DCDE4; + } + vehicle->acceleration = dword_9A2970[vehicle->vehicle_sprite_type]; + RCT2_GLOBAL(0x00F64E10, uint32)++; + goto loc_6DC462; + +loc_6DC9BC: + RCT2_GLOBAL(0x00F64E18, uint32) |= 0x20; + regs.eax = vehicle->remaining_distance + 1; + RCT2_GLOBAL(0x00F64E0C, sint32) -= regs.eax; + vehicle->remaining_distance -= regs.eax; + regs.ebx = vehicle->vehicle_sprite_type; + goto loc_6DCD2B; + + ///////////////////////////////////////// + // Dead code: 0x006DC9D9 to 0x006DCA79 // + ///////////////////////////////////////// + +loc_6DCA7A: + vehicle->var_B8 &= ~(1 << 1); + unk_F64E20->x = vehicle->x; + unk_F64E20->y = vehicle->y; + unk_F64E20->z = vehicle->z; + vehicle_invalidate(vehicle); + +loc_6DCA9A: + regs.ax = vehicle->track_progress - 1; + if (regs.ax != (short)0xFFFF) { + goto loc_6DCC2C; + } + + trackType = vehicle->track_type >> 2; + RCT2_GLOBAL(0x00F64E36, uint8) = gTrackDefinitions[trackType].vangle_end; + RCT2_GLOBAL(0x00F64E37, uint8) = gTrackDefinitions[trackType].bank_end; + mapElement = map_get_track_element_at_of_type_seq( + vehicle->track_x, vehicle->track_y, vehicle->track_z >> 3, + trackType, 0 + ); + { + track_begin_end trackBeginEnd; + if (!track_block_get_previous(vehicle->track_x, vehicle->track_y, mapElement, &trackBeginEnd)) { + goto loc_6DC9BC; + } + x = trackBeginEnd.begin_x; + y = trackBeginEnd.begin_y; + z = trackBeginEnd.begin_z; + direction = trackBeginEnd.begin_direction; + mapElement = trackBeginEnd.begin_element; + } + + if (!loc_6DB38B(vehicle, mapElement)) { + goto loc_6DCD4A; + } + + rideType = get_ride(mapElement->properties.track.ride_index)->type; + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_11; + if (RideData4[rideType].flags & RIDE_TYPE_FLAG4_3) { + if (mapElement->properties.track.colour & (1 << 2)) { + vehicle->update_flags |= VEHICLE_UPDATE_FLAG_11; + } + } + + vehicle->track_x = x; + vehicle->track_y = y; + vehicle->track_z = z; + + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_0) { + vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_0; + if (vehicle->next_vehicle_on_train == SPRITE_INDEX_NULL) { + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_8; + } + } + } + + vehicle->track_type = (mapElement->properties.track.type << 2) | (direction & 3); + vehicle->var_CF = (mapElement->properties.track.colour >> 4) << 1; + + moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, 0); + + // There are two bytes before the move info list + regs.ax = *((uint16*)((int)moveInfo - 2)) - 1; + +loc_6DCC2C: + vehicle->track_progress = regs.ax; + + moveInfo = vehicle_get_move_info(vehicle->var_CD, vehicle->track_type, vehicle->track_progress); + x = vehicle->track_x + moveInfo->x; + y = vehicle->track_y + moveInfo->y; + z = vehicle->track_z + moveInfo->z + RCT2_GLOBAL(0x0097D21A + (ride->type * 8), sint8); + + // Investigate redundant code + regs.ebx = 0; + if (regs.ax != unk_F64E20->x) { + regs.ebx |= 1; + } + if (regs.cx == unk_F64E20->y) { + regs.ebx |= 2; + } + if (regs.dx == unk_F64E20->z) { + regs.ebx |= 4; + } + regs.ebx = 0x368A; + vehicle->remaining_distance -= regs.ebx; + if ((sint32)vehicle->remaining_distance < 0) { + vehicle->remaining_distance = 0; + } + + unk_F64E20->x = x; + unk_F64E20->y = y; + unk_F64E20->z = z; + vehicle->sprite_direction = moveInfo->direction; + vehicle->bank_rotation = moveInfo->bank_rotation; + vehicle->vehicle_sprite_type = moveInfo->vehicle_sprite_type; + + if (rideEntry->vehicles[0].flags_b & VEHICLE_ENTRY_FLAG_B_9) { + if (vehicle->vehicle_sprite_type != 0) { + vehicle->var_4A = 0; + vehicle->swinging_car_var_0 = 0; + vehicle->var_4E = 0; + } + } + + if (vehicle == RCT2_GLOBAL(0x00F64E00, rct_vehicle*)) { + if (RCT2_GLOBAL(0x00F64E08, sint32) >= 0) { + regs.bp = vehicle->var_44; + if (vehicle_update_motion_collision_detection(vehicle, x, y, z, (uint16*)®s.bp)) { + goto loc_6DCD6B; + } + } + } + +loc_6DCD2B: + if (vehicle->remaining_distance >= 0) { + goto loc_6DCDE4; + } + vehicle->acceleration += dword_9A2970[vehicle->vehicle_sprite_type]; + RCT2_GLOBAL(0x00F64E10, uint32)++; + goto loc_6DCA9A; + +loc_6DCD4A: + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_5; + regs.eax = vehicle->remaining_distance - 0x368A; + RCT2_GLOBAL(0x00F64E0C, sint32) -= regs.eax; + vehicle->remaining_distance -= regs.eax; + regs.ebx = vehicle->vehicle_sprite_type; + goto loc_6DC99A; + +loc_6DCD6B: + regs.eax = vehicle->remaining_distance - 0x368A; + RCT2_GLOBAL(0x00F64E0C, sint32) -= regs.eax; + vehicle->remaining_distance -= regs.eax; + rct_vehicle *vEBP = GET_VEHICLE(regs.bp); + rct_vehicle *vEDI = RCT2_GLOBAL(0x00F64E04, rct_vehicle *); + regs.eax = abs(vEDI->velocity - vEBP->velocity); + if (regs.eax > 0xE0000) { + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_6)) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_COLLISION; + } + } + vEDI->velocity = vEBP->velocity >> 1; + vEBP->velocity = vEDI->velocity >> 1; + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_2; + goto loc_6DC99A; + +loc_6DCDE4: + sprite_move(unk_F64E20->x, unk_F64E20->y, unk_F64E20->z, (rct_sprite*)vehicle); + vehicle_invalidate(vehicle); + +loc_6DCE02: + vehicle->acceleration /= RCT2_GLOBAL(0x00F64E10, uint32); + if (vehicle->var_CD == 2) { + goto loc_6DCEB2; + } + trackType = vehicle->track_type >> 2; + if (!(RCT2_GLOBAL(0x0099BA64 + (trackType * 16), uint32) & 0x10)) { + goto loc_6DCEB2; + } + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_3; + if (trackType != TRACK_ELEM_END_STATION) { + goto loc_6DCEB2; + } + if (vehicle != RCT2_GLOBAL(0x00F64E04, rct_vehicle*)) { + goto loc_6DCEB2; + } + regs.ax = vehicle->track_progress; + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + goto loc_6DCE62; + } + regs.cx = 8; + if (regs.ax > regs.cx) { + goto loc_6DCE68; + } + goto loc_6DCEB2; + +loc_6DCE62: + if (regs.ax > 11) { + goto loc_6DCEB2; + } + +loc_6DCE68: + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_STATION; + regs.al = vehicle->track_x >> 5; + regs.ah = vehicle->track_y >> 5; + regs.dl = vehicle->track_z >> 3; + for (int i = 0; i < 4; i++) { + if ((uint16)regs.ax != ride->station_starts[i]) { + continue; + } + if ((uint16)regs.dl != ride->station_heights[i]) { + continue; + } + RCT2_GLOBAL(0x00F64E1C, uint32) = i; + } + +loc_6DCEB2: + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_0) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_ON_LIFT_HILL; + } + if (RCT2_GLOBAL(0x00F64E08, sint32) >= 0) { + regs.si = vehicle->next_vehicle_on_train; + if ((uint16)regs.si == SPRITE_INDEX_NULL) { + goto loc_6DCEFF; + } + vehicle = GET_VEHICLE((uint16)regs.si); + goto loc_6DC40E; + } + + if (vehicle == RCT2_GLOBAL(0x00F64E04, rct_vehicle*)) { + goto loc_6DCEFF; + } + vehicle = GET_VEHICLE(vehicle->prev_vehicle_on_ride); + goto loc_6DC40E; + +loc_6DCEFF: + vehicle = RCT2_GLOBAL(0x00F64E04, rct_vehicle*); + regs.eax = 0; + regs.ebp = 0; + regs.dx = 0; + regs.ebx = 0; + + for (;;) { + regs.ebx++; + regs.dx |= vehicle->update_flags; + regs.bp += vehicle->friction; + regs.eax += vehicle->acceleration; + regs.si = vehicle->next_vehicle_on_train; + if ((uint16)regs.si == SPRITE_INDEX_NULL) { + break; + } + vehicle = GET_VEHICLE((uint16)regs.si); + } + + vehicle = RCT2_GLOBAL(0x00F64E04, rct_vehicle*); + regs.eax /= regs.ebx; + regs.ecx = (regs.eax * 21) >> 9; + regs.eax = vehicle->velocity >> 12; + regs.ecx -= regs.eax; + regs.ebx = vehicle->velocity; + regs.edx = vehicle->velocity >> 8; + regs.edx *= regs.edx; + if (regs.ebx < 0) { + regs.edx = -regs.edx; + } + regs.edx >>= 4; + regs.eax = regs.edx / regs.ebp; + regs.ecx -= regs.eax; + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3)) { + goto loc_6DD069; + } + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_0) { + regs.eax = vehicle->speed * 0x4000; + if (regs.eax < vehicle->velocity) { + goto loc_6DD069; + } + } + regs.eax = vehicle->speed; + regs.bx = vehicle->track_type >> 2; + regs.ebx = regs.eax; + regs.eax <<= 14; + regs.ebx *= regs.ebp; + regs.ebx >>= 2; + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_3) { + regs.eax = -regs.eax; + } + regs.eax -= vehicle->velocity; + regs.edx = vehicle->powered_acceleration; + regs.edx <<= 1; + regs.eax *= regs.edx; + regs.eax = regs.eax / regs.ebx; + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_13)) { + goto loc_6DD054; + } + + if (regs.eax < 0) { + regs.eax >>= 4; + } + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SPINNING) { + vehicle->var_B6 = clamp(-0x200, (sint16)vehicle->var_B6, 0x200); + } + + if (vehicle->vehicle_sprite_type != 0) { + regs.eax = max(0, regs.eax); + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SPINNING) { + if (vehicle->vehicle_sprite_type == 2) { + vehicle->var_B6 = 0; + } + } + } + else { + loc_6DD054: + regs.ebx = abs(vehicle->velocity); + if (regs.ebx > 0x10000) { + regs.ecx = 0; + } + } + regs.ecx += regs.eax; + +loc_6DD069: + vehicle->acceleration = regs.ecx; + regs.eax = RCT2_GLOBAL(0x00F64E18, uint32); + regs.ebx = RCT2_GLOBAL(0x00F64E1C, uint32); + + if (outStation != NULL) *outStation = regs.ebx; + return regs.eax; } /** * * rct2: 0x006DAB4C */ -int sub_6DAB4C(rct_vehicle *vehicle, int *outStation) +int vehicle_update_track_motion(rct_vehicle *vehicle, int *outStation) { - registers regs; - regs.esi = (int)vehicle; + registers regs = { 0 }; - RCT2_CALLFUNC_Y(0x006DAB4C, ®s); + rct_ride *ride = get_ride(vehicle->ride); + rct_ride_entry *rideEntry = get_ride_entry(vehicle->ride_subtype); + rct_ride_entry_vehicle *vehicleEntry = vehicle_get_vehicle_entry(vehicle); + rct_map_element *mapElement = NULL; + + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_MINI_GOLF) { + return vehicle_update_track_motion_mini_golf(vehicle, outStation); + } + + RCT2_GLOBAL(0x00F64E2C, uint8) = 0; + RCT2_GLOBAL(0x00F64E04, rct_vehicle*) = vehicle; + RCT2_GLOBAL(0x00F64E18, uint32) = 0; + RCT2_GLOBAL(0x00F64E1C, uint32) = 0xFFFFFFFF; + + vehicle_update_track_motion_up_stop_check(vehicle); + sub_6DAB4C_chunk_2(vehicle); + sub_6DAB4C_chunk_3(vehicle); + + if (RCT2_GLOBAL(0x00F64E08, sint32) < 0) { + vehicle = vehicle_get_tail(vehicle); + } + // This will be the front vehicle even when traveling + // backwards. + RCT2_GLOBAL(0x00F64E00, rct_vehicle*) = vehicle; + + uint16 spriteId = vehicle->sprite_index; + for (rct_vehicle* car = vehicle; spriteId != 0xFFFF; car = GET_VEHICLE(spriteId)) { + vehicleEntry = vehicle_get_vehicle_entry(car); + + // Swinging cars + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SWINGING) { + vehicle_update_swinging_car(car); + } + // Spinning cars + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SPINNING) { + vehicle_update_spinning_car(car); + } + // Rider sprites?? animation?? + if ((vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_7) || (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_8)) { + sub_6D63D4(car); + } + car->acceleration = dword_9A2970[car->vehicle_sprite_type]; + RCT2_GLOBAL(0x00F64E10, uint32) = 1; + + regs.eax = RCT2_GLOBAL(0x00F64E0C, sint32) + car->remaining_distance; + car->remaining_distance = regs.eax; + + car->var_B8 &= ~(1 << 1); + unk_F64E20->x = car->x; + unk_F64E20->y = car->y; + unk_F64E20->z = car->z; + invalidate_sprite_2((rct_sprite*)car); + + while (true) { + if (car->remaining_distance < 0) { + // Backward loop + if (vehicle_update_track_motion_backwards(car, vehicleEntry, ride, rideEntry)) { + break; + } + else { + if (car->remaining_distance < 0x368A) { + break; + } + regs.ebx = dword_9A2970[car->vehicle_sprite_type]; + car->acceleration += regs.ebx; + RCT2_GLOBAL(0x00F64E10, uint32)++; + continue; + } + } + if (car->remaining_distance < 0x368A) { + // Location found + goto loc_6DBF3E; + } + if (vehicle_update_track_motion_forwards(car, vehicleEntry, ride, rideEntry)) { + break; + } + else { + if (car->remaining_distance >= 0) { + break; + } + regs.ebx = dword_9A2970[car->vehicle_sprite_type]; + car->acceleration = regs.ebx; + RCT2_GLOBAL(0x00F64E10, uint32)++; + continue; + } + } + // loc_6DBF20 + sprite_move(unk_F64E20->x, unk_F64E20->y, unk_F64E20->z, (rct_sprite*)car); + invalidate_sprite_2((rct_sprite*)car); + + loc_6DBF3E: + sub_6DBF3E(car); + + // loc_6DC0F7 + if (car->update_flags & VEHICLE_UPDATE_FLAG_0) { + RCT2_GLOBAL(0x00F64E18, uint32) |= VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_ON_LIFT_HILL; + } + if (RCT2_GLOBAL(0x00F64E08, sint32) >= 0) { + spriteId = car->next_vehicle_on_train; + } + else { + if (car == RCT2_GLOBAL(0x00F64E04, rct_vehicle*)) { + break; + } + spriteId = car->prev_vehicle_on_ride; + } + } + // loc_6DC144 + vehicle = RCT2_GLOBAL(0x00F64E04, rct_vehicle*); + + vehicleEntry = vehicle_get_vehicle_entry(vehicle); + //eax + sint32 totalAcceleration = 0; + //ebp + sint32 totalFriction = 0; + //Not used + regs.dx = 0; + //ebx + int numVehicles = 0; + + for (;;) { + numVehicles++; + // Not used? + regs.dx |= vehicle->update_flags; + totalFriction += vehicle->friction; + totalAcceleration += vehicle->acceleration; + + uint16 spriteIndex = vehicle->next_vehicle_on_train; + if (spriteIndex == SPRITE_INDEX_NULL) { + break; + } + vehicle = GET_VEHICLE(spriteIndex); + } + + vehicle = RCT2_GLOBAL(0x00F64E04, rct_vehicle*); + regs.eax = (totalAcceleration / numVehicles) * 21; + if (regs.eax < 0) { + regs.eax += 511; + } + regs.eax >>= 9; + regs.ecx = regs.eax; + regs.eax = vehicle->velocity; + if (regs.eax < 0) { + regs.eax = -regs.eax; + regs.eax >>= 12; + regs.eax = -regs.eax; + } else { + regs.eax >>= 12; + } + + regs.ecx -= regs.eax; + regs.edx = vehicle->velocity; + regs.ebx = regs.edx; + regs.edx >>= 8; + regs.edx *= regs.edx; + if (regs.ebx < 0) { + regs.edx = -regs.edx; + } + regs.edx >>= 4; + regs.eax = regs.edx; + regs.eax = regs.eax / totalFriction; + regs.ecx -= regs.eax; + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_3)) { + goto loc_6DC2FA; + } + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_0) { + regs.eax = vehicle->speed * 0x4000; + if (regs.eax < vehicle->velocity) { + goto loc_6DC2FA; + } + } + regs.eax = vehicle->speed; + uint16 trackType = vehicle->track_direction >> 2; + if (trackType == TRACK_ELEM_LEFT_QUARTER_TURN_1_TILE) { + goto loc_6DC22F; + } + if (trackType != TRACK_ELEM_RIGHT_QUARTER_TURN_1_TILE) { + goto loc_6DC23A; + } + if (vehicle->var_CD == 6) { + goto loc_6DC238; + } + +loc_6DC226: + regs.ebx = regs.eax >> 2; + regs.eax -= regs.ebx; + goto loc_6DC23A; + +loc_6DC22F: + if (vehicle->var_CD != 5) { + goto loc_6DC226; + } + +loc_6DC238: + regs.eax >>= 1; + +loc_6DC23A: + regs.ebx = regs.eax; + regs.eax <<= 14; + regs.ebx *= totalFriction; + regs.ebx >>= 2; + if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_3) { + regs.eax = -regs.eax; + } + regs.eax -= vehicle->velocity; + regs.edx = vehicle->powered_acceleration; + regs.edx <<= 1; + regs.eax *= regs.edx; + regs.eax /= regs.ebx; + + if (vehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_15) { + regs.eax <<= 2; + } + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_13)) { + goto loc_6DC2E3; + } + + if (regs.eax < 0) { + regs.eax >>= 4; + } + + if (vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SPINNING) { + regs.bx = vehicle->var_B6; + if (regs.bx > 512) { + regs.bx = 512; + } + if (regs.bx < -512) { + regs.bx = -512; + } + vehicle->var_B6 = regs.bx; + } + + if (vehicle->vehicle_sprite_type != 0) { + if (regs.eax < 0) { + regs.eax = 0; + } + + if (!(vehicleEntry->flags_b & VEHICLE_ENTRY_FLAG_B_SPINNING)) { + if (vehicle->vehicle_sprite_type == 2) { + vehicle->var_B6 = 0; + } + } + goto loc_6DC2F6; + } + +loc_6DC2E3: + regs.ebx = vehicle->velocity; + if (regs.ebx < 0) { + regs.ebx = -regs.ebx; + } + if (regs.ebx <= 0x10000) { + regs.ecx = 0; + } + +loc_6DC2F6: + regs.ecx += regs.eax; + goto loc_6DC316; + +loc_6DC2FA: + if (regs.ecx <= 0) { + if (regs.ecx >= -500) { + if (vehicle->velocity <= 0x8000) { + regs.ecx += 400; + } + } + } + +loc_6DC316: + regs.bx = vehicle->track_type >> 2; + if (regs.bx == TRACK_ELEM_WATER_SPLASH) { + if (vehicle->track_progress >= 48 && + vehicle->track_progress <= 128 + ) { + regs.eax = vehicle->velocity >> 6; + regs.ecx -= regs.eax; + } + } + + if (rideEntry->flags & RIDE_ENTRY_FLAG_9) { + if (!vehicle->is_child) { + regs.bx = vehicle->track_type >> 2; + if (track_element_is_covered(regs.bx)) { + if (vehicle->velocity > 0x20000) { + regs.eax = vehicle->velocity >> 6; + regs.ecx -= regs.eax; + } + } + } + } + + vehicle->acceleration = regs.ecx; + + regs.eax = RCT2_GLOBAL(0x00F64E18, uint32); + regs.ebx = RCT2_GLOBAL(0x00F64E1C, uint32); + + // hook_setreturnregisters(®s); if (outStation != NULL) *outStation = regs.ebx; return regs.eax; } -rct_ride_type_vehicle *vehicle_get_vehicle_entry(rct_vehicle *vehicle) +rct_ride_entry_vehicle *vehicle_get_vehicle_entry(rct_vehicle *vehicle) { - rct_ride_type *rideEntry = GET_RIDE_ENTRY(vehicle->ride_subtype); + rct_ride_entry *rideEntry = get_ride_entry(vehicle->ride_subtype); return &rideEntry->vehicles[vehicle->vehicle_type]; } + +int vehicle_get_total_num_peeps(rct_vehicle *vehicle) +{ + uint16 spriteIndex; + int numPeeps = 0; + for (;;) { + numPeeps += vehicle->num_peeps; + spriteIndex = vehicle->next_vehicle_on_train; + if (spriteIndex == SPRITE_INDEX_NULL) + break; + + vehicle = &(g_sprite_list[spriteIndex].vehicle); + } + + return numPeeps; +} + +/** + * + * rct2: 0x006DA1EC + */ +void vehicle_invalidate_window(rct_vehicle *vehicle) +{ + int viewVehicleIndex; + rct_ride *ride; + rct_window *w; + + w = window_find_by_number(WC_RIDE, vehicle->ride); + if (w == NULL) + return; + + ride = get_ride(vehicle->ride); + viewVehicleIndex = w->ride.view - 1; + if (viewVehicleIndex < 0 || viewVehicleIndex >= ride->num_vehicles) + return; + + if (vehicle->sprite_index != ride->vehicles[viewVehicleIndex]) + return; + + window_invalidate(w); +} diff --git a/src/ride/vehicle.h b/src/ride/vehicle.h index 1f8f175f8b..43bb30c32d 100644 --- a/src/ride/vehicle.h +++ b/src/ride/vehicle.h @@ -37,7 +37,7 @@ typedef struct { uint16 rotation_frame_mask; // 0x00 , 0x1A uint8 var_02; // 0x02 , 0x1C uint8 var_03; // 0x03 , 0x1D - uint32 var_04; // 0x04 , 0x1E + uint32 spacing; // 0x04 , 0x1E uint16 car_friction; // 0x08 , 0x22 sint8 tab_height; // 0x0A , 0x24 uint8 num_seats; // 0x0B , 0x25 @@ -46,8 +46,8 @@ typedef struct { uint8 sprite_height_negative; // 0x0F , 0x29 uint8 sprite_height_positive; // 0x10 , 0x2A uint8 var_11; // 0x11 , 0x2B - uint16 var_12; // 0x12 , 0x2C - uint16 var_14; // 0x14 , 0x2E + uint16 flags_a; // 0x12 , 0x2C + uint16 flags_b; // 0x14 , 0x2E uint16 var_16; // 0x16 , 0x30 uint32 base_image_id; // 0x18 , 0x32 uint32 var_1C; // 0x1C , 0x36 @@ -67,7 +67,9 @@ typedef struct { uint8 no_seating_rows; // 0x54 , 0x6E uint8 spinning_inertia; // 0x55 , 0x6F uint8 spinning_friction; // 0x56 , 0x70 - uint8 pad_57[0x3]; + uint8 friction_sound_id; // 0x57 , 0x71 + uint8 var_58; // 0x58 , 0x72 + uint8 sound_range; // 0x59 , 0x73 uint8 var_5A; // 0x5A , 0x74 uint8 powered_acceleration; // 0x5B , 0x75 uint8 powered_max_speed; // 0x5C , 0x76 @@ -76,7 +78,7 @@ typedef struct { uint8 draw_order; uint8 special_frames; // 0x60 , 0x7A sint8* peep_loading_positions; // 0x61 , 0x7B -} rct_ride_type_vehicle; +} rct_ride_entry_vehicle; typedef struct { uint8 sprite_identifier; // 0x00 @@ -88,7 +90,7 @@ typedef struct { // Height from center of sprite to bottom uint8 sprite_height_negative; // 0x09 uint16 sprite_index; // 0x0A - uint16 var_0C; + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -101,19 +103,26 @@ typedef struct { sint16 sprite_right; // 0x1A sint16 sprite_bottom; // 0x1C uint8 sprite_direction; // 0x1E - uint8 var_1F; - uint8 var_20; + uint8 vehicle_sprite_type; // 0x1F + uint8 bank_rotation; // 0x20 uint8 pad_21[3]; - uint32 var_24; + sint32 remaining_distance; // 0x24 sint32 velocity; // 0x28 - uint32 var_2C; + sint32 acceleration; // 0x2C uint8 ride; // 0x30 uint8 vehicle_type; // 0x31 rct_vehicle_colour colours; // 0x32 - uint16 var_34; + union { + uint16 track_progress; // 0x34 + struct { + sint8 var_34; + uint8 var_35; + }; + }; union { sint16 track_direction; // 0x36 (0000 0000 0000 0011) sint16 track_type; // 0x36 (0000 0011 1111 1100) + rct_xy8 boat_location; // 0x36 }; uint16 track_x; // 0x38 uint16 track_y; // 0x3A @@ -131,17 +140,24 @@ typedef struct { uint16 update_flags; // 0x48 uint8 var_4A; uint8 current_station; // 0x4B - uint16 var_4C; - uint16 var_4E; + union { + sint16 swinging_car_var_0; // 0x4C + sint16 current_time; // 0x4C + struct { + sint8 ferris_wheel_var_0; // 0x4C + sint8 ferris_wheel_var_1; // 0x4D + }; + }; + sint16 var_4E; uint8 status; // 0x50 - uint8 var_51; + uint8 sub_state; // 0x51 uint16 peep[32]; // 0x52 uint8 peep_tshirt_colours[32]; // 0x92 uint8 num_seats; // 0xB2 uint8 num_peeps; // 0xB3 uint8 next_free_seat; // 0xB4 - uint8 var_B5; - uint16 var_B6; + uint8 restraints_position; // 0xB5 0 == Close, 255 == Open + sint16 var_B6; uint16 var_B8; uint8 var_BA; uint8 sound1_id; // 0xBB @@ -149,28 +165,37 @@ typedef struct { uint8 sound2_id; // 0xBD uint8 sound2_volume; // 0xBE sint8 var_BF; - uint8 pad_C0[2]; + union { + uint16 var_C0; + uint16 time_waiting; // 0xC0 + uint16 cable_lift_target; // 0xC0 + }; uint8 speed; // 0xC2 - uint8 acceleration; // 0xC3 + uint8 powered_acceleration; // 0xC3 uint8 var_C4; uint8 var_C5; - uint8 pad_C6[2]; - uint32 var_C8; + uint8 pad_C6[0x2]; + uint16 var_C8; + uint16 var_CA; uint8 scream_sound_id; // 0xCC uint8 var_CD; union { uint8 var_CE; uint8 num_laps; // 0xCE }; - uint8 pad_CF[0x03]; - sint8 var_D2; + union { + uint8 var_CF; + uint8 break_speed; // 0xCF + }; + uint16 lost_time_out; // 0xD0 + sint8 vertical_drop_countdown; // 0xD1 uint8 var_D3; uint8 var_D4; - uint8 var_D5; + uint8 mini_golf_flags; // 0xD5 uint8 ride_subtype; // 0xD6 uint8 colours_extended; // 0xD7 - uint8 var_D8; - uint8 var_D9; + uint8 seat_rotation; // 0xD8 + uint8 target_seat_rotation; // 0xD9 } rct_vehicle; typedef struct { @@ -178,6 +203,54 @@ typedef struct { rct_vehicle *tail; } train_ref; +// Size: 0x09 +typedef struct { + uint16 x; // 0x00 + uint16 y; // 0x02 + uint16 z; // 0x04 + uint8 direction; // 0x06 + uint8 vehicle_sprite_type; // 0x07 + uint8 bank_rotation; // 0x08 +} rct_vehicle_info; + +enum { + VEHICLE_ENTRY_FLAG_A_0 = 1 << 0, + VEHICLE_ENTRY_FLAG_A_1 = 1 << 1, + VEHICLE_ENTRY_FLAG_A_2 = 1 << 2, + VEHICLE_ENTRY_FLAG_A_MINI_GOLF = 1 << 3, + VEHICLE_ENTRY_FLAG_A_4 = 1 << 4, + VEHICLE_ENTRY_FLAG_A_5 = 1 << 5, + VEHICLE_ENTRY_FLAG_A_6 = 1 << 6, + VEHICLE_ENTRY_FLAG_A_7 = 1 << 7, + VEHICLE_ENTRY_FLAG_A_8 = 1 << 8, + VEHICLE_ENTRY_FLAG_A_9 = 1 << 9, + VEHICLE_ENTRY_FLAG_A_10 = 1 << 10, + VEHICLE_ENTRY_FLAG_A_11 = 1 << 11, + VEHICLE_ENTRY_FLAG_A_12 = 1 << 12, + VEHICLE_ENTRY_FLAG_A_13 = 1 << 13, + VEHICLE_ENTRY_FLAG_A_14 = 1 << 14, + VEHICLE_ENTRY_FLAG_A_15 = 1 << 15, +}; + +enum { + VEHICLE_ENTRY_FLAG_B_0 = 1 << 0, + VEHICLE_ENTRY_FLAG_B_SWINGING = 1 << 1, + VEHICLE_ENTRY_FLAG_B_SPINNING = 1 << 2, + VEHICLE_ENTRY_FLAG_B_3 = 1 << 3, + VEHICLE_ENTRY_FLAG_B_4 = 1 << 4, + VEHICLE_ENTRY_FLAG_B_5 = 1 << 5, + VEHICLE_ENTRY_FLAG_B_6 = 1 << 6, + VEHICLE_ENTRY_FLAG_B_7 = 1 << 7, + VEHICLE_ENTRY_FLAG_B_8 = 1 << 8, + VEHICLE_ENTRY_FLAG_B_9 = 1 << 9, + VEHICLE_ENTRY_FLAG_B_10 = 1 << 10, + VEHICLE_ENTRY_FLAG_B_11 = 1 << 11, + VEHICLE_ENTRY_FLAG_B_12 = 1 << 12, + VEHICLE_ENTRY_FLAG_B_13 = 1 << 13, + VEHICLE_ENTRY_FLAG_B_14 = 1 << 14, + VEHICLE_ENTRY_FLAG_B_15 = 1 << 15, +}; + enum { VEHICLE_STATUS_MOVING_TO_END_OF_STATION, VEHICLE_STATUS_WAITING_FOR_PASSENGERS, @@ -186,22 +259,22 @@ enum { VEHICLE_STATUS_TRAVELLING, VEHICLE_STATUS_ARRIVING, VEHICLE_STATUS_UNLOADING_PASSENGERS, - VEHICLE_STATUS_TRAVELLING_07, + VEHICLE_STATUS_TRAVELLING_BOAT, VEHICLE_STATUS_CRASHING, VEHICLE_STATUS_CRASHED, - VEHICLE_STATUS_TRAVELLING_0A, + VEHICLE_STATUS_TRAVELLING_BUMPER_CARS, VEHICLE_STATUS_SWINGING, VEHICLE_STATUS_ROTATING, - VEHICLE_STATUS_ROTATING_0D, - VEHICLE_STATUS_OPERATING, + VEHICLE_STATUS_FERRIS_WHEEL_ROTATING, + VEHICLE_STATUS_SIMULATOR_OPERATING, VEHICLE_STATUS_SHOWING_FILM, - VEHICLE_STATUS_ROTATING_10, - VEHICLE_STATUS_OPERATING_11, - VEHICLE_STATUS_OPERATING_12, + VEHICLE_STATUS_SPACE_RINGS_OPERATING, + VEHICLE_STATUS_TOP_SPIN_OPERATING, + VEHICLE_STATUS_HAUNTED_HOUSE_OPERATING, VEHICLE_STATUS_DOING_CIRCUS_SHOW, - VEHICLE_STATUS_OPERATING_13, + VEHICLE_STATUS_CROOKED_HOUSE_OPERATING, VEHICLE_STATUS_WAITING_FOR_CABLE_LIFT, - VEHICLE_STATUS_TRAVELLING_15, + VEHICLE_STATUS_TRAVELLING_CABLE_LIFT, VEHICLE_STATUS_STOPPING, VEHICLE_STATUS_WAITING_FOR_PASSENGERS_17, VEHICLE_STATUS_WAITING_TO_START, @@ -223,7 +296,7 @@ enum{ VEHICLE_UPDATE_FLAG_7 = (1 << 7), VEHICLE_UPDATE_FLAG_BROKEN_CAR = (1 << 8), VEHICLE_UPDATE_FLAG_BROKEN_TRAIN = (1 << 9), - VEHICLE_UPDATE_FLAG_10 = (1 << 10), + VEHICLE_UPDATE_FLAG_ON_BREAK_FOR_DROP = (1 << 10), VEHICLE_UPDATE_FLAG_11 = (1 << 11), VEHICLE_UPDATE_FLAG_12 = (1 << 12), VEHICLE_UPDATE_FLAG_13 = (1 << 13), @@ -265,24 +338,45 @@ enum { VEHICLE_VISUAL_SUBMARINE }; +enum { + VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_AT_STATION = 1 << 0, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_1 = 1 << 1, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_2 = 1 << 2, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_3 = 1 << 3, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_ON_LIFT_HILL = 1 << 4, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_5 = 1 << 5, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_DERAILED = 1 << 6, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_VEHICLE_COLLISION = 1 << 7, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_8 = 1 << 8, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_9 = 1 << 9, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_10 = 1 << 10, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_11 = 1 << 11, + VEHICLE_UPDATE_MOTION_TRACK_FLAG_12 = 1 << 12, +}; + #define VEHICLE_SEAT_PAIR_FLAG 0x80 #define VEHICLE_SEAT_NUM_MASK 0x7F void vehicle_update_all(); int sub_6BC2F3(rct_vehicle* vehicle); -void sub_6BB9FF(rct_vehicle* vehicle); void vehicle_sounds_update(); void vehicle_get_g_forces(rct_vehicle *vehicle, int *verticalG, int *lateralG); void vehicle_set_map_toolbar(rct_vehicle *vehicle); int vehicle_is_used_in_pairs(rct_vehicle *vehicle); rct_vehicle *vehicle_get_head(rct_vehicle *vehicle); -void sub_6DEF56(rct_vehicle *cableLift); -rct_vehicle *cable_lift_segment_create(int rideIndex, int x, int y, int z, int direction, uint16 var_44, uint32 var_24, bool head); -bool sub_6DD365(rct_vehicle *vehicle); -int sub_6DAB4C(rct_vehicle *vehicle, int *outStation); -rct_ride_type_vehicle *vehicle_get_vehicle_entry(rct_vehicle *vehicle); +int vehicle_update_track_motion(rct_vehicle *vehicle, int *outStation); +rct_ride_entry_vehicle *vehicle_get_vehicle_entry(rct_vehicle *vehicle); +int vehicle_get_total_num_peeps(rct_vehicle *vehicle); +void vehicle_invalidate_window(rct_vehicle *vehicle); +void vehicle_update_test_finish(rct_vehicle* vehicle); +void vehicle_test_reset(rct_vehicle* vehicle); +void vehicle_peep_easteregg_here_we_are(rct_vehicle* vehicle); +rct_vehicle *vehicle_get_head(rct_vehicle *vehicle); +rct_vehicle *vehicle_get_tail(rct_vehicle *vehicle); +const rct_vehicle_info *vehicle_get_move_info(int cd, int typeAndDirection, int offset); +bool vehicle_update_bumper_car_collision(rct_vehicle *vehicle, sint16 x, sint16 y, uint16 *spriteId); /** Helper macro until rides are stored in this module. */ #define GET_VEHICLE(sprite_index) &(g_sprite_list[sprite_index].vehicle) -#endif \ No newline at end of file +#endif diff --git a/src/scenario.c b/src/scenario.c index 48888e0fc5..41eab2fd9a 100644 --- a/src/scenario.c +++ b/src/scenario.c @@ -19,6 +19,7 @@ *****************************************************************************/ #include "addresses.h" +#include "cheats.h" #include "config.h" #include "game.h" #include "world/climate.h" @@ -30,6 +31,7 @@ #include "management/marketing.h" #include "management/research.h" #include "management/news_item.h" +#include "network/network.h" #include "object.h" #include "openrct2.h" #include "peep/staff.h" @@ -45,11 +47,23 @@ #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 = ""; char gScenarioSavePath[MAX_PATH]; int gFirstTimeSave = 1; +uint32 gLastAutoSaveTick = 0; static int scenario_create_ducks(); static void scenario_objective_check(); @@ -58,13 +72,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 +84,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; } /** @@ -207,6 +186,7 @@ int scenario_load(const char *path) game_convert_strings_to_utf8(); game_fix_save_vars(); // OpenRCT2 fix broken save games + gLastAutoSaveTick = SDL_GetTicks(); return 1; } @@ -219,19 +199,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]; - - subsitute_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(); @@ -240,7 +207,7 @@ int scenario_load_and_play_from_path(const char *path) return 0; int len = strnlen(path, MAX_PATH) + 1; - safe_strncpy(_scenarioPath, path, len); + safe_strcpy(_scenarioPath, path, len); if (len - 1 == MAX_PATH) { _scenarioPath[MAX_PATH - 1] = '\0'; @@ -252,6 +219,12 @@ int scenario_load_and_play_from_path(const char *path) log_verbose("starting scenario, %s", path); scenario_begin(); + if (network_get_mode() == NETWORK_MODE_SERVER) { + network_send_map(); + } + if (network_get_mode() == NETWORK_MODE_CLIENT) { + network_close(); + } return 1; } @@ -312,25 +285,24 @@ void scenario_begin() finance_update_loan_hash(); - safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, s6Info->details, 256); - safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, s6Info->name, 64); + safe_strcpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, s6Info->details, 256); + safe_strcpy((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_strcpy(normalisedName, s6Info->name, sizeof(normalisedName)); + scenario_normalise_name(normalisedName); rct_string_id localisedStringIds[3]; - if (language_get_localised_scenario_strings(filename, localisedStringIds)) { - if (localisedStringIds[0] != (rct_string_id)STR_NONE) { - safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(localisedStringIds[0]), 32); + if (language_get_localised_scenario_strings(normalisedName, localisedStringIds)) { + if (localisedStringIds[0] != STR_NONE) { + safe_strcpy((char*)RCT2_ADDRESS_SCENARIO_NAME, language_get_string(localisedStringIds[0]), 32); } - if (localisedStringIds[1] != (rct_string_id)STR_NONE) { + if (localisedStringIds[1] != STR_NONE) { park_set_name(language_get_string(localisedStringIds[1])); } - if (localisedStringIds[2] != (rct_string_id)STR_NONE) { - safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, language_get_string(localisedStringIds[2]), 256); + if (localisedStringIds[2] != STR_NONE) { + safe_strcpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, language_get_string(localisedStringIds[2]), 256); } } else { rct_stex_entry* stex = g_stexEntries[0]; @@ -343,12 +315,12 @@ void scenario_begin() // Set localised scenario name format_string(buffer, stex->scenario_name, 0); - safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_NAME, buffer, 31); + safe_strcpy((char*)RCT2_ADDRESS_SCENARIO_NAME, buffer, 31); ((char*)RCT2_ADDRESS_SCENARIO_NAME)[31] = '\0'; // Set localised scenario details format_string(buffer, stex->details, 0); - safe_strncpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, buffer, 255); + safe_strcpy((char*)RCT2_ADDRESS_SCENARIO_DETAILS, buffer, 255); ((char*)RCT2_ADDRESS_SCENARIO_DETAILS)[255] = '\0'; } } @@ -417,14 +389,14 @@ void scenario_end() void scenario_set_filename(const char *value) { - subsitute_path(_scenarioPath, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), value); + substitute_path(_scenarioPath, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), value); _scenarioFileName = path_get_filename(_scenarioPath); } /** * * rct2: 0x0066A752 - **/ + */ void scenario_failure() { RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, uint32) = 0x80000001; @@ -437,29 +409,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,31 +443,23 @@ 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_strcpy(RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_COMPLETED_BY, char), name, 32); + scenario_scores_save(); } } RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_SCENARIO_COMPLETE_NAME_INPUT; } -/* +/** * Send a warning when entrance price is too high. - * rct2: 0x0066A80E - **/ + * rct2: 0x0066A80E + */ void scenario_entrance_fee_too_high_check() { uint16 x = 0, y = 0; @@ -511,40 +475,38 @@ void scenario_entrance_fee_too_high_check() } packed_xy = (y << 16) | x; - news_item_add_to_queue(NEWS_ITEM_BLANK, STR_ENTRANCE_FEE_TOO_HI, packed_xy); + if (gConfigNotifications.park_warnings) { + news_item_add_to_queue(NEWS_ITEM_BLANK, STR_ENTRANCE_FEE_TOO_HI, packed_xy); + } } } void scenario_autosave_check() { - // Timestamp in milliseconds - static uint32 last_save = 0; - - bool shouldSave = 0; - // Milliseconds since last save - uint32_t time_since_save = SDL_GetTicks() - last_save; + uint32 timeSinceSave = SDL_GetTicks() - gLastAutoSaveTick; + bool shouldSave = false; switch (gConfigGeneral.autosave_frequency) { case AUTOSAVE_EVERY_MINUTE: - shouldSave = time_since_save >= 1 * 60 * 1000; + shouldSave = timeSinceSave >= 1 * 60 * 1000; break; case AUTOSAVE_EVERY_5MINUTES: - shouldSave = time_since_save >= 5 * 60 * 1000; + shouldSave = timeSinceSave >= 5 * 60 * 1000; break; case AUTOSAVE_EVERY_15MINUTES: - shouldSave = time_since_save >= 15 * 60 * 1000; + shouldSave = timeSinceSave >= 15 * 60 * 1000; break; case AUTOSAVE_EVERY_30MINUTES: - shouldSave = time_since_save >= 30 * 60 * 1000; + shouldSave = timeSinceSave >= 30 * 60 * 1000; break; case AUTOSAVE_EVERY_HOUR: - shouldSave = time_since_save >= 60 * 60 * 1000; + shouldSave = timeSinceSave >= 60 * 60 * 1000; break; } if (shouldSave) { - last_save = SDL_GetTicks(); + gLastAutoSaveTick = SDL_GetTicks(); game_autosave(); } } @@ -553,7 +515,6 @@ static void scenario_day_update() { finance_update_daily_profit(); peep_update_days_in_queue(); - get_local_time(); switch (RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8)) { case OBJECTIVE_10_ROLLERCOASTERS: case OBJECTIVE_GUESTS_AND_RATING: @@ -610,31 +571,34 @@ static void scenario_month_update() static void scenario_update_daynight_cycle() { + float currentDayNightCycle = gDayNightCycle; gDayNightCycle = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) != SCREEN_FLAGS_PLAYING) return; - if (!gConfigGeneral.day_night_cycle) return; - - float monthFraction = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16) / (float)0x10000; - if (monthFraction < (1 / 8.0f)) { - gDayNightCycle = 0.0f; - } else if (monthFraction < (3 / 8.0f)) { - gDayNightCycle = (monthFraction - (1 / 8.0f)) / (2 / 8.0f); - } else if (monthFraction < (5 / 8.0f)) { - gDayNightCycle = 1.0f; - } else if (monthFraction < (7 / 8.0f)) { - gDayNightCycle = 1.0f - ((monthFraction - (5 / 8.0f)) / (2 / 8.0f)); - } else { - gDayNightCycle = 0.0f; + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) == SCREEN_FLAGS_PLAYING && gConfigGeneral.day_night_cycle) { + float monthFraction = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16) / (float)0x10000; + if (monthFraction < (1 / 8.0f)) { + gDayNightCycle = 0.0f; + } else if (monthFraction < (3 / 8.0f)) { + gDayNightCycle = (monthFraction - (1 / 8.0f)) / (2 / 8.0f); + } else if (monthFraction < (5 / 8.0f)) { + gDayNightCycle = 1.0f; + } else if (monthFraction < (7 / 8.0f)) { + gDayNightCycle = 1.0f - ((monthFraction - (5 / 8.0f)) / (2 / 8.0f)); + } else { + gDayNightCycle = 0.0f; + } } - platform_update_palette(RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8), 10, 236); + // Only update palette if day / night cycle has changed + if (gDayNightCycle != currentDayNightCycle) { + platform_update_palette(RCT2_ADDRESS(RCT2_ADDRESS_PALETTE, uint8), 10, 236); + } } -/* +/** * Scenario and finance related update iteration. - * rct2: 0x006C44B1 - **/ + * rct2: 0x006C44B1 + */ void scenario_update() { if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & ~SCREEN_FLAGS_PLAYING)) { @@ -721,6 +685,8 @@ static int scenario_create_ducks() /** * * rct2: 0x006E37D2 + * + * @return eax */ unsigned int scenario_rand() { @@ -794,7 +760,7 @@ int scenario_prepare_for_save() rct_stex_entry* stex = g_stexEntries[0]; if ((int)stex != 0xFFFFFFFF) { format_string(buffer, stex->scenario_name, NULL); - safe_strncpy(s6Info->name, buffer, sizeof(s6Info->name)); + safe_strcpy(s6Info->name, buffer, sizeof(s6Info->name)); memcpy(&s6Info->entry, &object_entry_groups[OBJECT_TYPE_SCENARIO_TEXT].entries[0], sizeof(rct_object_entry)); } @@ -827,8 +793,8 @@ int scenario_get_num_packed_objects_to_write() int i, count = 0; rct_object_entry_extended *entry = (rct_object_entry_extended*)0x00F3F03C; - for (i = 0; i < 721; i++, entry++) { - if (GET_RIDE_ENTRY(i) == (void *)0xFFFFFFFF || (entry->flags & 0xF0)) + for (i = 0; i < OBJECT_ENTRY_COUNT; i++, entry++) { + if (gObjectList[i] == (void *)0xFFFFFFFF || (entry->flags & 0xF0)) continue; count++; @@ -845,8 +811,8 @@ int scenario_write_packed_objects(SDL_RWops* rw) { int i; rct_object_entry_extended *entry = (rct_object_entry_extended*)0x00F3F03C; - for (i = 0; i < 721; i++, entry++) { - if (GET_RIDE_ENTRY(i) == (void *)0xFFFFFFFF || (entry->flags & 0xF0)) + for (i = 0; i < OBJECT_ENTRY_COUNT; i++, entry++) { + if (gObjectList[i] == (void *)0xFFFFFFFF || (entry->flags & 0xF0)) continue; if (!write_object_file(rw, (rct_object_entry*)entry)) @@ -885,8 +851,8 @@ int scenario_write_available_objects(FILE *file) // Write entries rct_object_entry_extended *srcEntry = (rct_object_entry_extended*)0x00F3F03C; rct_object_entry *dstEntry = (rct_object_entry*)buffer; - for (i = 0; i < 721; i++) { - if (GET_RIDE_ENTRY(i) == (void *)0xFFFFFFFF) + for (i = 0; i < OBJECT_ENTRY_COUNT; i++) { + if (gObjectList[i] == (void *)0xFFFFFFFF) memset(dstEntry, 0xFF, sizeof(rct_object_entry)); else *dstEntry = *((rct_object_entry*)srcEntry); @@ -921,7 +887,7 @@ static void sub_674BCF() char *dst = &savedExpansionPackNames[i * 128]; if (RCT2_GLOBAL(RCT2_ADDRESS_EXPANSION_FLAGS, uint16) & (1 << i)) { char *src = &(RCT2_ADDRESS(RCT2_ADDRESS_EXPANSION_NAMES, char)[i * 128]); - safe_strncpy(dst, src, 128); + safe_strcpy(dst, src, 128); } else { *dst = 0; } @@ -960,19 +926,23 @@ static void scenario_fix_ghosts(rct_s6_data *s6) (destinationElement - 1)->flags |= MAP_ELEMENT_FLAG_LAST_TILE; } } +} - // Remove trackless rides +static void scenario_remove_trackless_rides(rct_s6_data *s6) +{ bool rideHasTrack[MAX_RIDES]; ride_all_has_any_track_elements(rideHasTrack); for (int i = 0; i < MAX_RIDES; i++) { rct_ride *ride = &s6->rides[i]; - if (rideHasTrack[i] || ride->type == RIDE_TYPE_NULL) + if (rideHasTrack[i] || ride->type == RIDE_TYPE_NULL) { continue; + } ride->type = RIDE_TYPE_NULL; - if (is_user_string_id(ride->name)) + if (is_user_string_id(ride->name)) { s6->custom_strings[(ride->name % MAX_USER_STRINGS) * USER_STRING_MAX_LENGTH] = 0; + } } } @@ -1031,10 +1001,10 @@ int scenario_save(SDL_RWops* rw, int flags) memcpy(&s6->info, (rct_s6_info*)0x0141F570, sizeof(rct_s6_info)); - for (int i = 0; i < 721; i++) { + for (int i = 0; i < OBJECT_ENTRY_COUNT; i++) { rct_object_entry_extended *entry = &(RCT2_ADDRESS(0x00F3F03C, rct_object_entry_extended)[i]); - if (GET_RIDE_ENTRY(i) == (void *)0xFFFFFFFF) { + if (gObjectList[i] == (void *)0xFFFFFFFF) { memset(&s6->objects[i], 0xFF, sizeof(rct_object_entry)); } else { s6->objects[i] = *((rct_object_entry*)entry); @@ -1045,9 +1015,10 @@ int scenario_save(SDL_RWops* rw, int flags) memcpy(s6->map_elements, (void*)0x00F663B8, 0x180000); memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570); - safe_strncpy(s6->scenario_filename, _scenarioFileName, sizeof(s6->scenario_filename)); + safe_strcpy(s6->scenario_filename, _scenarioFileName, sizeof(s6->scenario_filename)); scenario_fix_ghosts(s6); + scenario_remove_trackless_rides(s6); game_convert_strings_to_rct2(s6); scenario_save_s6(rw, s6); @@ -1107,7 +1078,7 @@ int scenario_save_network(SDL_RWops* rw) for (int i = 0; i < 721; i++) { rct_object_entry_extended *entry = &(RCT2_ADDRESS(0x00F3F03C, rct_object_entry_extended)[i]); - if (GET_RIDE_ENTRY(i) == (void *)0xFFFFFFFF) { + if (gObjectList[i] == (void *)0xFFFFFFFF) { memset(&s6->objects[i], 0xFF, sizeof(rct_object_entry)); } else { s6->objects[i] = *((rct_object_entry*)entry); @@ -1118,13 +1089,34 @@ int scenario_save_network(SDL_RWops* rw) memcpy(s6->map_elements, (void*)0x00F663B8, 0x180000); memcpy(&s6->dword_010E63B8, (void*)0x010E63B8, 0x2E8570); + safe_strcpy(s6->scenario_filename, _scenarioFileName, sizeof(s6->scenario_filename)); + scenario_fix_ghosts(s6); + game_convert_strings_to_rct2(s6); scenario_save_s6(rw, s6); free(s6); + reset_loaded_objects(); + // Write other data not in normal save files SDL_WriteLE32(rw, RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint32)); + SDL_WriteLE32(rw, _guestGenerationProbability); + SDL_WriteLE32(rw, _suggestedGuestMaximum); + SDL_WriteU8(rw, gCheatsSandboxMode); + SDL_WriteU8(rw, gCheatsDisableClearanceChecks); + SDL_WriteU8(rw, gCheatsDisableSupportLimits); + SDL_WriteU8(rw, gCheatsShowAllOperatingModes); + SDL_WriteU8(rw, gCheatsShowVehiclesFromOtherTrackTypes); + SDL_WriteU8(rw, gCheatsFastLiftHill); + SDL_WriteU8(rw, gCheatsDisableBrakesFailure); + SDL_WriteU8(rw, gCheatsDisableAllBreakdowns); + SDL_WriteU8(rw, gCheatsUnlockAllPrices); + SDL_WriteU8(rw, gCheatsBuildInPauseMode); + SDL_WriteU8(rw, gCheatsIgnoreRideIntensity); + SDL_WriteU8(rw, gCheatsDisableVandalism); + SDL_WriteU8(rw, gCheatsNeverendingMarketing); + SDL_WriteU8(rw, gCheatsFreezeClimate); gfx_invalidate_screen(); return 1; @@ -1304,9 +1296,13 @@ static void scenario_objective_check_10_rollercoasters() FOR_ALL_RIDES(i, ride) { uint8 subtype_id = ride->subtype; - rct_ride_type *rideType = gRideTypeList[subtype_id]; + rct_ride_entry *rideType = get_ride_entry(subtype_id); + if (rideType == NULL) { + continue; + } - if ((rideType->category[0] == RIDE_GROUP_ROLLERCOASTER || rideType->category[1] == RIDE_GROUP_ROLLERCOASTER) && + if (rideType != NULL && + (rideType->category[0] == RIDE_GROUP_ROLLERCOASTER || rideType->category[1] == RIDE_GROUP_ROLLERCOASTER) && ride->status == RIDE_STATUS_OPEN && ride->excitement >= RIDE_RATING(6,00) && type_already_counted[subtype_id] == 0){ type_already_counted[subtype_id]++; @@ -1320,20 +1316,28 @@ static void scenario_objective_check_10_rollercoasters() /** * - * rct2: 0x0066A13C + * rct2: 0x0066A13C */ static void scenario_objective_check_guests_and_rating() { if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, uint16) < 700 && RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16) >= 1) { RCT2_GLOBAL(RCT2_ADDRESS_PARK_RATING_WARNING_DAYS, uint16)++; if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_RATING_WARNING_DAYS, uint16) == 1) { - news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_4_WEEKS_REMAINING, 0); + if (gConfigNotifications.park_rating_warnings) { + news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_4_WEEKS_REMAINING, 0); + } } else if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_RATING_WARNING_DAYS, uint16) == 8) { - news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_3_WEEKS_REMAINING, 0); + if (gConfigNotifications.park_rating_warnings) { + news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_3_WEEKS_REMAINING, 0); + } } else if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_RATING_WARNING_DAYS, uint16) == 15) { - news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_2_WEEKS_REMAINING, 0); + if (gConfigNotifications.park_rating_warnings) { + news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_2_WEEKS_REMAINING, 0); + } } else if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_RATING_WARNING_DAYS, uint16) == 22) { - news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_1_WEEK_REMAINING, 0); + if (gConfigNotifications.park_rating_warnings) { + news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_RATING_WARNING_1_WEEK_REMAINING, 0); + } } else if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_RATING_WARNING_DAYS, uint16) == 29) { news_item_add_to_queue(NEWS_ITEM_GRAPH, STR_PARK_HAS_BEEN_CLOSED_DOWN, 0); RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_PARK_OPEN; @@ -1360,8 +1364,8 @@ static void scenario_objective_check_monthly_ride_income() /** * Checks if there are 10 rollercoasters of different subtype with * excitement > 700 and a minimum length; - * rct2: 0x0066A6B5 - **/ + * rct2: 0x0066A6B5 + */ static void scenario_objective_check_10_rollercoasters_length() { int i, rcs = 0; @@ -1373,7 +1377,10 @@ static void scenario_objective_check_10_rollercoasters_length() FOR_ALL_RIDES(i, ride) { uint8 subtype_id = ride->subtype; - rct_ride_type *rideType = gRideTypeList[subtype_id]; + rct_ride_entry *rideType = get_ride_entry(subtype_id); + if (rideType == NULL) { + continue; + } if ((rideType->category[0] == RIDE_GROUP_ROLLERCOASTER || rideType->category[1] == RIDE_GROUP_ROLLERCOASTER) && ride->status == RIDE_STATUS_OPEN && ride->excitement >= RIDE_RATING(7,00) && type_already_counted[subtype_id] == 0){ @@ -1431,10 +1438,10 @@ static void scenario_objective_check_monthly_food_income() scenario_success(); } -/* +/** * Checks the win/lose conditions of the current objective. - * rct2: 0x0066A4B2 - **/ + * rct2: 0x0066A4B2 + */ static void scenario_objective_check() { uint8 objective_type = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8), diff --git a/src/scenario.h b/src/scenario.h index 4aed2a22e9..bb480a41c0 100644 --- a/src/scenario.h +++ b/src/scenario.h @@ -61,7 +61,7 @@ typedef struct { rct_object_entry entry; // 0x188 } rct_s6_info; -/* +/** * Scenario scores file header. * size: 0x10 */ @@ -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 { @@ -274,8 +287,7 @@ typedef struct { rct_research_item research_items[500]; uint16 word_01359208; char scenario_name[64]; - char scenario_description[255]; - uint8 byte_01359349; + char scenario_description[256]; uint8 current_interest_rate; uint8 pad_0135934B; uint32 dword_0135934C; @@ -297,17 +309,17 @@ typedef struct { uint8 byte_01389E10[6000]; uint16 num_map_animations; uint8 pad_0138B582[2]; - uint16 word_0138B584; - uint16 word_0138B586; - uint16 word_0138B588; - uint16 word_0138B58A; - uint16 word_0138B58C; - uint16 word_0138B58E; + uint16 ride_ratings_proximity_x; + uint16 ride_ratings_proximity_y; + uint16 ride_ratings_proximity_z; + uint16 ride_ratings_proximity_start_x; + uint16 ride_ratings_proximity_start_y; + uint16 ride_ratings_proximity_start_z; uint8 ride_ratings_current_ride; uint8 ride_ratings_state; - uint8 byte_0138B592; - uint8 byte_0138B593; - uint16 word_0138B594; + uint8 ride_ratings_proximity_track_type; + uint8 ride_ratings_proximity_base_height; + uint16 ride_ratings_proximity_total; uint16 word_0138B596; uint16 word_0138B598; uint16 word_0138B59A; @@ -385,11 +397,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 +426,62 @@ 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; +extern uint32 gLastAutoSaveTick; -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_HARBOUR, + 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 diff --git a/src/scenario_list.c b/src/scenario_list.c index 78940c8935..9e10f635d6 100644 --- a/src/scenario_list.c +++ b/src/scenario_list.c @@ -19,228 +19,532 @@ *****************************************************************************/ #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_strcpy(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_strcpy(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_strcpy(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_strcpy(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 - subsitute_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_strcpy(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_strcpy(newEntry->name, s6Info.name, sizeof(newEntry->name)); + safe_strcpy(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] != STR_NONE) { + safe_strcpy(scenarioEntry->name, language_get_string(localisedStringIds[0]), 64); + } + if (localisedStringIds[2] != STR_NONE) { + safe_strcpy(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; + } + } + } 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); + } } diff --git a/src/scenario_sources.c b/src/scenario_sources.c new file mode 100644 index 0000000000..e6ebcc8e8f --- /dev/null +++ b/src/scenario_sources.c @@ -0,0 +1,307 @@ +#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" }, + { "Haunted Harbour", "Haunted Harbor" }, + { "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_HARBOUR, "Haunted Harbour", 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_strcpy(name, name + 4, 64); + } else { + safe_strcpy(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_strcpy(name, ScenarioAliases[i].original, 64); + } + } +} diff --git a/src/sprites.h b/src/sprites.h index 3d75810080..16856007ae 100644 --- a/src/sprites.h +++ b/src/sprites.h @@ -44,9 +44,29 @@ enum { SPR_RESIZE = 5058, + SPR_RIDE_CONSTRUCTION_STRAIGHT = 5137, + SPR_RIDE_CONSTRUCTION_LEFT_CURVE = 5138, + SPR_RIDE_CONSTRUCTION_RIGHT_CURVE = 5139, + SPR_RIDE_CONSTRUCTION_LEFT_CURVE_SMALL = 5140, + SPR_RIDE_CONSTRUCTION_RIGHT_CURVE_SMALL = 5141, + SPR_RIDE_CONSTRUCTION_LEFT_CURVE_LARGE = 5142, + SPR_RIDE_CONSTRUCTION_RIGHT_CURVE_LARGE = 5143, + SPR_RIDE_CONSTRUCTION_SLOPE_DOWN_STEEP = 5144, + SPR_RIDE_CONSTRUCTION_SLOPE_DOWN = 5145, + SPR_RIDE_CONSTRUCTION_SLOPE_LEVEL = 5146, + SPR_RIDE_CONSTRUCTION_SLOPE_UP = 5147, + SPR_RIDE_CONSTRUCTION_SLOPE_UP_STEEP = 5148, + + SPR_RIDE_CONSTRUCTION_LEFT_BANK = 5153, + SPR_RIDE_CONSTRUCTION_NO_BANK = 5154, + SPR_RIDE_CONSTRUCTION_RIGHT_BANK = 5155, + SPR_RIDE_CONSTRUCTION_U_SHAPED_TRACK = 5156, + SPR_RIDE_CONSTRUCTION_O_SHAPED_TRACK = 5157, + SPR_PREVIOUS = 5160, SPR_NEXT = 5161, - + SPR_DEMOLISH_CURRENT_SECTION = 5162, + SPR_CHAIN_LIFT = 5163, SPR_CONSTRUCTION = 5164, SPR_DEMOLISH = 5165, SPR_HEARING_VIEWPORT = 5166, @@ -54,6 +74,7 @@ enum { SPR_RENAME = 5168, SPR_ROTATE_ARROW = 5169, + SPR_PAINTBRUSH = 5173, SPR_PICKUP_BTN = 5174, SPR_PATROL_BTN = 5175, SPR_BUY_LAND_RIGHTS = 5176, @@ -192,7 +213,7 @@ enum { SPR_TAB_RIDE_14 = SPR_TAB_RIDE_0 + 14, SPR_TAB_RIDE_15 = SPR_TAB_RIDE_0 + 15, - STR_TAB_PARK = 5466, + SPR_TAB_PARK = 5466, SPR_AWARD_MOST_UNTIDY = 5469, SPR_MOST_TIDY = SPR_AWARD_MOST_UNTIDY + 1, @@ -393,6 +414,7 @@ enum { SPR_G2_TAB_NEWS = SPR_G2_BEGIN + 58, SPR_G2_LOCKED = SPR_G2_BEGIN + 59, + SPR_G2_MENU_MULTIPLAYER = SPR_G2_BEGIN + 60, }; #endif diff --git a/src/title.c b/src/title.c index a6b35904f9..4a5edec729 100644 --- a/src/title.c +++ b/src/title.c @@ -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; @@ -383,7 +381,7 @@ static void title_do_next_script_opcode() // Construct full relative path if (gConfigTitleSequences.presets[_scriptCurrentPreset].path[0]) { - safe_strncpy(path, gConfigTitleSequences.presets[_scriptCurrentPreset].path, MAX_PATH); + safe_strcpy(path, gConfigTitleSequences.presets[_scriptCurrentPreset].path, MAX_PATH); } else { platform_get_user_directory(path, "title sequences"); @@ -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); } @@ -470,7 +500,7 @@ void DrawOpenRCT2(int x, int y) rct_drawpixelinfo *dpi = RCT2_ADDRESS(RCT2_ADDRESS_SCREEN_DPI, rct_drawpixelinfo); // Draw background - gfx_fill_rect_inset(dpi, x, y, x + 128, y + 20, 0x80 | 12, 0x8); + gfx_fill_rect_inset(dpi, x, y, x + 128, y + 20, TRANSLUCENT(COLOUR_DARK_GREEN), 0x8); // Write format codes utf8 *ch = buffer; @@ -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(); @@ -602,9 +632,11 @@ static uint8 *title_script_load() char parts[3 * 128], *token, *part1, *part2, *src; utf8 path[MAX_PATH]; - utf8 filePath[] = "data/title/script.txt"; + utf8 dataPath[MAX_PATH]; + utf8 filePath[] = "title/script.txt"; - sprintf(path, "%s%c%s", gExePath, platform_get_path_separator(), filePath); + platform_get_openrct_data_path(dataPath); + sprintf(path, "%s%c%s", dataPath, platform_get_path_separator(), filePath); log_verbose("loading title script, %s", path); file = SDL_RWFromFile(path, "r"); if (file == NULL) { @@ -686,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; } @@ -709,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 { diff --git a/src/title.h b/src/title.h index 890a6bdf60..88270393ee 100644 --- a/src/title.h +++ b/src/title.h @@ -34,8 +34,9 @@ enum { TITLE_SCRIPT_END, TITLE_SCRIPT_SPEED, TITLE_SCRIPT_LOOP, - TITLE_SCRIPT_ENDLOOP -} TITLE_SCRIPT_COMMANDS; + TITLE_SCRIPT_ENDLOOP, + TITLE_SCRIPT_LOADRCT1, +}; extern sint32 gTitleScriptCommand; extern uint8 gTitleScriptSave; diff --git a/src/tutorial.c b/src/tutorial.c deleted file mode 100644 index 07e6b4c725..0000000000 --- a/src/tutorial.c +++ /dev/null @@ -1,43 +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 . - *****************************************************************************/ - -#include "addresses.h" -#include "localisation/localisation.h" -#include "tutorial.h" -#include "windows/error.h" - -/** - * - * 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); -} \ No newline at end of file diff --git a/src/tutorial.h b/src/tutorial.h deleted file mode 100644 index d1b2eced61..0000000000 --- a/src/tutorial.h +++ /dev/null @@ -1,27 +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 . - *****************************************************************************/ - -#ifndef _TUTORIAL_H_ -#define _TUTORIAL_H_ - -void tutorial_start(int type); -void tutorial_stop(); - -#endif diff --git a/src/util/sawyercoding.c b/src/util/sawyercoding.c index d73bda1fda..1a6ba9b15d 100644 --- a/src/util/sawyercoding.c +++ b/src/util/sawyercoding.c @@ -21,6 +21,8 @@ #include "../addresses.h" #include "../platform/platform.h" #include "sawyercoding.h" +#include "../scenario.h" +#include "util.h" static size_t decode_chunk_rle(const uint8* src_buffer, uint8* dst_buffer, size_t length); static size_t decode_chunk_repeat(uint8 *buffer, size_t length); @@ -137,6 +139,11 @@ size_t sawyercoding_read_chunk(SDL_RWops* rw, uint8 *buffer) size_t sawyercoding_write_chunk_buffer(uint8 *dst_file, uint8* buffer, sawyercoding_chunk_header chunkHeader){ uint8 *encode_buffer, *encode_buffer2; + if (gUseRLE == false) { + if (chunkHeader.encoding == CHUNK_ENCODING_RLE || chunkHeader.encoding == CHUNK_ENCODING_RLECOMPRESSED) { + chunkHeader.encoding = CHUNK_ENCODING_NONE; + } + } switch (chunkHeader.encoding){ case CHUNK_ENCODING_NONE: memcpy(dst_file, &chunkHeader, sizeof(sawyercoding_chunk_header)); @@ -416,8 +423,10 @@ static size_t encode_chunk_repeat(const uint8 *src_buffer, uint8 *dst_buffer, si bestRepeatCount = 0; for (repeatIndex = searchIndex; repeatIndex <= searchEnd; repeatIndex++) { repeatCount = 0; - maxRepeatCount = min(7, searchEnd - repeatIndex); + maxRepeatCount = min(min(7, searchEnd - repeatIndex), length - i - 1); for (j = 0; j <= maxRepeatCount; j++) { + assert(repeatIndex + j < length); + assert(i + j < length); if (src_buffer[repeatIndex + j] == src_buffer[i + j]) { repeatCount++; } else { diff --git a/src/util/util.c b/src/util/util.c index 890423e0fd..a09f2251cb 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -18,9 +18,16 @@ * along with this program. If not, see . *****************************************************************************/ -#include "util.h" +// Include common.h before SDL, otherwise M_PI gets redefined +#include "../common.h" + #include +#include "../localisation/localisation.h" #include "../platform/platform.h" +#include "util.h" +#include "zlib.h" + +bool gUseRLE = true; int squaredmetres_to_squaredfeet(int squaredMetres) { @@ -40,7 +47,13 @@ int mph_to_kmph(int mph) { // 1 mph = 1.60934 kmph // RCT2 approximates as 1.609375 - return (mph * 1648) / 1024; + return (mph * 1648) >> 10; +} + +int mph_to_dmps(int mph) +{ + // 1 mph = 4.4704 decimeters/s + return (mph * 73243) >> 14; } bool filename_valid_characters(const utf8 *filename) @@ -55,62 +68,67 @@ bool filename_valid_characters(const utf8 *filename) const char *path_get_filename(const utf8 *path) { - const char *result, *ch; + // Find last slash or backslash in the path + char *filename = strrchr(path, platform_get_path_separator()); - result = path; - for (ch = path; *ch != 0; ch++) { - if (*ch == '/' || *ch == '\\') { - if (*(ch + 1) != 0) - result = ch + 1; - } + // Checks if the path is valid (e.g. not just a file name) + if (filename == NULL) + { + // Return the input string to keep things working + return path; } - return result; + // Increase pointer by one, to get rid of the slashes + filename++; + + 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) { - const char *extension = NULL; - const char *ch = path; - while (*ch != 0) { - if (*ch == '.') - extension = ch; + // Get the filename from the path + const char *filename = path_get_filename(path); - ch++; - } + // Try to find the most-right dot in the filename + char *extension = strrchr(filename, '.'); + + // When no dot was found, return a pointer to the null-terminator if (extension == NULL) - extension = ch; + extension = strrchr(filename, '\0'); + return extension; } void path_set_extension(utf8 *path, const utf8 *newExtension) { - char *extension = NULL; - char *ch = path; - while (*ch != 0) { - if (*ch == '.') - extension = ch; - - ch++; - } - if (extension == NULL) - extension = ch; + // 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'); if (newExtension[0] != '.') - *extension++ = '.'; + *endOfString++ = '.'; - strcpy(extension, newExtension); + // Append the extension to the path + safe_strcpy(endOfString, newExtension, MAX_PATH - (endOfString - path) - 1); } void path_remove_extension(utf8 *path) { - char *ch = path + strlen(path); - for (--ch; ch >= path; --ch) { - if (*ch == '.') { - *ch = '\0'; - break; - } - } + // Find last dot in filename, and replace it with a null-terminator + 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) @@ -144,7 +162,14 @@ int bitscanforward(int source) #if _MSC_VER >= 1400 // Visual Studio 2005 uint8 success = _BitScanForward(&i, source); return success != 0 ? i : -1; + #elif __GNUC__ + int success = __builtin_ffs(source); + return success - 1; #else + #pragma message "Falling back to iterative bitscan forward, consider using intrinsics" + // This is a low-hanging optimisation boost, check if your compiler offers + // any intrinsic. + // cf. https://github.com/OpenRCT2/OpenRCT2/pull/2093 for (i = 0; i < 32; i++) if (source & (1u << i)) return i; @@ -181,21 +206,79 @@ int strcicmp(char const *a, char const *b) } } -char *safe_strncpy(char * destination, const char * source, size_t size) +utf8 * safe_strtrunc(utf8 * text, size_t size) +{ + assert(text != NULL); + + if (size == 0) return text; + + const char *sourceLimit = text + size - 1; + char *ch = text; + char *last = text; + uint32 codepoint; + while ((codepoint = utf8_get_next(ch, (const utf8 **)&ch)) != 0) { + if (ch <= sourceLimit) { + last = ch; + } else { + break; + } + } + *last = 0; + + return text; +} + +char *safe_strcpy(char * destination, const char * source, size_t size) { assert(destination != NULL); assert(source != NULL); - if (size == 0) - { + if (size == 0) return destination; + + char * result = destination; + + bool truncated = false; + const char *sourceLimit = source + size - 1; + const char *ch = source; + uint32 codepoint; + while ((codepoint = utf8_get_next(ch, &ch)) != 0) { + if (ch <= sourceLimit) { + destination = utf8_write_codepoint(destination, codepoint); + } else { + truncated = true; + } + } + *destination = 0; + + if (truncated) { + log_warning("Truncating string \"%s\" to %d bytes.", result, 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 (size_t i = 0; i < size; i++) - { - if (*source != '\0') - { + for (; i < size; i++) { + if (*source != '\0') { *destination++ = *source++; } else { *destination = *source; @@ -203,14 +286,40 @@ char *safe_strncpy(char * destination, const char * source, size_t size) break; } } - if (!terminated) - { + + if (!terminated) { result[size - 1] = '\0'; - log_warning("Truncating string %s to %d bytes.", destination, size); + 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 = strnlen(destination, size); + 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_strcpy(destination, source, size); +} + bool utf8_is_bom(const char *str) { return str[0] == (char)0xEF && str[1] == (char)0xBB && str[2] == (char)0xBF; @@ -237,4 +346,78 @@ uint32 util_rand() { srand2 = srand3; srand3 = srand3 ^ (srand3 >> 19) ^ temp ^ (temp >> 8); return srand3; -} \ No newline at end of file +} + +#define CHUNK 128*1024 +#define MAX_ZLIB_REALLOC 4*1024*1024 + +/** + * @brief Inflates zlib-compressed data + * @param data Data to be decompressed + * @param data_in_size Size of data to be decompressed + * @param data_out_size Pointer to a variable where output size will be written. If not 0, it will be used to set initial output buffer size. + * @return Returns a pointer to memory holding decompressed data or NULL on failure. + * @note It is caller's responsibility to free() the returned pointer once done with it. + */ +unsigned char *util_zlib_inflate(unsigned char *data, size_t data_in_size, size_t *data_out_size) +{ + int ret = Z_OK; + uLongf out_size = *data_out_size; + if (out_size == 0) + { + // Try to guesstimate the size needed for output data by applying the + // same ratio it would take to compress data_in_size. + out_size = data_in_size * data_in_size / compressBound(data_in_size); + out_size = min(MAX_ZLIB_REALLOC, out_size); + } + size_t buffer_size = out_size; + unsigned char *buffer = malloc(buffer_size); + do { + if (ret == Z_BUF_ERROR) + { + buffer_size *= 2; + out_size = buffer_size; + buffer = realloc(buffer, buffer_size); + } else if (ret == Z_STREAM_ERROR) { + log_error("Your build is shipped with broken zlib. Please use the official build."); + free(buffer); + return NULL; + } + ret = uncompress(buffer, &out_size, data, data_in_size); + } while (ret != Z_OK); + buffer = realloc(buffer, out_size); + *data_out_size = out_size; + return buffer; +} + +/** + * @brief Deflates input using zlib + * @param data Data to be compressed + * @param data_in_size Size of data to be compressed + * @param data_out_size Pointer to a variable where output size will be written + * @return Returns a pointer to memory holding compressed data or NULL on failure. + * @note It is caller's responsibility to free() the returned pointer once done with it. + */ +unsigned char *util_zlib_deflate(unsigned char *data, size_t data_in_size, size_t *data_out_size) +{ + int ret = Z_OK; + uLongf out_size = *data_out_size; + size_t buffer_size = compressBound(data_in_size); + unsigned char *buffer = malloc(buffer_size); + do { + if (ret == Z_BUF_ERROR) + { + buffer_size *= 2; + out_size = buffer_size; + buffer = realloc(buffer, buffer_size); + } else if (ret == Z_STREAM_ERROR) { + log_error("Your build is shipped with broken zlib. Please use the official build."); + free(buffer); + return NULL; + } + ret = compress(buffer, &out_size, data, data_in_size); + } while (ret != Z_OK); + *data_out_size = out_size; + buffer = realloc(buffer, *data_out_size); + return buffer; +} diff --git a/src/util/util.h b/src/util/util.h index 23ea66c2d2..e20d536745 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -23,15 +23,19 @@ #include "../common.h" +extern bool gUseRLE; + int squaredmetres_to_squaredfeet(int squaredMetres); int metres_to_feet(int metres); int mph_to_kmph(int mph); +int mph_to_dmps(int mph); 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); @@ -39,7 +43,11 @@ int bitscanforward(int source); 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); +utf8 * safe_strtrunc(utf8 * text, size_t size); +char *safe_strcpy(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); @@ -47,4 +55,7 @@ bool str_is_null_or_empty(const char *str); void util_srand(int source); uint32 util_rand(); +unsigned char *util_zlib_deflate(unsigned char *data, size_t data_in_size, size_t *data_out_size); +unsigned char *util_zlib_inflate(unsigned char *data, size_t data_in_size, size_t *data_out_size); + #endif diff --git a/src/version.h b/src/version.h new file mode 100644 index 0000000000..fb6b801106 --- /dev/null +++ b/src/version.h @@ -0,0 +1,43 @@ +#ifndef _VERSION_H_ +#define _VERSION_H_ + +#include "common.h" + +#define OPENRCT2_NAME "OpenRCT2" +#define OPENRCT2_VERSION "0.0.4-rc1" +#define OPENRCT2_ARCHITECTURE "x86" + +// Platform +#ifdef __WINDOWS__ + #define OPENRCT2_PLATFORM "Windows" +#endif +#ifdef __LINUX__ + #define OPENRCT2_PLATFORM "Linux" +#endif +#ifdef __MACOSX__ + #define OPENRCT2_PLATFORM "OS X" +#endif +#ifndef OPENRCT2_PLATFORM + #error Unknown platform! +#endif + +#define OPENRCT2_TIMESTAMP __DATE__ " " __TIME__ + +// The following constants are for automated build servers +#ifndef OPENRCT2_BUILD_NUMBER + #define OPENRCT2_BUILD_NUMBER "" +#endif +#ifndef OPENRCT2_BUILD_SERVER + #define OPENRCT2_BUILD_SERVER "" +#endif +#ifndef OPENRCT2_BRANCH + #define OPENRCT2_BRANCH "develop" +#endif +#ifndef OPENRCT2_COMMIT_SHA1 + #define OPENRCT2_COMMIT_SHA1 "" +#endif +#ifndef OPENRCT2_COMMIT_SHA1_SHORT + #define OPENRCT2_COMMIT_SHA1_SHORT "" +#endif + +#endif diff --git a/src/windows/banner.c b/src/windows/banner.c index d084a8de62..74fca235c6 100644 --- a/src/windows/banner.c +++ b/src/windows/banner.c @@ -44,9 +44,9 @@ enum WINDOW_BANNER_WIDGET_IDX { WIDX_BANNER_TEXT, WIDX_BANNER_NO_ENTRY, WIDX_BANNER_DEMOLISH, - WIDX_MAIN_COLOR, - WIDX_TEXT_COLOR_DROPDOWN, - WIDX_TEXT_COLOR_DROPDOWN_BUTTON + WIDX_MAIN_COLOUR, + WIDX_TEXT_COLOUR_DROPDOWN, + WIDX_TEXT_COLOUR_DROPDOWN_BUTTON }; rct_widget window_banner_widgets[] = { @@ -57,9 +57,9 @@ rct_widget window_banner_widgets[] = { { WWT_FLATBTN, 1, WW - 25, WW - 2, 19, 42, 0x1430, STR_CHANGE_BANNER_TEXT_TIP}, // change banner button { WWT_FLATBTN, 1, WW - 25, WW - 2, 43, 66, 0x143A, STR_SET_AS_NO_ENTRY_BANNER_TIP}, // no entry button { WWT_FLATBTN, 1, WW - 25, WW - 2, 67, 90, 0x142D, STR_DEMOLISH_BANNER_TIP}, // demolish button - { WWT_COLORBTN, 1, 5, 16, WH - 16,WH - 5, 0x0FFFFFFFF, STR_SELECT_MAIN_COLOR_TIP}, // high money + { WWT_COLOURBTN, 1, 5, 16, WH - 16,WH - 5, 0x0FFFFFFFF, STR_SELECT_MAIN_SIGN_COLOUR_TIP}, // high money { WWT_DROPDOWN, 1, 43, 81, WH - 16,WH - 5, 0x0FFFFFFFF, 65535}, // high money - { WWT_DROPDOWN_BUTTON, 1, 70, 80, WH - 15,WH - 6, 0x36C, STR_SELECT_TEXT_COLOR_TIP}, // high money + { WWT_DROPDOWN_BUTTON, 1, 70, 80, WH - 15,WH - 6, 0x36C, STR_SELECT_TEXT_COLOUR_TIP}, // high money { WIDGETS_END }, }; @@ -124,9 +124,9 @@ void window_banner_open(rct_windownumber number) (1 << WIDX_BANNER_TEXT) | (1 << WIDX_BANNER_NO_ENTRY) | (1 << WIDX_BANNER_DEMOLISH) | - (1 << WIDX_MAIN_COLOR) | - (1 << WIDX_TEXT_COLOR_DROPDOWN) | - (1 << WIDX_TEXT_COLOR_DROPDOWN_BUTTON); + (1 << WIDX_MAIN_COLOUR) | + (1 << WIDX_TEXT_COLOUR_DROPDOWN) | + (1 << WIDX_TEXT_COLOUR_DROPDOWN_BUTTON); w->number = number; window_init_scroll_widgets(w); @@ -172,7 +172,10 @@ void window_banner_open(rct_windownumber number) window_invalidate(w); } -/* rct2: 0x6ba4d6*/ +/** + * + * rct2: 0x6ba4d6 + */ static void window_banner_mouseup(rct_window *w, int widgetIndex) { rct_banner* banner = &gBanners[w->number]; @@ -204,16 +207,19 @@ static void window_banner_mouseup(rct_window *w, int widgetIndex) } } -/* rct2: 0x6ba4ff */ +/** + * + * rct2: 0x6ba4ff + */ static void window_banner_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { rct_banner* banner = &gBanners[w->number]; switch (widgetIndex) { - case WIDX_MAIN_COLOR: + case WIDX_MAIN_COLOUR: window_dropdown_show_colour(w, widget, w->colours[1] | 0x80, banner->colour); break; - case WIDX_TEXT_COLOR_DROPDOWN_BUTTON: + case WIDX_TEXT_COLOUR_DROPDOWN_BUTTON: for( int i = 0; i < 13; ++i){ gDropdownItemsFormat[i] = 1142; @@ -238,28 +244,34 @@ static void window_banner_mousedown(int widgetIndex, rct_window*w, rct_widget* w } } -/* rct2: 0x6ba517 */ +/** + * + * rct2: 0x6ba517 + */ static void window_banner_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { rct_banner* banner = &gBanners[w->number]; switch(widgetIndex){ - case WIDX_MAIN_COLOR: + case WIDX_MAIN_COLOUR: if (dropdownIndex == -1) break; - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_BANNER_STYLE, banner->text_colour, 0); + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_BANNER_STYLE, banner->text_colour, banner->flags); break; - case WIDX_TEXT_COLOR_DROPDOWN_BUTTON: + case WIDX_TEXT_COLOUR_DROPDOWN_BUTTON: if (dropdownIndex == -1) break; - game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, banner->colour, GAME_COMMAND_SET_BANNER_STYLE, dropdownIndex + 1, 0); + game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, banner->colour, GAME_COMMAND_SET_BANNER_STYLE, dropdownIndex + 1, banner->flags); break; } } -/* rct2: 0x6ba50c */ +/** + * + * rct2: 0x6ba50c + */ static void window_banner_textinput(rct_window *w, int widgetIndex, char *text) { if (widgetIndex == WIDX_BANNER_TEXT && text != NULL) { @@ -269,41 +281,44 @@ static void window_banner_textinput(rct_window *w, int widgetIndex, char *text) } } -/* rct2: 0x006BA44D */ +/** + * + * rct2: 0x006BA44D + */ static void window_banner_invalidate(rct_window *w) { colour_scheme_update(w); rct_banner* banner = &gBanners[w->number]; - rct_widget* colour_btn = &window_banner_widgets[WIDX_MAIN_COLOR]; + rct_widget* colour_btn = &window_banner_widgets[WIDX_MAIN_COLOUR]; colour_btn->type = WWT_EMPTY; //sceneray item not sure why we use this instead of banner? rct_scenery_entry* sceneryEntry = g_bannerSceneryEntries[banner->type]; - if (sceneryEntry->banner.flags & 1) colour_btn->type = WWT_COLORBTN; + if (sceneryEntry->banner.flags & 1) colour_btn->type = WWT_COLOURBTN; w->pressed_widgets &= ~(1ULL<disabled_widgets &= ~( (1ULL<flags & BANNER_FLAG_NO_ENTRY){ w->pressed_widgets |= (1ULL<disabled_widgets |= (1ULL<image = (banner->colour << 19) + 0x600013C3; - rct_widget* drop_down_widget = &window_banner_widgets[WIDX_TEXT_COLOR_DROPDOWN]; + rct_widget* drop_down_widget = &window_banner_widgets[WIDX_TEXT_COLOUR_DROPDOWN]; drop_down_widget->image = banner->text_colour + 2996; } -/* rct2:0x006BA4C5 */ +/* rct2: 0x006BA4C5 */ static void window_banner_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -314,7 +329,10 @@ static void window_banner_paint(rct_window *w, rct_drawpixelinfo *dpi) } } -/* rct2: 0x6BA7B5 */ +/** + * + * rct2: 0x6BA7B5 + */ static void window_banner_unknown_14(rct_window *w) { rct_viewport* view = w->viewport; diff --git a/src/windows/changelog.c b/src/windows/changelog.c index fa37953a29..ee067b94d4 100644 --- a/src/windows/changelog.c +++ b/src/windows/changelog.c @@ -1,14 +1,15 @@ #include "../addresses.h" #include "../localisation/localisation.h" +#include "../interface/themes.h" #include "../interface/widget.h" #include "../interface/window.h" #include "../interface/viewport.h" -#include "../world/scenery.h" -#include "../world/map.h" -#include "../world/footpath.h" -#include "../util/util.h" #include "../openrct2.h" #include "../platform/platform.h" +#include "../util/util.h" +#include "../world/footpath.h" +#include "../world/map.h" +#include "../world/scenery.h" enum { WIDX_BACKGROUND, @@ -105,9 +106,6 @@ rct_window *window_changelog_open() window->enabled_widgets = (1 << WIDX_CLOSE); window_init_scroll_widgets(window); - window->colours[0] = 7; - window->colours[1] = 7; - window->colours[2] = 7; window->min_width = MIN_WW; window->min_height = MIN_WH; window->max_width = MIN_WW; @@ -157,6 +155,8 @@ static void window_changelog_scrollgetsize(rct_window *w, int scrollIndex, int * static void window_changelog_invalidate(rct_window *w) { + colour_scheme_update(w); + window_changelog_widgets[WIDX_BACKGROUND].right = w->width - 1; window_changelog_widgets[WIDX_BACKGROUND].bottom = w->height - 1; window_changelog_widgets[WIDX_TITLE].right = w->width - 2; diff --git a/src/windows/cheats.c b/src/windows/cheats.c index e905ac7577..c417d27cdc 100644 --- a/src/windows/cheats.c +++ b/src/windows/cheats.c @@ -30,16 +30,14 @@ #include "../scenario.h" #include "../sprites.h" #include "../world/climate.h" -#include "../world/footpath.h" #include "../world/park.h" #include "../world/sprite.h" -#include "../world/scenery.h" #include "../interface/themes.h" #include "../cheats.h" +#include "../network/network.h" +#include "../management/marketing.h" #include "error.h" - -#define CHEATS_MONEY_INCREMENT MONEY(5000,00) -#define CHEATS_TRAM_INCREMENT 250 +#include "dropdown.h" #define CHEATS_PARK_RATING_SPINNER_PAUSE 20 @@ -99,10 +97,11 @@ enum WINDOW_CHEATS_WIDGET_IDX { WIDX_DECREASE_PARK_RATING, WIDX_WIN_SCENARIO, WIDX_HAVE_FUN, + WIDX_NEVERENDING_MARKETING, WIDX_CLIMATE_GROUP, WIDX_FREEZE_CLIMATE, - WIDX_WEATHER_SUN, - WIDX_WEATHER_THUNDER, + WIDX_WEATHER, + WIDX_WEATHER_DROPDOWN_BUTTON, WIDX_STAFF_GROUP, WIDX_CLEAR_GRASS, WIDX_MOWED_GRASS, @@ -124,24 +123,6 @@ enum WINDOW_CHEATS_WIDGET_IDX { WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES }; -enum { - GUEST_PARAMETER_HAPPINESS, - GUEST_PARAMETER_ENERGY, - GUEST_PARAMETER_HUNGER, - GUEST_PARAMETER_THIRST, - GUEST_PARAMETER_NAUSEA, - GUEST_PARAMETER_NAUSEA_TOLERANCE, - GUEST_PARAMETER_BATHROOM, - GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY -}; - -enum { - OBJECT_MONEY, - OBJECT_PARK_MAP, - OBJECT_BALLOON, - OBJECT_UMBRELLA -}; - #pragma region MEASUREMENTS #define WW 249 @@ -185,7 +166,7 @@ enum { static rct_widget window_cheats_money_widgets[] = { MAIN_CHEATS_WIDGETS, { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), STR_CHEAT_5K_MONEY, STR_NONE }, // high money - { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(5), HPL(5), STR_CHEAT_CLEAR_LOAN, STR_NONE }, // Clear loan + { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(3), HPL(3), STR_CHEAT_CLEAR_LOAN, STR_NONE }, // Clear loan { WIDGETS_END }, }; @@ -208,7 +189,7 @@ static rct_widget window_cheats_guests_widgets[] = { { WWT_CLOSEBOX, 1, MIN_BTN_LEFT, MIN_BTN_RIGHT, YPL(7), HPL(7), STR_MIN, STR_NONE }, // bathroom min { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(9), HPL(9), STR_CHEAT_MORE_THAN_1, STR_NONE }, // ride intensity > 1 { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(9), HPL(9), STR_CHEAT_LESS_THAN_15, STR_NONE }, // ride intensity < 15 - { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(10), OHPL(10), STR_CHEAT_IGNORE_INTENSITY, STR_NONE }, // guests ignore intensity + { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(10), OHPL(10), STR_CHEAT_IGNORE_INTENSITY, STR_CHEAT_TIP_IGNORE_INTENSITY }, // guests ignore intensity { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(11), OHPL(11), STR_CHEAT_DISABLE_VANDALISM, STR_CHEAT_DISABLE_VANDALISM_TIP }, // disable vandalism { WWT_GROUPBOX, 1, XPL(0) - GROUP_SPACE, WPL(1) + GROUP_SPACE, YPL(13), HPL(15.5), STR_CHEAT_GIVE_ALL_GUESTS, STR_NONE }, // Guests parameters group frame { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(14), HPL(14), STR_CHEAT_CURRENCY_FORMAT, STR_NONE }, // give guests money @@ -224,21 +205,22 @@ static rct_widget window_cheats_guests_widgets[] = { //Strings for following moved to window_cheats_paint() static rct_widget window_cheats_misc_widgets[] = { MAIN_CHEATS_WIDGETS, - { WWT_GROUPBOX, 1, XPL(0) - GROUP_SPACE, WPL(1) + GROUP_SPACE, YPL(0), HPL(5.5), STR_CHEAT_GENERAL_GROUP, STR_NONE }, // General group - { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), STR_CHEAT_OPEN_PARK, STR_NONE}, // open / close park + { WWT_GROUPBOX, 1, XPL(0) - GROUP_SPACE, WPL(1) + GROUP_SPACE, YPL(0), HPL(6.25), STR_CHEAT_GENERAL_GROUP, STR_NONE }, // General group + { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), STR_CHEAT_OPEN_PARK, STR_CHEAT_TIP_OPEN_PARK }, // open / close park { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(1), HPL(1), STR_CHEAT_PARK_PARAMETERS, STR_CHEAT_TIP_PARK_PARAMETERS}, // Park parameters { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(2), HPL(2), STR_CHEAT_SANDBOX_MODE, STR_CHEAT_SANDBOX_MODE_TIP}, // Sandbox mode (edit land ownership in-game) - { WWT_CHECKBOX, 1, XPL(0), OWPL, YPL(3), OHPL(3), STR_CHEAT_UNLOCK_PRICES, STR_NONE}, // Unlock all prices + { WWT_CHECKBOX, 1, XPL(0), OWPL, YPL(3), OHPL(3), STR_CHEAT_UNLOCK_PRICES, STR_CHEAT_TIP_UNLOCK_PRICES }, // Unlock all prices { WWT_CHECKBOX, 1, XPL(0), WPL(0), YPL(4), HPL(4), STR_FORCE_PARK_RATING, STR_NONE}, // Force park rating { WWT_SPINNER, 1, XPL(1), WPL(1) - 10, YPL(4) + 2, HPL(4) - 3, STR_NONE, STR_NONE }, // park rating { WWT_DROPDOWN_BUTTON, 1, WPL(1) - 10, WPL(1), YPL(4) + 3, YPL(4) + 7, STR_NUMERIC_UP, STR_NONE }, // increase rating { WWT_DROPDOWN_BUTTON, 1, WPL(1) - 10, WPL(1), YPL(4) + 8, YPL(4) + 12, STR_NUMERIC_DOWN, STR_NONE }, // decrease rating { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(5), HPL(5), STR_CHEAT_WIN_SCENARIO, STR_NONE}, // Win scenario { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(5), HPL(5), STR_CHEAT_HAVE_FUN, STR_NONE}, // Have fun! - { WWT_GROUPBOX, 1, XPL(0) - GROUP_SPACE, WPL(1) + GROUP_SPACE, YPL(7), HPL(9.5), STR_CHEAT_CLIMATE_GROUP, STR_NONE }, // Climate group - { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(8), HPL(8), STR_CHEAT_FREEZE_CLIMATE, STR_NONE}, // Freeze climate - { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(9), HPL(9), STR_CHEAT_FORCE_SUN, STR_NONE}, // Sun - { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(9), HPL(9), STR_CHEAT_FORCE_THUNDER, STR_NONE}, // Thunder + { WWT_CHECKBOX, 1, XPL(0), WPL(0), YPL(6), HPL(6), STR_CHEAT_NEVERENDING_MARKETING, STR_CHEAT_TIP_NEVERENDING_MARKETING }, // neverending marketing campaigns + { WWT_GROUPBOX, 1, XPL(0) - GROUP_SPACE, WPL(1) + GROUP_SPACE, YPL(7.25), HPL(9.5), STR_CHEAT_CLIMATE_GROUP, STR_NONE }, // Climate group + { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(8), HPL(8), STR_CHEAT_FREEZE_CLIMATE, STR_CHEAT_TIP_FREEZE_CLIMATE }, // Freeze climate + { WWT_DROPDOWN, 1, XPL(1), WPL(1), YPL(9) + 2, YPL(9) + 13, STR_NONE, STR_FORCE_WEATHER_TOOLTIP }, // Force weather + { WWT_DROPDOWN_BUTTON, 1, WPL(1) - 11, WPL(1) - 1, YPL(9) + 3, YPL(9) + 12, STR_DROPDOWN_GLYPH, STR_FORCE_WEATHER_TOOLTIP }, // Force weather { WWT_GROUPBOX, 1, XPL(0) - GROUP_SPACE, WPL(1) + GROUP_SPACE, YPL(11), HPL(15.5), STR_CHEAT_STAFF_GROUP, STR_NONE }, // Staff group { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(12), HPL(12), STR_CHEAT_CLEAR_GRASS, STR_NONE}, // Clear grass { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(12), HPL(12), STR_CHEAT_MOWED_GRASS, STR_NONE}, // Mowed grass @@ -253,14 +235,14 @@ static rct_widget window_cheats_misc_widgets[] = { }; static rct_widget window_cheats_rides_widgets[] = { MAIN_CHEATS_WIDGETS, - { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(0), HPL(0), STR_CHEAT_RENEW_RIDES, STR_NONE}, // Renew rides - { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(1), HPL(1), STR_CHEAT_MAKE_DESTRUCTABLE, STR_NONE}, // Make destructable - { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), STR_CHEAT_FIX_ALL_RIDES, STR_NONE }, // Fix all rides - { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(11), OHPL(11) + 8, STR_CHEAT_410_HILL_LIFT, STR_NONE }, // 410 km/h lift hill - { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(9), OHPL(9), STR_CHEAT_DISABLE_BRAKES_FAILURE, STR_NONE }, // Disable brakes failure - { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(10), OHPL(10), STR_CHEAT_DISABLE_BREAKDOWNS, STR_NONE }, // Disable all breakdowns - { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(8), OHPL(8), STR_CHEAT_BUILD_IN_PAUSE_MODE, STR_NONE }, // Build in pause mode - { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(2), HPL(2), STR_CHEAT_RESET_CRASH_STATUS, STR_NONE }, // Reset crash status + { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(0), HPL(0), STR_CHEAT_RENEW_RIDES, STR_CHEAT_TIP_RENEW_RIDES }, // Renew rides + { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(1), HPL(1), STR_CHEAT_MAKE_DESTRUCTABLE, STR_CHEAT_TIP_MAKE_DESTRUCTABLE }, // All destructable + { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(1), HPL(1), STR_CHEAT_FIX_ALL_RIDES, STR_CHEAT_TIP_FIX_ALL_RIDES }, // Fix all rides + { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(11), OHPL(11) + 8, STR_CHEAT_UNLOCK_OPERATING_LIMITS, STR_CHEAT_UNLOCK_OPERATING_LIMITS_TIP },// 410 km/h lift hill etc. + { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(9), OHPL(9), STR_CHEAT_DISABLE_BRAKES_FAILURE, STR_CHEAT_TIP_DISABLE_BRAKES_FAILURE }, // Disable brakes failure + { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(10), OHPL(10), STR_CHEAT_DISABLE_BREAKDOWNS, STR_CHEAT_TIP_DISABLE_BREAKDOWNS }, // Disable all breakdowns + { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(8), OHPL(8), STR_CHEAT_BUILD_IN_PAUSE_MODE, STR_CHEAT_TIP_BUILD_IN_PAUSE_MODE }, // Build in pause mode + { WWT_CLOSEBOX, 1, XPL(0), WPL(0), YPL(2), HPL(2), STR_CHEAT_RESET_CRASH_STATUS, STR_CHEAT_TIP_RESET_CRASH_STATUS }, // Reset crash status { WWT_CLOSEBOX, 1, XPL(1), WPL(1), YPL(2), HPL(2), STR_CHEAT_10_MINUTE_INSPECTIONS, STR_CHEAT_10_MINUTE_INSPECTIONS_TIP }, // 10 minute inspections { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(7), OHPL(7), STR_CHEAT_SHOW_ALL_OPERATING_MODES, STR_NONE }, // Show all operating modes { WWT_CHECKBOX, 2, XPL(0), OWPL, YPL(6), OHPL(6), STR_CHEAT_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES, STR_NONE }, // Show vehicles from other track types @@ -275,6 +257,8 @@ static rct_widget *window_cheats_page_widgets[] = { }; static void window_cheats_money_mouseup(rct_window *w, int widgetIndex); +static void window_cheats_misc_mousedown(int widgetIndex, rct_window *w, rct_widget* widget); +static void window_cheats_misc_dropdown(rct_window *w, int widgetIndex, int dropdownIndex); static void window_cheats_guests_mouseup(rct_window *w, int widgetIndex); static void window_cheats_misc_mouseup(rct_window *w, int widgetIndex); static void window_cheats_rides_mouseup(rct_window *w, int widgetIndex); @@ -349,8 +333,8 @@ static rct_window_event_list window_cheats_misc_events = { NULL, window_cheats_misc_mouseup, NULL, - NULL, - NULL, + window_cheats_misc_mousedown, + window_cheats_misc_dropdown, NULL, window_cheats_update, NULL, @@ -418,7 +402,7 @@ static rct_window_event_list *window_cheats_page_events[] = { static uint64 window_cheats_page_enabled_widgets[] = { (1ULL << WIDX_CLOSE) | (1ULL << WIDX_TAB_1) | (1ULL << WIDX_TAB_2) | (1ULL << WIDX_TAB_3) | (1ULL << WIDX_TAB_4) | (1ULL << WIDX_HIGH_MONEY) | (1ULL << WIDX_CLEAR_LOAN), (1ULL << WIDX_CLOSE) | (1ULL << WIDX_TAB_1) | (1ULL << WIDX_TAB_2) | (1ULL << WIDX_TAB_3) | (1ULL << WIDX_TAB_4) | (1ULL << WIDX_GUEST_PARAMETERS_GROUP) | (1ULL << WIDX_GUEST_HAPPINESS_MAX) | (1ULL << WIDX_GUEST_HAPPINESS_MIN) | (1ULL << WIDX_GUEST_ENERGY_MAX) | (1ULL << WIDX_GUEST_ENERGY_MIN) | (1ULL << WIDX_GUEST_HUNGER_MAX) | (1ULL << WIDX_GUEST_HUNGER_MIN) | (1ULL << WIDX_GUEST_THIRST_MAX) | (1ULL << WIDX_GUEST_THIRST_MIN) | (1ULL << WIDX_GUEST_NAUSEA_MAX) | (1ULL << WIDX_GUEST_NAUSEA_MIN) | (1ULL << WIDX_GUEST_NAUSEA_TOLERANCE_MAX) | (1ULL << WIDX_GUEST_NAUSEA_TOLERANCE_MIN) | (1ULL << WIDX_GUEST_BATHROOM_MAX) | (1ULL << WIDX_GUEST_BATHROOM_MIN) | (1ULL << WIDX_GUEST_RIDE_INTENSITY_MORE_THAN_1) | (1ULL << WIDX_GUEST_RIDE_INTENSITY_LESS_THAN_15) | (1ULL << WIDX_GUEST_IGNORE_RIDE_INTENSITY) | (1ULL << WIDX_GIVE_ALL_GUESTS_GROUP) | (1ULL << WIDX_GIVE_GUESTS_MONEY) | (1ULL << WIDX_GIVE_GUESTS_PARK_MAPS) | (1ULL << WIDX_GIVE_GUESTS_BALLOONS) | (1ULL << WIDX_GIVE_GUESTS_UMBRELLAS) | (1ULL << WIDX_TRAM_GUESTS) | (1ULL << WIDX_REMOVE_ALL_GUESTS) | (1ULL << WIDX_EXPLODE_GUESTS) | (1ULL << WIDX_DISABLE_VANDALISM), - (1ULL << WIDX_CLOSE) | (1ULL << WIDX_TAB_1) | (1ULL << WIDX_TAB_2) | (1ULL << WIDX_TAB_3) | (1ULL << WIDX_TAB_4) | (1ULL << WIDX_FREEZE_CLIMATE) | (1ULL << WIDX_OPEN_CLOSE_PARK) | (1ULL << WIDX_WEATHER_SUN) | (1ULL << WIDX_WEATHER_THUNDER) | (1ULL << WIDX_CLEAR_GRASS) | (1ULL << WIDX_MOWED_GRASS) | (1ULL << WIDX_WATER_PLANTS) | (1ULL << WIDX_FIX_VANDALISM) | (1ULL << WIDX_REMOVE_LITTER) | (1ULL << WIDX_WIN_SCENARIO) | (1ULL << WIDX_HAVE_FUN) | (1ULL << WIDX_UNLOCK_ALL_PRICES) | (1ULL << WIDX_SANDBOX_MODE) | (1ULL << WIDX_FAST_STAFF) | (1ULL << WIDX_NORMAL_STAFF) | (1ULL << WIDX_PARK_PARAMETERS) | (1ULL << WIDX_FORCE_PARK_RATING) | (1ULL << WIDX_INCREASE_PARK_RATING) | (1ULL << WIDX_DECREASE_PARK_RATING), + (1ULL << WIDX_CLOSE) | (1ULL << WIDX_TAB_1) | (1ULL << WIDX_TAB_2) | (1ULL << WIDX_TAB_3) | (1ULL << WIDX_TAB_4) | (1ULL << WIDX_FREEZE_CLIMATE) | (1ULL << WIDX_OPEN_CLOSE_PARK) | (1ULL << WIDX_WEATHER) | (1ULL << WIDX_WEATHER_DROPDOWN_BUTTON) | (1ULL << WIDX_CLEAR_GRASS) | (1ULL << WIDX_MOWED_GRASS) | (1ULL << WIDX_WATER_PLANTS) | (1ULL << WIDX_FIX_VANDALISM) | (1ULL << WIDX_REMOVE_LITTER) | (1ULL << WIDX_WIN_SCENARIO) | (1ULL << WIDX_HAVE_FUN) | (1ULL << WIDX_NEVERENDING_MARKETING) | (1ULL << WIDX_UNLOCK_ALL_PRICES) | (1ULL << WIDX_SANDBOX_MODE) | (1ULL << WIDX_FAST_STAFF) | (1ULL << WIDX_NORMAL_STAFF) | (1ULL << WIDX_PARK_PARAMETERS) | (1ULL << WIDX_FORCE_PARK_RATING) | (1ULL << WIDX_INCREASE_PARK_RATING) | (1ULL << WIDX_DECREASE_PARK_RATING), (1ULL << WIDX_CLOSE) | (1ULL << WIDX_TAB_1) | (1ULL << WIDX_TAB_2) | (1ULL << WIDX_TAB_3) | (1ULL << WIDX_TAB_4) | (1ULL << WIDX_RENEW_RIDES) | (1ULL << WIDX_MAKE_DESTRUCTIBLE) | (1ULL << WIDX_FIX_ALL) | (1ULL << WIDX_FAST_LIFT_HILL) | (1ULL << WIDX_DISABLE_BRAKES_FAILURE) | (1ULL << WIDX_DISABLE_ALL_BREAKDOWNS) | (1ULL << WIDX_BUILD_IN_PAUSE_MODE) | (1ULL << WIDX_RESET_CRASH_STATUS) | (1ULL << WIDX_10_MINUTE_INSPECTIONS) | (1ULL << WIDX_SHOW_ALL_OPERATING_MODES) | (1ULL << WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES) }; @@ -431,333 +415,8 @@ static rct_string_id window_cheats_page_titles[] = { static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w); -int park_rating_spinner_value; int park_rating_spinner_pressed_for = 0; -#pragma region Cheat functions - -static void cheat_set_grass_length(int length) -{ - int x, y; - rct_map_element *mapElement; - - for (y = 0; y < 256; y++) { - for (x = 0; x < 256; x++) { - mapElement = map_get_surface_element_at(x, y); - if (!(mapElement->properties.surface.ownership & OWNERSHIP_OWNED)) - continue; - - if (map_element_get_terrain(mapElement) != TERRAIN_GRASS) - continue; - - if ((mapElement->properties.surface.terrain & 0x1F) > 0) - continue; - - mapElement->properties.surface.grass_length = length; - } - } - - gfx_invalidate_screen(); -} - -static void cheat_water_plants() -{ - map_element_iterator it; - - map_element_iterator_begin(&it); - do { - if (map_element_get_type(it.element) == MAP_ELEMENT_TYPE_SCENERY) { - it.element->properties.scenery.age = 0; - } - } while (map_element_iterator_next(&it)); - - gfx_invalidate_screen(); -} - -static void cheat_fix_vandalism() -{ - map_element_iterator it; - - map_element_iterator_begin(&it); - do { - if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH) - continue; - - if ((it.element->properties.path.additions & 0x0F) == 0) - continue; - - it.element->flags &= ~MAP_ELEMENT_FLAG_BROKEN; - } while (map_element_iterator_next(&it)); - - gfx_invalidate_screen(); -} - -static void cheat_remove_litter() -{ - rct_litter* litter; - uint16 spriteIndex, nextSpriteIndex; - - for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_LITTER, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) { - litter = &(g_sprite_list[spriteIndex].litter); - nextSpriteIndex = litter->next; - sprite_remove((rct_sprite*)litter); - } - - map_element_iterator it; - rct_scenery_entry *sceneryEntry; - - map_element_iterator_begin(&it); - do { - if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_PATH) - continue; - - if ((it.element->properties.path.additions & 0x0F) == 0) - continue; - - sceneryEntry = g_pathBitSceneryEntries[(it.element->properties.path.additions & 0xF) - 1]; - if(sceneryEntry->path_bit.var_06 & (1 << 0)) - it.element->properties.path.addition_status = 0xFF; - - } while (map_element_iterator_next(&it)); - - gfx_invalidate_screen(); -} - -static void cheat_fix_rides() -{ - int rideIndex; - rct_ride *ride; - rct_peep *mechanic; - - FOR_ALL_RIDES(rideIndex, ride) - { - if ((ride->mechanic_status != RIDE_MECHANIC_STATUS_FIXING) && (ride->lifecycle_flags & (RIDE_LIFECYCLE_BREAKDOWN_PENDING | RIDE_LIFECYCLE_BROKEN_DOWN))) - { - mechanic = ride_get_assigned_mechanic(ride); - - if (mechanic != NULL){ - remove_peep_from_ride(mechanic); - } - - ride_fix_breakdown(rideIndex, 0); - ride->window_invalidate_flags |= RIDE_INVALIDATE_RIDE_MAIN | RIDE_INVALIDATE_RIDE_LIST; - } - } -} - -static void cheat_renew_rides() -{ - int i; - rct_ride *ride; - - FOR_ALL_RIDES(i, ride) - { - // Set build date to current date (so the ride is brand new) - ride->build_date = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16); - // Set reliability to 100 - ride->reliability = (100 << 8); - } - window_invalidate_by_class(WC_RIDE); -} - -static void cheat_make_destructible() -{ - int i; - rct_ride *ride; - FOR_ALL_RIDES(i, ride) - { - if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) - ride->lifecycle_flags&=~RIDE_LIFECYCLE_INDESTRUCTIBLE; - if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK) - ride->lifecycle_flags&=~RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK; - } - window_invalidate_by_class(WC_RIDE); -} - -static void cheat_reset_crash_status() -{ - int i; - rct_ride *ride; - - FOR_ALL_RIDES(i, ride){ - //reset crash status - if (ride->lifecycle_flags & RIDE_LIFECYCLE_CRASHED) - ride->lifecycle_flags&=~RIDE_LIFECYCLE_CRASHED; - //reset crash history - ride->last_crash_type=RIDE_CRASH_TYPE_NONE; - } - window_invalidate_by_class(WC_RIDE); -} - -static void cheat_10_minute_inspections() -{ - int i; - rct_ride *ride; - - FOR_ALL_RIDES(i, ride) { - // Set inspection interval to 10 minutes - ride->inspection_interval = RIDE_INSPECTION_EVERY_10_MINUTES; - } - window_invalidate_by_class(WC_RIDE); -} - -static void cheat_increase_money(money32 amount) -{ - money32 currentMoney; - - currentMoney = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32)); - if (currentMoney < INT_MAX - amount) - currentMoney += amount; - else - currentMoney = INT_MAX; - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, sint32) = ENCRYPT_MONEY(currentMoney); - - window_invalidate_by_class(WC_FINANCES); - window_invalidate_by_class(WC_BOTTOM_TOOLBAR); -} - -static void cheat_clear_loan() -{ - // First give money - cheat_increase_money(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32)); - - // Then pay the loan - money32 newLoan; - newLoan = MONEY(0, 00); - game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, newLoan, GAME_COMMAND_SET_CURRENT_LOAN, 0, 0); -} - -static void cheat_generate_guests(int count) -{ - int i; - - for (i = 0; i < count; i++) - generate_new_guest(); - - window_invalidate_by_class(WC_BOTTOM_TOOLBAR); -} - -static void cheat_set_guest_parameter(int parameter, int value) -{ - int spriteIndex; - rct_peep *peep; - - FOR_ALL_GUESTS(spriteIndex, peep) { - switch(parameter) { - case GUEST_PARAMETER_HAPPINESS: - peep->happiness = value; - break; - case GUEST_PARAMETER_ENERGY: - peep->energy = value; - break; - case GUEST_PARAMETER_HUNGER: - peep->hunger = value; - break; - case GUEST_PARAMETER_THIRST: - peep->thirst = value; - break; - case GUEST_PARAMETER_NAUSEA: - peep->nausea = value; - break; - case GUEST_PARAMETER_NAUSEA_TOLERANCE: - peep->nausea_tolerance = value; - break; - case GUEST_PARAMETER_BATHROOM: - peep->bathroom = value; - break; - case GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY: - peep->intensity = (15 << 4) | value; - break; - } - peep_update_sprite_type(peep); - } - -} - -static void cheat_give_all_guests(int object) -{ - int spriteIndex; - rct_peep *peep; - - FOR_ALL_GUESTS(spriteIndex, peep) { - switch(object) - { - case OBJECT_MONEY: - peep->cash_in_pocket = MONEY(1000,00); - break; - case OBJECT_PARK_MAP: - peep->item_standard_flags |= PEEP_ITEM_MAP; - break; - case OBJECT_BALLOON: - peep->item_standard_flags |= PEEP_ITEM_BALLOON; - peep->balloon_colour=scenario_rand_max(31); - peep_update_sprite_type(peep); - break; - case OBJECT_UMBRELLA: - peep->item_standard_flags |= PEEP_ITEM_UMBRELLA; - peep->umbrella_colour=scenario_rand_max(31); - peep_update_sprite_type(peep); - break; - } - } - window_invalidate_by_class(WC_PEEP); -} - -static void cheat_remove_all_guests() -{ - rct_peep *peep; - uint16 spriteIndex, nextSpriteIndex; - - for (spriteIndex = RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_START_PEEP, uint16); spriteIndex != SPRITE_INDEX_NULL; spriteIndex = nextSpriteIndex) { - peep = &(g_sprite_list[spriteIndex].peep); - nextSpriteIndex = peep->next; - if (peep->type == PEEP_TYPE_GUEST) { - peep_remove(peep); - } - } - - int i; - rct_ride *ride; - - FOR_ALL_RIDES(i, ride) - { - ride_clear_for_construction(i); - ride_set_status(i, RIDE_STATUS_CLOSED); - - for(int i=0;i<4;i++) { - ride->queue_length[i] = 0; - ride->last_peep_in_queue[i]=0xFFFF; - } - } - window_invalidate_by_class(WC_RIDE); - gfx_invalidate_screen(); -} - -static void cheat_explode_guests() -{ - int sprite_index; - rct_peep *peep; - - FOR_ALL_GUESTS(sprite_index, peep) { - if (scenario_rand_max(6) == 0) { - peep->flags |= PEEP_FLAGS_EXPLODE; - } - } -} - -static void cheat_set_staff_speed(uint8 value) -{ - uint16 spriteIndex; - rct_peep *peep; - - FOR_ALL_STAFF(spriteIndex, peep) { - peep->energy = value; - peep->energy_growth_rate = value; - } -} - -#pragma endregion - void window_cheats_open() { rct_window* window; @@ -775,6 +434,42 @@ void window_cheats_open() park_rating_spinner_value = get_forced_park_rating() >= 0 ? get_forced_park_rating() : 999; } +static void window_cheats_misc_mousedown(int widgetIndex, rct_window *w, rct_widget* widget) +{ + rct_widget *dropdownWidget; + int i; + + if (widgetIndex != WIDX_WEATHER_DROPDOWN_BUTTON) + return; + + dropdownWidget = widget - 1; + + for (i = 0; i < 6; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = STR_SUNNY + i; + } + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + DROPDOWN_FLAG_STAY_OPEN, + 6, + dropdownWidget->right - dropdownWidget->left - 3 + ); + + int currentWeather = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER, uint8); + dropdown_set_checked(currentWeather, true); +} + +static void window_cheats_misc_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) +{ + if (widgetIndex != WIDX_WEATHER_DROPDOWN_BUTTON || dropdownIndex == -1) + return; + + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_FORCEWEATHER, dropdownIndex, GAME_COMMAND_CHEAT, 0, 0); +} + static void window_cheats_money_mouseup(rct_window *w, int widgetIndex) { switch (widgetIndex) { @@ -788,10 +483,10 @@ static void window_cheats_money_mouseup(rct_window *w, int widgetIndex) window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_HIGH_MONEY: - cheat_increase_money(CHEATS_MONEY_INCREMENT); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_INCREASEMONEY, CHEATS_MONEY_INCREMENT, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_CLEAR_LOAN: - cheat_clear_loan(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_CLEARLOAN, CHEATS_MONEY_INCREMENT, GAME_COMMAND_CHEAT, 0, 0); break; } } @@ -809,83 +504,79 @@ static void window_cheats_guests_mouseup(rct_window *w, int widgetIndex) window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_GUEST_HAPPINESS_MAX: - cheat_set_guest_parameter(GUEST_PARAMETER_HAPPINESS,255); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_HAPPINESS, GAME_COMMAND_CHEAT, 255, 0); break; case WIDX_GUEST_HAPPINESS_MIN: - cheat_set_guest_parameter(GUEST_PARAMETER_HAPPINESS,0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_HAPPINESS, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GUEST_ENERGY_MAX: - cheat_set_guest_parameter(GUEST_PARAMETER_ENERGY,127); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_ENERGY, GAME_COMMAND_CHEAT, 127, 0); break; case WIDX_GUEST_ENERGY_MIN: - cheat_set_guest_parameter(GUEST_PARAMETER_ENERGY,0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_ENERGY, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GUEST_HUNGER_MAX: - cheat_set_guest_parameter(GUEST_PARAMETER_HUNGER,0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_HUNGER, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GUEST_HUNGER_MIN: - cheat_set_guest_parameter(GUEST_PARAMETER_HUNGER,255); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_HUNGER, GAME_COMMAND_CHEAT, 255, 0); break; case WIDX_GUEST_THIRST_MAX: - cheat_set_guest_parameter(GUEST_PARAMETER_THIRST,0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_THIRST, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GUEST_THIRST_MIN: - cheat_set_guest_parameter(GUEST_PARAMETER_THIRST,255); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_THIRST, GAME_COMMAND_CHEAT, 255, 0); break; case WIDX_GUEST_NAUSEA_MAX: - cheat_set_guest_parameter(GUEST_PARAMETER_NAUSEA,255); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_NAUSEA, GAME_COMMAND_CHEAT, 255, 0); break; case WIDX_GUEST_NAUSEA_MIN: - cheat_set_guest_parameter(GUEST_PARAMETER_NAUSEA,0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_NAUSEA, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GUEST_NAUSEA_TOLERANCE_MAX: - cheat_set_guest_parameter(GUEST_PARAMETER_NAUSEA_TOLERANCE,PEEP_NAUSEA_TOLERANCE_HIGH); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_NAUSEA_TOLERANCE, GAME_COMMAND_CHEAT, PEEP_NAUSEA_TOLERANCE_HIGH, 0); break; case WIDX_GUEST_NAUSEA_TOLERANCE_MIN: - cheat_set_guest_parameter(GUEST_PARAMETER_NAUSEA_TOLERANCE,PEEP_NAUSEA_TOLERANCE_NONE); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_NAUSEA_TOLERANCE, GAME_COMMAND_CHEAT, PEEP_NAUSEA_TOLERANCE_NONE, 0); break; case WIDX_GUEST_BATHROOM_MAX: - cheat_set_guest_parameter(GUEST_PARAMETER_BATHROOM,255); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_BATHROOM, GAME_COMMAND_CHEAT, 255, 0); break; case WIDX_GUEST_BATHROOM_MIN: - cheat_set_guest_parameter(GUEST_PARAMETER_BATHROOM,0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_BATHROOM, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GUEST_RIDE_INTENSITY_MORE_THAN_1: - cheat_set_guest_parameter(GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY,1); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY, GAME_COMMAND_CHEAT, 1, 0); break; case WIDX_GUEST_RIDE_INTENSITY_LESS_THAN_15: - cheat_set_guest_parameter(GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY,0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGUESTPARAMETER, GUEST_PARAMETER_PREFERRED_RIDE_INTENSITY, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_TRAM_GUESTS: - cheat_generate_guests(CHEATS_TRAM_INCREMENT); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_GENERATEGUESTS, CHEATS_TRAM_INCREMENT, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_REMOVE_ALL_GUESTS: - cheat_remove_all_guests(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_REMOVEALLGUESTS, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_EXPLODE_GUESTS: - cheat_explode_guests(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_EXPLODEGUESTS, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GIVE_GUESTS_MONEY: - cheat_give_all_guests(OBJECT_MONEY); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_GIVEALLGUESTS, OBJECT_MONEY, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GIVE_GUESTS_PARK_MAPS: - cheat_give_all_guests(OBJECT_PARK_MAP); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_GIVEALLGUESTS, OBJECT_PARK_MAP, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GIVE_GUESTS_BALLOONS: - cheat_give_all_guests(OBJECT_BALLOON); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_GIVEALLGUESTS, OBJECT_BALLOON, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GIVE_GUESTS_UMBRELLAS: - cheat_give_all_guests(OBJECT_UMBRELLA); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_GIVEALLGUESTS, OBJECT_UMBRELLA, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_GUEST_IGNORE_RIDE_INTENSITY: - gConfigCheat.ignore_ride_intensity ^= 1; - config_save_default(); - window_invalidate(w); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_IGNORERIDEINTENSITY, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_DISABLE_VANDALISM: - gConfigCheat.disable_vandalism ^= 1; - config_save_default(); - window_invalidate(w); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_DISABLEVANDALISM, 0, GAME_COMMAND_CHEAT, 0, 0); break; } } @@ -903,81 +594,70 @@ static void window_cheats_misc_mouseup(rct_window *w, int widgetIndex) window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_FREEZE_CLIMATE: - toggle_climate_lock(); - w->widgets[widgetIndex].image = w->widgets[widgetIndex].image == STR_CHEAT_FREEZE_CLIMATE ? STR_CHEAT_UNFREEZE_CLIMATE : STR_CHEAT_FREEZE_CLIMATE; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_FREEZECLIMATE, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_OPEN_CLOSE_PARK: - park_set_open(park_is_open() ? 0 : 1); - break; - case WIDX_WEATHER_SUN: - climate_force_weather(WEATHER_SUNNY); - break; - case WIDX_WEATHER_THUNDER: - climate_force_weather(WEATHER_THUNDER); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_OPENCLOSEPARK, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_CLEAR_GRASS: - cheat_set_grass_length(GRASS_LENGTH_CLEAR_0); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGRASSLENGTH, GRASS_LENGTH_CLEAR_0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_MOWED_GRASS: - cheat_set_grass_length(GRASS_LENGTH_MOWED); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETGRASSLENGTH, GRASS_LENGTH_MOWED, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_WATER_PLANTS: - cheat_water_plants(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_WATERPLANTS, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_FIX_VANDALISM: - cheat_fix_vandalism(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_FIXVANDALISM, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_REMOVE_LITTER: - cheat_remove_litter(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_REMOVELITTER, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_WIN_SCENARIO: - scenario_success(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_WINSCENARIO, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_HAVE_FUN: - RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) = OBJECTIVE_HAVE_FUN; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_HAVEFUN, 0, GAME_COMMAND_CHEAT, 0, 0); + break; + case WIDX_NEVERENDING_MARKETING: + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_NEVERENDINGMARKETING, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_UNLOCK_ALL_PRICES: - gConfigCheat.unlock_all_prices ^= 1; - config_save_default(); - window_invalidate(w); - window_invalidate_by_class(WC_RIDE); - window_invalidate_by_class(WC_PARK_INFORMATION); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_UNLOCKALLPRICES, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_SANDBOX_MODE: - gCheatsSandboxMode = !gCheatsSandboxMode; - w->widgets[widgetIndex].image = w->widgets[widgetIndex].image == STR_CHEAT_SANDBOX_MODE ? STR_CHEAT_SANDBOX_MODE_DISABLE : STR_CHEAT_SANDBOX_MODE; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SANDBOXMODE, 0, GAME_COMMAND_CHEAT, 0, 0); // To prevent tools from staying active after disabling cheat - tool_cancel(); - window_invalidate_by_class(WC_MAP); - window_invalidate_by_class(WC_FOOTPATH); + //tool_cancel(); break; case WIDX_FAST_STAFF: - cheat_set_staff_speed(0xFF); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETSTAFFSPEED, 0xFF, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_NORMAL_STAFF: - cheat_set_staff_speed(0x60); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETSTAFFSPEED, 0x60, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_PARK_PARAMETERS: window_editor_scenario_options_open(); break; case WIDX_FORCE_PARK_RATING: if (get_forced_park_rating() >= 0){ - set_forced_park_rating(-1); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETFORCEDPARKRATING, -1, GAME_COMMAND_CHEAT, 0, 0); } else { - set_forced_park_rating(park_rating_spinner_value); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETFORCEDPARKRATING, park_rating_spinner_value, GAME_COMMAND_CHEAT, 0, 0); } break; case WIDX_INCREASE_PARK_RATING: park_rating_spinner_value = min(999, 10 * (park_rating_spinner_value / 10 + 1)); widget_invalidate_by_class(WC_CHEATS, WIDX_PARK_RATING_SPINNER); if (get_forced_park_rating() >= 0) - set_forced_park_rating(park_rating_spinner_value); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETFORCEDPARKRATING, park_rating_spinner_value, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_DECREASE_PARK_RATING: park_rating_spinner_value = max(0, 10 * (park_rating_spinner_value / 10 - 1)); widget_invalidate_by_class(WC_CHEATS, WIDX_PARK_RATING_SPINNER); if (get_forced_park_rating() >= 0) - set_forced_park_rating(park_rating_spinner_value); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SETFORCEDPARKRATING, park_rating_spinner_value, GAME_COMMAND_CHEAT, 0, 0); break; } } @@ -995,48 +675,40 @@ static void window_cheats_rides_mouseup(rct_window *w, int widgetIndex) window_cheats_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_RENEW_RIDES: - cheat_renew_rides(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_RENEWRIDES, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_MAKE_DESTRUCTIBLE: - cheat_make_destructible(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_MAKEDESTRUCTIBLE, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_FIX_ALL: - cheat_fix_rides(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_FIXRIDES, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_FAST_LIFT_HILL: - gConfigCheat.fast_lift_hill ^= 1; - config_save_default(); - window_invalidate(w); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_FASTLIFTHILL, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_DISABLE_BRAKES_FAILURE: - gConfigCheat.disable_brakes_failure ^= 1; - config_save_default(); - window_invalidate(w); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_DISABLEBRAKESFAILURE, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_DISABLE_ALL_BREAKDOWNS: - gConfigCheat.disable_all_breakdowns ^= 1; - config_save_default(); - window_invalidate(w); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_DISABLEALLBREAKDOWNS, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_BUILD_IN_PAUSE_MODE: - gConfigCheat.build_in_pause_mode ^= 1; - config_save_default(); - window_invalidate(w); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_BUILDINPAUSEMODE, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_RESET_CRASH_STATUS: - cheat_reset_crash_status(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_RESETCRASHSTATUS, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_10_MINUTE_INSPECTIONS: - cheat_10_minute_inspections(); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_10MINUTEINSPECTIONS, 0, GAME_COMMAND_CHEAT, 0, 0); break; case WIDX_SHOW_ALL_OPERATING_MODES: - gCheatsShowAllOperatingModes = !gCheatsShowAllOperatingModes; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SHOWALLOPERATINGMODES, 0, GAME_COMMAND_CHEAT, 0, 0); if (gCheatsShowAllOperatingModes) { window_error_open(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE); } break; case WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES: - gCheatsShowVehiclesFromOtherTrackTypes = !gCheatsShowVehiclesFromOtherTrackTypes; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SHOWVEHICLESFROMOTHERTRACKTYPES, 0, GAME_COMMAND_CHEAT, 0, 0); if (gCheatsShowVehiclesFromOtherTrackTypes) { window_error_open(STR_WARNING_IN_CAPS, STR_THIS_FEATURE_IS_CURRENTLY_UNSTABLE); } @@ -1089,21 +761,24 @@ static void window_cheats_invalidate(rct_window *w) break; case WINDOW_CHEATS_PAGE_GUESTS: RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, int) = 10000; - widget_set_checkbox_value(w, WIDX_GUEST_IGNORE_RIDE_INTENSITY, gConfigCheat.ignore_ride_intensity); - widget_set_checkbox_value(w, WIDX_DISABLE_VANDALISM, gConfigCheat.disable_vandalism); + widget_set_checkbox_value(w, WIDX_GUEST_IGNORE_RIDE_INTENSITY, gCheatsIgnoreRideIntensity); + widget_set_checkbox_value(w, WIDX_DISABLE_VANDALISM, gCheatsDisableVandalism); break; case WINDOW_CHEATS_PAGE_MISC: w->widgets[WIDX_OPEN_CLOSE_PARK].image = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_OPEN ? STR_CHEAT_CLOSE_PARK : STR_CHEAT_OPEN_PARK; - widget_set_checkbox_value(w, WIDX_UNLOCK_ALL_PRICES, gConfigCheat.unlock_all_prices); + widget_set_checkbox_value(w, WIDX_UNLOCK_ALL_PRICES, gCheatsUnlockAllPrices); widget_set_checkbox_value(w, WIDX_FORCE_PARK_RATING, get_forced_park_rating() >= 0); + w->widgets[WIDX_SANDBOX_MODE].image = gCheatsSandboxMode ? STR_CHEAT_SANDBOX_MODE_DISABLE : STR_CHEAT_SANDBOX_MODE; + w->widgets[WIDX_FREEZE_CLIMATE].image = gCheatsFreezeClimate ? STR_CHEAT_UNFREEZE_CLIMATE : STR_CHEAT_FREEZE_CLIMATE; + widget_set_checkbox_value(w, WIDX_NEVERENDING_MARKETING, gCheatsNeverendingMarketing); break; case WINDOW_CHEATS_PAGE_RIDES: RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 255; - widget_set_checkbox_value(w, WIDX_FAST_LIFT_HILL, gConfigCheat.fast_lift_hill); - widget_set_checkbox_value(w, WIDX_DISABLE_BRAKES_FAILURE, gConfigCheat.disable_brakes_failure); - widget_set_checkbox_value(w, WIDX_DISABLE_ALL_BREAKDOWNS, gConfigCheat.disable_all_breakdowns); - widget_set_checkbox_value(w, WIDX_BUILD_IN_PAUSE_MODE, gConfigCheat.build_in_pause_mode); + widget_set_checkbox_value(w, WIDX_FAST_LIFT_HILL, gCheatsFastLiftHill); + widget_set_checkbox_value(w, WIDX_DISABLE_BRAKES_FAILURE, gCheatsDisableBrakesFailure); + widget_set_checkbox_value(w, WIDX_DISABLE_ALL_BREAKDOWNS, gCheatsDisableAllBreakdowns); + widget_set_checkbox_value(w, WIDX_BUILD_IN_PAUSE_MODE, gCheatsBuildInPauseMode); widget_set_checkbox_value(w, WIDX_SHOW_ALL_OPERATING_MODES, gCheatsShowAllOperatingModes); widget_set_checkbox_value(w, WIDX_SHOW_VEHICLES_FROM_OTHER_TRACK_TYPES, gCheatsShowVehiclesFromOtherTrackTypes); break; @@ -1116,6 +791,11 @@ static void window_cheats_invalidate(rct_window *w) // Set title w->widgets[WIDX_TITLE].image = window_cheats_page_titles[w->page]; + + + // Current weather + int currentWeather = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_WEATHER, uint8); + window_cheats_misc_widgets[WIDX_WEATHER].image = STR_SUNNY + currentWeather; } static void window_cheats_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -1124,12 +804,13 @@ static void window_cheats_paint(rct_window *w, rct_drawpixelinfo *dpi) window_cheats_draw_tab_images(dpi, w); if (w->page == WINDOW_CHEATS_PAGE_MONEY){ - RCT2_GLOBAL(0x0013CE952, money32) = CHEATS_MONEY_INCREMENT; - gfx_draw_string_left(dpi, STR_CHEAT_TIP_5K_MONEY, (void*)0x0013CE952, 0, w->x + XPL(0) + TXTO, w->y + YPL(0) + TXTO); - gfx_draw_string_left(dpi, STR_CHEAT_TIP_CLEAR_LOAN, NULL, 0, w->x + XPL(0) + TXTO, w->y + YPL(4) + TXTO); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = CHEATS_MONEY_INCREMENT; + gfx_draw_string_left(dpi, STR_CHEAT_TIP_5K_MONEY, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + XPL(0) + TXTO, w->y + YPL(0) + TXTO); + gfx_draw_string_left(dpi, STR_CHEAT_TIP_CLEAR_LOAN, NULL, 0, w->x + XPL(0) + TXTO, w->y + YPL(2) + TXTO); } else if(w->page == WINDOW_CHEATS_PAGE_MISC){ gfx_draw_string_left(dpi, STR_CHEAT_STAFF_SPEED, NULL, 0, w->x + XPL(0) + TXTO, w->y + YPL(15) + TXTO); + gfx_draw_string_left(dpi, STR_FORCE_WEATHER, NULL, 0, w->x + XPL(0) + TXTO, w->y + YPL(9) + TXTO); gfx_draw_string_right(dpi, 5182, &park_rating_spinner_value, w->colours[2], w->x + WPL(1) - 10 - TXTO, w->y + YPL(4) + TXTO); } else if (w->page == WINDOW_CHEATS_PAGE_GUESTS){ @@ -1166,7 +847,7 @@ static void window_cheats_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) // Misc tab if (!(w->disabled_widgets & (1 << WIDX_TAB_3))) { - sprite_idx = STR_TAB_PARK; + sprite_idx = SPR_TAB_PARK; gfx_draw_sprite(dpi, sprite_idx, w->x + w->widgets[WIDX_TAB_3].left, w->y + w->widgets[WIDX_TAB_3].top, 0); } diff --git a/src/windows/clear_scenery.c b/src/windows/clear_scenery.c index e6ef342c3d..ebc5251efb 100644 --- a/src/windows/clear_scenery.c +++ b/src/windows/clear_scenery.c @@ -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; diff --git a/src/windows/demolish_ride_prompt.c b/src/windows/demolish_ride_prompt.c index 0f95dd8269..892d3d12e0 100644 --- a/src/windows/demolish_ride_prompt.c +++ b/src/windows/demolish_ride_prompt.c @@ -134,13 +134,13 @@ static void window_ride_demolish_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); - rct_ride* ride = GET_RIDE(w->number); + rct_ride* ride = get_ride(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = ride->name; - RCT2_GLOBAL(0x13CE954, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; int x = w->x + WW / 2; int y = w->y + (WH / 2) - 3; - gfx_draw_string_centred_wrapped(dpi, (void*)0x13CE952, x, y, WW - 4, STR_DEMOLISH_RIDE_ID, 0); + gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, WW - 4, STR_DEMOLISH_RIDE_ID, 0); } diff --git a/src/windows/dropdown.c b/src/windows/dropdown.c index 2b471441e4..0c4dd532a5 100644 --- a/src/windows/dropdown.c +++ b/src/windows/dropdown.c @@ -56,12 +56,18 @@ uint64 gDropdownItemsDisabled; bool gDropdownIsColour; int gDropdownLastColourHover; int gDropdownHighlightedIndex; +int gDropdownDefaultIndex; bool dropdown_is_checked(int index) { return gDropdownItemsChecked & (1ULL << index); } +bool dropdown_is_disabled(int index) +{ + return gDropdownItemsDisabled & (1ULL << index); +} + void dropdown_set_checked(int index, bool value) { if (value) { @@ -160,9 +166,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 +210,8 @@ 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; + gDropdownDefaultIndex = -1; + gInputState = INPUT_STATE_DROPDOWN_ACTIVE; } /** @@ -230,9 +237,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,11 +281,9 @@ 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; - - // Copy the following properties until all use of it is decompiled - gDropdownHighlightedIndex = gDropdownHighlightedIndex; gDropdownIsColour = false; + gDropdownDefaultIndex = -1; + gInputState = INPUT_STATE_DROPDOWN_ACTIVE; } void window_dropdown_close() @@ -292,7 +297,7 @@ static void window_dropdown_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); - gDropdownHighlightedIndex = gDropdownHighlightedIndex; + int highlightedIndex = gDropdownHighlightedIndex; for (int i = 0; i < gDropdownNumItems; i++) { cell_x = i % _dropdown_num_columns; cell_y = i / _dropdown_num_columns; @@ -313,7 +318,7 @@ static void window_dropdown_paint(rct_window *w, rct_drawpixelinfo *dpi) } } else { // - if (i == gDropdownHighlightedIndex) { + if (i == highlightedIndex) { l = w->x + 2 + (cell_x * _dropdown_item_width); t = w->y + 2 + (cell_y * _dropdown_item_height); r = l + _dropdown_item_width - 1; @@ -324,8 +329,8 @@ 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]); - if (item == (uint16)-2 && gDropdownHighlightedIndex == i) + image = (uint32)gDropdownItemsArgs[i]; + if (item == (uint16)-2 && highlightedIndex == i) image++; gfx_draw_sprite( @@ -344,9 +349,9 @@ static void window_dropdown_paint(rct_window *w, rct_drawpixelinfo *dpi) // Calculate colour colour = w->colours[0] & 0x7F; - if (i == gDropdownHighlightedIndex) + if (i == highlightedIndex) colour = 2; - if (gDropdownItemsDisabled & (1ULL << i)) + if (dropdown_is_disabled(i)) if (i < 64) colour = (w->colours[0] & 0x7F) | 0x40; @@ -364,7 +369,8 @@ static void window_dropdown_paint(rct_window *w, rct_drawpixelinfo *dpi) } } -/* New function based on 6e914e +/** + * New function based on 6e914e * returns -1 if index is invalid */ int dropdown_index_from_point(int x, int y, rct_window *w) @@ -395,6 +401,7 @@ void window_dropdown_show_colour(rct_window *w, rct_widget *widget, uint8 dropdo } /** + * * rct2: 0x006ED43D * al: dropdown colour * ah: selected colour @@ -413,11 +420,12 @@ void window_dropdown_show_colour_available(rct_window *w, rct_widget *widget, ui if (availableColours & (1 << i)) numItems++; + int defaultIndex = -1; // Set items for (i = 0; i < 32; i++) { if (availableColours & (1 << i)) { if (selectedColour == i) - gDropdownHighlightedIndex = i; + defaultIndex = i; gDropdownItemsFormat[i] = 0xFFFE; gDropdownItemsArgs[i] = ((uint64)i << 32) | (0x20000000 | (i << 19) | 5059); @@ -439,4 +447,5 @@ void window_dropdown_show_colour_available(rct_window *w, rct_widget *widget, ui gDropdownIsColour = true; gDropdownLastColourHover = -1; + gDropdownDefaultIndex = defaultIndex; } diff --git a/src/windows/dropdown.h b/src/windows/dropdown.h index 43dcc4cf0d..8262c8eeb4 100644 --- a/src/windows/dropdown.h +++ b/src/windows/dropdown.h @@ -40,7 +40,10 @@ extern uint64 gDropdownItemsDisabled; extern bool gDropdownIsColour; extern int gDropdownLastColourHover; extern int gDropdownHighlightedIndex; +extern int gDropdownDefaultIndex; +bool dropdown_is_checked(int index); +bool dropdown_is_disabled(int index); void dropdown_set_checked(int index, bool value); void dropdown_set_disabled(int index, bool value); diff --git a/src/windows/editor_bottom_toolbar.c b/src/windows/editor_bottom_toolbar.c index 8e466117f9..ec420f64d7 100644 --- a/src/windows/editor_bottom_toolbar.c +++ b/src/windows/editor_bottom_toolbar.c @@ -22,6 +22,7 @@ #include "../audio/audio.h" #include "../config.h" #include "../editor.h" +#include "../input.h" #include "../scenario.h" #include "../sprites.h" #include "../localisation/localisation.h" @@ -317,34 +318,6 @@ void window_editor_bottom_toolbar_jump_forward_to_objective_selection() { gfx_invalidate_screen(); } -/** - * - * rct2: 0x00675181 - */ -static int show_save_scenario_dialog(char *resultPath) -{ - rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; - - int result; - char title[256]; - char filename[MAX_PATH]; - char filterName[256]; - - - format_string(title, STR_SAVE_SCENARIO, NULL); - subsitute_path(filename, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIOS_PATH, char), s6Info->name); - strcat(filename, ".SC6"); - format_string(filterName, STR_RCT2_SCENARIO_FILE, NULL); - - audio_pause_sounds(); - result = platform_open_common_file_dialog(0, title, filename, "*.SC6", filterName); - audio_unpause_sounds(); - - if (result) - safe_strncpy(resultPath, filename, MAX_PATH); - return result; -} - /** * * rct2: 0x0066F7C0 @@ -352,8 +325,6 @@ static int show_save_scenario_dialog(char *resultPath) void window_editor_bottom_toolbar_jump_forward_to_save_scenario() { rct_s6_info *s6Info = (rct_s6_info*)0x0141F570; - int parkFlagsBackup, success; - char path[256]; if (!scenario_prepare_for_save()) { window_error_open(STR_UNABLE_TO_SAVE_SCENARIO_FILE, RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id)); @@ -362,37 +333,7 @@ void window_editor_bottom_toolbar_jump_forward_to_save_scenario() } window_close_all(); - window_loadsave_open(LOADSAVETYPE_SAVE | LOADSAVETYPE_SCENARIO, s6Info->name); - return; - - if (!show_save_scenario_dialog(path)) { - gfx_invalidate_screen(); - return; - } - - // - s6Info->editor_step = 255; - - // Ensure path has .SC6 extension - path_set_extension(path, ".SC6"); - - // Save the scenario - parkFlagsBackup = RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32); - RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) &= ~PARK_FLAGS_18; - SDL_RWops* rw = SDL_RWFromFile(path, "wb+"); - if (rw != NULL) { - success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 3 : 2); - SDL_RWclose(rw); - } - RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) = parkFlagsBackup; - - if (success) { - title_load(); - } else { - window_error_open(STR_SCENARIO_SAVE_FAILED, -1); - s6Info->editor_step = EDITOR_STEP_OBJECTIVE_SELECTION; - } } /** @@ -535,10 +476,11 @@ void window_editor_bottom_toolbar_paint(rct_window *w, rct_drawpixelinfo *dpi) window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].top + 6 + w->y, 0); int textColour = w->colours[1] & 0x7F; - - if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, uint8) == WC_BOTTOM_TOOLBAR && - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint8) == WIDX_PREVIOUS_STEP_BUTTON) + if (gHoverWidget.window_classification == WC_BOTTOM_TOOLBAR && + gHoverWidget.widget_index == WIDX_PREVIOUS_STEP_BUTTON + ) { textColour = 2; + } short textX = (window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].left + 30 + window_editor_bottom_toolbar_widgets[WIDX_PREVIOUS_IMAGE].right) / 2 + w->x; @@ -559,9 +501,11 @@ void window_editor_bottom_toolbar_paint(rct_window *w, rct_drawpixelinfo *dpi) int textColour = w->colours[1] & 0x7F; - if (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, uint8) == WC_BOTTOM_TOOLBAR && - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, uint8) == WIDX_NEXT_STEP_BUTTON) + if (gHoverWidget.window_classification == WC_BOTTOM_TOOLBAR && + gHoverWidget.widget_index == WIDX_NEXT_STEP_BUTTON + ) { textColour = 2; + } short textX = (window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].left + window_editor_bottom_toolbar_widgets[WIDX_NEXT_IMAGE].right - 30) / 2 + w->x; diff --git a/src/windows/editor_inventions_list.c b/src/windows/editor_inventions_list.c index a8396b77d1..c35aee7efd 100644 --- a/src/windows/editor_inventions_list.c +++ b/src/windows/editor_inventions_list.c @@ -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->var_494)) - static void window_editor_inventions_list_drag_open(rct_research_item *researchItem); static void move_research_item(rct_research_item *beforeItem); @@ -165,7 +163,9 @@ static int research_item_is_always_researched(rct_research_item *researchItem) return (researchItem->entryIndex & (RESEARCH_ENTRY_FLAG_RIDE_ALWAYS_RESEARCHED | RESEARCH_ENTRY_FLAG_SCENERY_SET_ALWAYS_RESEARCHED)) != 0; } -/* rct2: 0x0068596F +/** + * + * rct2: 0x0068596F * Sets rides that are in use to be always researched */ static void research_rides_setup(){ @@ -179,7 +179,7 @@ static void research_rides_setup(){ // Set research required for rides in use for (uint16 rideIndex = 0; rideIndex < 255; rideIndex++){ - rct_ride* ride = &g_ride_list[rideIndex]; + rct_ride* ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_NULL)continue; RCT2_ADDRESS(0x0098DA38, uint8*)[OBJECT_TYPE_RIDE][ride->subtype] |= 1; } @@ -195,13 +195,13 @@ static void research_rides_setup(){ uint8 ride_base_type = (research->entryIndex >> 8) & 0xFF; uint8 object_index = research->entryIndex & 0xFF; - rct_ride_type* ride_entry = GET_RIDE_ENTRY(object_index); + rct_ride_entry* ride_entry = get_ride_entry(object_index); uint8 master_found = 0; if (!(ride_entry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE)){ for (uint8 rideType = 0; rideType < object_entry_group_counts[OBJECT_TYPE_RIDE]; rideType++){ - rct_ride_type* master_ride = GET_RIDE_ENTRY(rideType); + rct_ride_entry* master_ride = get_ride_entry(rideType); if (master_ride == NULL || (uint32)master_ride == 0xFFFFFFFF) continue; @@ -240,7 +240,9 @@ static void research_rides_setup(){ } } -/* rct2: 0x0068590C +/** + * + * rct2: 0x0068590C * Sets the critical scenery sets to always researched */ static void research_scenery_sets_setup(){ @@ -283,8 +285,9 @@ static void research_always_researched_setup() /** * * rct2: 0x00685A79 + * Do not use the research list outside of the inventions list window with the flags */ -static void sub_685A79() +static void research_remove_flags() { for (rct_research_item* research = gResearchItems; research->entryIndex != RESEARCHED_ITEMS_END_2; @@ -303,7 +306,7 @@ static void sub_685A79() */ static rct_string_id research_item_get_name(uint32 researchItem) { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_scenery_set_entry *sceneryEntry; if (researchItem < 0x10000) { @@ -314,8 +317,8 @@ static rct_string_id research_item_get_name(uint32 researchItem) return sceneryEntry->name; } - rideEntry = GET_RIDE_ENTRY(researchItem & 0xFF); - if (rideEntry == NULL || rideEntry == (rct_ride_type*)0xFFFFFFFF) + rideEntry = get_ride_entry(researchItem & 0xFF); + if (rideEntry == NULL || rideEntry == (rct_ride_entry*)0xFFFFFFFF) return 0; if (rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) @@ -433,7 +436,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); } } @@ -500,7 +503,7 @@ static rct_research_item *get_research_item_at(int x, int y) widgetIndex = window_find_widget_from_point(w, x, y); widget = &w->widgets[widgetIndex]; if (widgetIndex == WIDX_PRE_RESEARCHED_SCROLL || widgetIndex == WIDX_RESEARCH_ORDER_SCROLL) { - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DOWN_WIDGETINDEX, uint32) = widgetIndex; + gPressedWidget.widget_index = widgetIndex; widget_scroll_get_part(w, widget, x, y, &outX, &outY, &outScrollArea, &outScrollId); if (outScrollArea == SCROLL_PART_VIEW) { outScrollId = outScrollId == 0 ? 0 : 1; @@ -545,7 +548,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; } @@ -554,15 +557,15 @@ void window_editor_inventions_list_open() * rct2: 0x006853D2 */ static void window_editor_inventions_list_close(rct_window *w) -{ +{ + research_remove_flags(); + // When used in-game (as a cheat) if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_EDITOR)) { gSilentResearch = true; sub_684AC3(); gSilentResearch = false; } - - sub_685A79(); } /** @@ -664,8 +667,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); } } @@ -766,7 +769,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; @@ -785,7 +788,7 @@ static void window_editor_inventions_list_paint(rct_window *w, rct_drawpixelinfo if (chunk == NULL || chunk == (void*)0xFFFFFFFF) return; - object_paint(objectEntryType, 3, objectEntryType, x, y, 0, (int)dpi, (int)chunk); + object_paint(objectEntryType, chunk, dpi, x, y); // Item name x = w->x + ((widget->left + widget->right) / 2) + 1; @@ -838,7 +841,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; @@ -908,8 +911,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, @@ -918,9 +921,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); } /** @@ -935,8 +936,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); } } diff --git a/src/windows/editor_main.c b/src/windows/editor_main.c index dcdd7d1830..f469b2420e 100644 --- a/src/windows/editor_main.c +++ b/src/windows/editor_main.c @@ -97,4 +97,4 @@ void window_editor_main_open() static void window_editor_main_paint(rct_window *w, rct_drawpixelinfo *dpi) { viewport_render(dpi, w->viewport, dpi->x, dpi->y, dpi->x + dpi->width, dpi->y + dpi->height); -} \ No newline at end of file +} diff --git a/src/windows/editor_object_selection.c b/src/windows/editor_object_selection.c index ffe8457740..2baec032a9 100644 --- a/src/windows/editor_object_selection.c +++ b/src/windows/editor_object_selection.c @@ -21,6 +21,7 @@ #include "../addresses.h" #include "../audio/audio.h" +#include "../config.h" #include "../game.h" #include "../interface/themes.h" #include "../interface/widget.h" @@ -33,10 +34,10 @@ #include "../ride/ride_data.h" #include "../ride/track.h" #include "../scenario.h" +#include "../util/util.h" +#include "../world/footpath.h" #include "dropdown.h" #include "error.h" -#include "../util/util.h" - enum { FILTER_RCT2 = (1 << 0), @@ -320,14 +321,14 @@ static int visible_list_sort_ride_type(const void *rawA, const void *rawB) static void visible_list_refresh(rct_window *w) { - int numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32); + int numObjects = gInstalledObjectsCount; visible_list_dispose(); _listItems = malloc(numObjects * sizeof(list_item)); _numListItems = 0; list_item *currentListItem = &_listItems[0]; - rct_object_entry *entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry *entry = gInstalledObjects; uint8 *itemFlags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); for (int i = 0; i < numObjects; i++) { rct_object_filters *filter = get_object_filter(i); @@ -419,7 +420,7 @@ void window_editor_object_selection_open() window->var_4AE = 0; window->selected_tab = 0; window->selected_list_item = -1; - window->var_494 = 0xFFFFFFFF; + window->object_entry = (rct_object_entry *) 0xFFFFFFFF; window->min_width = 600; window->min_height = 400; window->max_width = 1200; @@ -428,14 +429,17 @@ void window_editor_object_selection_open() visible_list_refresh(window); } -/* rct2: 0x006ABCD1 */ +/** + * + * rct2: 0x006ABCD1 + */ static void setup_track_manager_objects(){ uint8 ride_list[128] = { 0 }; uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; uint16 num_objects = 0; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ uint8 object_type = installedObject->flags & 0xF; if (object_type == OBJECT_TYPE_RIDE){ *selection_flags |= OBJECT_SELECTION_FLAG_6; @@ -467,8 +471,7 @@ static void setup_track_manager_objects(){ if (ride_type == 0xFF) continue; - if (!(RCT2_ADDRESS(RCT2_ADDRESS_RIDE_FLAGS, uint32)[ride_type * 2] & - RIDE_TYPE_FLAG_HAS_TRACK)) + if (!ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_TRACK)) continue; if (pos[3] & (1 << 0)){ @@ -493,13 +496,16 @@ static void setup_track_manager_objects(){ RCT2_GLOBAL(0x00F43412, uint16) = num_objects; } -/* rct2: 0x006ABC1E */ +/** + * + * rct2: 0x006ABC1E + */ static void setup_track_designer_objects(){ uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; uint16 num_objects = 0; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ uint8 object_type = installedObject->flags & 0xF; if (object_type == OBJECT_TYPE_RIDE){ *selection_flags |= OBJECT_SELECTION_FLAG_6; @@ -547,7 +553,10 @@ static void setup_track_designer_objects(){ RCT2_GLOBAL(0x00F43412, uint16) = num_objects; } -/* rct2: 0x006AA82B */ +/** + * + * rct2: 0x006AA82B + */ static void setup_in_use_selection_flags(){ for (uint8 object_type = 0; object_type < 11; object_type++){ @@ -568,7 +577,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)) { @@ -582,10 +590,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: @@ -623,7 +630,7 @@ static void setup_in_use_selection_flags(){ } while (map_element_iterator_next(&iter)); for (uint8 ride_index = 0; ride_index < 0xFF; ride_index++){ - rct_ride* ride = GET_RIDE(ride_index); + rct_ride* ride = get_ride(ride_index); if (ride->type == RIDE_TYPE_NULL) continue; @@ -632,9 +639,9 @@ static void setup_in_use_selection_flags(){ } uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ *selection_flags &= ~OBJECT_SELECTION_FLAG_IN_USE; uint8 entry_type, entry_index; @@ -653,11 +660,14 @@ static void setup_in_use_selection_flags(){ } } -/* rct2: 0x006AB211 */ +/** + * + * rct2: 0x006AB211 + */ static int sub_6AB211(){ - uint32 total_objects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); + uint32 total_objects = gInstalledObjectsCount; - RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*) = rct2_malloc(total_objects); + RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*) = malloc(total_objects); if (RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*) == NULL){ log_error("Failed to allocate memory for object flag list."); @@ -670,9 +680,9 @@ static int sub_6AB211(){ RCT2_ADDRESS(0x00F433E1, uint16)[object_type] = 0; } - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ uint8 object_type = installedObject->flags & 0xF; RCT2_ADDRESS(0x00F433E1, uint16)[object_type]++; @@ -703,23 +713,26 @@ static int sub_6AB211(){ return 1; } -/* rct2: 0x006AB316 */ -static void editor_object_flags_free(){ - if (RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*) == NULL){ - return; - } - rct2_free(RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*)); - RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*) = NULL; +/** + * + * rct2: 0x006AB316 + */ +static void editor_object_flags_free() +{ + SafeFree(RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*)); } -/* rct2: 0x00685791 */ +/** + * + * rct2: 0x00685791 + */ void remove_selected_objects_from_research(rct_object_entry* installedObject){ uint8 entry_type, entry_index; if (!find_object_in_entry_group(installedObject, &entry_type, &entry_index)) return; if (entry_type == OBJECT_TYPE_RIDE){ - rct_ride_type* rideEntry = (rct_ride_type*)object_entry_groups[entry_type].chunks[entry_index]; + rct_ride_entry* rideEntry = (rct_ride_entry*)object_entry_groups[entry_type].chunks[entry_index]; research_remove(entry_index | rideEntry->ride_type[0] << 8 | 0x10000); research_remove(entry_index | rideEntry->ride_type[1] << 8 | 0x10000); research_remove(entry_index | rideEntry->ride_type[2] << 8 | 0x10000); @@ -729,15 +742,18 @@ void remove_selected_objects_from_research(rct_object_entry* installedObject){ } } -/* rct2: 0x006ABB66 */ +/** + * + * rct2: 0x006ABB66 + */ void unload_unselected_objects(){ uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ if (!(*selection_flags & OBJECT_SELECTION_FLAG_SELECTED)){ remove_selected_objects_from_research(installedObject); - object_unload(installedObject); + object_unload_chunk(installedObject); } selection_flags++; installedObject = object_get_next(installedObject); @@ -761,7 +777,6 @@ static void window_editor_object_selection_close(rct_window *w) if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_EDITOR) { research_populate_list_random(); - research_remove_non_separate_vehicle_types(); } else { // Used for in-game object selection cheat @@ -771,6 +786,7 @@ static void window_editor_object_selection_close(rct_window *w) sub_684AC3(); gSilentResearch = false; } + research_remove_non_separate_vehicle_types(); window_new_ride_init_vars(); visible_list_dispose(); @@ -815,7 +831,7 @@ static void window_editor_object_selection_mouseup(rct_window *w, int widgetInde visible_list_refresh(w); w->selected_list_item = -1; - w->var_494 = 0xFFFFFFFF; + w->object_entry = (rct_object_entry *) 0xFFFFFFFF; w->scrolls[0].v_top = 0; object_free_scenario_text(); window_invalidate(w); @@ -835,7 +851,7 @@ static void window_editor_object_selection_mouseup(rct_window *w, int widgetInde visible_list_refresh(w); w->selected_list_item = -1; - w->var_494 = 0xFFFFFFFF; + w->object_entry = (rct_object_entry *) 0xFFFFFFFF; w->scrolls[0].v_top = 0; object_free_scenario_text(); window_invalidate(w); @@ -1030,7 +1046,7 @@ static void window_editor_object_selection_scroll_mouseover(rct_window *w, int s return; w->selected_list_item = selectedObject; - w->var_494 = (uint32)installedEntry; + w->object_entry = installedEntry; object_free_scenario_text(); if (selectedObject != -1) object_get_scenario_text(installedEntry); @@ -1107,15 +1123,12 @@ static void window_editor_object_selection_invalidate(rct_window *w) RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, rct_string_id) = STR_OBJECT_SELECTION_RIDE_VEHICLES_ATTRACTIONS + w->selected_tab; if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) { w->widgets[WIDX_TITLE].image = STR_TRACK_DESIGNS_MANAGER_SELECT_RIDE_TYPE; - w->widgets[WIDX_CLOSE].type = WWT_EMPTY; w->widgets[WIDX_INSTALL_TRACK].type = WWT_DROPDOWN_BUTTON; } else if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) { w->widgets[WIDX_TITLE].image = STR_ROLLER_COASTER_DESIGNER_SELECT_RIDE_TYPES_VEHICLES; - w->widgets[WIDX_CLOSE].type = WWT_CLOSEBOX; w->widgets[WIDX_INSTALL_TRACK].type = WWT_EMPTY; } else { w->widgets[WIDX_TITLE].image = STR_OBJECT_SELECTION; - w->widgets[WIDX_CLOSE].type = WWT_CLOSEBOX; w->widgets[WIDX_INSTALL_TRACK].type = WWT_EMPTY; } @@ -1324,14 +1337,14 @@ 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->var_494; + highlightedEntry = w->object_entry; type = highlightedEntry->flags & 0x0F; // Draw preview widget = &w->widgets[WIDX_PREVIEW]; x = w->x + (widget->left + widget->right) / 2 + 1; y = w->y + (widget->top + widget->bottom) / 2 + 1; - object_paint(type, 3, type, x, y, 0, (int)dpi, (int)stex_entry); + object_paint(type, stex_entry, dpi, x, y); // Draw name of object x = w->x + (widget->left + widget->right) / 2 + 1; @@ -1377,9 +1390,17 @@ static void window_editor_object_selection_paint(rct_window *w, rct_drawpixelinf gfx_draw_string_centred_clipped(dpi, stringId, NULL, 0, x, y, width); // Draw description of object - x = w->x + w->widgets[WIDX_LIST].right + 4; - y += 15; - object_paint(type, 259, type, x, y, (int)w, (int)dpi, (int)stex_entry); + stringId = object_desc(type, stex_entry); + if (stringId != STR_NONE) { + x = w->x + w->widgets[WIDX_LIST].right + 4; + y += 15; + int width = w->x + w->width - x - 4; + if (type == OBJECT_TYPE_SCENARIO_TEXT) { + gfx_draw_string_left_wrapped(dpi, &stringId, x, y, width, 3168, 0); + } else { + gfx_draw_string_left_wrapped(dpi, &stringId, x, y + 5, width, 1191, 0); + } + } // Draw object source source = (highlightedEntry->flags & 0xF0) >> 4; @@ -1395,7 +1416,7 @@ static void window_editor_object_selection_paint(rct_window *w, rct_drawpixelinf if (w->selected_tab == WINDOW_OBJECT_SELECTION_PAGE_RIDE_VEHICLES_ATTRACTIONS) { y = w->y + w->height - 3 - 12 - 14 - 14; - rct_ride_type *rideType = (rct_ride_type*)stex_entry; + rct_ride_entry *rideType = (rct_ride_entry*)stex_entry; for (int i = 0; i < 3; i++) { if (rideType->ride_type[i] == 255) continue; @@ -1440,7 +1461,7 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi // Highlight background colour = 142; - if (listItem->entry == (rct_object_entry*)w->var_494 && !(*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; } @@ -1458,7 +1479,7 @@ static void window_editor_object_selection_scrollpaint(rct_window *w, rct_drawpi x = RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER ? 0 : 15; - char *bufferWithColour = (char*)0x0141ED68; + char *bufferWithColour = (char*)RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER; char *buffer = utf8_write_codepoint(bufferWithColour, colour); if (*listItem->flags & OBJECT_SELECTION_FLAG_6) { colour = w->colours[1] & 0x7F; @@ -1497,7 +1518,7 @@ static void window_editor_object_set_page(rct_window *w, int page) w->selected_tab = page; w->selected_list_item = -1; - w->var_494 = 0xFFFFFFFF; + w->object_entry = (rct_object_entry *)0xFFFFFFFF; w->scrolls[0].v_top = 0; object_free_scenario_text(); @@ -1548,7 +1569,10 @@ static void window_editor_object_selection_select_required_objects() window_editor_object_selection_select_object(0, 0xF, &RequiredSelectedObjects[i]); } -/* rct2: 0x006AA770 */ +/** + * + * rct2: 0x006AA770 + */ void reset_selected_object_count_and_size(){ for (uint8 object_type = 0; object_type < 11; object_type++){ RCT2_ADDRESS(0x00F433F7, uint16)[object_type] = 0; @@ -1557,9 +1581,9 @@ void reset_selected_object_count_and_size(){ uint32 total_object_size = 0; uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ uint8 object_type = installedObject->flags & 0xF; if (*selection_flags & OBJECT_SELECTION_FLAG_SELECTED){ @@ -1587,12 +1611,15 @@ void reset_selected_object_count_and_size(){ RCT2_GLOBAL(RCT2_ADDRESS_SELECTED_OBJECTS_FILE_SIZE, uint32) = total_object_size; } -/* rct2: 0x006AB863 */ +/** + * + * rct2: 0x006AB863 + */ void set_required_object_flags(rct_object_entry* required_object){ uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ if (object_entry_compare(required_object, installedObject)){ *selection_flags |= OBJECT_SELECTION_FLAG_REQUIRED; @@ -1627,18 +1654,21 @@ void set_required_object_flags(rct_object_entry* required_object){ } } -/* rct2: 0x006AB923 */ +/** + * + * rct2: 0x006AB923 + */ void reset_required_object_flags(){ uint8* selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ *selection_flags &= ~OBJECT_SELECTION_FLAG_REQUIRED; selection_flags++; } selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ if (*selection_flags & OBJECT_SELECTION_FLAG_SELECTED){ uint8* pos = (uint8*)installedObject; // Skip sizeof(rct_object_entry) @@ -1671,7 +1701,7 @@ void reset_required_object_flags(){ } } -/* +/** * Master objects are objects that are not * optional / required dependants of an * object. @@ -1708,10 +1738,10 @@ static int window_editor_object_selection_select_object(uint8 bh, int flags, rct selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); // There was previously a check to make sure the object list had an item - rct_object_entry* installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry* installedObject = gInstalledObjects; uint8 not_found = 1; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i){ + for (int i = gInstalledObjectsCount; i > 0; --i){ if (object_entry_compare(entry, installedObject)){ not_found = 0; break; @@ -1851,7 +1881,7 @@ static int window_editor_object_selection_select_object(uint8 bh, int flags, rct } if (bh != 0 && !(flags&(1 << 1))){ - uint32* arguments = RCT2_ADDRESS(0x0013CE952, uint32); + uint32* arguments = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32); object_create_identifier_name((char*)0x009BC95A, installedObject); *arguments = (uint32)0x009BC95A; set_object_selection_error(bh, 3172); @@ -1885,7 +1915,7 @@ static int window_editor_object_selection_select_object(uint8 bh, int flags, rct * Returns the position in the list. * Object_selection_flags, installed_entry also populated * - * rct2: 0x006AA703 + * rct2: 0x006AA703 */ static int get_object_from_object_selection(uint8 object_type, int y, uint8 *object_selection_flags, rct_object_entry **installed_entry) { @@ -1926,7 +1956,7 @@ static void window_editor_object_selection_manage_tracks() RCT2_GLOBAL(0xF44157, uint8) = entry_index; - rct_ride_type* ride_entry = GET_RIDE_ENTRY(entry_index); + rct_ride_entry* ride_entry = get_ride_entry(entry_index); uint8* ride_type_array = &ride_entry->ride_type[0]; int ride_type; @@ -1945,17 +1975,17 @@ static void window_editor_object_selection_manage_tracks() static void editor_load_selected_objects() { uint8 *selection_flags = RCT2_GLOBAL(RCT2_ADDRESS_EDITOR_OBJECT_FLAGS_LIST, uint8*); - rct_object_entry *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry *installed_entry = gInstalledObjects; - if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) == 0) + if (gInstalledObjectsCount == 0) return; - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i != 0; i--, selection_flags++) { + for (int i = gInstalledObjectsCount; i != 0; i--, selection_flags++) { if (*selection_flags & OBJECT_SELECTION_FLAG_SELECTED) { uint8 entry_index, entry_type; if (!find_object_in_entry_group(installed_entry, &entry_type, &entry_index)){ int chunk_size; - if (!object_load(-1, installed_entry, &chunk_size)) { + if (!object_load_chunk(-1, installed_entry, &chunk_size)) { log_error("Failed to load entry %.8s", installed_entry->name); } } @@ -1999,7 +2029,7 @@ static void window_editor_object_selection_textinput(rct_window *w, int widgetIn } else { memset(_filter_string, 0, sizeof(_filter_string)); - safe_strncpy(_filter_string, text, sizeof(_filter_string)); + safe_strcpy(_filter_string, text, sizeof(_filter_string)); } filter_update_counts(); @@ -2028,9 +2058,9 @@ static bool filter_string(rct_object_entry *entry, rct_object_filters *filter) char name_lower[MAX_PATH]; char type_lower[MAX_PATH]; char filter_lower[sizeof(_filter_string)]; - safe_strncpy(name_lower, name, MAX_PATH); - safe_strncpy(type_lower, ride_type, MAX_PATH); - safe_strncpy(filter_lower, _filter_string, sizeof(_filter_string)); + safe_strcpy(name_lower, name, MAX_PATH); + safe_strcpy(type_lower, ride_type, MAX_PATH); + safe_strcpy(filter_lower, _filter_string, sizeof(_filter_string)); // Make use of lowercase characters only for (int i = 0; name_lower[i] != '\0'; i++) @@ -2074,14 +2104,14 @@ static bool filter_chunks(rct_object_entry *entry, rct_object_filters *filter) static void filter_update_counts() { if (!_FILTER_ALL || strlen(_filter_string) > 0) { - rct_object_entry *installed_entry = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*); + rct_object_entry *installed_entry = gInstalledObjects; rct_object_filters *filter; uint8 type; for (int i = 0; i < 11; i++) { _filter_object_counts[i] = 0; } - for (int i = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32); i > 0; --i) { - filter = get_object_filter(RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, uint32) - i); + for (int i = gInstalledObjectsCount; i > 0; --i) { + filter = get_object_filter(gInstalledObjectsCount - i); type = installed_entry->flags & 0xF; if (filter_source(installed_entry) && filter_string(installed_entry, filter) && filter_chunks(installed_entry, filter)) { _filter_object_counts[type]++; diff --git a/src/windows/editor_objective_options.c b/src/windows/editor_objective_options.c index d1cc24b9ea..ef5b8647f1 100644 --- a/src/windows/editor_objective_options.c +++ b/src/windows/editor_objective_options.c @@ -402,15 +402,15 @@ static void window_editor_objective_options_main_mouseup(rct_window *w, int widg window_editor_objective_options_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_PARK_NAME: - RCT2_GLOBAL(0x013CE962, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 16, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); window_text_input_open(w, WIDX_PARK_NAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), 0, 32); break; case WIDX_SCENARIO_NAME: - safe_strncpy((char*)0x009BC677, s6Info->name, 64); + safe_strcpy((char*)0x009BC677, s6Info->name, 64); window_text_input_open(w, WIDX_SCENARIO_NAME, STR_SCENARIO_NAME, STR_ENTER_SCENARIO_NAME, 3165, 0, 64); break; case WIDX_DETAILS: - safe_strncpy((char*)0x009BC677, s6Info->details, 256); + safe_strcpy((char*)0x009BC677, s6Info->details, 256); window_text_input_open(w, WIDX_DETAILS, 3315, 3316, 3165, 0, 256); break; } @@ -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, @@ -988,12 +988,12 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi width = w->widgets[WIDX_PARK_NAME].left - 16; if (stex != NULL) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = stex->park_name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = stex->park_name; } else { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id); } - RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x0013573D8, uint32); - gfx_draw_string_left_clipped(dpi, 3298, (void*)0x013CE952, 0, x, y, width); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + gfx_draw_string_left_clipped(dpi, 3298, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, width); // Scenario name x = w->x + 8; @@ -1001,13 +1001,13 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi width = w->widgets[WIDX_SCENARIO_NAME].left - 16; if (stex != NULL) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = stex->scenario_name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = stex->scenario_name; } else { - safe_strncpy((char*)0x009BC677, s6Info->name, 64); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = 3165; + safe_strcpy((char*)0x009BC677, s6Info->name, 64); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 3165; } - RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x0013573D8, uint32); - gfx_draw_string_left_clipped(dpi, 3300, (void*)0x013CE952, 0, x, y, width); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + gfx_draw_string_left_clipped(dpi, 3300, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, width); // Scenario details label x = w->x + 8; @@ -1020,13 +1020,13 @@ static void window_editor_objective_options_main_paint(rct_window *w, rct_drawpi width = w->widgets[WIDX_DETAILS].left - 4; if (stex != NULL) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = stex->details; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = stex->details; } else { - safe_strncpy((char*)0x009BC677, s6Info->details, 256); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = 3165; + safe_strcpy((char*)0x009BC677, s6Info->details, 256); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 3165; } - RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(0x0013573D8, uint32); - gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, width, 1191, 0); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, width, 1191, 0); // Scenario category label x = w->x + 8; @@ -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); } @@ -1118,7 +1118,7 @@ static void window_editor_objective_options_rides_scrollmousedown(rct_window *w, if (i < 0 || i >= w->no_list_items) return; - ride = GET_RIDE(i); + ride = get_ride(i); ride->lifecycle_flags ^= RIDE_LIFECYCLE_INDESTRUCTIBLE; window_invalidate(w); } @@ -1208,7 +1208,7 @@ static void window_editor_objective_options_rides_scrollpaint(rct_window *w, rct } // Checkbox mark - ride = GET_RIDE(i); + ride = get_ride(i); if (ride->lifecycle_flags & RIDE_LIFECYCLE_INDESTRUCTIBLE) { RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = stringId == 1193 ? 0xFFFE : 0xFFFF; gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1] & 0x7F, 2, y); diff --git a/src/windows/editor_scenario_options.c b/src/windows/editor_scenario_options.c index 4073444ec4..c116b31f6c 100644 --- a/src/windows/editor_scenario_options.c +++ b/src/windows/editor_scenario_options.c @@ -399,7 +399,7 @@ static void window_editor_scenario_options_draw_tab_images(rct_window *w, rct_dr // Tab 3 widget = &w->widgets[WIDX_TAB_3]; - spriteIndex = STR_TAB_PARK; + spriteIndex = SPR_TAB_PARK; gfx_draw_sprite(dpi, spriteIndex, w->x + widget->left, w->y + widget->top, 0); } @@ -444,10 +444,9 @@ static void window_editor_scenario_options_financial_mouseup(rct_window *w, int window_editor_scenario_options_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_NO_MONEY: - if(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) { + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) { RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) ^= PARK_FLAGS_NO_MONEY_SCENARIO; - } - else { + } else { RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) ^= PARK_FLAGS_NO_MONEY; // Invalidate all windows that have anything to do with finance window_invalidate_by_class(WC_RIDE); @@ -455,6 +454,7 @@ static void window_editor_scenario_options_financial_mouseup(rct_window *w, int window_invalidate_by_class(WC_PARK_INFORMATION); window_invalidate_by_class(WC_FINANCES); window_invalidate_by_class(WC_BOTTOM_TOOLBAR); + window_invalidate_by_class(WC_TOP_TOOLBAR); } window_invalidate(w); break; @@ -543,15 +543,23 @@ static void window_editor_scenario_options_financial_mousedown(int widgetIndex, break; case WIDX_INTEREST_RATE_INCREASE: if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32) < 80) { - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32)++; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32) < 0) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32) = 0; + } else { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32)++; + } } else { window_error_open(3254, STR_NONE); } window_invalidate(w); break; case WIDX_INTEREST_RATE_DECREASE: - if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32) >= 0) { - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32)--; + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32) > 0) { + if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32) > 80) { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32) = 80; + } else { + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32)--; + } } else { window_error_open(3255, STR_NONE); } @@ -676,7 +684,9 @@ static void window_editor_scenario_options_financial_paint(rct_window *w, rct_dr x = w->x + w->widgets[WIDX_INTEREST_RATE].left + 1; y = w->y + w->widgets[WIDX_INTEREST_RATE].top; - gfx_draw_string_left(dpi, 3247, &RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32), 0, x, y); + + money16 interestRate = (money16)clamp(INT16_MIN, RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, money32), INT16_MAX); + gfx_draw_string_left(dpi, 3247, &interestRate, 0, x, y); } } diff --git a/src/windows/error.c b/src/windows/error.c index bba3cbece5..ee2bf178d7 100644 --- a/src/windows/error.c +++ b/src/windows/error.c @@ -87,17 +87,17 @@ void window_error_open(rct_string_id title, rct_string_id message) window_close_by_class(WC_ERROR); dst = _window_error_text; - args = (char*)0x0013CE952; + args = (char*)RCT2_ADDRESS_COMMON_FORMAT_ARGS; // Format the title dst = utf8_write_codepoint(dst, FORMAT_BLACK); - if (title != (rct_string_id)STR_NONE) { + if (title != STR_NONE) { format_string(dst, title, args); dst = get_string_end(dst); } // Format the message - if (message != (rct_string_id)STR_NONE) { + if (message != STR_NONE) { dst = utf8_write_codepoint(dst, FORMAT_NEWLINE); format_string(dst, message, args); dst = get_string_end(dst); @@ -181,4 +181,4 @@ static void window_error_paint(rct_window *w, rct_drawpixelinfo *dpi) l = w->x + (w->width + 1) / 2 - 1; t = w->y + 1; draw_string_centred_raw(dpi, l, t, _window_error_num_lines, _window_error_text); -} \ No newline at end of file +} diff --git a/src/windows/error.h b/src/windows/error.h index 6f30cc74f2..83bdfebeef 100644 --- a/src/windows/error.h +++ b/src/windows/error.h @@ -25,4 +25,4 @@ void window_error_open(rct_string_id title, rct_string_id message); -#endif \ No newline at end of file +#endif diff --git a/src/windows/finances.c b/src/windows/finances.c index 006b9a76ff..26311266fd 100644 --- a/src/windows/finances.c +++ b/src/windows/finances.c @@ -640,7 +640,7 @@ static void window_finances_summary_invalidate(rct_window *w) } window_finances_set_pressed_tab(w); - RCT2_GLOBAL(0x013CE952 + 6, money32) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, money32) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_LOAN, money32); } /** @@ -682,12 +682,12 @@ static void window_finances_summary_paint(rct_window *w, rct_drawpixelinfo *dpi) continue; // Month heading - RCT2_GLOBAL(0x0013CE952, uint16) = STR_FINANCES_SUMMARY_MONTH_HEADING; - RCT2_GLOBAL(0x0013CE952 + 2, uint16) = monthyear; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_FINANCES_SUMMARY_MONTH_HEADING; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = monthyear; draw_string_right_underline( dpi, monthyear == currentMonthYear ? 1193 : 1191, - (void*)0x0013CE952, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x + 80, y - 1 @@ -734,12 +734,13 @@ static void window_finances_summary_paint(rct_window *w, rct_drawpixelinfo *dpi) // Loan and interest rate gfx_draw_string_left(dpi, STR_FINANCES_SUMMARY_LOAN, NULL, 0, w->x + 4, w->y + 229); - RCT2_GLOBAL(0x0013CE952, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, uint8); - gfx_draw_string_left(dpi, STR_FINANCES_SUMMARY_AT_X_PER_YEAR, (void*)0x0013CE952, 0, w->x + 156, w->y + 229); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_INTEREST_RATE, uint8); + gfx_draw_string_left(dpi, STR_FINANCES_SUMMARY_AT_X_PER_YEAR, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + 156, w->y + 229); // Current cash - RCT2_GLOBAL(0x0013CE952, money32) = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, money32)); - gfx_draw_string_left(dpi, STR_CASH_LABEL, (void*)0x0013CE952, 0, w->x + 4, w->y + 244); + money32 currentCash = DECRYPT_MONEY(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONEY_ENCRYPTED, money32)); + rct_string_id stringId = currentCash >= 0 ? STR_CASH_LABEL : STR_CASH_NEGATIVE_LABEL; + gfx_draw_string_left(dpi, stringId, ¤tCash, 0, w->x + 4, w->y + 244); // Objective related financial information if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_MONTHLY_FOOD_INCOME) { @@ -751,8 +752,8 @@ static void window_finances_summary_paint(rct_window *w, rct_drawpixelinfo *dpi) lastMonthProfit += RCT2_GLOBAL(0x013578A0, money32); lastMonthProfit += RCT2_GLOBAL(0x013578A4, money32); } - RCT2_GLOBAL(0x0013CE952, money32) = lastMonthProfit; - gfx_draw_string_left(dpi, STR_LAST_MONTH_PROFIT_FROM_FOOD_DRINK_MERCHANDISE_SALES_LABEL, (void*)0x0013CE952, 0, w->x + 280, w->y + 229); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = lastMonthProfit; + gfx_draw_string_left(dpi, STR_LAST_MONTH_PROFIT_FROM_FOOD_DRINK_MERCHANDISE_SALES_LABEL, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + 280, w->y + 229); } else { // Park value and company value gfx_draw_string_left(dpi, STR_PARK_VALUE_LABEL, (void*)RCT2_ADDRESS_CURRENT_PARK_VALUE, 0, w->x + 280, w->y + 229); @@ -1183,15 +1184,15 @@ static void window_finances_marketing_paint(rct_window *w, rct_drawpixelinfo *dp noCampaignsActive = 0; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id); - RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); // Set special parameters switch (i) { case ADVERTISING_CAMPAIGN_RIDE_FREE: case ADVERTISING_CAMPAIGN_RIDE: - ride = GET_RIDE(gMarketingCampaignRideIndex[i]); + ride = get_ride(gMarketingCampaignRideIndex[i]); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; break; case ADVERTISING_CAMPAIGN_FOOD_OR_DRINK_FREE: RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ShopItemStringIds[gMarketingCampaignRideIndex[i]].plural; @@ -1199,7 +1200,7 @@ static void window_finances_marketing_paint(rct_window *w, rct_drawpixelinfo *dp } // Advertisement - gfx_draw_string_left_clipped(dpi, STR_VOUCHERS_FOR_FREE_ENTRY_TO + i, (void*)0x013CE952, 0, x + 4, y, 296); + gfx_draw_string_left_clipped(dpi, STR_VOUCHERS_FOR_FREE_ENTRY_TO + i, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x + 4, y, 296); // Duration weeksRemaining = (gMarketingCampaignDaysLeft[i] % 128); diff --git a/src/windows/footpath.c b/src/windows/footpath.c index fb16189460..46564f0de5 100644 --- a/src/windows/footpath.c +++ b/src/windows/footpath.c @@ -146,8 +146,9 @@ static rct_window_event_list window_footpath_events = { NULL }; -money32 _window_footpath_cost; -sint8 _window_footpath_provisional_path_arrow_timer; +static money32 _window_footpath_cost; +static sint8 _window_footpath_provisional_path_arrow_timer; +static uint8 _lastUpdatedCameraRotation = UINT8_MAX; static void window_footpath_mousedown_direction(int direction); static void window_footpath_mousedown_slope(int slope); @@ -216,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(); } @@ -262,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; @@ -277,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; @@ -469,16 +470,23 @@ static void window_footpath_update(rct_window *w) widget_invalidate(w, WIDX_CONSTRUCT); window_footpath_update_provisional_path_for_bridge_mode(w); + // #2502: The camera might have changed rotation, so we need to update which directional buttons are pressed + uint8 currentRotation = get_current_rotation(); + if (_lastUpdatedCameraRotation != currentRotation) { + _lastUpdatedCameraRotation = currentRotation; + window_footpath_set_enabled_and_pressed_widgets(); + } + // 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); @@ -821,7 +829,7 @@ static void window_footpath_start_bridge_at_point(int screenX, int screenY) } /** - * Construct a piece of footpath while in bridge building mode. + * Construct a piece of footpath while in bridge building mode. * rct2: 0x006A79B7 */ static void window_footpath_construct() diff --git a/src/windows/game_bottom_toolbar.c b/src/windows/game_bottom_toolbar.c index c63c6e4599..3eb0286f4d 100644 --- a/src/windows/game_bottom_toolbar.c +++ b/src/windows/game_bottom_toolbar.c @@ -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,9 +86,11 @@ 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); -/* rct2: 0x0097BFDC */ +/** + * + * rct2: 0x0097BFDC + */ static rct_window_event_list window_game_bottom_toolbar_events = { NULL, window_game_bottom_toolbar_mouseup, @@ -217,7 +220,7 @@ static void window_game_bottom_toolbar_tooltip(rct_window* w, int widgetIndex, r switch (widgetIndex) { case WIDX_MONEY: RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, int) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PROFIT, sint32); - RCT2_GLOBAL(0x013CE956, int) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, int) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_VALUE, sint32); break; case WIDX_PARK_RATING: RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_PARK_RATING, sint16); @@ -227,7 +230,7 @@ static void window_game_bottom_toolbar_tooltip(rct_window* w, int widgetIndex, r day = ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_TICKS, uint16) * days_in_month[month]) >> 16) & 0xFF; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = STR_DATE_DAY_1 + day; - RCT2_GLOBAL(0x013CE954, short) = STR_MONTH_MARCH + month; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, short) = STR_MONTH_MARCH + month; break; } } @@ -355,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) @@ -384,8 +385,8 @@ static void window_game_bottom_toolbar_draw_left_panel(rct_drawpixelinfo *dpi, r dpi, (RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, int) < 0 ? 1391 : 1390), x, y - 3, - (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) == 2 && RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, sint32) == WIDX_MONEY ? 2 : w->colours[0] & 0x7F), - (void*)0x013CE952 + (gHoverWidget.window_classification == WC_BOTTOM_TOOLBAR && gHoverWidget.widget_index == WIDX_MONEY ? COLOUR_WHITE : w->colours[0] & 0x7F), + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS ); y += 7; } @@ -395,7 +396,7 @@ static void window_game_bottom_toolbar_draw_left_panel(rct_drawpixelinfo *dpi, r dpi, STR_NUM_GUESTS + RCT2_GLOBAL(RCT2_ADDRESS_GUEST_CHANGE_MODIFIER, uint8), x, y, - (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) == 2 && RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, sint32) == WIDX_GUESTS ? 2 : w->colours[0] & 0x7F), + (gHoverWidget.window_classification == WC_BOTTOM_TOOLBAR && gHoverWidget.widget_index == WIDX_GUESTS ? COLOUR_WHITE : w->colours[0] & 0x7F), (void*)RCT2_ADDRESS_GUESTS_IN_PARK ); @@ -455,15 +456,15 @@ static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo *dpi, rct_string_id stringId = DateFormatStringFormatIds[gConfigGeneral.date_format]; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = STR_DATE_DAY_1 + day; - RCT2_GLOBAL(0x013CE954, short) = month; - RCT2_GLOBAL(0x013CE956, short) = year; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, short) = month; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, short) = year; gfx_draw_string_centred( dpi, stringId, x, y, - (RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WINDOWCLASS, rct_windowclass) == 2 && RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_OVER_WIDGETINDEX, sint32) == WIDX_DATE ? 2 : w->colours[0] & 0x7F), - (void*)0x013CE952 + (gHoverWidget.window_classification == WC_BOTTOM_TOOLBAR && gHoverWidget.widget_index == WIDX_DATE ? COLOUR_WHITE : w->colours[0] & 0x7F), + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS ); // Temperature @@ -477,7 +478,7 @@ static void window_game_bottom_toolbar_draw_right_panel(rct_drawpixelinfo *dpi, format = STR_FAHRENHEIT_VALUE; } RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = temperature; - gfx_draw_string_left(dpi, format, (void*)0x013CE952, 0, x, y + 6); + gfx_draw_string_left(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y + 6); x += 30; // Current weather @@ -536,8 +537,10 @@ static void window_game_bottom_toolbar_draw_news_item(rct_drawpixelinfo *dpi, rc if (newsItem->flags & 1) break; - rct_drawpixelinfo* cliped_dpi = clip_drawpixelinfo(dpi, x + 1, 22, y + 1, 22); - if (!cliped_dpi) break; + rct_drawpixelinfo cliped_dpi; + if (!clip_drawpixelinfo(&cliped_dpi, dpi, x + 1, y + 1, 22, 22)) { + break; + } rct_peep* peep = GET_PEEP(newsItem->assoc); int clip_x = 10, clip_y = 19; @@ -548,35 +551,33 @@ 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++; uint32 image_id = image_id_base; image_id |= 0xA0000000 | (peep->tshirt_colour << 19) | (peep->trousers_colour << 24); - gfx_draw_sprite(cliped_dpi, image_id, clip_x, clip_y, 0); + gfx_draw_sprite(&cliped_dpi, image_id, clip_x, clip_y, 0); if (image_id_base >= 0x2A1D && image_id_base < 0x2A3D){ image_id_base += 32; image_id_base |= 0x20000000 | (peep->balloon_colour << 19); - gfx_draw_sprite(cliped_dpi, image_id_base, clip_x, clip_y, 0); + gfx_draw_sprite(&cliped_dpi, image_id_base, clip_x, clip_y, 0); } else if (image_id_base >= 0x2BBD && image_id_base < 0x2BDD){ image_id_base += 32; image_id_base |= 0x20000000 | (peep->umbrella_colour << 19); - gfx_draw_sprite(cliped_dpi, image_id_base, clip_x, clip_y, 0); + gfx_draw_sprite(&cliped_dpi, image_id_base, clip_x, clip_y, 0); } else if (image_id_base >= 0x29DD && image_id_base < 0x29FD){ image_id_base += 32; image_id_base |= 0x20000000 | (peep->hat_colour << 19); - gfx_draw_sprite(cliped_dpi, image_id_base, clip_x, clip_y, 0); + gfx_draw_sprite(&cliped_dpi, image_id_base, clip_x, clip_y, 0); } - - rct2_free(cliped_dpi); break; case NEWS_ITEM_MONEY: gfx_draw_sprite(dpi, SPR_FINANCE, x, y, 0); @@ -596,17 +597,10 @@ 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 */ +/** + * + * rct2: 0x0066C6D8 + */ static void window_game_bottom_toolbar_update(rct_window* w){ w->frame_no++; @@ -616,7 +610,10 @@ static void window_game_bottom_toolbar_update(rct_window* w){ window_game_bottom_toolbar_invalidate_dirty_widgets(w); } -/* rct2: 0x006C644 */ +/** + * + * rct2: 0x0066C644 + */ static void window_game_bottom_toolbar_cursor(rct_window *w, int widgetIndex, int x, int y, int *cursorId) { switch (widgetIndex) { @@ -624,18 +621,24 @@ 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; } } -/* rct2: 0x0066C6F2 */ +/** + * + * rct2: 0x0066C6F2 + */ static void window_game_bottom_toolbar_unknown05(rct_window *w) { window_game_bottom_toolbar_invalidate_dirty_widgets(w); } -/* rct2: 0x0066C6F2 */ +/** + * + * rct2: 0x0066C6F2 + */ static void window_game_bottom_toolbar_invalidate_dirty_widgets(rct_window *w) { if (RCT2_GLOBAL(RCT2_ADDRESS_BTM_TOOLBAR_DIRTY_FLAGS, uint16) & BTM_TB_DIRTY_FLAG_MONEY){ diff --git a/src/windows/guest.c b/src/windows/guest.c index 2a9eb29bdd..6f56af5c45 100644 --- a/src/windows/guest.c +++ b/src/windows/guest.c @@ -480,7 +480,8 @@ uint32 window_guest_page_enabled_widgets[] = { }; /** - * rct2: 0x006989E9 + * + * rct2: 0x006989E9 * */ void window_guest_open(rct_peep* peep){ @@ -502,8 +503,8 @@ 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->var_494 = 0; + window->picked_peep_frame = 0; + window->highlighted_item = 0; window_guest_disable_widgets(window); window->min_width = 192; window->min_height = 157; @@ -529,9 +530,10 @@ void window_guest_open(rct_peep* peep){ window_guest_viewport_init(window); } -/* rct2: 0x006987A6 +/** * Disables the finance tab when no money. * Disables peep pickup when in certain no pickup states. + * rct2: 0x006987A6 */ void window_guest_disable_widgets(rct_window* w){ rct_peep* peep = &g_sprite_list[w->number].peep; @@ -552,17 +554,23 @@ void window_guest_disable_widgets(rct_window* w){ w->disabled_widgets = disabled_widgets; } -/* rct2: 0x00696A75 */ +/** + * + * rct2: 0x00696A75 + */ 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(); } } -/* rct2: 0x00696FBE */ +/** + * + * rct2: 0x00696FBE + */ void window_guest_overview_resize(rct_window *w){ window_guest_disable_widgets(w); window_event_invalidate_call(w); @@ -589,7 +597,10 @@ void window_guest_overview_resize(rct_window *w){ window_guest_viewport_init(w); } -/* rct2: 0x00696A06 */ +/** + * + * rct2: 0x00696A06 + */ void window_guest_overview_mouse_up(rct_window *w, int widgetIndex) { rct_peep* peep = GET_PEEP(w->number); @@ -607,6 +618,15 @@ void window_guest_overview_mouse_up(rct_window *w, int widgetIndex) window_guest_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_PICKUP: + { // remove this block when peep pick up is finally converted to a game command + int player = network_get_player_index(network_get_current_player_id()); + if (player != -1) { + if (!network_can_perform_action(network_get_group_index(network_get_player_group(player)), 11/*Guest action*/)) { + window_error_open(STR_CANT_DO_THIS, STR_PERMISSION_DENIED); + return; + } + } + } // if (!peep_can_be_picked_up(peep)) { return; } @@ -614,7 +634,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); @@ -632,14 +652,17 @@ void window_guest_overview_mouse_up(rct_window *w, int widgetIndex) window_scroll_to_viewport(w); break; case WIDX_TRACK: - g_sprite_list[w->number].peep.flags ^= PEEP_FLAGS_TRACKING; + g_sprite_list[w->number].peep.peep_flags ^= PEEP_FLAGS_TRACKING; break; } } -/* rct2: 0x696AA0 */ +/** + * + * 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)) @@ -684,7 +707,10 @@ void window_guest_overview_unknown_14(rct_window *w) window_guest_viewport_init(w); } -/* rct2: 0x0069883C */ +/** + * + * rct2: 0x0069883C + */ void window_guest_viewport_init(rct_window* w){ if (w->page != WINDOW_GUEST_OVERVIEW) return; @@ -787,7 +813,8 @@ void window_guest_viewport_init(rct_window* w){ } /** - * rct2: 0x6983dd + * + * rct2: 0x6983dd * used by window_staff as well */ void window_guest_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ @@ -801,8 +828,10 @@ void window_guest_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ int y = widget->top + 1 + w->y; if (w->page == WINDOW_GUEST_OVERVIEW) height++; - rct_drawpixelinfo* clip_dpi = clip_drawpixelinfo(dpi, x, width, y, height ); - if (!clip_dpi) return; + rct_drawpixelinfo clip_dpi; + if (!clip_drawpixelinfo(&clip_dpi, dpi, x, y, width, height)) { + return; + } x = 14; y = 20; @@ -812,44 +841,45 @@ 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; if (w->page == WINDOW_GUEST_OVERVIEW){ - eax = w->var_494>>16; + eax = w->highlighted_item>>16; eax &= 0xFFFC; } ebx += eax; int sprite_id = ebx | (peep->tshirt_colour << 19) | (peep->trousers_colour << 24) | 0xA0000000; - gfx_draw_sprite( clip_dpi, sprite_id, x, y, 0); + gfx_draw_sprite(&clip_dpi, sprite_id, x, y, 0); // If holding a balloon if (ebx >= 0x2A1D && ebx < 0x2A3D){ ebx += 32; ebx |= (peep->balloon_colour << 19) | 0x20000000; - gfx_draw_sprite( clip_dpi, ebx, x, y, 0); + gfx_draw_sprite(&clip_dpi, ebx, x, y, 0); } // If holding umbrella if (ebx >= 0x2BBD && ebx < 0x2BDD){ ebx += 32; ebx |= (peep->umbrella_colour << 19) | 0x20000000; - gfx_draw_sprite(clip_dpi, ebx, x, y, 0); + gfx_draw_sprite(&clip_dpi, ebx, x, y, 0); } // If wearing hat if (ebx >= 0x29DD && ebx < 0x29FD){ ebx += 32; ebx |= (peep->hat_colour << 19) | 0x20000000; - gfx_draw_sprite( clip_dpi, ebx, x, y, 0); + gfx_draw_sprite(&clip_dpi, ebx, x, y, 0); } - - rct2_free(clip_dpi); } -/* rct2: 0x69869b */ +/** + * + * rct2: 0x69869b + */ void window_guest_stats_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ if (w->disabled_widgets & (1 << WIDX_TAB_2)) return; @@ -878,7 +908,10 @@ void window_guest_stats_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ gfx_draw_sprite(dpi, image_id, x, y, 0); } -/* rct2: 0x69861F */ +/** + * + * rct2: 0x69861F + */ void window_guest_rides_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ if (w->disabled_widgets & (1 << WIDX_TAB_3)) return; @@ -895,7 +928,10 @@ void window_guest_rides_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ gfx_draw_sprite(dpi, image_id, x, y, 0); } -/* rct2: 0x698597 */ +/** + * + * rct2: 0x698597 + */ void window_guest_finance_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ if (w->disabled_widgets & (1 << WIDX_TAB_4)) return; @@ -912,7 +948,10 @@ void window_guest_finance_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ gfx_draw_sprite(dpi, image_id, x, y, 0); } -/* rct2: 0x6985D8 */ +/** + * + * rct2: 0x6985D8 + */ void window_guest_thoughts_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ if (w->disabled_widgets & (1 << WIDX_TAB_5)) return; @@ -929,7 +968,10 @@ void window_guest_thoughts_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ gfx_draw_sprite(dpi, image_id, x, y, 0); } -/* rct2: 0x698661 */ +/** + * + * rct2: 0x698661 + */ void window_guest_inventory_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ if (w->disabled_widgets & (1 << WIDX_TAB_6)) return; @@ -942,7 +984,10 @@ void window_guest_inventory_tab_paint(rct_window* w, rct_drawpixelinfo* dpi){ gfx_draw_sprite(dpi, image_id, x, y, 0); } -/* rct2: 0x696887 */ +/** + * + * rct2: 0x696887 + */ void window_guest_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -966,13 +1011,13 @@ void window_guest_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) uint32 argument1, argument2; rct_peep* peep = GET_PEEP(w->number); get_arguments_from_action(peep, &argument1, &argument2); - RCT2_GLOBAL(0x13CE952, uint32) = argument1; - RCT2_GLOBAL(0x13CE952 + 4, uint32) = argument2; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = argument1; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = argument2; rct_widget* widget = &w->widgets[WIDX_ACTION_LBL]; int x = (widget->left + widget->right) / 2 + w->x; int y = w->y + widget->top - 1; int width = widget->right - widget->left; - gfx_draw_string_centred_clipped(dpi, 1191, (void*)0x13CE952, 0, x, y, width); + gfx_draw_string_centred_clipped(dpi, 1191, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, width); // Draw the marquee thought widget = &w->widgets[WIDX_MARQUEE]; @@ -980,14 +1025,15 @@ void window_guest_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) int left = widget->left + 2 + w->x; int top = widget->top + w->y; int height = widget->bottom - widget->top; - rct_drawpixelinfo* dpi_marquee = clip_drawpixelinfo(dpi, left, width, top, height); + rct_drawpixelinfo dpi_marquee; + if (!clip_drawpixelinfo(&dpi_marquee, dpi, left, top, width, height)) { + return; + } - if (!dpi_marquee)return; int i = 0; for (; i < PEEP_MAX_THOUGHTS; ++i){ if (peep->thoughts[i].type == PEEP_THOUGHT_TYPE_NONE){ w->list_information_type = 0; - rct2_free(dpi_marquee); return; } if (peep->thoughts[i].var_2 == 1){ // If a fresh thought @@ -996,23 +1042,23 @@ void window_guest_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) } if (i == PEEP_MAX_THOUGHTS){ w->list_information_type = 0; - rct2_free(dpi_marquee); return; } get_arguments_from_thought(peep->thoughts[i], &argument1, &argument2); - RCT2_GLOBAL(0x13CE952, uint32) = argument1; - RCT2_GLOBAL(0x13CE952 + 4, uint32) = argument2; - RCT2_GLOBAL(0x13CE952 + 8, uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = argument1; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = argument2; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint16) = 0; x = widget->right - widget->left - w->list_information_type; - gfx_draw_string_left(dpi_marquee, 1193, (void*)0x13CE952, 0, x, 0); - - rct2_free(dpi_marquee); + gfx_draw_string_left(&dpi_marquee, 1193, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, 0); } -/* rct2: 0x696749*/ +/** + * + * rct2: 0x696749 + */ void window_guest_overview_invalidate(rct_window *w) { colour_scheme_update(w); @@ -1026,11 +1072,11 @@ void window_guest_overview_invalidate(rct_window *w) w->pressed_widgets |= 1ULL << (w->page + WIDX_TAB_1); rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952,uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954,uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS,uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2,uint32) = peep->id; w->pressed_widgets &= ~(1<flags & 0x8){ + if (peep->peep_flags & PEEP_FLAGS_TRACKING){ w->pressed_widgets |= (1<var_494 >> 16; + int var_496 = w->highlighted_item >> 16; var_496++; var_496 %= 24; - w->var_494 &= 0x0000FFFF; - w->var_494 |= var_496 << 16; + w->highlighted_item &= 0x0000FFFF; + w->highlighted_item |= var_496 << 16; widget_invalidate(w, WIDX_TAB_1); widget_invalidate(w, WIDX_TAB_2); w->list_information_type += 2; - if ((w->var_494 & 0xFFFF) == 0xFFFF) - w->var_494 &= 0xFFFF0000; + if ((w->highlighted_item & 0xFFFF) == 0xFFFF) + w->highlighted_item &= 0xFFFF0000; else - w->var_494++; + w->highlighted_item++; // Disable peep watching thought for multiplayer as its client specific if (network_get_mode() == NETWORK_MODE_NONE) { // Create the "I have the strangest feeling I am being watched thought" - if ((w->var_494 & 0xFFFF) >= 3840) { - if (!(w->var_494 & 0x3FF)) { + if ((w->highlighted_item & 0xFFFF) >= 3840) { + if (!(w->highlighted_item & 0x3FF)) { int random = util_rand() & 0xFFFF; if (random <= 0x2AAA) { rct_peep* peep = GET_PEEP(w->number); @@ -1100,7 +1149,7 @@ void window_guest_overview_update(rct_window* w){ } } -/* rct2:0x696A6A */ +/* rct2: 0x696A6A */ void window_guest_overview_text_input(rct_window *w, int widgetIndex, char *text) { if (widgetIndex != WIDX_RENAME) @@ -1115,7 +1164,10 @@ void window_guest_overview_text_input(rct_window *w, int widgetIndex, char *text game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 24)), GAME_COMMAND_SET_PEEP_NAME, *((int*)(text + 32)), *((int*)(text + 28))); } -/* rct2: 0x696A5F */ +/** + * + * rct2: 0x696A5F + */ void window_guest_overview_tool_update(rct_window* w, int widgetIndex, int x, int y) { if (widgetIndex != WIDX_PICKUP) @@ -1137,7 +1189,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); @@ -1148,22 +1200,25 @@ 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; - int ebp = peep->tshirt_colour << 19; - int ecx = peep->trousers_colour << 24; + uint32 imageId = g_sprite_entries[peep->sprite_type].sprite_image[11].base_image; + imageId += w->picked_peep_frame >> 2; - ebx |= ebp | ecx | 0xA0000000; - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, uint32) = ebx; + imageId |= (peep->tshirt_colour << 19) | (peep->trousers_colour << 24) | 0xA0000000; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, uint32) = imageId; } -/* rct2: 0x696A54 */ +/** + * + * rct2: 0x696A54 + */ void window_guest_overview_tool_down(rct_window* w, int widgetIndex, int x, int y) { if (widgetIndex != WIDX_PICKUP) @@ -1206,7 +1261,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; @@ -1215,10 +1270,13 @@ void window_guest_overview_tool_down(rct_window* w, int widgetIndex, int x, int sub_693B58(peep); tool_cancel(); - RCT2_GLOBAL(0x9DE550, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; } -/* rct2: 0x696A49 */ +/** + * + * rct2: 0x696A49 + */ void window_guest_overview_tool_abort(rct_window *w, int widgetIndex) { if (widgetIndex != WIDX_PICKUP) @@ -1228,7 +1286,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){ @@ -1236,17 +1294,18 @@ 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; } -/* rct2:0x69744F, 0x697795, 0x697BDD, 0x697E18, 0x698279 +/** * This is a combination of 5 functions that were identical + * rct2: 0x69744F, 0x697795, 0x697BDD, 0x697E18, 0x698279 */ void window_guest_mouse_up(rct_window *w, int widgetIndex) { @@ -1265,21 +1324,28 @@ void window_guest_mouse_up(rct_window *w, int widgetIndex) } } -/* rct2: 0x697488 */ +/** + * + * rct2: 0x697488 + */ void window_guest_stats_resize(rct_window *w) { window_set_resize(w, 192, 162, 192, 162); } -/* rct2: 0x6974ED, 0x00697959, 0x00697C7B, 0x00697ED2, 0x00698333 +/** * This is a combination of 5 functions that were identical + * rct2: 0x6974ED, 0x00697959, 0x00697C7B, 0x00697ED2, 0x00698333 */ void window_guest_unknown_05(rct_window *w) { widget_invalidate(w, WIDX_TAB_1); } -/* rct2: 0x69746A */ +/** + * + * rct2: 0x69746A + */ void window_guest_stats_update(rct_window *w) { w->frame_no++; @@ -1289,7 +1355,10 @@ void window_guest_stats_update(rct_window *w) window_invalidate(w); } -/* rct2: 0x69707D */ +/** + * + * rct2: 0x69707D + */ void window_guest_stats_invalidate(rct_window *w) { colour_scheme_update(w); @@ -1302,8 +1371,8 @@ void window_guest_stats_invalidate(rct_window *w) w->pressed_widgets |= 1ULL << (w->page + WIDX_TAB_1); rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; window_guest_stats_widgets[WIDX_BACKGROUND].right = w->width - 1; window_guest_stats_widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -1344,7 +1413,10 @@ void window_guest_stats_bars_paint(int value, int x, int y, rct_window *w, rct_d } -/* rct2: 0x0069711D */ +/** + * + * rct2: 0x0069711D + */ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -1365,7 +1437,7 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) int y = w->y + window_guest_rides_widgets[WIDX_PAGE_BACKGROUND].top + 4; //Happiness - gfx_draw_string_left(dpi, 1662, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 1662, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); int happiness = peep->happiness; if (happiness < 10)happiness = 10; @@ -1377,7 +1449,7 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) //Energy y += 10; - gfx_draw_string_left(dpi, 1664, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 1664, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); int energy = ((peep->energy - 32) * 85) / 32; ebp = 14; @@ -1389,7 +1461,7 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) //Hunger y += 10; - gfx_draw_string_left(dpi, 1665, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 1665, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); int hunger = peep->hunger; if (hunger > 190) hunger = 190; @@ -1408,7 +1480,7 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) //Thirst y += 10; - gfx_draw_string_left(dpi, 1666, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 1666, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); int thirst = peep->thirst; if (thirst > 190) thirst = 190; @@ -1427,7 +1499,7 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) //Nausea y += 10; - gfx_draw_string_left(dpi, 1663, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 1663, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); int nausea = peep->nausea - 32; @@ -1443,7 +1515,7 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) //Bathroom y += 10; - gfx_draw_string_left(dpi, 1667, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 1667, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); int bathroom = peep->bathroom - 32; if (bathroom > 210) bathroom = 210; @@ -1465,8 +1537,8 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) int eax = RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_TICKS, uint32); eax -= peep->time_in_park; eax >>= 11; - RCT2_GLOBAL(0x13CE952, uint16) = eax & 0xFFFF; - gfx_draw_string_left(dpi, 1458, (void*)0x13CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = eax & 0xFFFF; + gfx_draw_string_left(dpi, 1458, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } y += 19; @@ -1478,31 +1550,37 @@ void window_guest_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) // Intensity int intensity = peep->intensity / 16; - RCT2_GLOBAL(0x13CE952, uint16) = intensity; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = intensity; int string_id = 1658; if (peep->intensity & 0xF){ - RCT2_GLOBAL(0x13CE952, uint16) = peep->intensity & 0xF; - RCT2_GLOBAL(0x13CE954, uint16) = intensity; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->intensity & 0xF; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = intensity; string_id = 1659; if (intensity == 15) string_id = 1660; } - gfx_draw_string_left(dpi, string_id, (void*)0x13CE952, 0, x + 4, y); + gfx_draw_string_left(dpi, string_id, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x + 4, y); // Nausea tolerance y += 10; int nausea_tolerance = peep->nausea_tolerance & 0x3; - RCT2_GLOBAL(0x13CE952, uint16) = nausea_tolerance + 2368; - gfx_draw_string_left(dpi, 1661, (void*)0x13CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = nausea_tolerance + 2368; + gfx_draw_string_left(dpi, 1661, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } -/* rct2: 0x006978F4 */ +/** + * + * rct2: 0x006978F4 + */ void window_guest_rides_resize(rct_window *w) { window_set_resize(w, 192, 128, 500, 400); } -/* rct2: 0x6977B0 */ +/** + * + * rct2: 0x6977B0 + */ void window_guest_rides_update(rct_window *w) { w->frame_no++; @@ -1522,7 +1600,7 @@ void window_guest_rides_update(rct_window *w) uint8 ride_id_bit = ride_id % 8; uint8 ride_id_offset = ride_id / 8; if (peep->rides_been_on[ride_id_offset] & (1 << ride_id_bit)){ - rct_ride* ride = GET_RIDE(ride_id); + rct_ride* ride = get_ride(ride_id); if (RCT2_ADDRESS(0x97C3AF, uint8)[ride->type] == 0){ w->list_item_positions[curr_list_position] = ride_id; curr_list_position++; @@ -1536,13 +1614,19 @@ void window_guest_rides_update(rct_window *w) } } -/* rct2: 0x697844 */ +/** + * + * rct2: 0x697844 + */ void window_guest_rides_tooltip(rct_window* w, int widgetIndex, rct_string_id *stringId) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_LIST; } -/* rct2: 0x69784E */ +/** + * + * rct2: 0x69784E + */ void window_guest_rides_scroll_get_size(rct_window *w, int scrollIndex, int *width, int *height) { *height = w->no_list_items * 10; @@ -1565,7 +1649,10 @@ void window_guest_rides_scroll_get_size(rct_window *w, int scrollIndex, int *wid } } -/* rct2: 0x006978CC */ +/** + * + * rct2: 0x006978CC + */ void window_guest_rides_scroll_mouse_down(rct_window *w, int scrollIndex, int x, int y) { int index; @@ -1576,7 +1663,10 @@ void window_guest_rides_scroll_mouse_down(rct_window *w, int scrollIndex, int x, window_ride_main_open(w->list_item_positions[index]); } -/* rct2: 0x0069789C */ +/** + * + * rct2: 0x0069789C + */ void window_guest_rides_scroll_mouse_over(rct_window *w, int scrollIndex, int x, int y) { int index; @@ -1590,7 +1680,10 @@ void window_guest_rides_scroll_mouse_over(rct_window *w, int scrollIndex, int x, window_invalidate(w); } -/* rct2: 0x0069757A */ +/** + * + * rct2: 0x0069757A + */ void window_guest_rides_invalidate(rct_window *w) { colour_scheme_update(w); @@ -1603,8 +1696,8 @@ void window_guest_rides_invalidate(rct_window *w) w->pressed_widgets |= 1ULL << (w->page + WIDX_TAB_1); rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; window_guest_rides_widgets[WIDX_BACKGROUND].right = w->width - 1; window_guest_rides_widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -1623,7 +1716,10 @@ void window_guest_rides_invalidate(rct_window *w) window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_6); } -/* rct2: 0x00697637 */ +/** + * + * rct2: 0x00697637 + */ void window_guest_rides_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -1648,17 +1744,20 @@ void window_guest_rides_paint(rct_window *w, rct_drawpixelinfo *dpi) int ride_string_id = 3094; int ride_string_arguments = 0; if (peep->favourite_ride != 0xFF){ - rct_ride* ride = GET_RIDE(peep->favourite_ride); + rct_ride* ride = get_ride(peep->favourite_ride); ride_string_arguments = ride->name_arguments; ride_string_id = ride->name; } - RCT2_GLOBAL(0x13CE952, uint16) = ride_string_id; - RCT2_GLOBAL(0x13CE954, uint32) = ride_string_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ride_string_id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride_string_arguments; - gfx_draw_string_left_clipped(dpi, 3093, (void*)0x13CE952, 0, x, y, w->width - 14); + gfx_draw_string_left_clipped(dpi, 3093, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, w->width - 14); } -/* rct2: 0x006976FC */ +/** + * + * rct2: 0x006976FC + */ void window_guest_rides_scroll_paint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { // ax @@ -1680,19 +1779,25 @@ void window_guest_rides_scroll_paint(rct_window *w, rct_drawpixelinfo *dpi, int gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x2000031); string_format = 1193; } - rct_ride* ride = GET_RIDE(w->list_item_positions[list_index]); + rct_ride* ride = get_ride(w->list_item_positions[list_index]); gfx_draw_string_left(dpi, string_format, (void*)&ride->name, 0, 0, y - 1); } } -/* rct2: 0x00697C16 */ +/** + * + * rct2: 0x00697C16 + */ void window_guest_finance_resize(rct_window *w) { window_set_resize(w, 210, 134, 210, 134); } -/* rct2: 0x00697BF8 */ +/** + * + * rct2: 0x00697BF8 + */ void window_guest_finance_update(rct_window *w) { w->frame_no++; @@ -1701,7 +1806,10 @@ void window_guest_finance_update(rct_window *w) widget_invalidate(w, WIDX_TAB_4); } -/* rct2: 0x00697968 */ +/** + * + * rct2: 0x00697968 + */ void window_guest_finance_invalidate(rct_window *w) { colour_scheme_update(w); @@ -1715,8 +1823,8 @@ void window_guest_finance_invalidate(rct_window *w) rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; window_guest_finance_widgets[WIDX_BACKGROUND].right = w->width - 1; window_guest_finance_widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -1732,7 +1840,10 @@ void window_guest_finance_invalidate(rct_window *w) window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_6); } -/* rct2: 0x00697A08 */ +/** + * + * rct2: 0x00697A08 + */ void window_guest_finance_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -1751,67 +1862,70 @@ void window_guest_finance_paint(rct_window *w, rct_drawpixelinfo *dpi) int y = w->y + window_guest_finance_widgets[WIDX_PAGE_BACKGROUND].top + 4; // Cash in pocket - RCT2_GLOBAL(0x13CE952, money32) = peep->cash_in_pocket; - gfx_draw_string_left(dpi, 1457, (void*)0x13CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = peep->cash_in_pocket; + gfx_draw_string_left(dpi, 1457, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); // Cash spent y += 10; - RCT2_GLOBAL(0x13CE952, money32) = peep->cash_spent; - gfx_draw_string_left(dpi, 1456, (void*)0x13CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = peep->cash_spent; + gfx_draw_string_left(dpi, 1456, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 20; gfx_fill_rect_inset(dpi, x, y - 6, x + 179, y - 5, w->colours[1], 32); // Paid to enter - RCT2_GLOBAL(0x13CE952, money32) = peep->paid_to_enter; - gfx_draw_string_left(dpi, 2296, (void*)0x13CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = peep->paid_to_enter; + gfx_draw_string_left(dpi, 2296, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); // Paid on rides y += 10; - RCT2_GLOBAL(0x13CE952, money32) = peep->paid_on_rides; - RCT2_GLOBAL(0x13CE956, uint16) = peep->no_of_rides; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = peep->paid_on_rides; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = peep->no_of_rides; if (peep->no_of_rides != 1){ - gfx_draw_string_left(dpi, 2298, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2298, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } else{ - gfx_draw_string_left(dpi, 2297, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2297, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } // Paid on food y += 10; - RCT2_GLOBAL(0x13CE952, money32) = peep->paid_on_food; - RCT2_GLOBAL(0x13CE956, uint16) = peep->no_of_food; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = peep->paid_on_food; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = peep->no_of_food; if (peep->no_of_food != 1){ - gfx_draw_string_left(dpi, 2300, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2300, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } else{ - gfx_draw_string_left(dpi, 2299, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2299, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } // Paid on drinks y += 10; - RCT2_GLOBAL(0x13CE952, money32) = peep->paid_on_drink; - RCT2_GLOBAL(0x13CE956, uint16) = peep->no_of_drinks; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = peep->paid_on_drink; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = peep->no_of_drinks; if (peep->no_of_drinks != 1){ - gfx_draw_string_left(dpi, 2302, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2302, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } else{ - gfx_draw_string_left(dpi, 2301, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2301, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } // Paid on souvenirs y += 10; - RCT2_GLOBAL(0x13CE952, money32) = peep->paid_on_souvenirs; - RCT2_GLOBAL(0x13CE956, uint16) = peep->no_of_souvenirs; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, money32) = peep->paid_on_souvenirs; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = peep->no_of_souvenirs; if (peep->no_of_souvenirs != 1){ - gfx_draw_string_left(dpi, 2304, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2304, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } else{ - gfx_draw_string_left(dpi, 2303, (void*)0x13CE952, 0, x, y); + gfx_draw_string_left(dpi, 2303, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } } -/* rct2: 0x00697E33 */ +/** + * + * rct2: 0x00697E33 + */ void window_guest_thoughts_resize(rct_window *w) { rct_peep* peep = GET_PEEP(w->number); @@ -1823,7 +1937,10 @@ void window_guest_thoughts_resize(rct_window *w) window_set_resize(w, 192, 159, 500, 450); } -/* rct2: 0x00697EB4 */ +/** + * + * rct2: 0x00697EB4 + */ void window_guest_thoughts_update(rct_window *w) { w->frame_no++; @@ -1832,7 +1949,10 @@ void window_guest_thoughts_update(rct_window *w) widget_invalidate(w, WIDX_TAB_5); } -/* rct2: 0x00697C8A */ +/** + * + * rct2: 0x00697C8A + */ void window_guest_thoughts_invalidate(rct_window *w) { colour_scheme_update(w); @@ -1846,8 +1966,8 @@ void window_guest_thoughts_invalidate(rct_window *w) rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; window_guest_thoughts_widgets[WIDX_BACKGROUND].right = w->width - 1; window_guest_thoughts_widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -1863,7 +1983,10 @@ void window_guest_thoughts_invalidate(rct_window *w) window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_6); } -/* rct2: 0x00697D2A */ +/** + * + * rct2: 0x00697D2A + */ void window_guest_thoughts_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -1890,14 +2013,14 @@ void window_guest_thoughts_paint(rct_window *w, rct_drawpixelinfo *dpi) uint32 argument1, argument2; get_arguments_from_thought(*thought, &argument1, &argument2); - RCT2_GLOBAL(0x13CE952, uint32) = argument1; - RCT2_GLOBAL(0x13CE956, uint32) = argument2; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = argument1; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = argument2; int width = window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].right - window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].left - 8; - y += gfx_draw_string_left_wrapped(dpi, (void*)0x13CE952, x, y, width, 1191, 0); + y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, width, 1191, 0); // If this is the last visable line end drawing. if (y > w->y + window_guest_thoughts_widgets[WIDX_PAGE_BACKGROUND].bottom - 32) return; @@ -1905,7 +2028,10 @@ void window_guest_thoughts_paint(rct_window *w, rct_drawpixelinfo *dpi) } -/* rct2: 0x00698294 */ +/** + * + * rct2: 0x00698294 + */ void window_guest_inventory_resize(rct_window *w) { rct_peep* peep = GET_PEEP(w->number); @@ -1917,7 +2043,10 @@ void window_guest_inventory_resize(rct_window *w) window_set_resize(w, 192, 159, 500, 450); } -/* rct2: 0x00698315 */ +/** + * + * rct2: 0x00698315 + */ void window_guest_inventory_update(rct_window *w) { w->frame_no++; @@ -1926,7 +2055,10 @@ void window_guest_inventory_update(rct_window *w) widget_invalidate(w, WIDX_TAB_6); } -/* rct2: 0x00697EE1 */ +/** + * + * rct2: 0x00697EE1 + */ void window_guest_inventory_invalidate(rct_window *w) { colour_scheme_update(w); @@ -1940,8 +2072,8 @@ void window_guest_inventory_invalidate(rct_window *w) rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; window_guest_inventory_widgets[WIDX_BACKGROUND].right = w->width - 1; window_guest_inventory_widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -1973,7 +2105,7 @@ static rct_string_id window_guest_inventory_format_item(rct_peep *peep, int item RCT2_GLOBAL(args + 0, uint32) |= 0x20000000 | peep->balloon_colour << 19; break; case SHOP_ITEM_PHOTO: - ride = GET_RIDE(peep->photo1_ride_ref); + ride = get_ride(peep->photo1_ride_ref); RCT2_GLOBAL(args + 6, uint16) = ride->name; RCT2_GLOBAL(args + 8, uint32) = ride->name_arguments; break; @@ -1988,7 +2120,7 @@ static rct_string_id window_guest_inventory_format_item(rct_peep *peep, int item RCT2_GLOBAL(args + 10, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); break; case VOUCHER_TYPE_RIDE_FREE: - ride = GET_RIDE(peep->voucher_arguments); + ride = get_ride(peep->voucher_arguments); RCT2_GLOBAL(args + 6, uint16) = 2419; RCT2_GLOBAL(args + 8, uint16) = ride->name; RCT2_GLOBAL(args + 10, uint32) = ride->name_arguments; @@ -2011,17 +2143,17 @@ static rct_string_id window_guest_inventory_format_item(rct_peep *peep, int item RCT2_GLOBAL(args + 0, uint32) |= 0x20000000 | peep->tshirt_colour << 19; break; case SHOP_ITEM_PHOTO2: - ride = GET_RIDE(peep->photo2_ride_ref); + ride = get_ride(peep->photo2_ride_ref); RCT2_GLOBAL(args + 6, uint16) = ride->name; RCT2_GLOBAL(args + 8, uint32) = ride->name_arguments; break; case SHOP_ITEM_PHOTO3: - ride = GET_RIDE(peep->photo3_ride_ref); + ride = get_ride(peep->photo3_ride_ref); RCT2_GLOBAL(args + 6, uint16) = ride->name; RCT2_GLOBAL(args + 8, uint32) = ride->name_arguments; break; case SHOP_ITEM_PHOTO4: - ride = GET_RIDE(peep->photo4_ride_ref); + ride = get_ride(peep->photo4_ride_ref); RCT2_GLOBAL(args + 6, uint16) = ride->name; RCT2_GLOBAL(args + 8, uint32) = ride->name_arguments; break; @@ -2030,7 +2162,10 @@ static rct_string_id window_guest_inventory_format_item(rct_peep *peep, int item return STR_GUEST_ITEM_FORMAT; } -/* rct2: 0x00697F81 */ +/** + * + * rct2: 0x00697F81 + */ void window_guest_inventory_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -2058,7 +2193,7 @@ void window_guest_inventory_paint(rct_window *w, rct_drawpixelinfo *dpi) if (y >= maxY) break; if (!peep_has_item(peep, item)) continue; - void *args = (void*)0x013CE952; + void *args = (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS; rct_string_id stringId = window_guest_inventory_format_item(peep, item, (uint8*)args); y += gfx_draw_string_left_wrapped(dpi, args, x, y, itemNameWidth, stringId, 0); numItems++; diff --git a/src/windows/guest_list.c b/src/windows/guest_list.c index 04edb7f2ce..1cd8f5d03a 100644 --- a/src/windows/guest_list.c +++ b/src/windows/guest_list.c @@ -205,7 +205,7 @@ void window_guest_list_open_with_filter(int type, int index) rct_ride *ride = NULL; if (type != 3) { // common for cases 0, 1, 2 - ride = GET_RIDE(index & 0x000000FF); + ride = get_ride(index & 0x000000FF); eax = ride->name; edx = ride->name_arguments; } @@ -217,7 +217,7 @@ void window_guest_list_open_with_filter(int type, int index) eax = (eax << 16) + 1435; - if ((RCT2_GLOBAL(0x97CF40 + ride->type * 8, uint32) & 0x400000) != 0) + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IN_RIDE)) eax++; RCT2_GLOBAL(0x00F1EDF6, uint32) = eax; @@ -433,7 +433,7 @@ static void window_guest_list_scrollgetsize(rct_window *w, int scrollIndex, int if (_window_guest_list_selected_filter != -1) if (window_guest_list_is_peep_in_filter(peep)) continue; - if (_window_guest_list_tracking_only && !(peep->flags & PEEP_FLAGS_TRACKING)) + if (_window_guest_list_tracking_only && !(peep->peep_flags & PEEP_FLAGS_TRACKING)) continue; numGuests++; } @@ -495,7 +495,7 @@ static void window_guest_list_scrollmousedown(rct_window *w, int scrollIndex, in if (_window_guest_list_selected_filter != -1) if (window_guest_list_is_peep_in_filter(peep)) continue; - if (_window_guest_list_tracking_only && !(peep->flags & PEEP_FLAGS_TRACKING)) + if (_window_guest_list_tracking_only && !(peep->peep_flags & PEEP_FLAGS_TRACKING)) continue; if (i == 0) { @@ -572,10 +572,11 @@ static void window_guest_list_invalidate(rct_window *w) window_guest_list_widgets[WIDX_TITLE].right = w->width - 2; window_guest_list_widgets[WIDX_CLOSE].left = w->width - 13; window_guest_list_widgets[WIDX_CLOSE].right = w->width - 3; - window_guest_list_widgets[WIDX_GUEST_LIST].right = w->width - 4; window_guest_list_widgets[WIDX_GUEST_LIST].bottom = w->height - 15; window_guest_list_widgets[WIDX_PAGE_DROPDOWN].image = _window_guest_list_selected_page + 3440; + window_guest_list_widgets[WIDX_TRACKING].left = 321 - 350 + w->width; + window_guest_list_widgets[WIDX_TRACKING].right = 344 - 350 + w->width; } /** @@ -590,7 +591,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, @@ -603,7 +604,7 @@ static void window_guest_list_paint(rct_window *w, rct_drawpixelinfo *dpi) i = (_window_guest_list_selected_tab == 1 ? w->list_information_type / 4 : 0); gfx_draw_sprite( dpi, - 5568 + i, + SPR_TAB_GUESTS_0 + i, window_guest_list_widgets[WIDX_TAB_2].left + w->x, window_guest_list_widgets[WIDX_TAB_2].top + w->y, 0 ); @@ -630,7 +631,7 @@ static void window_guest_list_paint(rct_window *w, rct_drawpixelinfo *dpi) x = w->x + 4; y = w->y + window_guest_list_widgets[WIDX_GUEST_LIST].bottom + 2; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, sint16) = w->var_492; - gfx_draw_string_left(dpi, (w->var_492 == 1 ? 1755 : 1754), (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, (w->var_492 == 1 ? 1755 : 1754), (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } } @@ -655,16 +656,16 @@ 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->flags &= ~(SPRITE_FLAGS_PEEP_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->flags |= SPRITE_FLAGS_PEEP_FLASHING; } - if (_window_guest_list_tracking_only && !(peep->flags & PEEP_FLAGS_TRACKING)) + if (_window_guest_list_tracking_only && !(peep->peep_flags & PEEP_FLAGS_TRACKING)) continue; // @@ -682,8 +683,8 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, // Guest name RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x013CE954, uint32) = peep->id; - gfx_draw_string_left_clipped(dpi, format, (void*)0x013CE952, 0, 0, y - 1, 113); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + gfx_draw_string_left_clipped(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 0, y - 1, 113); switch (_window_guest_list_selected_view) { case VIEW_ACTIONS: @@ -691,7 +692,7 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, gfx_draw_sprite(dpi, get_peep_face_sprite_small(peep), 118, y, 0); // Tracking icon - if (peep->flags & PEEP_FLAGS_TRACKING) + if (peep->peep_flags & PEEP_FLAGS_TRACKING) gfx_draw_sprite(dpi, 5129, 112, y, 0); // Action @@ -699,8 +700,8 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, get_arguments_from_action(peep, &argument_1, &argument_2); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = argument_1; - RCT2_GLOBAL(0x013CE952 + 4, uint32) = argument_2; - gfx_draw_string_left_clipped(dpi, format, (void*)0x013CE952, 0, 133, y - 1, 314); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = argument_2; + gfx_draw_string_left_clipped(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 133, y - 1, 314); break; case VIEW_THOUGHTS: // For each thought @@ -716,8 +717,8 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, get_arguments_from_thought(peep->thoughts[j], &argument_1, &argument_2); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = argument_1; - RCT2_GLOBAL(0x013CE952 + 4, uint32) = argument_2; - gfx_draw_string_left_clipped(dpi, format, (void*)0x013CE952, 0, 118, y - 1, 329); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = argument_2; + gfx_draw_string_left_clipped(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 118, y - 1, 329); break; } break; @@ -754,13 +755,13 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, // Draw action RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = _window_guest_list_groups_argument_1[i]; - RCT2_GLOBAL(0x013CE952 + 4, uint32) = _window_guest_list_groups_argument_2[i]; - RCT2_GLOBAL(0x013CE952 + 10, uint32) = numGuests; - gfx_draw_string_left_clipped(dpi, format, (void*)0x013CE952, 0, 0, y - 1, 414); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = _window_guest_list_groups_argument_2[i]; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 10, uint32) = numGuests; + gfx_draw_string_left_clipped(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 0, y - 1, 414); // Draw guest count - RCT2_GLOBAL(0x013CE95A, uint16) = STR_GUESTS_COUNT_COMMA_SEP; - gfx_draw_string_right(dpi, format, (void*)0x0013CE95A, 0, 326, y - 1); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint16) = STR_GUESTS_COUNT_COMMA_SEP; + gfx_draw_string_right(dpi, format, (void*)(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8), 0, 326, y - 1); } y += 21; } @@ -770,7 +771,7 @@ static void window_guest_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, /** - * returns 0 for in filter and 1 for not in filter + * returns 0 for in filter and 1 for not in filter * rct2: 0x0069B865 */ static int window_guest_list_is_peep_in_filter(rct_peep* peep) @@ -793,11 +794,11 @@ static int window_guest_list_is_peep_in_filter(rct_peep* peep) } /** - * rct2:0x0069B7EA * Calculates a hash value (arguments) for comparing peep actions/thoughts + * rct2: 0x0069B7EA * peep (esi) - * argument_1 (0x013CE952) - * argument_2 (0x013CE954) + * argument_1 (0x013CE952) (RCT2_ADDRESS_COMMON_FORMAT_ARGS) + * argument_2 (0x013CE954) (RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2) */ static void get_arguments_from_peep(rct_peep *peep, uint32 *argument_1, uint32* argument_2) { @@ -841,11 +842,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->flags |= SPRITE_FLAGS_PEEP_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->flags & SPRITE_FLAGS_PEEP_VISIBLE)) continue; // New group, cap at 240 though @@ -856,7 +857,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->flags &= ~(SPRITE_FLAGS_PEEP_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 +869,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->flags & SPRITE_FLAGS_PEEP_VISIBLE)) continue; uint32 argument1, argument2; @@ -879,7 +880,7 @@ static void window_guest_list_find_groups() // Assign guest _window_guest_list_groups_num_guests[groupIndex]++; - peep2->var_0C &= ~(1 << 8); + peep2->flags &= ~(SPRITE_FLAGS_PEEP_VISIBLE); // Add face sprite, cap at 56 though if (_window_guest_list_groups_num_guests[groupIndex] >= 56) diff --git a/src/windows/install_track.c b/src/windows/install_track.c index 1b631782ae..a000405116 100644 --- a/src/windows/install_track.c +++ b/src/windows/install_track.c @@ -137,9 +137,7 @@ void window_install_track_open(const char* path) strncpy(track_path, path, MAX_PATH); track_path[MAX_PATH - 1] = '\0'; - char* track_name_pointer = track_path; - while (*track_name_pointer++ != '\0'); - while (*--track_name_pointer != '\\'); + char* track_name_pointer = strrchr(track_path, platform_get_path_separator()); track_name_pointer++; strncpy(track_dest_name, track_name_pointer, MAX_PATH); @@ -184,7 +182,7 @@ static void window_install_track_select(rct_window *w, int index) 1); char track_path[MAX_PATH] = { 0 }; - subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem); + substitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem); if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) { window_track_manage_open(); @@ -291,7 +289,7 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi) uint16 holes, speed, drops, dropHeight, inversions; fixed32_2dp rating; int x, y, colour, gForces, airTime; - rct_g1_element tmpElement, *subsituteElement; + rct_g1_element tmpElement, *substituteElement; window_draw_widgets(w, dpi); @@ -312,16 +310,16 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi) rct_track_td6* track_td6 = &trackDesign->track_td6; - subsituteElement = &g1Elements[0]; - tmpElement = *subsituteElement; - subsituteElement->offset = image; - subsituteElement->width = 370; - subsituteElement->height = 217; - subsituteElement->x_offset = 0; - subsituteElement->y_offset = 0; - subsituteElement->flags = G1_FLAG_BMP; + substituteElement = &g1Elements[0]; + tmpElement = *substituteElement; + substituteElement->offset = image; + substituteElement->width = 370; + substituteElement->height = 217; + substituteElement->x_offset = 0; + substituteElement->y_offset = 0; + substituteElement->flags = G1_FLAG_BMP; gfx_draw_sprite(dpi, 0, x, y, 0); - *subsituteElement = tmpElement; + *substituteElement = tmpElement; x = w->x + (widget->left + widget->right) / 2; y = w->y + widget->bottom - 12; @@ -380,9 +378,9 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi) } // Ride length - RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1345; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->ride_length; - gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 214); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 1345; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->ride_length; + gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, 214); y += 10; } @@ -437,9 +435,9 @@ static void window_install_track_paint(rct_window *w, rct_drawpixelinfo *dpi) if (track_td6->space_required_x != 0xFF) { // Space required - RCT2_GLOBAL(0x013CE952 + 0, uint16) = track_td6->space_required_x; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->space_required_y; - gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)0x013CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = track_td6->space_required_x; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->space_required_y; + gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 10; } diff --git a/src/windows/land.c b/src/windows/land.c index f97044bcea..5824ef87fd 100644 --- a/src/windows/land.c +++ b/src/windows/land.c @@ -215,14 +215,14 @@ static void window_land_mouseup(rct_window *w, int widgetIndex) static void window_land_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { int i; - + int defaultIndex = -1; switch (widgetIndex) { case WIDX_FLOOR: for (i = 0; i < 14; i++) { gDropdownItemsFormat[i] = -1; gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + window_land_floor_texture_order[i]; if (window_land_floor_texture_order[i] == _selectedFloorTexture) - gDropdownHighlightedIndex = i; + defaultIndex = i; } window_dropdown_show_image( w->x + widget->left, w->y + widget->top, @@ -233,13 +233,14 @@ static void window_land_mousedown(int widgetIndex, rct_window*w, rct_widget* wid 47, 36, gAppropriateImageDropdownItemsPerRow[14] ); + gDropdownDefaultIndex = defaultIndex; break; case WIDX_WALL: for (i = 0; i < 4; i++) { gDropdownItemsFormat[i] = -1; gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + window_land_wall_texture_order[i]; if (window_land_wall_texture_order[i] == _selectedWallTexture) - gDropdownHighlightedIndex = i; + defaultIndex = i; } window_dropdown_show_image( w->x + widget->left, w->y + widget->top, @@ -250,6 +251,7 @@ static void window_land_mousedown(int widgetIndex, rct_window*w, rct_widget* wid 47, 36, gAppropriateImageDropdownItemsPerRow[4] ); + gDropdownDefaultIndex = defaultIndex; break; case WIDX_PREVIEW: window_land_inputsize(w); @@ -272,7 +274,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 +290,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 +323,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); } @@ -408,6 +410,6 @@ static void window_land_paint(rct_window *w, rct_drawpixelinfo *dpi) if (price != 0 && !(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, sint32) = price; - gfx_draw_string_centred(dpi, 986, x, y, 0, (void*)0x013CE952); + gfx_draw_string_centred(dpi, 986, x, y, 0, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); } } diff --git a/src/windows/land_rights.c b/src/windows/land_rights.c index b59432fee9..6d5b6723f0 100644 --- a/src/windows/land_rights.c +++ b/src/windows/land_rights.c @@ -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; diff --git a/src/windows/loadsave.c b/src/windows/loadsave.c index d9d9b5a3f4..7f802dec40 100644 --- a/src/windows/loadsave.c +++ b/src/windows/loadsave.c @@ -71,7 +71,6 @@ static rct_widget window_loadsave_widgets[] = { static void window_loadsave_close(rct_window *w); static void window_loadsave_mouseup(rct_window *w, int widgetIndex); -static void window_loadsave_update(rct_window *w); static void window_loadsave_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); static void window_loadsave_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); static void window_loadsave_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); @@ -144,8 +143,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) @@ -156,11 +153,10 @@ rct_window *window_loadsave_open(int type, char *defaultName) int includeNewItem; rct_window* w; _type = type; - _defaultName[0] = 0; + _defaultName[0] = '\0'; if (!str_is_null_or_empty(defaultName)) { - safe_strncpy(_defaultName, path_get_filename(defaultName), sizeof(_defaultName)); - path_remove_extension(_defaultName); + safe_strcpy(_defaultName, defaultName, sizeof(_defaultName)); } w = window_bring_to_front_by_class(WC_LOADSAVE); @@ -176,23 +172,26 @@ rct_window *window_loadsave_open(int type, char *defaultName) _loadsaveType = type; switch (type & 0x0F) { case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME): - w->widgets[WIDX_TITLE].image = STR_LOAD_GAME; + w->widgets[WIDX_TITLE].image = STR_FILE_DIALOG_TITLE_LOAD_GAME; break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME) : - w->widgets[WIDX_TITLE].image = STR_SAVE_GAME; + w->widgets[WIDX_TITLE].image = STR_FILE_DIALOG_TITLE_SAVE_GAME; break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE) : - w->widgets[WIDX_TITLE].image = STR_LOAD_LANDSCAPE; + w->widgets[WIDX_TITLE].image = STR_FILE_DIALOG_TITLE_LOAD_LANDSCAPE; break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE) : - w->widgets[WIDX_TITLE].image = STR_SAVE_LANDSCAPE; + w->widgets[WIDX_TITLE].image = STR_FILE_DIALOG_TITLE_SAVE_LANDSCAPE; break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_SCENARIO) : - w->widgets[WIDX_TITLE].image = STR_SAVE_SCENARIO; + w->widgets[WIDX_TITLE].image = STR_FILE_DIALOG_TITLE_SAVE_SCENARIO; break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK) : - w->widgets[WIDX_TITLE].image = 1039; + w->widgets[WIDX_TITLE].image = STR_FILE_DIALOG_TITLE_INSTALL_NEW_TRACK_DESIGN; break; + default: + log_error("Unsupported load / save type: %d", type & 0x0F); + return NULL; } w->no_list_items = 0; @@ -221,21 +220,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; @@ -251,7 +241,7 @@ rct_window *window_loadsave_open(int type, char *defaultName) } */ - safe_strncpy(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), MAX_PATH); + safe_strcpy(path, RCT2_ADDRESS(RCT2_ADDRESS_TRACKS_PATH, char), MAX_PATH); ch = strchr(path, '*'); if (ch != NULL) *ch = 0; @@ -276,8 +266,8 @@ static void window_loadsave_close(rct_window *w) static void window_loadsave_mouseup(rct_window *w, int widgetIndex) { - int result; - char filename[MAX_PATH], filter[MAX_PATH]; + int result = 0; + char path[MAX_PATH], filter[MAX_PATH]; switch (widgetIndex){ case WIDX_CLOSE: @@ -288,7 +278,7 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) char directory[MAX_PATH]; int includeNewItem = (_type & 1) == LOADSAVETYPE_SAVE; - safe_strncpy(directory, _parentDirectory, sizeof(directory)); + safe_strcpy(directory, _parentDirectory, sizeof(directory)); window_loadsave_populate_list(w, includeNewItem, directory, _extension); window_init_scroll_widgets(w); w->no_list_items = _listItemsCount; @@ -305,40 +295,64 @@ static void window_loadsave_mouseup(rct_window *w, int widgetIndex) break; } case WIDX_BROWSE: - safe_strncpy(filename, _directory, MAX_PATH); - if (_type & LOADSAVETYPE_SAVE) - strcat(filename, (char*)RCT2_ADDRESS_SCENARIO_NAME); + safe_strcpy(path, _directory, MAX_PATH); + if (_type & LOADSAVETYPE_SAVE) { + strcat(path, _defaultName); + } memset(filter, '\0', MAX_PATH); - safe_strncpy(filter, "*", MAX_PATH); - strncat(filter, _extension, MAX_PATH); + safe_strcpy(filter, "*", MAX_PATH); + strncat(filter, _extension, MAX_PATH - strnlen(filter, MAX_PATH) - 1); + + file_dialog_desc desc; + memset(&desc, 0, sizeof(desc)); + desc.initial_directory = _directory; + if (_type & LOADSAVETYPE_SAVE) { + desc.default_filename = path; + } switch (_type) { case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) : - result = platform_open_common_file_dialog(1, (char*)language_get_string(STR_LOAD_GAME), filename, filter, _extension); + desc.type = FD_OPEN; + desc.title = language_get_string(STR_FILE_DIALOG_TITLE_LOAD_GAME); + desc.filters[0].name = language_get_string(STR_OPENRCT2_SAVED_GAME); + desc.filters[0].pattern = "*.sv4;*.sv6"; break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_GAME) : - result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_GAME), filename, filter, _extension); + desc.type = FD_SAVE; + desc.title = language_get_string(STR_FILE_DIALOG_TITLE_SAVE_GAME); + desc.filters[0].name = language_get_string(STR_OPENRCT2_SAVED_GAME); + desc.filters[0].pattern = "*.sv6"; break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE) : - result = platform_open_common_file_dialog(1, (char*)language_get_string(STR_LOAD_LANDSCAPE), filename, filter, _extension); + desc.type = FD_OPEN; + desc.title = language_get_string(STR_FILE_DIALOG_TITLE_LOAD_LANDSCAPE); + desc.filters[0].name = language_get_string(STR_OPENRCT2_LANDSCAPE_FILE); + desc.filters[0].pattern = "*.sc4;*.sv4;*.sc6;*.sv6"; break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_LANDSCAPE) : - result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_LANDSCAPE), filename, filter, _extension); + desc.type = FD_SAVE; + desc.title = language_get_string(STR_FILE_DIALOG_TITLE_SAVE_LANDSCAPE); + desc.filters[0].name = language_get_string(STR_OPENRCT2_LANDSCAPE_FILE); + desc.filters[0].pattern = "*.sc6"; break; case (LOADSAVETYPE_SAVE | LOADSAVETYPE_SCENARIO) : - result = platform_open_common_file_dialog(0, (char*)language_get_string(STR_SAVE_SCENARIO), filename, filter, _extension); + desc.type = FD_SAVE; + desc.title = language_get_string(STR_FILE_DIALOG_TITLE_SAVE_SCENARIO); + desc.filters[0].name = language_get_string(STR_OPENRCT2_SCENARIO_FILE); + desc.filters[0].pattern = "*.sc6"; break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_TRACK) : - result = platform_open_common_file_dialog(1, (char*)language_get_string(1039), filename, filter, _extension); + desc.type = FD_OPEN; + desc.title = language_get_string(STR_FILE_DIALOG_TITLE_INSTALL_NEW_TRACK_DESIGN); + desc.filters[0].name = language_get_string(STR_OPENRCT2_TRACK_DESIGN_FILE); + desc.filters[0].pattern = "*.td4;*.td6"; break; } + result = platform_open_common_file_dialog(path, &desc); if (result) { - if (!has_extension(filename, _extension)) { - strncat(filename, _extension, MAX_PATH); - } - window_loadsave_select(w, filename); + window_loadsave_select(w, path); } break; case WIDX_SORT_NAME: @@ -396,7 +410,7 @@ static void window_loadsave_scrollmousedown(rct_window *w, int scrollIndex, int includeNewItem = (_type & 1) == LOADSAVETYPE_SAVE; char directory[MAX_PATH]; - safe_strncpy(directory, _listItems[selectedItem].path, sizeof(directory)); + safe_strcpy(directory, _listItems[selectedItem].path, sizeof(directory)); window_loadsave_populate_list(w, includeNewItem, directory, _extension); window_init_scroll_widgets(w); @@ -448,7 +462,7 @@ static void window_loadsave_textinput(rct_window *w, int widgetIndex, char *text return; } - safe_strncpy(path, _directory, sizeof(path)); + safe_strcpy(path, _directory, sizeof(path)); strncat(path, text, sizeof(path) - strnlen(path, MAX_PATH) - 1); strncat(path, _extension, sizeof(path) - strnlen(path, MAX_PATH) - 1); @@ -480,8 +494,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]; @@ -489,7 +504,7 @@ static void window_loadsave_paint(rct_window *w, rct_drawpixelinfo *dpi) utf8 *ch = buffer; ch = utf8_write_codepoint(ch, FORMAT_MEDIUMFONT); ch = utf8_write_codepoint(ch, FORMAT_BLACK); - safe_strncpy(ch, _shortenedDirectory, sizeof(buffer) - (ch - buffer)); + safe_strcpy(ch, _shortenedDirectory, sizeof(buffer) - (ch - buffer)); // Draw shadow gfx_draw_string(dpi, buffer, 0, w->x + 4, w->y + 20); @@ -510,41 +525,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; @@ -573,15 +553,6 @@ static void window_loadsave_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, i } } -static int compare_string_case_insensitive(char const *a, char const *b) -{ - for (;; a++, b++) { - int d = tolower(*a) - tolower(*b); - if (d != 0 || !*a) - return d; - } -} - static int list_item_sort(const void *a, const void *b) { const loadsave_list_item *itemA = (loadsave_list_item*)a; @@ -592,15 +563,15 @@ static int list_item_sort(const void *a, const void *b) switch (gConfigGeneral.load_save_sort){ case SORT_NAME_ASCENDING: - return compare_string_case_insensitive(itemA->name, itemB->name); + return strcicmp(itemA->name, itemB->name); case SORT_NAME_DESCENDING: - return -compare_string_case_insensitive(itemA->name, itemB->name); + return -strcicmp(itemA->name, itemB->name); case SORT_DATE_DESCENDING: return (int) -difftime(itemA->date_modified, itemB->date_modified); case SORT_DATE_ASCENDING: return (int) difftime(itemA->date_modified, itemB->date_modified); default: - return compare_string_case_insensitive(itemA->name, itemB->name); + return strcicmp(itemA->name, itemB->name); } } @@ -621,14 +592,14 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con loadsave_list_item *listItem; char filter[MAX_PATH]; - safe_strncpy(_directory, directory, sizeof(_directory)); + safe_strcpy(_directory, directory, sizeof(_directory)); if (_extension != extension) { - safe_strncpy(_extension, extension, sizeof(_extension)); + safe_strcpy(_extension, extension, sizeof(_extension)); _extension[sizeof(_extension) - 1] = '\0'; } _shortenedDirectory[0] = '\0'; - safe_strncpy(filter, directory, sizeof(filter)); + safe_strcpy(filter, directory, sizeof(filter)); strncat(filter, "*", sizeof(filter) - strnlen(filter, MAX_PATH) - 1); strncat(filter, extension, sizeof(filter) - strnlen(filter, MAX_PATH) - 1); @@ -669,7 +640,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con if(directory[i]==separator) break; } - safe_strncpy(_parentDirectory, directory, sizeof(_parentDirectory)); + safe_strcpy(_parentDirectory, directory, sizeof(_parentDirectory)); _parentDirectory[i+1] = '\0'; if(_parentDirectory[0]=='\0' && platform_get_drives()==0) w->disabled_widgets |= (1<path, '\0', MAX_PATH); - safe_strncpy(listItem->path, directory, MAX_PATH); - strncat(listItem->path, subDir, MAX_PATH); - safe_strncpy(listItem->name, subDir, sizeof(listItem->name)); + safe_strcpy(listItem->path, directory, MAX_PATH); + strncat(listItem->path, subDir, MAX_PATH - strnlen(listItem->path, MAX_PATH) - 1); + safe_strcpy(listItem->name, subDir, sizeof(listItem->name)); listItem->type = TYPE_DIRECTORY; _listItemsCount++; } platform_enumerate_files_end(fileEnumHandle); - window_loadsave_sort_list(sortStartIndex, _listItemsCount - 1); fileEnumHandle = platform_enumerate_files_begin(filter); while (platform_enumerate_files_next(fileEnumHandle, &fileInfo)) { @@ -709,8 +679,8 @@ 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)); + safe_strcpy(listItem->path, directory, 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); @@ -728,6 +698,7 @@ static void window_loadsave_populate_list(rct_window *w, int includeNewItem, con _listItemsCount++; } platform_enumerate_files_end(fileEnumHandle); + window_loadsave_sort_list(sortStartIndex, _listItemsCount - 1); } } @@ -745,8 +716,8 @@ static void window_loadsave_select(rct_window *w, const char *path) case (LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME) : if (gLoadSaveTitleSequenceSave) { utf8 newName[MAX_PATH]; - char *extension = (char*)path_get_extension(path_get_filename(path)); - safe_strncpy(newName, path_get_filename(path), MAX_PATH); + char *extension = (char*)path_get_extension(path); + safe_strcpy(newName, path_get_filename(path), MAX_PATH); if (_stricmp(extension, ".sv6") != 0 && _stricmp(extension, ".sc6") != 0) strcat(newName, ".sv6"); if (title_sequence_save_exists(gCurrentTitleSequence, newName)) { @@ -758,21 +729,14 @@ static void window_loadsave_select(rct_window *w, const char *path) window_close(w); } window_loadsave_invoke_callback(MODAL_RESULT_OK); - } - else if (game_load_save(path)) { - if (_loadsaveType & LOADSAVETYPE_NETWORK) { - network_begin_server(gConfigNetwork.default_port); - } - - safe_strncpy(gScenarioSavePath, path, MAX_PATH); + } else if (game_load_save(path)) { + safe_strcpy(gScenarioSavePath, path, MAX_PATH); gFirstTimeSave = 0; window_close(w); gfx_invalidate_screen(); window_loadsave_invoke_callback(MODAL_RESULT_OK); - rct2_endupdate(); - } - else { + } else { // 1050, not the best message... window_error_open(STR_LOAD_GAME, 1050); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); @@ -784,12 +748,10 @@ static void window_loadsave_select(rct_window *w, const char *path) int success = scenario_save(rw, gConfigGeneral.save_plugin_data ? 1 : 0); SDL_RWclose(rw); if (success) { - - safe_strncpy(gScenarioSavePath, path, MAX_PATH); + safe_strcpy(gScenarioSavePath, path, MAX_PATH); gFirstTimeSave = 0; window_close_by_class(WC_LOADSAVE); - game_do_command(0, 1047, 0, -1, GAME_COMMAND_SET_RIDE_APPEARANCE, 0, 0); gfx_invalidate_screen(); window_loadsave_invoke_callback(MODAL_RESULT_OK); @@ -803,13 +765,10 @@ static void window_loadsave_select(rct_window *w, const char *path) } break; case (LOADSAVETYPE_LOAD | LOADSAVETYPE_LANDSCAPE) : - editor_load_landscape(path); - if (1) { + if (editor_load_landscape(path)) { gfx_invalidate_screen(); window_loadsave_invoke_callback(MODAL_RESULT_OK); - rct2_endupdate(); - } - else { + } else { // 1050, not the best message... window_error_open(STR_LOAD_LANDSCAPE, 1050); window_loadsave_invoke_callback(MODAL_RESULT_FAIL); @@ -854,7 +813,7 @@ static void window_loadsave_select(rct_window *w, const char *path) window_loadsave_invoke_callback(MODAL_RESULT_OK); title_load(); } else { - window_error_open(STR_SAVE_SCENARIO, STR_SCENARIO_SAVE_FAILED); + window_error_open(STR_FILE_DIALOG_TITLE_SAVE_SCENARIO, STR_SCENARIO_SAVE_FAILED); s6Info->editor_step = EDITOR_STEP_OBJECTIVE_SELECTION; window_loadsave_invoke_callback(MODAL_RESULT_FAIL); } @@ -941,8 +900,8 @@ static rct_window *window_overwrite_prompt_open(const char *name, const char *pa w->flags |= WF_TRANSPARENT; w->colours[0] = 154; - safe_strncpy(_window_overwrite_prompt_name, name, sizeof(_window_overwrite_prompt_name)); - safe_strncpy(_window_overwrite_prompt_path, path, sizeof(_window_overwrite_prompt_path)); + safe_strcpy(_window_overwrite_prompt_name, name, sizeof(_window_overwrite_prompt_name)); + safe_strcpy(_window_overwrite_prompt_path, path, sizeof(_window_overwrite_prompt_path)); return w; } diff --git a/src/windows/main.c b/src/windows/main.c index e1bdf08aa8..36278bdb96 100644 --- a/src/windows/main.c +++ b/src/windows/main.c @@ -92,7 +92,7 @@ void window_main_open() /** * - * rct2: 0x66CCAE + * rct2: 0x66CCAE * This function immediately jumps to 0x00685BE1 this is the second function * decompiled. */ diff --git a/src/windows/map.c b/src/windows/map.c index b932d36c1b..95e6bc513a 100644 --- a/src/windows/map.c +++ b/src/windows/map.c @@ -75,15 +75,15 @@ static rct_widget window_map_widgets[] = { { WWT_CAPTION, 0, 1, 243, 1, 14, STR_MAP, STR_WINDOW_TITLE_TIP }, { WWT_CLOSEBOX, 0, 232, 242, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, { WWT_RESIZE, 1, 0, 244, 43, 257, STR_NONE, STR_NONE }, - { WWT_COLORBTN, 1, 3, 33, 17, 43, 0x02000144E, STR_SHOW_PEOPLE_ON_MAP_TIP }, - { WWT_COLORBTN, 1, 34, 64, 17, 43, 0x02000144E, STR_SHOW_RIDES_STALLS_ON_MAP_TIP }, + { WWT_COLOURBTN, 1, 3, 33, 17, 43, 0x02000144E, STR_SHOW_PEOPLE_ON_MAP_TIP }, + { WWT_COLOURBTN, 1, 34, 64, 17, 43, 0x02000144E, STR_SHOW_RIDES_STALLS_ON_MAP_TIP }, { WWT_SCROLL, 1, 3, 241, 46, 225, 0x3, STR_NONE }, { WWT_SPINNER, 1, 104, 198, 229, 240, 0xC8C, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 187, 197, 230, 234, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 187, 197, 235, 239, STR_NUMERIC_DOWN, STR_NONE }, { WWT_FLATBTN, 1, 4, 27, 1, 24, SPR_BUY_LAND_RIGHTS, STR_SELECT_PARK_OWNED_LAND_TIP }, { WWT_FLATBTN, 1, 4, 27, 1, 24, SPR_PARK_ENTRANCE, STR_BUILD_PARK_ENTRANCE_TIP }, - { WWT_FLATBTN, 1, 28, 51, 1, 24, STR_NONE, STR_SET_STARTING_POSITIONS_TIP }, + { WWT_FLATBTN, 1, 28, 51, 1, 24, SPR_NONE, STR_SET_STARTING_POSITIONS_TIP }, { WWT_IMGBTN, 1, 4, 47, 17, 48, SPR_LAND_TOOL_SIZE_0, STR_NONE }, { WWT_TRNBTN, 1, 5, 20, 18, 33, 0x02000157B, STR_ADJUST_SMALLER_LAND_TIP }, { WWT_TRNBTN, 1, 31, 46, 32, 47, 0x02000157D, STR_ADJUST_LARGER_LAND_TIP }, @@ -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(); @@ -318,8 +318,8 @@ static void window_map_mouseup(rct_window *w, int widgetIndex) if (tool_set(w, widgetIndex, 2)) break; - RCT2_GLOBAL(0x9E32D2, sint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint32) |= INPUT_FLAG_6; + RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_GHOST_EXISTS, sint8) = 0; + gInputFlags |= INPUT_FLAG_6; show_gridlines(); show_land_rights(); @@ -527,7 +527,7 @@ static void window_map_scrollgetsize(rct_window *w, int scrollIndex, int *width, */ static void window_map_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) { - int mapX, mapY, mapZ; + int mapX = 0, mapY = 0, mapZ = 0; rct_window *mainWindow; map_window_screen_to_map(x, y, &mapX, &mapY); @@ -636,7 +636,7 @@ static void window_map_textinput(rct_window *w, int widgetIndex, char *text) } } -/* +/** * * rct2: 0x0068D140 */ @@ -740,9 +740,9 @@ 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) && - RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, uint8) == WC_MAP && - RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint8) == WIDX_BUILD_PARK_ENTRANCE + (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 ) { w->widgets[WIDX_ROTATE_90].type = WWT_FLATBTN; } @@ -752,11 +752,11 @@ 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 - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint8) != WIDX_SET_LAND_RIGHTS) { + if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != WIDX_SET_LAND_RIGHTS) { window_map_show_default_scenario_editor_buttons(w); } else { // if in set land rights mode: show land tool buttons + modes w->widgets[WIDX_LAND_TOOL].type = WWT_IMGBTN; @@ -863,7 +863,7 @@ static void window_map_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int sc */ static void window_map_init_map() { - memset(RCT2_GLOBAL(RCT2_ADDRESS_MAP_IMAGE_DATA, void*), 0x0A0A0A0A, 256 * 256 * sizeof(uint32)); + memset(RCT2_GLOBAL(RCT2_ADDRESS_MAP_IMAGE_DATA, void*), 0x0A, 256 * 256 * sizeof(uint32)); RCT2_GLOBAL(0x00F1AD6C, uint32) = 0; } @@ -930,20 +930,20 @@ static void window_map_show_default_scenario_editor_buttons(rct_window *w) { w->widgets[WIDX_MAP_SIZE_SPINNER].type = WWT_SPINNER; w->widgets[WIDX_MAP_SIZE_SPINNER_UP].type = WWT_DROPDOWN_BUTTON; w->widgets[WIDX_MAP_SIZE_SPINNER_DOWN].type = WWT_DROPDOWN_BUTTON; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) - 2; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE, uint16) - 2; } 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); } @@ -968,7 +968,7 @@ static void window_map_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi) /** * - * part of window_map_paint_peep_overlay and window_map_paint_train_overlay + * part of window_map_paint_peep_overlay and window_map_paint_train_overlay */ static void window_map_transform_to_map_coords(sint16 *left, sint16 *top) { @@ -1012,7 +1012,7 @@ static void window_map_paint_peep_overlay(rct_drawpixelinfo *dpi) uint16 spriteIndex; sint16 left, right, bottom, top; - sint16 color; + sint16 colour; FOR_ALL_PEEPS(spriteIndex, peep) { left = peep->x; @@ -1026,26 +1026,26 @@ static void window_map_paint_peep_overlay(rct_drawpixelinfo *dpi) right = left; bottom = top; - color = 0x14; + colour = 0x14; - if ((peep->var_0C & 0x200) != 0) { + if ((peep->flags & SPRITE_FLAGS_PEEP_FLASHING) != 0) { if (peep->type == PEEP_TYPE_STAFF) { if ((RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) & (1 << 3)) != 0) { - color = 0x8A; + colour = 0x8A; left--; if ((RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) & (1 << 15)) == 0) - color = 0xA; + colour = 0xA; } } else { if ((RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) & (1 << 1)) != 0) { - color = 0xAC; + colour = 0xAC; left--; if ((RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_MAP_FLASHING_FLAGS, uint16) & (1 << 15)) == 0) - color = 0x15; + colour = 0x15; } } } - gfx_fill_rect(dpi, left, top, right, bottom, color); + gfx_fill_rect(dpi, left, top, right, bottom, colour); } } @@ -1082,8 +1082,8 @@ static void window_map_paint_train_overlay(rct_drawpixelinfo *dpi) } /** - * The call to gfx_fill_rect was originally wrapped in sub_68DABD which made sure that arguments were ordered correctly, - * but it doesn't look like it's ever necessary here so the call was removed. + * The call to gfx_fill_rect was originally wrapped in sub_68DABD which made sure that arguments were ordered correctly, + * but it doesn't look like it's ever necessary here so the call was removed. * * rct2: 0x0068D8CE */ @@ -1399,7 +1399,8 @@ static const uint16 ElementTypeMaskColour[] = { 0x0000, // MAP_ELEMENT_TYPE_ENTRANCE 0xFFFF, // MAP_ELEMENT_TYPE_FENCE 0x0000, // MAP_ELEMENT_TYPE_SCENERY_MULTIPLE - 0xFFFF // MAP_ELEMENT_TYPE_BANNER + 0xFFFF, // MAP_ELEMENT_TYPE_BANNER + 0x0000, // MAP_ELEMENT_TYPE_CORRUPT }; static const uint16 ElementTypeAddColour[] = { @@ -1410,7 +1411,8 @@ static const uint16 ElementTypeAddColour[] = { 0xBABA, // MAP_ELEMENT_TYPE_ENTRANCE 0x0000, // MAP_ELEMENT_TYPE_FENCE 0x6363, // MAP_ELEMENT_TYPE_SCENERY_MULTIPLE - 0x0000 // MAP_ELEMENT_TYPE_BANNER + 0x0000, // MAP_ELEMENT_TYPE_BANNER + 0x4444, // MAP_ELEMENT_TYPE_CORRUPT }; enum { @@ -1545,10 +1547,14 @@ static uint16 map_window_get_pixel_colour_peep(int x, int y) if (!(mapElement->properties.surface.ownership & OWNERSHIP_OWNED)) colour = 10 | (colour & 0xFF00); + const int maxSupportedMapElementType = (int)countof(ElementTypeAddColour); while (!map_element_is_last_for_tile(mapElement++)) { - int mapElementType = map_element_get_type(mapElement); - colour &= ElementTypeMaskColour[mapElementType >> 2]; - colour |= ElementTypeAddColour[mapElementType >> 2]; + int mapElementType = map_element_get_type(mapElement) >> 2; + if (mapElementType >= maxSupportedMapElementType) { + mapElementType = MAP_ELEMENT_TYPE_CORRUPT >> 2; + } + colour &= ElementTypeMaskColour[mapElementType]; + colour |= ElementTypeAddColour[mapElementType]; } return colour; @@ -1582,7 +1588,7 @@ static uint16 map_window_get_pixel_colour_ride(int x, int y) break; // fall-through case MAP_ELEMENT_TYPE_TRACK: - ride = GET_RIDE(mapElement->properties.track.ride_index); + ride = get_ride(mapElement->properties.track.ride_index); colour = RideKeyColours[RideColourKey[ride->type]]; break; } @@ -1597,7 +1603,7 @@ static uint16 map_window_get_pixel_colour_ride(int x, int y) static void map_window_set_pixels(rct_window *w) { uint16 colour = 0, *destination; - int x, y, dx, dy; + int x = 0, y = 0, dx = 0, dy = 0; destination = (uint16*)((RCT2_GLOBAL(0x00F1AD6C, uint32) * 511) + RCT2_GLOBAL(RCT2_ADDRESS_MAP_IMAGE_DATA, uint32) + 255); switch (get_current_rotation()) { diff --git a/src/windows/map_tooltip.c b/src/windows/map_tooltip.c index 8499a0b7d2..d09f2df031 100644 --- a/src/windows/map_tooltip.c +++ b/src/windows/map_tooltip.c @@ -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, uint8); + inputFlags = gInputFlags; // Check for cursor movement _cursorHoldDuration++; @@ -95,7 +95,7 @@ void window_map_tooltip_update_visibility() if ( _cursorHoldDuration < 25 || RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS, sint16) == -1 || - (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 3) || + (gInputPlaceObjectModifier & 3) || window_find_by_class(WC_ERROR) != NULL ) { window_close_by_class(WC_MAP_TOOLTIP); @@ -148,8 +148,8 @@ static void window_map_tooltip_update(rct_window *w) */ static void window_map_tooltip_paint(rct_window *w, rct_drawpixelinfo *dpi) { - if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS, rct_string_id) == (rct_string_id)STR_NONE) + if (RCT2_GLOBAL(RCT2_ADDRESS_MAP_TOOLTIP_ARGS, rct_string_id) == STR_NONE) return; gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_MAP_TOOLTIP_ARGS, w->x + (w->width / 2), w->y + (w->height / 2), w->width, 1162, 0); -} \ No newline at end of file +} diff --git a/src/windows/mapgen.c b/src/windows/mapgen.c index 03cb6a5e18..7676ad49ad 100644 --- a/src/windows/mapgen.c +++ b/src/windows/mapgen.c @@ -391,7 +391,7 @@ static uint32 window_mapgen_page_hold_down_widgets[] = { #pragma endregion -const int window_mapgen_tab_animation_loops[] = { 16, 16 }; +const int window_mapgen_tab_animation_loops[] = { 16, 16, 16 }; #define MINIMUM_MAP_SIZE_TECHNICAL 15 #define MAXIMUM_MAP_SIZE_TECHNICAL 256 @@ -429,7 +429,7 @@ static int _placeTrees = 1; static int _simplex_low = 6; static int _simplex_high = 10; -static sint16 _simplex_base_freq = 60; +static sint32 _simplex_base_freq = 60; static int _simplex_octaves = 4; rct_window *window_mapgen_open() @@ -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; } @@ -509,7 +509,7 @@ static void window_mapgen_base_mouseup(rct_window *w, int widgetIndex) static void window_mapgen_base_mousedown(int widgetIndex, rct_window *w, rct_widget* widget) { int i; - + int defaultIndex = -1; switch (widgetIndex) { case WIDX_MAP_SIZE_UP: _mapSize = min(_mapSize + 1, MAXIMUM_MAP_SIZE_TECHNICAL); @@ -540,7 +540,7 @@ static void window_mapgen_base_mousedown(int widgetIndex, rct_window *w, rct_wid gDropdownItemsFormat[i] = -1; gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + window_land_floor_texture_order[i]; if (window_land_floor_texture_order[i] == _floorTexture) - gDropdownHighlightedIndex = i; + defaultIndex = i; } window_dropdown_show_image( w->x + widget->left, w->y + widget->top, @@ -551,13 +551,14 @@ static void window_mapgen_base_mousedown(int widgetIndex, rct_window *w, rct_wid 47, 36, gAppropriateImageDropdownItemsPerRow[14] ); + gDropdownDefaultIndex = defaultIndex; break; case WIDX_WALL_TEXTURE: for (i = 0; i < 4; i++) { gDropdownItemsFormat[i] = -1; gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + window_land_wall_texture_order[i]; if (window_land_wall_texture_order[i] == _wallTexture) - gDropdownHighlightedIndex = i; + defaultIndex = i; } window_dropdown_show_image( w->x + widget->left, w->y + widget->top, @@ -568,6 +569,7 @@ static void window_mapgen_base_mousedown(int widgetIndex, rct_window *w, rct_wid 47, 36, gAppropriateImageDropdownItemsPerRow[4] ); + gDropdownDefaultIndex = defaultIndex; break; } } @@ -583,7 +585,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 +601,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 +792,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; @@ -818,7 +820,7 @@ static void window_mapgen_simplex_mouseup(rct_window *w, int widgetIndex) static void window_mapgen_simplex_mousedown(int widgetIndex, rct_window *w, rct_widget* widget) { int i; - + int defaultIndex = -1; switch (widgetIndex) { case WIDX_SIMPLEX_LOW_UP: _simplex_low = min(_simplex_low + 1, 24); @@ -873,7 +875,7 @@ static void window_mapgen_simplex_mousedown(int widgetIndex, rct_window *w, rct_ gDropdownItemsFormat[i] = -1; gDropdownItemsArgs[i] = SPR_FLOOR_TEXTURE_GRASS + window_land_floor_texture_order[i]; if (window_land_floor_texture_order[i] == _floorTexture) - gDropdownHighlightedIndex = i; + defaultIndex = i; } window_dropdown_show_image( w->x + widget->left, w->y + widget->top, @@ -884,13 +886,14 @@ static void window_mapgen_simplex_mousedown(int widgetIndex, rct_window *w, rct_ 47, 36, gAppropriateImageDropdownItemsPerRow[14] ); + gDropdownDefaultIndex = defaultIndex; break; case WIDX_SIMPLEX_WALL_TEXTURE: for (i = 0; i < 4; i++) { gDropdownItemsFormat[i] = -1; gDropdownItemsArgs[i] = SPR_WALL_TEXTURE_ROCK + window_land_wall_texture_order[i]; if (window_land_wall_texture_order[i] == _wallTexture) - gDropdownHighlightedIndex = i; + defaultIndex = i; } window_dropdown_show_image( w->x + widget->left, w->y + widget->top, @@ -901,6 +904,7 @@ static void window_mapgen_simplex_mousedown(int widgetIndex, rct_window *w, rct_ 47, 36, gAppropriateImageDropdownItemsPerRow[4] ); + gDropdownDefaultIndex = defaultIndex; break; } } @@ -916,7 +920,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 +937,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; diff --git a/src/windows/maze_construction.c b/src/windows/maze_construction.c index a3c992b76d..3b304e0c4f 100644 --- a/src/windows/maze_construction.c +++ b/src/windows/maze_construction.c @@ -139,7 +139,7 @@ static void window_maze_construction_construct(int direction); /** * - * rct2: 0x006CB481 + * rct2: 0x006CB481 */ rct_window *window_maze_construction_open() { @@ -159,7 +159,7 @@ rct_window *window_maze_construction_open() /** * - * rct2: 0x006CD811 + * rct2: 0x006CD811 */ static void window_maze_construction_close(rct_window *w) { @@ -176,7 +176,7 @@ static void window_maze_construction_close(rct_window *w) hide_gridlines(); uint8 rideIndex = _currentRideIndex; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride->overall_view == 0xFFFF) { int savedPausedState = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8); RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) = 0; @@ -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(); @@ -208,7 +208,7 @@ static void window_maze_construction_entrance_mouseup(rct_window *w, int widgetI /** * - * rct2: 0x006CD461 + * rct2: 0x006CD461 */ static void window_maze_construction_mouseup(rct_window *w, int widgetIndex) { @@ -233,7 +233,7 @@ static void window_maze_construction_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006CD623 + * rct2: 0x006CD623 */ static void window_maze_construction_resize(rct_window *w) { @@ -265,7 +265,7 @@ static void window_maze_construction_resize(rct_window *w) /** * - * rct2: 0x006CD48C + * rct2: 0x006CD48C */ static void window_maze_construction_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { @@ -287,10 +287,16 @@ static void window_maze_construction_mousedown(int widgetIndex, rct_window *w, r /** * - * rct2: 0x006CD767 + * rct2: 0x006CD767 */ static void window_maze_construction_update(rct_window *w) { + rct_ride *ride = get_ride(_currentRideIndex); + if (ride == NULL || ride->status != RIDE_STATUS_CLOSED) { + window_close(w); + return; + } + switch (_rideConstructionState) { case RIDE_CONSTRUCTION_STATE_PLACE: if (!widget_is_active_tool(w, WIDX_MAZE_DIRECTION_GROUPBOX)) { @@ -311,7 +317,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, uint8) & INPUT_FLAG_TOOL_ACTIVE) && + (gInputFlags & INPUT_FLAG_TOOL_ACTIVE) && RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WINDOWCLASS, rct_windowclass) == WC_RIDE_CONSTRUCTION ) { tool_cancel(); @@ -323,7 +329,7 @@ static void window_maze_construction_update(rct_window *w) /** * - * rct2: 0x006CD63E + * rct2: 0x006CD63E */ static void window_maze_construction_toolupdate(rct_window* w, int widgetIndex, int x, int y) { @@ -357,7 +363,7 @@ static void window_maze_construction_entrance_tooldown(int x, int y, rct_window* uint8 rideIndex = RCT2_GLOBAL(0x00F44192, uint8); uint8 is_exit = RCT2_GLOBAL(0x00F44191, uint8); - RCT2_GLOBAL(0x00141E9AE, rct_string_id) = is_exit ? 1144 : 1145; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = is_exit ? 1144 : 1145; money32 cost = game_do_command( x, @@ -377,16 +383,16 @@ static void window_maze_construction_entrance_tooldown(int x, int y, rct_window* RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, sint16), RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16)); - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); if (ride_are_all_possible_entrances_and_exits_built(ride)){ tool_cancel(); - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15)) + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK)) window_close(w); } else{ RCT2_GLOBAL(0x00F44191, uint8) = is_exit ^ 1; window_invalidate_by_class(WC_RIDE_CONSTRUCTION); - RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint8) = is_exit ? WIDX_MAZE_ENTRANCE : WIDX_MAZE_EXIT; + RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) = is_exit ? WIDX_MAZE_ENTRANCE : WIDX_MAZE_EXIT; } } @@ -409,20 +415,20 @@ static void window_maze_construction_tooldown(rct_window* w, int widgetIndex, in /** * - * rct2: 0x006CD435 + * rct2: 0x006CD435 */ static void window_maze_construction_invalidate(rct_window *w) { - rct_ride *ride = GET_RIDE(_currentRideIndex); + rct_ride *ride = get_ride(_currentRideIndex); // Set window title arguments - RCT2_GLOBAL(0x013CE956, rct_string_id) = ride->name; - RCT2_GLOBAL(0x013CE958, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, rct_string_id) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint32) = ride->name_arguments; } /** * - * rct2: 0x006CD45B + * rct2: 0x006CD45B */ static void window_maze_construction_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -431,7 +437,7 @@ static void window_maze_construction_paint(rct_window *w, rct_drawpixelinfo *dpi /** * - * rct2: 0x006CD887 + * rct2: 0x006CD887 */ void window_maze_construction_update_pressed_widgets() { @@ -464,7 +470,7 @@ void window_maze_construction_update_pressed_widgets() /** * - * rct2: 0x006CD4AB + * rct2: 0x006CD4AB */ static void window_maze_construction_construct(int direction) { diff --git a/src/windows/multiplayer.c b/src/windows/multiplayer.c new file mode 100644 index 0000000000..460f6d68a3 --- /dev/null +++ b/src/windows/multiplayer.c @@ -0,0 +1,713 @@ +/***************************************************************************** + * 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 . + *****************************************************************************/ + +#include "../interface/themes.h" +#include "../interface/widget.h" +#include "../interface/window.h" +#include "../localisation/localisation.h" +#include "../network/network.h" +#include "../sprites.h" +#include "../util/util.h" +#include "dropdown.h" + +enum { + WINDOW_MULTIPLAYER_PAGE_PLAYERS, + WINDOW_MULTIPLAYER_PAGE_GROUPS +}; + +enum WINDOW_MULTIPLAYER_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_CONTENT_PANEL, + WIDX_TAB1, + WIDX_TAB2, + + WIDX_LIST = 6, + + WIDX_DEFAULT_GROUP = 6, + WIDX_DEFAULT_GROUP_DROPDOWN, + WIDX_ADD_GROUP, + WIDX_REMOVE_GROUP, + WIDX_RENAME_GROUP, + WIDX_SELECTED_GROUP, + WIDX_SELECTED_GROUP_DROPDOWN, + WIDX_PERMISSIONS_LIST, +}; + +static rct_widget window_multiplayer_players_widgets[] = { + { WWT_FRAME, 0, 0, 339, 0, 239, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 338, 1, 14, STR_MULTIPLAYER, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, STR_NONE }, // content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_PLAYERS_TIP }, // tab + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_GROUPS_TIP }, // tab + { WWT_SCROLL, 1, 3, 336, 60, 236, 2, STR_NONE }, // list + { WIDGETS_END } +}; + +static rct_widget window_multiplayer_groups_widgets[] = { + { WWT_FRAME, 0, 0, 339, 0, 239, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 338, 1, 14, STR_MULTIPLAYER, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, STR_NONE }, // content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_PLAYERS_TIP }, // tab + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_GROUPS_TIP }, // tab + { WWT_DROPDOWN, 1, 141, 315, 46, 57, 0x0FFFFFFFF, STR_NONE }, // default group + { WWT_DROPDOWN_BUTTON, 1, 305, 315, 47, 56, 876, STR_NONE }, // + { WWT_DROPDOWN_BUTTON, 1, 11, 102, 65, 76, STR_ADD_GROUP, STR_NONE }, // add group button + { WWT_DROPDOWN_BUTTON, 1, 113, 204, 65, 76, STR_REMOVE_GROUP, STR_NONE }, // remove group button + { WWT_DROPDOWN_BUTTON, 1, 215, 306, 65, 76, STR_RENAME_GROUP, STR_NONE }, // rename group button + { WWT_DROPDOWN, 1, 72, 246, 80, 91, 0x0FFFFFFFF, STR_NONE }, // selected group + { WWT_DROPDOWN_BUTTON, 1, 236, 246, 81, 90, 876, STR_NONE }, // + { WWT_SCROLL, 1, 3, 316, 94, 300, 2, STR_NONE }, // permissions list + { WIDGETS_END } +}; + +static rct_widget *window_multiplayer_page_widgets[] = { + window_multiplayer_players_widgets, + window_multiplayer_groups_widgets +}; + +const uint64 window_multiplayer_page_enabled_widgets[] = { + (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2), + (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) | (1 << WIDX_DEFAULT_GROUP) | (1 << WIDX_DEFAULT_GROUP_DROPDOWN) | (1 << WIDX_ADD_GROUP) | (1 << WIDX_REMOVE_GROUP) | (1 << WIDX_RENAME_GROUP) | (1 << WIDX_SELECTED_GROUP) | (1 << WIDX_SELECTED_GROUP_DROPDOWN) +}; + +static uint8 _selectedGroup = 0; + +static void window_multiplayer_players_mouseup(rct_window *w, int widgetIndex); +static void window_multiplayer_players_resize(rct_window *w); +static void window_multiplayer_players_mousedown(int widgetIndex, rct_window* w, rct_widget* widget); +static void window_multiplayer_players_update(rct_window *w); +static void window_multiplayer_players_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); +static void window_multiplayer_players_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); +static void window_multiplayer_players_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); +static void window_multiplayer_players_invalidate(rct_window *w); +static void window_multiplayer_players_paint(rct_window *w, rct_drawpixelinfo *dpi); +static void window_multiplayer_players_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); + +static void window_multiplayer_groups_mouseup(rct_window *w, int widgetIndex); +static void window_multiplayer_groups_resize(rct_window *w); +static void window_multiplayer_groups_mousedown(int widgetIndex, rct_window* w, rct_widget* widget); +static void window_multiplayer_groups_dropdown(rct_window *w, int widgetIndex, int dropdownIndex); +static void window_multiplayer_groups_update(rct_window *w); +static void window_multiplayer_groups_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); +static void window_multiplayer_groups_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); +static void window_multiplayer_groups_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); +static void window_multiplayer_groups_text_input(rct_window *w, int widgetIndex, char *text); +static void window_multiplayer_groups_invalidate(rct_window *w); +static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dpi); +static void window_multiplayer_groups_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); + +static rct_window_event_list window_multiplayer_players_events = { + NULL, + window_multiplayer_players_mouseup, + window_multiplayer_players_resize, + window_multiplayer_players_mousedown, + NULL, + NULL, + window_multiplayer_players_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_multiplayer_players_scrollgetsize, + window_multiplayer_players_scrollmousedown, + NULL, + window_multiplayer_players_scrollmouseover, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_multiplayer_players_invalidate, + window_multiplayer_players_paint, + window_multiplayer_players_scrollpaint +}; + +static rct_window_event_list window_multiplayer_groups_events = { + NULL, + window_multiplayer_groups_mouseup, + window_multiplayer_groups_resize, + window_multiplayer_groups_mousedown, + window_multiplayer_groups_dropdown, + NULL, + window_multiplayer_groups_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_multiplayer_groups_scrollgetsize, + window_multiplayer_groups_scrollmousedown, + NULL, + window_multiplayer_groups_scrollmouseover, + window_multiplayer_groups_text_input, + NULL, + NULL, + NULL, + NULL, + NULL, + window_multiplayer_groups_invalidate, + window_multiplayer_groups_paint, + window_multiplayer_groups_scrollpaint +}; + +static rct_window_event_list *window_multiplayer_page_events[] = { + &window_multiplayer_players_events, + &window_multiplayer_groups_events +}; + +const int window_multiplayer_animation_divisor[] = { 4, 4 }; +const int window_multiplayer_animation_frames[] = { 8, 16 }; + +static void window_multiplayer_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi); +static void window_multiplayer_set_page(rct_window* w, int page); + +void window_multiplayer_open() +{ + rct_window* window; + + // Check if window is already open + window = window_bring_to_front_by_class(WC_MULTIPLAYER); + if (window != NULL) + return; + + window = window_create_auto_pos(320, 144, &window_multiplayer_players_events, WC_MULTIPLAYER, WF_10 | WF_RESIZABLE); + + window_multiplayer_set_page(window, WINDOW_MULTIPLAYER_PAGE_PLAYERS); + + window->page = WINDOW_MULTIPLAYER_PAGE_PLAYERS; + window->list_information_type = 0; +} + +static void window_multiplayer_set_page(rct_window* w, int page){ + w->page = page; + w->frame_no = 0; + w->no_list_items = 0; + w->selected_list_item = -1; + + w->enabled_widgets = window_multiplayer_page_enabled_widgets[page]; + w->hold_down_widgets = 0; + w->event_handlers = window_multiplayer_page_events[page]; + w->pressed_widgets = 0; + w->widgets = window_multiplayer_page_widgets[page]; + window_event_resize_call(w); + window_event_invalidate_call(w); + window_init_scroll_widgets(w); + window_invalidate(w); +} + +static void window_multiplayer_anchor_border_widgets(rct_window *w) +{ + w->widgets[WIDX_BACKGROUND].right = w->width - 1; + w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; + w->widgets[WIDX_TITLE].right = w->width - 2; + w->widgets[WIDX_CONTENT_PANEL].right = w->width - 1; + w->widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1; + w->widgets[WIDX_CLOSE].left = w->width - 13; + w->widgets[WIDX_CLOSE].right = w->width - 3; +} + +static void window_multiplayer_set_pressed_tab(rct_window *w) +{ + for (int i = 0; i < 2; i++) { + w->pressed_widgets &= ~(1 << (WIDX_TAB1 + i)); + } + w->pressed_widgets |= 1LL << (WIDX_TAB1 + w->page); +} + +static void window_multiplayer_groups_show_group_dropdown(rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + int numItems, i; + + dropdownWidget = widget - 1; + + numItems = network_get_num_groups(); + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + numItems, + widget->right - dropdownWidget->left + ); + + for (i = 0; i < network_get_num_groups(); i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = network_get_group_name_string_id(i); + } + if (widget == &window_multiplayer_groups_widgets[WIDX_DEFAULT_GROUP_DROPDOWN]) { + dropdown_set_checked(network_get_group_index(network_get_default_group()), true); + } else + if (widget == &window_multiplayer_groups_widgets[WIDX_SELECTED_GROUP_DROPDOWN]) { + dropdown_set_checked(network_get_group_index(_selectedGroup), true); + } +} + +static void window_multiplayer_players_mouseup(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + } +} + +static void window_multiplayer_players_resize(rct_window *w) +{ + window_set_resize(w, 420, 124, 500, 450); + + w->no_list_items = network_get_num_players(); + w->list_item_positions[0] = 0; + + w->selected_list_item = -1; + window_invalidate(w); +} + +static void window_multiplayer_players_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) +{ + switch (widgetIndex) { + case WIDX_TAB1: + case WIDX_TAB2: + if (w->page != widgetIndex - WIDX_TAB1) { + window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1); + } + break; + } +} + +static void window_multiplayer_players_update(rct_window *w) +{ + w->frame_no++; + widget_invalidate(w, WIDX_TAB1 + w->page); +} + +static void window_multiplayer_players_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) +{ + int i; + + if (w->selected_list_item != -1) { + w->selected_list_item = -1; + window_invalidate(w); + } + + *height = network_get_num_players() * 10; + i = *height - window_multiplayer_players_widgets[WIDX_LIST].bottom + window_multiplayer_players_widgets[WIDX_LIST].top + 21; + if (i < 0) + i = 0; + if (i < w->scrolls[0].v_top) { + w->scrolls[0].v_top = i; + window_invalidate(w); + } +} + +static void window_multiplayer_players_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) +{ + int index; + + index = y / 10; + if (index >= w->no_list_items) + return; + + w->selected_list_item = index; + window_invalidate(w); + + rct_widget *listWidget = &w->widgets[WIDX_LIST]; + int ddx = w->x + listWidget->left + x - w->scrolls[0].h_left; + int ddy = w->y + listWidget->top + y - w->scrolls[0].v_top; + + window_player_open(network_get_player_id(index)); +} + +static void window_multiplayer_players_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) +{ + int index; + + index = y / 10; + if (index >= w->no_list_items) + return; + + w->selected_list_item = index; + window_invalidate(w); +} + +static void window_multiplayer_players_invalidate(rct_window *w) +{ + colour_scheme_update(w); + + window_multiplayer_set_pressed_tab(w); + window_multiplayer_anchor_border_widgets(w); + window_multiplayer_players_widgets[WIDX_LIST].right = w->width - 4; + window_multiplayer_players_widgets[WIDX_LIST].bottom = w->height - 0x0F; + window_align_tabs(w, WIDX_TAB1, WIDX_TAB2); +} + +static void window_multiplayer_players_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + rct_string_id stringId; + int x, y; + + window_draw_widgets(w, dpi); + window_multiplayer_draw_tab_images(w, dpi); + + // Columns + gfx_draw_string_left(dpi, STR_PLAYER, NULL, w->colours[2], w->x + 6, 58 - 12 + w->y + 1); + gfx_draw_string_left(dpi, STR_GROUP, NULL, w->colours[2], w->x + 180, 58 - 12 + w->y + 1); + gfx_draw_string_left(dpi, STR_LAST_ACTION, NULL, w->colours[2], w->x + 263, 58 - 12 + w->y + 1); + gfx_draw_string_left(dpi, STR_PING, NULL, w->colours[2], w->x + 363, 58 - 12 + w->y + 1); + + // Number of players + stringId = w->no_list_items == 1 ? STR_X_PLAYER : STR_X_PLAYERS; + x = w->x + 4; + y = w->y + w->widgets[WIDX_LIST].bottom + 2; + gfx_draw_string_left(dpi, stringId, &w->no_list_items, w->colours[2], x, y); +} + +static void window_multiplayer_players_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) +{ + int y; + + y = 0; + for (int i = 0; i < network_get_num_players(); i++) { + if (y > dpi->y + dpi->height) { + break; + } + + if (y + 11 >= dpi->y) { + char buffer[300]; + + // Draw player name + char* lineCh = buffer; + int colour = 0; + if (i == w->selected_list_item) { + gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031); + safe_strcpy(&buffer[0], network_get_player_name(i), sizeof(buffer)); + colour = w->colours[2]; + } else { + if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); + } else { + lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); + } + safe_strcpy(lineCh, network_get_player_name(i), sizeof(buffer) - (lineCh - buffer)); + } + gfx_clip_string(buffer, 230); + gfx_draw_string(dpi, buffer, colour, 0, y - 1); + + // Draw group name + lineCh = buffer; + int group = network_get_group_index(network_get_player_group(i)); + if (group != -1) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); + safe_strcpy(lineCh, network_get_group_name(group), sizeof(buffer) - (lineCh - buffer)); + gfx_clip_string(buffer, 80); + gfx_draw_string(dpi, buffer, colour, 173, y - 1); + } + + // Draw last action + int action = network_get_player_last_action(i, 2000); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_ACTION_NA; + if (action != -999) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_action_name_string_id(action); + } + gfx_draw_string_left_clipped(dpi, 1191, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 256, y - 1, 100); + + // Draw ping + lineCh = buffer; + int ping = network_get_player_ping(i); + if (ping <= 100) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); + } else + if (ping <= 250) { + lineCh = utf8_write_codepoint(lineCh, FORMAT_YELLOW); + } else { + lineCh = utf8_write_codepoint(lineCh, FORMAT_RED); + } + sprintf(lineCh, "%d ms", ping); + gfx_draw_string(dpi, buffer, colour, 356, y - 1); + } + y += 10; + } +} + +static void window_multiplayer_groups_mouseup(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_ADD_GROUP: + game_do_command(0, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_MODIFY_GROUPS, 0, 0); + break; + case WIDX_REMOVE_GROUP: + game_do_command(1 | (_selectedGroup << 8), GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_MODIFY_GROUPS, 0, 0); + break; + case WIDX_RENAME_GROUP:; + int groupIndex = network_get_group_index(_selectedGroup); + const utf8 *groupName = network_get_group_name(groupIndex); + window_text_input_raw_open(w, widgetIndex, STR_GROUP_NAME, STR_ENTER_NEW_NAME_FOR_THIS_GROUP, (utf8*)groupName, 32); + break; + } +} + +static void window_multiplayer_groups_resize(rct_window *w) +{ + window_set_resize(w, 320, 200, 320, 500); + + w->no_list_items = network_get_num_actions(); + w->list_item_positions[0] = 0; + + w->selected_list_item = -1; + window_invalidate(w); +} + +static void window_multiplayer_groups_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) +{ + switch (widgetIndex) { + case WIDX_TAB1: + case WIDX_TAB2: + if (w->page != widgetIndex - WIDX_TAB1) { + window_multiplayer_set_page(w, widgetIndex - WIDX_TAB1); + } + break; + case WIDX_DEFAULT_GROUP_DROPDOWN: + window_multiplayer_groups_show_group_dropdown(w, widget); + break; + case WIDX_SELECTED_GROUP_DROPDOWN: + window_multiplayer_groups_show_group_dropdown(w, widget); + break; + } +} + +static void window_multiplayer_groups_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) +{ + if (dropdownIndex == -1) { + return; + } + + switch(widgetIndex){ + case WIDX_DEFAULT_GROUP_DROPDOWN: + game_do_command(4 | (network_get_group_id(dropdownIndex) << 8), GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_MODIFY_GROUPS, 0, 0); + break; + case WIDX_SELECTED_GROUP_DROPDOWN: + _selectedGroup = network_get_group_id(dropdownIndex); + break; + } + + window_invalidate(w); +} + +static void window_multiplayer_groups_update(rct_window *w) +{ + w->frame_no++; + widget_invalidate(w, WIDX_TAB1 + w->page); +} + +static void window_multiplayer_groups_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) +{ + int i; + + if (w->selected_list_item != -1) { + w->selected_list_item = -1; + window_invalidate(w); + } + + *height = network_get_num_actions() * 10; + i = *height - window_multiplayer_groups_widgets[WIDX_LIST].bottom + window_multiplayer_groups_widgets[WIDX_LIST].top + 21; + if (i < 0) + i = 0; + if (i < w->scrolls[0].v_top) { + w->scrolls[0].v_top = i; + window_invalidate(w); + } +} + +static void window_multiplayer_groups_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) +{ + int index; + + index = y / 10; + if (index >= w->no_list_items) + return; + + w->selected_list_item = index; + window_invalidate(w); + + rct_widget *listWidget = &w->widgets[WIDX_LIST]; + int ddx = w->x + listWidget->left + x - w->scrolls[0].h_left; + int ddy = w->y + listWidget->top + y - w->scrolls[0].v_top; + + game_do_command(2 | (_selectedGroup << 8), GAME_COMMAND_FLAG_APPLY, index, 0, GAME_COMMAND_MODIFY_GROUPS, 0, 0); +} + +static void window_multiplayer_groups_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) +{ + int index; + + index = y / 10; + if (index >= w->no_list_items) + return; + + w->selected_list_item = index; + window_invalidate(w); +} + +static void window_multiplayer_groups_text_input(rct_window *w, int widgetIndex, char *text) +{ + if (widgetIndex != WIDX_RENAME_GROUP) + return; + + if (text == NULL) + return; + + game_do_command(3 | (_selectedGroup << 8) | (1 << 16), GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 0)), GAME_COMMAND_MODIFY_GROUPS, *((int*)(text + 8)), *((int*)(text + 4))); + game_do_command(3 | (_selectedGroup << 8) | (2 << 16), GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 12)), GAME_COMMAND_MODIFY_GROUPS, *((int*)(text + 20)), *((int*)(text + 16))); + game_do_command(3 | (_selectedGroup << 8) | (0 << 16), GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 24)), GAME_COMMAND_MODIFY_GROUPS, *((int*)(text + 32)), *((int*)(text + 28))); +} + +static void window_multiplayer_groups_invalidate(rct_window *w) +{ + window_multiplayer_set_pressed_tab(w); + window_multiplayer_anchor_border_widgets(w); + window_multiplayer_groups_widgets[WIDX_PERMISSIONS_LIST].right = w->width - 4; + window_multiplayer_groups_widgets[WIDX_PERMISSIONS_LIST].bottom = w->height - 0x0F; + window_align_tabs(w, WIDX_TAB1, WIDX_TAB2); + + // select other group if one is removed + while (network_get_group_index(_selectedGroup) == -1 && _selectedGroup > 0) { + _selectedGroup--; + } +} + +static void window_multiplayer_groups_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); + window_multiplayer_draw_tab_images(w, dpi); + + rct_widget* widget = &window_multiplayer_groups_widgets[WIDX_DEFAULT_GROUP]; + int group = network_get_group_index(network_get_default_group()); + if (group != -1) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_group_name_string_id(group); + gfx_draw_string_centred_clipped( + dpi, + 1193, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, + 0, + w->x + (widget->left + widget->right - 11) / 2, + w->y + widget->top, + widget->right - widget->left - 8 + ); + } + + int x = w->x + window_multiplayer_groups_widgets[WIDX_CONTENT_PANEL].left + 4; + int y = w->y + window_multiplayer_groups_widgets[WIDX_CONTENT_PANEL].top + 4; + + gfx_draw_string_left(dpi, STR_DEFAULT_GROUP, NULL, w->colours[2], x, y); + + y += 20; + + gfx_fill_rect_inset(dpi, x, y - 6, x + 310, y - 5, w->colours[1], 32); + + widget = &window_multiplayer_groups_widgets[WIDX_SELECTED_GROUP]; + group = network_get_group_index(_selectedGroup); + if (group != -1) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_group_name_string_id(group); + gfx_draw_string_centred_clipped( + dpi, + 1193, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, + 0, + w->x + (widget->left + widget->right - 11) / 2, + w->y + widget->top, + widget->right - widget->left - 8 + ); + } +} + +static void window_multiplayer_groups_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) +{ + int y = 0; + + gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ColourMapA[w->colours[1]].mid_light); + + for (int i = 0; i < network_get_num_actions(); i++) { + if (i == w->selected_list_item) { + gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031); + } + if (y > dpi->y + dpi->height) { + break; + } + + if (y + 11 >= dpi->y) { + char buffer[300] = {0}; + char* lineCh; + int groupindex = network_get_group_index(_selectedGroup); + if (groupindex != -1){ + if (network_can_perform_action(groupindex, i)) { + lineCh = buffer; + lineCh = utf8_write_codepoint(lineCh, FORMAT_WINDOW_COLOUR_2); + lineCh = utf8_write_codepoint(lineCh, FORMAT_TICK); + gfx_draw_string(dpi, buffer, 0, 0, y - 1); + } + } + + // Draw action name + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_action_name_string_id(i); + gfx_draw_string_left(dpi, 1193, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 10, y - 1); + } + y += 10; + } +} + +static void window_multiplayer_draw_tab_image(rct_window *w, rct_drawpixelinfo *dpi, int page, int spriteIndex) +{ + int widgetIndex = WIDX_TAB1 + page; + + if (!(w->disabled_widgets & (1LL << widgetIndex))) { + if (w->page == page) { + int numFrames = window_multiplayer_animation_frames[w->page]; + if (numFrames > 1) { + int frame = w->frame_no / window_multiplayer_animation_divisor[w->page]; + spriteIndex += (frame % numFrames); + } + } + + gfx_draw_sprite(dpi, spriteIndex, w->x + w->widgets[widgetIndex].left, w->y + w->widgets[widgetIndex].top, 0); + } +} + +static void window_multiplayer_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_multiplayer_draw_tab_image(w, dpi, 0, SPR_TAB_GUESTS_0); + window_multiplayer_draw_tab_image(w, dpi, 1, SPR_TAB_OBJECTIVE_0); +} diff --git a/src/windows/music_credits.c b/src/windows/music_credits.c index 8908fc8520..3ef2a2bfee 100644 --- a/src/windows/music_credits.c +++ b/src/windows/music_credits.c @@ -173,4 +173,4 @@ static void window_music_credits_scrollpaint(rct_window *w, rct_drawpixelinfo *d string += 1; } -} \ No newline at end of file +} diff --git a/src/windows/network_status.c b/src/windows/network_status.c index 1aadcf2d51..da2b84d988 100644 --- a/src/windows/network_status.c +++ b/src/windows/network_status.c @@ -25,7 +25,7 @@ #include "../util/util.h" #include "../network/network.h" -char _password[33]; +static char _password[33]; enum WINDOW_NETWORK_STATUS_WIDGET_IDX { WIDX_BACKGROUND, @@ -43,6 +43,7 @@ static rct_widget window_network_status_widgets[] = { static char window_network_status_text[1024]; +static void window_network_status_onclose(rct_window *w); static void window_network_status_mouseup(rct_window *w, int widgetIndex); static void window_network_status_update(rct_window *w); static void window_network_status_textinput(rct_window *w, int widgetIndex, char *text); @@ -50,7 +51,7 @@ static void window_network_status_invalidate(rct_window *w); static void window_network_status_paint(rct_window *w, rct_drawpixelinfo *dpi); static rct_window_event_list window_network_status_events = { - NULL, + window_network_status_onclose, window_network_status_mouseup, NULL, NULL, @@ -80,14 +81,15 @@ static rct_window_event_list window_network_status_events = { NULL }; -void window_network_status_open(const char* text) -{ - rct_window* window; +static close_callback _onClose = NULL; - safe_strncpy(window_network_status_text, text, sizeof(window_network_status_text)); +void window_network_status_open(const char* text, close_callback onClose) +{ + _onClose = onClose; + safe_strcpy(window_network_status_text, text, sizeof(window_network_status_text)); // Check if window is already open - window = window_bring_to_front_by_class(WC_NETWORK_STATUS); + rct_window *window = window_bring_to_front_by_class(WC_NETWORK_STATUS); if (window != NULL) return; @@ -106,13 +108,11 @@ void window_network_status_open(const char* text) window->page = 0; window->list_information_type = 0; - window->colours[0] = 7; - window->colours[1] = 7; - window->colours[2] = 7; } void window_network_status_close() { + _onClose = NULL; window_close_by_class(WC_NETWORK_STATUS); } @@ -126,6 +126,13 @@ void window_network_status_open_password() window_text_input_raw_open(window, WIDX_PASSWORD, STR_PASSWORD_REQUIRED, STR_PASSWORD_REQUIRED_DESC, _password, 32); } +static void window_network_status_onclose(rct_window *w) +{ + if (_onClose != NULL) { + _onClose(); + } +} + static void window_network_status_mouseup(rct_window *w, int widgetIndex) { switch (widgetIndex) { @@ -146,7 +153,7 @@ static void window_network_status_textinput(rct_window *w, int widgetIndex, char switch (widgetIndex) { case WIDX_PASSWORD: if (text != NULL) - safe_strncpy(_password, text, sizeof(_password)); + safe_strcpy(_password, text, sizeof(_password)); break; } if (text == NULL) { @@ -158,6 +165,8 @@ static void window_network_status_textinput(rct_window *w, int widgetIndex, char static void window_network_status_invalidate(rct_window *w) { + colour_scheme_update(w); + window_network_status_widgets[WIDX_BACKGROUND].right = w->width - 1; window_network_status_widgets[WIDX_BACKGROUND].bottom = w->height - 1; window_network_status_widgets[WIDX_TITLE].right = w->width - 2; diff --git a/src/windows/new_campaign.c b/src/windows/new_campaign.c index f2af8b3227..927a7b58f4 100644 --- a/src/windows/new_campaign.c +++ b/src/windows/new_campaign.c @@ -106,8 +106,8 @@ int ride_value_compare(const void *a, const void *b) { rct_ride *rideA, *rideB; - rideA = GET_RIDE(*((uint8*)a)); - rideB = GET_RIDE(*((uint8*)b)); + rideA = get_ride(*((uint8*)a)); + rideB = get_ride(*((uint8*)b)); return rideB->value - rideA->value; } @@ -116,8 +116,8 @@ int ride_name_compare(const void *a, const void *b) char rideAName[256], rideBName[256]; rct_ride *rideA, *rideB; - rideA = GET_RIDE(*((uint8*)a)); - rideB = GET_RIDE(*((uint8*)b)); + rideA = get_ride(*((uint8*)a)); + rideB = get_ride(*((uint8*)b)); format_string(rideAName, rideA->name, &rideA->name_arguments); format_string(rideBName, rideB->name, &rideB->name_arguments); @@ -199,7 +199,10 @@ static void window_new_campaign_get_shop_items() uint64 items = 0; FOR_ALL_RIDES(i, ride) { - rct_ride_type *rideType = gRideTypeList[ride->subtype]; + rct_ride_entry *rideType = get_ride_entry(ride->subtype); + if (rideType == NULL) { + continue; + } uint8 itemType = rideType->shop_item; if (itemType != 255) items |= 1LL << itemType; @@ -274,7 +277,7 @@ static void window_new_campaign_mousedown(int widgetIndex, rct_window *w, rct_wi if (window_new_campaign_rides[i] == 255) break; - rct_ride *ride = GET_RIDE(window_new_campaign_rides[i]); + rct_ride *ride = get_ride(window_new_campaign_rides[i]); gDropdownItemsFormat[i] = 1142; gDropdownItemsArgs[i] = ((uint64)ride->name_arguments << 16ULL) | ride->name; numItems++; @@ -341,7 +344,7 @@ static void window_new_campaign_invalidate(rct_window *w) window_new_campaign_widgets[WIDX_RIDE_DROPDOWN_BUTTON].type = WWT_DROPDOWN_BUTTON; window_new_campaign_widgets[WIDX_RIDE_LABEL].image = STR_MARKETING_RIDE; if (w->campaign.ride_id != SELECTED_RIDE_UNDEFINED) { - rct_ride *ride = GET_RIDE(w->campaign.ride_id); + rct_ride *ride = get_ride(w->campaign.ride_id); window_new_campaign_widgets[WIDX_RIDE_DROPDOWN].image = ride->name; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = ride->name_arguments; } diff --git a/src/windows/new_ride.c b/src/windows/new_ride.c index fc9d702cc6..14ff14767e 100644 --- a/src/windows/new_ride.c +++ b/src/windows/new_ride.c @@ -19,20 +19,21 @@ *****************************************************************************/ #include "../addresses.h" -#include "../config.h" #include "../audio/audio.h" +#include "../config.h" #include "../game.h" -#include "../management/news_item.h" -#include "../management/research.h" -#include "../object.h" -#include "../rct1.h" -#include "../ride/ride.h" -#include "../localisation/localisation.h" -#include "../world/scenery.h" -#include "../ride/track.h" #include "../interface/widget.h" #include "../interface/window.h" #include "../interface/themes.h" +#include "../localisation/localisation.h" +#include "../management/news_item.h" +#include "../management/research.h" +#include "../network/network.h" +#include "../object.h" +#include "../rct1.h" +#include "../ride/ride.h" +#include "../ride/track.h" +#include "../world/scenery.h" #define _window_new_ride_current_tab RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_RIDE_LIST_SELECTED_TAB, uint8) @@ -253,6 +254,7 @@ static void window_new_ride_select(rct_window *w); static ride_list_item _lastTrackDesignCountRideType; static int _lastTrackDesignCount; +static bool _trackSelectionByType; /** * @@ -281,7 +283,7 @@ void window_new_ride_init_vars() { /** * rct2: 0x006B6F3E * - * Note: When the user has selection by track type enabled, the categories are determined by the track type, not those in the rct_ride_type. + * Note: When the user has selection by track type enabled, the categories are determined by the track type, not those in the rct_ride_entry. */ static void window_new_ride_populate_list() { @@ -289,7 +291,6 @@ static void window_new_ride_populate_list() uint8 currentCategory = _window_new_ride_current_tab; ride_list_item *nextListItem = (ride_list_item*)0x00F43523; - rct_ride_type **rideEntries = (rct_ride_type**)0x009ACFA4; // For each ride type in the view order list for (i = 0; i < countof(RideTypeViewOrder); i++) { @@ -325,7 +326,7 @@ static void window_new_ride_populate_list() continue; // Ride entries - rct_ride_type *rideEntry = rideEntries[rideEntryIndex]; + rct_ride_entry *rideEntry = get_ride_entry(rideEntryIndex); // Check if ride is in this category if (!gConfigInterface.select_by_track_type && (currentCategory != rideEntry->category[0] && currentCategory != rideEntry->category[1])) @@ -372,6 +373,7 @@ static void window_new_ride_populate_list() nextListItem->type = 255; nextListItem->entry_index = 255; + _trackSelectionByType = gConfigInterface.select_by_track_type; } /** @@ -473,13 +475,13 @@ rct_window *window_new_ride_open_research() void window_new_ride_focus(ride_list_item rideItem) { rct_window *w; - rct_ride_type *rideType; + rct_ride_entry *rideType; w = window_find_by_class(WC_CONSTRUCT_RIDE); if (w == NULL) return; - rideType = GET_RIDE_ENTRY(rideItem.entry_index); + rideType = get_ride_entry(rideItem.entry_index); if(!gConfigInterface.select_by_track_type) window_new_ride_set_page(w, rideType->category[0]); @@ -651,6 +653,11 @@ static void window_new_ride_update(rct_window *w) if (w->new_ride.selected_ride_id != -1 && w->new_ride.selected_ride_countdown-- == 0) window_new_ride_select(w); + + if (_trackSelectionByType != gConfigInterface.select_by_track_type) { + window_new_ride_populate_list(); + widget_invalidate(w, WIDX_RIDE_LIST); + } } /** @@ -686,7 +693,7 @@ static void window_new_ride_scrollmousedown(rct_window *w, int scrollIndex, int return; RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_RIDE_LIST_HIGHLIGHTED_ITEM, ride_list_item)[_window_new_ride_current_tab] = item; - w->new_ride.selected_ride_id = *((sint16*)&item); + w->new_ride.selected_ride_id = item.ride_type_and_entry; audio_play_sound_panned(SOUND_CLICK_1, w->x + (w->width / 2), 0, 0, 0); w->new_ride.selected_ride_countdown = 8; @@ -706,10 +713,10 @@ static void window_new_ride_scrollmouseover(rct_window *w, int scrollIndex, int item = window_new_ride_scroll_get_ride_list_item_at(w, x, y); - if (w->new_ride.highlighted_ride_id == *((sint16*)&item)) + if (w->new_ride.highlighted_ride_id == item.ride_type_and_entry) return; - w->new_ride.highlighted_ride_id = *((sint16*)&item); + w->new_ride.highlighted_ride_id = item.ride_type_and_entry; RCT2_ADDRESS(RCT2_ADDRESS_WINDOW_RIDE_LIST_HIGHLIGHTED_ITEM, ride_list_item)[_window_new_ride_current_tab] = item; window_invalidate(w); } @@ -758,7 +765,7 @@ static void window_new_ride_paint(rct_window *w, rct_drawpixelinfo *dpi) window_new_ride_draw_tab_images(dpi, w); if (_window_new_ride_current_tab != WINDOW_NEW_RIDE_PAGE_RESEARCH) { - ride_list_item item = *((ride_list_item*)&w->new_ride.highlighted_ride_id); + ride_list_item item = { .ride_type_and_entry = w->new_ride.highlighted_ride_id }; if (item.type != 255 || item.entry_index != 255) window_new_ride_paint_ride_information(w, dpi, item, w->x + 3, w->y + w->height - 52, w->width - 6); } else { @@ -772,8 +779,6 @@ static void window_new_ride_paint(rct_window *w, rct_drawpixelinfo *dpi) */ static void window_new_ride_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { - rct_ride_type **rideEntries = (rct_ride_type**)0x009ACFA4; - if (_window_new_ride_current_tab == WINDOW_NEW_RIDE_PAGE_RESEARCH) return; @@ -783,7 +788,7 @@ static void window_new_ride_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, i int y = 1; ride_list_item *listItem = (ride_list_item*)0x00F43523; while (listItem->type != 255 || listItem->entry_index != 255) { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; // Draw flat button rectangle int flags = 0; if (w->new_ride.selected_ride_id == *((sint16*)listItem)) @@ -792,7 +797,7 @@ static void window_new_ride_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, i gfx_fill_rect_inset(dpi, x, y, x + 115, y + 115, w->colours[1], 0x80 | flags); // Draw ride image with feathered border - rideEntry = rideEntries[listItem->entry_index]; + rideEntry = get_ride_entry(listItem->entry_index); int image_id = rideEntry->images_offset; if (listItem->type != rideEntry->ride_type[0]) { image_id++; @@ -847,9 +852,9 @@ static int get_num_track_designs(ride_list_item item) { track_load_list(item); - uint8 *trackDesignList = (uint8*)0x00F441EC; + char *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char); int count = 0; - while (*trackDesignList != 0 && trackDesignList < (uint8*)0x00F635EC) { + while (*trackDesignList != 0 && trackDesignList < (char*)0x00F635EC) { trackDesignList += 128; count++; } @@ -862,8 +867,7 @@ static int get_num_track_designs(ride_list_item item) */ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixelinfo *dpi, ride_list_item item, int x, int y, int width) { - rct_ride_type **rideEntries = (rct_ride_type**)0x009ACFA4; - rct_ride_type *rideEntry = rideEntries[item.entry_index]; + rct_ride_entry *rideEntry = get_ride_entry(item.entry_index); // Ride name and description rct_string_id rideName = rideEntry->name; @@ -873,13 +877,17 @@ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixeli rideDescription = item.type + 512; } - RCT2_GLOBAL(0x013CE952 + 0, rct_string_id) = rideName; - RCT2_GLOBAL(0x013CE952 + 2, rct_string_id) = rideDescription; - gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, width, 1690, 0); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, rct_string_id) = rideName; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, rct_string_id) = rideDescription; + gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, width, 1690, 0); // Number of designs available if (ride_type_has_flag(item.type, RIDE_TYPE_FLAG_HAS_TRACK)) { - if (item.type != _lastTrackDesignCountRideType.type || item.entry_index != _lastTrackDesignCountRideType.entry_index) { + // Track designs are disabled in multiplayer, so don't say there are any designs available when in multiplayer + if (network_get_mode() != NETWORK_MODE_NONE) { + _lastTrackDesignCount = 0; + } + else if (item.type != _lastTrackDesignCountRideType.type || item.entry_index != _lastTrackDesignCountRideType.entry_index) { _lastTrackDesignCountRideType = item; _lastTrackDesignCount = get_num_track_designs(item); } @@ -887,13 +895,13 @@ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixeli rct_string_id stringId; switch (_lastTrackDesignCount) { case 0: - stringId = 3338; + stringId = STR_CUSTOM_DESIGNED_LAYOUT; break; case 1: - stringId = 3339; + stringId = STR_1_DESIGN_AVAILABLE; break; default: - stringId = 3340; + stringId = STR_X_DESIGNS_AVAILABLE; break; } gfx_draw_string_left(dpi, stringId, &_lastTrackDesignCount, 0, x, y + 39); @@ -913,7 +921,7 @@ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixeli // rct_string_id stringId = 1691; - if (!ride_type_has_flag(item.type, RIDE_TYPE_FLAG_15)) + if (!ride_type_has_flag(item.type, RIDE_TYPE_FLAG_HAS_NO_TRACK)) stringId++; gfx_draw_string_right(dpi, stringId, &price, 0, x + width, y + 39); @@ -926,17 +934,26 @@ static void window_new_ride_paint_ride_information(rct_window *w, rct_drawpixeli */ static void window_new_ride_select(rct_window *w) { - ride_list_item item = *((ride_list_item*)&w->new_ride.selected_ride_id); + ride_list_item item = { .ride_type_and_entry = w->new_ride.selected_ride_id }; if (item.type == 255) return; window_close(w); window_close_construction_windows(); - if (ride_type_has_flag(item.type, RIDE_TYPE_FLAG_HAS_TRACK)) { + bool allowTrackDesigns = true; +#ifndef NETWORK_DISABLE + // TODO: FIX NETWORK TRACKS + // Until tracks work with the network this will disable them + if (network_get_mode() != NETWORK_MODE_NONE) { + allowTrackDesigns = false; + } +#endif + + if (allowTrackDesigns && ride_type_has_flag(item.type, RIDE_TYPE_FLAG_HAS_TRACK)) { track_load_list(item); - uint8 *trackDesignList = (uint8*)0x00F441EC; + char *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char); if (*trackDesignList != 0) { window_track_list_open(item); return; diff --git a/src/windows/news.c b/src/windows/news.c index 0df430e2de..1ea43167e0 100644 --- a/src/windows/news.c +++ b/src/windows/news.c @@ -33,6 +33,7 @@ enum WINDOW_NEWS_WIDGET_IDX { WIDX_BACKGROUND, WIDX_TITLE, WIDX_CLOSE, + WIDX_SETTINGS, WIDX_SCROLL }; @@ -40,7 +41,8 @@ static rct_widget window_news_widgets[] = { { WWT_FRAME, 0, 0, 399, 0, 299, 0x0FFFFFFFF, STR_NONE }, // panel / background { WWT_CAPTION, 0, 1, 398, 1, 14, STR_RECENT_MESSAGES, STR_WINDOW_TITLE_TIP }, // title bar { WWT_CLOSEBOX, 0, 387, 397, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button - { WWT_SCROLL, 0, 4, 395, 18, 295, 2, STR_NONE }, // scroll + { WWT_FLATBTN, 0, 372, 395, 18, 41, 5201, STR_NONE }, // settings + { WWT_SCROLL, 0, 4, 395, 44, 295, 2, STR_NONE }, // scroll { WIDGETS_END }, }; @@ -103,7 +105,7 @@ void window_news_open() 0 ); window->widgets = window_news_widgets; - window->enabled_widgets = (1 << WIDX_CLOSE); + window->enabled_widgets = (1 << WIDX_CLOSE) | (1 << WIDX_SETTINGS); window_init_scroll_widgets(window); window->news.var_480 = -1; } @@ -130,6 +132,9 @@ static void window_news_mouseup(rct_window *w, int widgetIndex) case WIDX_CLOSE: window_close(w); break; + case WIDX_SETTINGS: + window_news_options_open(); + break; } } @@ -291,8 +296,8 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s // Date text RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_DATE_DAY_1 + newsItem->day - 1; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = STR_MONTH_MARCH + (newsItem->month_year % 8); - gfx_draw_string_left(dpi, 2235, (void*)0x013CE952, 2, 4, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = STR_MONTH_MARCH + (newsItem->month_year % 8); + gfx_draw_string_left(dpi, 2235, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 2, 4, y); // Item text utf8 buffer[400]; @@ -323,8 +328,10 @@ static void window_news_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int s case NEWS_ITEM_PEEP: case NEWS_ITEM_PEEP_ON_RIDE: { - rct_drawpixelinfo* cliped_dpi = clip_drawpixelinfo(dpi, x + 1, 22, yy + 1, 22); - if (!cliped_dpi) break; + rct_drawpixelinfo cliped_dpi; + if (!clip_drawpixelinfo(&cliped_dpi, dpi, x + 1, yy + 1, 22, 22)) { + break; + } rct_peep* peep = GET_PEEP(newsItem->assoc); int clip_x = 10, clip_y = 19; @@ -339,13 +346,11 @@ 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); - gfx_draw_sprite(cliped_dpi, image_id, clip_x, clip_y, 0); - - rct2_free(cliped_dpi); + gfx_draw_sprite(&cliped_dpi, image_id, clip_x, clip_y, 0); break; } case NEWS_ITEM_MONEY: diff --git a/src/windows/news_options.c b/src/windows/news_options.c new file mode 100644 index 0000000000..a42ce2a5a0 --- /dev/null +++ b/src/windows/news_options.c @@ -0,0 +1,288 @@ +#include "../config.h" +#include "../interface/widget.h" +#include "../interface/window.h" +#include "../localisation/localisation.h" +#include "../sprites.h" + +enum { + NOTIFICATION_CATEGORY_PARK, + NOTIFICATION_CATEGORY_RIDE, + NOTIFICATION_CATEGORY_GUEST +}; + +typedef struct { + uint8 category; + rct_string_id caption; + size_t config_offset; + +} notification_def; + +static const notification_def NewsItemOptionDefinitions[] = { + { NOTIFICATION_CATEGORY_PARK, STR_NOTIFICATION_PARK_AWARD, offsetof(notification_configuration, park_award) }, + { NOTIFICATION_CATEGORY_PARK, STR_NOTIFICATION_PARK_MARKETING_CAMPAIGN_FINISHED, offsetof(notification_configuration, park_marketing_campaign_finished) }, + { NOTIFICATION_CATEGORY_PARK, STR_NOTIFICATION_PARK_WARNINGS, offsetof(notification_configuration, park_warnings) }, + { NOTIFICATION_CATEGORY_PARK, STR_NOTIFICATION_PARK_RATING_WARNINGS, offsetof(notification_configuration, park_rating_warnings) }, + { NOTIFICATION_CATEGORY_RIDE, STR_NOTIFICATION_RIDE_BROKEN_DOWN, offsetof(notification_configuration, ride_broken_down) }, + { NOTIFICATION_CATEGORY_RIDE, STR_NOTIFICATION_RIDE_CRASHED, offsetof(notification_configuration, ride_crashed) }, + { NOTIFICATION_CATEGORY_RIDE, STR_NOTIFICATION_RIDE_WARNINGS, offsetof(notification_configuration, ride_warnings) }, + { NOTIFICATION_CATEGORY_RIDE, STR_NOTIFICATION_RIDE_RESEARCHED, offsetof(notification_configuration, ride_researched) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_WARNINGS, offsetof(notification_configuration, guest_warnings) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_LOST, offsetof(notification_configuration, guest_lost) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_LEFT_PARK, offsetof(notification_configuration, guest_left_park) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_QUEUING_FOR_RIDE, offsetof(notification_configuration, guest_queuing_for_ride) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_ON_RIDE, offsetof(notification_configuration, guest_on_ride) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_LEFT_RIDE, offsetof(notification_configuration, guest_left_ride) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_BOUGHT_ITEM, offsetof(notification_configuration, guest_bought_item) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_USED_FACILITY, offsetof(notification_configuration, guest_used_facility) }, + { NOTIFICATION_CATEGORY_GUEST, STR_NOTIFICATION_GUEST_DIED, offsetof(notification_configuration, guest_died) }, +}; + +enum WINDOW_NEWS_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_TAB_CONTENT_PANEL, + WIDX_TAB_PARK, + WIDX_TAB_RIDE, + WIDX_TAB_GUEST, + WIDX_CHECKBOX_0 +}; + +static rct_widget window_news_options_widgets[] = { + { WWT_FRAME, 0, 0, 399, 0, 299, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 398, 1, 14, STR_NOTIFICATION_SETTINGS, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 387, 397, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button + { WWT_RESIZE, 1, 0, 399, 43, 299, 0x0FFFFFFFF, STR_NONE }, // tab content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_NONE }, // tab 1 + { WWT_TAB, 1, 34, 64, 17, 43, 0x02000144E, STR_NONE }, // tab 2 + { WWT_TAB, 1, 65, 95, 17, 43, 0x02000144E, STR_NONE }, // tab 2 + + { WWT_CHECKBOX, 2, 3, 349, 46, 59, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + { WWT_CHECKBOX, 2, 0, 0, 0, 0, STR_NONE, STR_NONE }, + + { WIDGETS_END }, +}; + +static void window_news_options_mouseup(rct_window *w, int widgetIndex); +static void window_news_options_update(rct_window *w); +static void window_news_options_invalidate(rct_window *w); +static void window_news_options_paint(rct_window *w, rct_drawpixelinfo *dpi); + +static rct_window_event_list window_news_options_events = { + NULL, + window_news_options_mouseup, + NULL, + NULL, + NULL, + NULL, + window_news_options_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_news_options_invalidate, + window_news_options_paint, + NULL +}; + +static void window_news_options_set_page(rct_window *w, int page); +static void window_news_options_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi); +static bool *get_notification_value_ptr(const notification_def *ndef); + +void window_news_options_open() +{ + rct_window* window; + + // Check if window is already open + window = window_bring_to_front_by_class(WC_NOTIFICATION_OPTIONS); + if (window == NULL) { + window = window_create_centred( + 400, + 300, + &window_news_options_events, + WC_NOTIFICATION_OPTIONS, + 0 + ); + window->widgets = window_news_options_widgets; + window->enabled_widgets = + (1 << WIDX_CLOSE) | + (1 << WIDX_TAB_PARK) | + (1 << WIDX_TAB_RIDE) | + (1 << WIDX_TAB_GUEST); + window_init_scroll_widgets(window); + window->colours[0] = COLOUR_GREY; + window->colours[1] = COLOUR_LIGHT_BLUE; + window->colours[2] = COLOUR_LIGHT_BLUE; + } +} + +static void window_news_options_mouseup(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_TAB_PARK: + case WIDX_TAB_RIDE: + case WIDX_TAB_GUEST: + window_news_options_set_page(w, widgetIndex - WIDX_TAB_PARK); + break; + default: + { + int checkBoxIndex = widgetIndex - WIDX_CHECKBOX_0; + if (checkBoxIndex >= 0) { + int matchIndex = 0; + for (int i = 0; i < countof(NewsItemOptionDefinitions); i++) { + const notification_def *ndef = &NewsItemOptionDefinitions[i]; + if (ndef->category != w->page) continue; + + if (matchIndex == checkBoxIndex) { + // Toggle value + bool *configValue = get_notification_value_ptr(ndef); + *configValue = !(*configValue); + + config_save_default(); + + widget_invalidate(w, widgetIndex); + break; + } + matchIndex++; + } + } + break; + } + } +} + +static void window_news_options_update(rct_window *w) +{ + w->frame_no++; + widget_invalidate(w, WIDX_TAB_PARK + w->page); +} + +static void window_news_options_invalidate(rct_window *w) +{ + // colour_scheme_update(w); + + // Set pressed tab + w->pressed_widgets &= ~(1ULL << WIDX_TAB_PARK); + w->pressed_widgets &= ~(1ULL << WIDX_TAB_RIDE); + w->pressed_widgets &= ~(1ULL << WIDX_TAB_GUEST); + w->pressed_widgets |= (1ULL << (WIDX_TAB_PARK + w->page)); + + // Set checkboxes + rct_widget *baseCheckBox = &w->widgets[WIDX_CHECKBOX_0]; + int y = baseCheckBox->top; + + int checkboxWidgetIndex = WIDX_CHECKBOX_0; + rct_widget *checkboxWidget = &w->widgets[checkboxWidgetIndex]; + for (int i = 0; i < countof(NewsItemOptionDefinitions); i++) { + const notification_def *ndef = &NewsItemOptionDefinitions[i]; + if (ndef->category != w->page) continue; + + w->enabled_widgets |= (1ULL << checkboxWidgetIndex); + + checkboxWidget->type = WWT_CHECKBOX; + checkboxWidget->left = baseCheckBox->left; + checkboxWidget->right = baseCheckBox->right; + checkboxWidget->top = y; + checkboxWidget->bottom = checkboxWidget->top + 13; + checkboxWidget->image = ndef->caption; + + const bool *configValue = get_notification_value_ptr(ndef); + widget_set_checkbox_value(w, checkboxWidgetIndex, *configValue); + + checkboxWidgetIndex++; + checkboxWidget++; + y += 13; + } + + // Remove unused checkboxes + while (checkboxWidget->type != WWT_LAST) { + w->enabled_widgets &= ~(1ULL << checkboxWidgetIndex); + + checkboxWidget->type = WWT_EMPTY; + checkboxWidgetIndex++; + checkboxWidget++; + } + + // Resize window to fit checkboxes exactly + y += 3; + + if (w->height != y) { + window_invalidate(w); + w->height = y; + w->widgets[WIDX_BACKGROUND].bottom = y - 1; + w->widgets[WIDX_TAB_CONTENT_PANEL].bottom = y - 1; + window_invalidate(w); + } +} + +static void window_news_options_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); + window_news_options_draw_tab_images(w, dpi); +} + +static void window_news_options_set_page(rct_window *w, int page) +{ + if (w->page != page) { + w->page = page; + w->frame_no = 0; + window_invalidate(w); + } +} + +const int window_news_option_tab_animation_divisor[] = { 1, 4, 4 }; +const int window_news_option_tab_animation_frames[] = { 1, 16, 8 }; + +static void window_news_options_draw_tab_image(rct_window *w, rct_drawpixelinfo *dpi, int page, int spriteIndex) +{ + int widgetIndex = WIDX_TAB_PARK + page; + + if (!(w->disabled_widgets & (1LL << widgetIndex))) { + if (w->page == page) { + int numFrames = window_news_option_tab_animation_frames[w->page]; + if (numFrames > 1) { + int frame = w->frame_no / window_news_option_tab_animation_divisor[w->page]; + spriteIndex += (frame % numFrames); + } + } + + gfx_draw_sprite(dpi, spriteIndex, w->x + w->widgets[widgetIndex].left, w->y + w->widgets[widgetIndex].top, 0); + } +} + +static void window_news_options_draw_tab_images(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_news_options_draw_tab_image(w, dpi, NOTIFICATION_CATEGORY_PARK, SPR_TAB_PARK); + window_news_options_draw_tab_image(w, dpi, NOTIFICATION_CATEGORY_RIDE, SPR_TAB_RIDE_0); + window_news_options_draw_tab_image(w, dpi, NOTIFICATION_CATEGORY_GUEST, SPR_TAB_GUESTS_0); +} + +static bool *get_notification_value_ptr(const notification_def *ndef) +{ + bool *configValue = (bool*)((size_t)&gConfigNotifications + ndef->config_offset); + return configValue; +} diff --git a/src/windows/options.c b/src/windows/options.c index 14f072530a..cdbb0a936d 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -48,6 +48,7 @@ enum WINDOW_OPTIONS_PAGE { WINDOW_OPTIONS_PAGE_DISPLAY, + WINDOW_OPTIONS_PAGE_RENDERING, WINDOW_OPTIONS_PAGE_CULTURE, WINDOW_OPTIONS_PAGE_AUDIO, WINDOW_OPTIONS_PAGE_CONTROLS_AND_INTERFACE, @@ -69,29 +70,37 @@ enum WINDOW_OPTIONS_WIDGET_IDX { WIDX_TAB_4, WIDX_TAB_5, WIDX_TAB_6, + WIDX_TAB_7, WIDX_PAGE_START, // Display WIDX_HARDWARE_GROUP = WIDX_PAGE_START, - WIDX_RESOLUTION, - WIDX_RESOLUTION_DROPDOWN, WIDX_FULLSCREEN, WIDX_FULLSCREEN_DROPDOWN, - WIDX_HARDWARE_DISPLAY_CHECKBOX, - WIDX_UNCAP_FPS_CHECKBOX, - WIDX_MINIMIZE_FOCUS_LOSS, - WIDX_STEAM_OVERLAY_PAUSE, + WIDX_RESOLUTION, + WIDX_RESOLUTION_DROPDOWN, WIDX_SCALE, WIDX_SCALE_UP, WIDX_SCALE_DOWN, - WIDX_RENDERING_GROUP, + WIDX_HARDWARE_DISPLAY_CHECKBOX, + WIDX_SCALE_QUALITY, + WIDX_SCALE_QUALITY_DROPDOWN, + WIDX_SCALE_USE_NN_AT_INTEGER_SCALES_CHECKBOX, + WIDX_STEAM_OVERLAY_PAUSE, + WIDX_UNCAP_FPS_CHECKBOX, + WIDX_SHOW_FPS_CHECKBOX, + WIDX_MINIMIZE_FOCUS_LOSS, + + // Rendering + WIDX_RENDERING_GROUP = WIDX_PAGE_START, WIDX_TILE_SMOOTHING_CHECKBOX, WIDX_GRIDLINES_CHECKBOX, WIDX_CONSTRUCTION_MARKER, WIDX_CONSTRUCTION_MARKER_DROPDOWN, WIDX_DAY_NIGHT_CHECKBOX, WIDX_UPPER_CASE_BANNERS_CHECKBOX, + WIDX_DISABLE_LIGHTNING_EFFECT_CHECKBOX, // Culture / Units WIDX_LANGUAGE = WIDX_PAGE_START, @@ -115,12 +124,13 @@ enum WINDOW_OPTIONS_WIDGET_IDX { WIDX_AUDIO_FOCUS_CHECKBOX, WIDX_TITLE_MUSIC, WIDX_TITLE_MUSIC_DROPDOWN, - WIDX_MASTER_VOLUME, + WIDX_SOUND_VOLUME, WIDX_MUSIC_VOLUME, // Controls and interface WIDX_CONTROLS_GROUP = WIDX_PAGE_START, WIDX_SCREEN_EDGE_SCROLLING, + WIDX_TRAP_CURSOR, WIDX_INVERT_DRAG, WIDX_HOTKEY_DROPDOWN, WIDX_THEMES_GROUP, @@ -133,21 +143,27 @@ 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, + WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, WIDX_SAVE_PLUGIN_DATA_CHECKBOX, + WIDX_TEST_UNFINISHED_TRACKS, + WIDX_DEBUGGING_TOOLS, + WIDX_STAY_CONNECTED_AFTER_DESYNC, WIDX_AUTOSAVE, WIDX_AUTOSAVE_DROPDOWN, - WIDX_TEST_UNFINISHED_TRACKS, - WIDX_AUTO_STAFF_PLACEMENT, - WIDX_HANDYMEN_MOW_DEFAULT, - WIDX_DEBUGGING_TOOLS, WIDX_TITLE_SEQUENCE, WIDX_TITLE_SEQUENCE_DROPDOWN, WIDX_TITLE_SEQUENCE_BUTTON, - WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, - WIDX_STAY_CONNECTED_AFTER_DESYNC, + WIDX_AUTO_STAFF_PLACEMENT, + WIDX_HANDYMEN_MOW_DEFAULT, + WIDX_AUTO_OPEN_SHOPS, + WIDX_DEFAULT_INSPECTION_INTERVAL, + WIDX_DEFAULT_INSPECTION_INTERVAL_DROPDOWN, // Twitch WIDX_CHANNEL_BUTTON = WIDX_PAGE_START, @@ -159,7 +175,7 @@ enum WINDOW_OPTIONS_WIDGET_IDX { }; #define WW 310 -#define WH 280 +#define WH 332 #define MAIN_OPTIONS_WIDGETS \ { WWT_FRAME, 0, 0, WW-1, 0, WH-1, STR_NONE, STR_NONE }, \ @@ -167,34 +183,55 @@ enum WINDOW_OPTIONS_WIDGET_IDX { { WWT_CLOSEBOX, 0, WW-13, WW-3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, \ { WWT_RESIZE, 1, 0, WW-1, 43, WH-1, 0xFFFFFFFF, STR_NONE }, \ { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_OPTIONS_DISPLAY_TIP }, \ - { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_OPTIONS_CULTURE_TIP }, \ - { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPTIONS_AUDIO_TIP }, \ - { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_OPTIONS_CONTROLS_AND_INTERFACE_TIP }, \ - { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_OPTIONS_MISCELLANEOUS_TIP }, \ - { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_OPTIONS_TWITCH_TIP } + { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_OPTIONS_RENDERING_TIP }, \ + { WWT_TAB, 1, 65, 95, 17, 43, 0x2000144E, STR_OPTIONS_CULTURE_TIP }, \ + { WWT_TAB, 1, 96, 126, 17, 43, 0x2000144E, STR_OPTIONS_AUDIO_TIP }, \ + { WWT_TAB, 1, 127, 157, 17, 43, 0x2000144E, STR_OPTIONS_CONTROLS_AND_INTERFACE_TIP }, \ + { WWT_TAB, 1, 158, 188, 17, 43, 0x2000144E, STR_OPTIONS_MISCELLANEOUS_TIP }, \ + { WWT_TAB, 1, 189, 209, 17, 43, 0x2000144E, STR_OPTIONS_TWITCH_TIP } static rct_widget window_options_display_widgets[] = { MAIN_OPTIONS_WIDGETS, - { WWT_GROUPBOX, 1, 5, 304, 53, 175, STR_HARDWARE_GROUP, STR_NONE }, // Hardware group - { WWT_DROPDOWN, 1, 155, 299, 68, 79, STR_RESOLUTION_X_BY_Y, STR_NONE }, // resolution - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 69, 78, STR_DROPDOWN_GLYPH, STR_NONE }, - { WWT_DROPDOWN, 1, 155, 299, 83, 94, 871, STR_NONE }, // fullscreen - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 84, 93, STR_DROPDOWN_GLYPH, STR_NONE }, - { WWT_CHECKBOX, 1, 10, 290, 99, 110, STR_HARDWARE_DISPLAY, STR_NONE }, // hardware display - { WWT_CHECKBOX, 1, 10, 290, 114, 125, STR_UNCAP_FPS, STR_NONE }, // uncap fps - { WWT_CHECKBOX, 1, 10, 290, 129, 140, STR_MININISE_FULL_SCREEN_ON_FOCUS_LOSS, STR_NONE }, // minimise fullscreen focus loss - { WWT_CHECKBOX, 1, 10, 290, 144, 155, STR_STEAM_OVERLAY_PAUSE, STR_NONE }, // minimise fullscreen focus loss - { WWT_SPINNER, 1, 155, 299, 159, 170, STR_NONE, STR_NONE }, // scale spinner - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 160, 164, STR_NUMERIC_UP, STR_NONE }, // scale spinner up - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 165, 169, STR_NUMERIC_DOWN, STR_NONE }, // scale spinner down + { WWT_GROUPBOX, 1, 5, 304, 53, 205, STR_HARDWARE_GROUP, STR_NONE }, // Hardware group - { WWT_GROUPBOX, 1, 5, 304, 179, 270, STR_RENDERING_GROUP, STR_NONE }, // Rendering group - { WWT_CHECKBOX, 1, 10, 290, 194, 205, STR_TILE_SMOOTHING, STR_TILE_SMOOTHING_TIP }, // landscape smoothing - { WWT_CHECKBOX, 1, 10, 290, 209, 220, STR_GRIDLINES, STR_GRIDLINES_TIP }, // gridlines - { WWT_DROPDOWN, 1, 155, 299, 224, 234, STR_NONE, STR_NONE }, // construction marker - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 225, 233, STR_DROPDOWN_GLYPH, STR_NONE }, - { WWT_CHECKBOX, 1, 10, 290, 239, 250, STR_CYCLE_DAY_NIGHT, STR_NONE }, // cycle day-night - { WWT_CHECKBOX, 1, 10, 290, 254, 265, STR_UPPER_CASE_BANNERS, STR_NONE }, // upper case banners + { WWT_DROPDOWN, 1, 155, 299, 68, 79, 871, STR_NONE }, // fullscreen + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 69, 78, STR_DROPDOWN_GLYPH, STR_NONE }, + + { WWT_DROPDOWN, 1, 155, 299, 83, 94, STR_RESOLUTION_X_BY_Y, STR_NONE }, // resolution + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 84, 93, STR_DROPDOWN_GLYPH, STR_NONE }, + + { WWT_SPINNER, 1, 155, 299, 98, 109, STR_NONE, STR_NONE }, // scale spinner + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 99, 103, STR_NUMERIC_UP, STR_NONE }, // scale spinner up + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 104, 108, STR_NUMERIC_DOWN, STR_NONE }, // scale spinner down + + { WWT_CHECKBOX, 1, 10, 290, 113, 124, STR_HARDWARE_DISPLAY, STR_NONE }, // hardware display + + { WWT_DROPDOWN, 1, 155, 299, 128, 139, STR_NONE, STR_REQUIRES_HW_DISPLAY }, // scaling quality hint + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 129, 138, STR_DROPDOWN_GLYPH, STR_REQUIRES_HW_DISPLAY_TIP }, + { WWT_CHECKBOX, 1, 25, 290, 143, 154, STR_USE_NN_AT_INTEGER_SCALE, STR_REQUIRES_HW_DISPLAY_TIP }, // use nn scaling at integer scales + + { WWT_CHECKBOX, 1, 25, 290, 158, 169, STR_STEAM_OVERLAY_PAUSE, STR_NONE }, // pause on steam overlay + + { WWT_CHECKBOX, 1, 10, 290, 174, 185, STR_UNCAP_FPS, STR_NONE }, // uncap fps + { WWT_CHECKBOX, 1, 155, 299, 174, 185, STR_SHOW_FPS, STR_NONE }, // show fps + { WWT_CHECKBOX, 1, 10, 290, 189, 200, STR_MININISE_FULL_SCREEN_ON_FOCUS_LOSS, STR_NONE }, // minimise fullscreen focus loss + + + { WIDGETS_END }, +}; + +static rct_widget window_options_rendering_widgets[] = { + MAIN_OPTIONS_WIDGETS, +#define FRAME_RENDERING_START 53 + { WWT_GROUPBOX, 1, 5, 304, FRAME_RENDERING_START + 0, FRAME_RENDERING_START + 106, STR_RENDERING_GROUP, STR_NONE }, // Rendering group + { WWT_CHECKBOX, 1, 10, 290, FRAME_RENDERING_START + 15, FRAME_RENDERING_START + 26, STR_TILE_SMOOTHING, STR_TILE_SMOOTHING_TIP }, // landscape smoothing + { WWT_CHECKBOX, 1, 10, 290, FRAME_RENDERING_START + 30, FRAME_RENDERING_START + 41, STR_GRIDLINES, STR_GRIDLINES_TIP }, // gridlines + { WWT_DROPDOWN, 1, 155, 299, FRAME_RENDERING_START + 45, FRAME_RENDERING_START + 55, STR_NONE, STR_NONE }, // construction marker + { WWT_DROPDOWN_BUTTON, 1, 288, 298, FRAME_RENDERING_START + 46, FRAME_RENDERING_START + 54, STR_DROPDOWN_GLYPH, STR_NONE }, + { WWT_CHECKBOX, 1, 10, 290, FRAME_RENDERING_START + 60, FRAME_RENDERING_START + 71, STR_CYCLE_DAY_NIGHT, STR_NONE }, // cycle day-night + { WWT_CHECKBOX, 1, 10, 290, FRAME_RENDERING_START + 75, FRAME_RENDERING_START + 86, STR_UPPER_CASE_BANNERS, STR_NONE }, // upper case banners + { WWT_CHECKBOX, 1, 10, 290, FRAME_RENDERING_START + 90, FRAME_RENDERING_START + 101, STR_DISABLE_LIGHTNING_EFFECT, STR_NONE }, // disable lightning effect +#undef FRAME_RENDERING_START { WIDGETS_END }, }; @@ -220,7 +257,7 @@ static rct_widget window_options_audio_widgets[] = { { WWT_DROPDOWN, 1, 10, 299, 53, 64, 865, STR_NONE }, // audio device { WWT_DROPDOWN_BUTTON, 1, 288, 298, 54, 63, STR_DROPDOWN_GLYPH, STR_NONE }, { WWT_CHECKBOX, 1, 10, 229, 69, 80, STR_SOUND, STR_NONE }, // enable / disable sound - { WWT_CHECKBOX, 1, 10, 229, 84, 95, STR_MUSIC, STR_NONE }, // enable / disable music + { WWT_CHECKBOX, 1, 10, 229, 84, 95, STR_RIDE_MUSIC, STR_NONE }, // enable / disable ride music { WWT_CHECKBOX, 1, 10, 229, 98, 110, STR_AUDIO_FOCUS, STR_NONE }, // enable / disable audio disabled on focus lost { WWT_DROPDOWN, 1, 155, 299, 112, 124, STR_NONE, STR_NONE }, // title music { WWT_DROPDOWN_BUTTON, 1, 288, 298, 113, 123, STR_DROPDOWN_GLYPH, STR_NONE }, @@ -231,41 +268,48 @@ static rct_widget window_options_audio_widgets[] = { static rct_widget window_options_controls_and_interface_widgets[] = { MAIN_OPTIONS_WIDGETS, - { WWT_GROUPBOX, 1, 5, 304, 53, 114, STR_CONTROLS_GROUP, STR_NONE }, // Controls group - { WWT_CHECKBOX, 2, 10, 299, 68, 79, STR_SCREEN_EDGE_SCROLLING, STR_SCREEN_EDGE_SCROLLING_TIP }, // Edge scrolling - { WWT_CHECKBOX, 2, 10, 299, 83, 94, STR_INVERT_RIGHT_MOUSE_DRAG, STR_NONE }, // Invert right mouse dragging - { WWT_DROPDOWN_BUTTON, 1, 26, 185, 98, 109, STR_HOTKEY, STR_HOTKEY_TIP }, // Set hotkeys buttons + { WWT_GROUPBOX, 1, 5, 304, 53, 129, STR_CONTROLS_GROUP, STR_NONE }, // Controls group + { WWT_CHECKBOX, 2, 10, 299, 68, 79, STR_SCREEN_EDGE_SCROLLING, STR_SCREEN_EDGE_SCROLLING_TIP }, // Edge scrolling + { WWT_CHECKBOX, 2, 10, 299, 83, 94, STR_TRAP_MOUSE, STR_NONE }, // Trap mouse + { WWT_CHECKBOX, 2, 10, 299, 98, 109, STR_INVERT_RIGHT_MOUSE_DRAG, STR_NONE }, // Invert right mouse dragging + { WWT_DROPDOWN_BUTTON, 1, 26, 185, 113, 124, STR_HOTKEY, STR_HOTKEY_TIP }, // Set hotkeys buttons - { WWT_GROUPBOX, 1, 5, 304, 118, 164, STR_THEMES_GROUP, STR_NONE }, // Toolbar buttons group - { WWT_DROPDOWN, 1, 155, 299, 132, 143, STR_NONE, STR_NONE }, // Themes - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 133, 142, STR_DROPDOWN_GLYPH, STR_NONE }, - { WWT_DROPDOWN_BUTTON, 1, 10, 145, 148, 159, STR_EDIT_THEMES_BUTTON, STR_NONE }, // Themes button + { WWT_GROUPBOX, 1, 5, 304, 133, 179, STR_THEMES_GROUP, STR_NONE }, // Toolbar buttons group + { WWT_DROPDOWN, 1, 155, 299, 147, 158, STR_NONE, STR_NONE }, // Themes + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 148, 157, STR_DROPDOWN_GLYPH, STR_NONE }, + { WWT_DROPDOWN_BUTTON, 1, 10, 145, 163, 174, STR_EDIT_THEMES_BUTTON, STR_NONE }, // Themes button - { WWT_GROUPBOX, 1, 5, 304, 168, 230, STR_TOOLBAR_BUTTONS_GROUP, STR_NONE }, // Toolbar buttons group - { WWT_CHECKBOX, 2, 10, 145, 199, 210, STR_FINANCES_BUTTON_ON_TOOLBAR, STR_NONE }, // Finances - { WWT_CHECKBOX, 2, 10, 145, 214, 225, STR_RESEARCH_BUTTON_ON_TOOLBAR, STR_NONE }, // Research - { WWT_CHECKBOX, 2, 155, 299, 199, 210, STR_CHEATS_BUTTON_ON_TOOLBAR, STR_NONE }, // Cheats - { WWT_CHECKBOX, 2, 155, 299, 214, 225, STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR, STR_NONE }, // Recent messages + { WWT_GROUPBOX, 1, 5, 304, 183, 245, STR_TOOLBAR_BUTTONS_GROUP, STR_NONE }, // Toolbar buttons group + { WWT_CHECKBOX, 2, 10, 145, 214, 225, STR_FINANCES_BUTTON_ON_TOOLBAR, STR_NONE }, // Finances + { WWT_CHECKBOX, 2, 10, 145, 229, 240, STR_RESEARCH_BUTTON_ON_TOOLBAR, STR_NONE }, // Research + { WWT_CHECKBOX, 2, 155, 299, 214, 225, STR_CHEATS_BUTTON_ON_TOOLBAR, STR_NONE }, // Cheats + { WWT_CHECKBOX, 2, 155, 299, 229, 240, STR_SHOW_RECENT_MESSAGES_ON_TOOLBAR, STR_NONE }, // Recent messages - { WWT_CHECKBOX, 2, 10, 299, 239, 250, STR_SELECT_BY_TRACK_TYPE, STR_SELECT_BY_TRACK_TYPE_TIP }, // Select by track type + { 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 }, }; static rct_widget window_options_misc_widgets[] = { MAIN_OPTIONS_WIDGETS, - { WWT_CHECKBOX, 2, 10, 299, 54, 65, STR_REAL_NAME, STR_REAL_NAME_TIP }, - { WWT_CHECKBOX, 2, 10, 299, 69, 80, STR_SAVE_PLUGIN_DATA, STR_SAVE_PLUGIN_DATA_TIP }, - { WWT_DROPDOWN, 1, 155, 299, 83, 94, STR_NONE, STR_NONE }, - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 84, 93, STR_DROPDOWN_GLYPH, STR_NONE }, - { WWT_CHECKBOX, 2, 10, 299, 114, 125, STR_TEST_UNFINISHED_TRACKS, STR_TEST_UNFINISHED_TRACKS_TIP }, // test unfinished tracks - { WWT_CHECKBOX, 2, 10, 299, 129, 140, STR_AUTO_STAFF_PLACEMENT, STR_NONE }, // auto staff placement - { WWT_CHECKBOX, 2, 10, 299, 144, 155, STR_HANDYMEN_MOW_BY_DEFAULT, STR_NONE }, // handymen mow by default - { WWT_CHECKBOX, 2, 10, 299, 159, 170, STR_ENABLE_DEBUGGING_TOOLS, STR_NONE }, // enable debugging tools - { WWT_DROPDOWN, 1, 155, 299, 173, 184, STR_NONE, STR_NONE }, - { WWT_DROPDOWN_BUTTON, 1, 288, 298, 174, 183, STR_DROPDOWN_GLYPH, STR_NONE }, - { WWT_DROPDOWN_BUTTON, 1, 26, 185, 189, 200, STR_EDIT_TITLE_SEQUENCES_BUTTON, STR_NONE }, // Title sequences button - { WWT_CHECKBOX, 2, 10, 299, 204, 215, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM_TIP }, // Allow loading with incorrect checksum - { WWT_CHECKBOX, 2, 10, 299, 219, 230, STR_STAY_CONNECTED_AFTER_DESYNC, STR_NONE }, // Do not disconnect after the client desynchronises with the server + { WWT_CHECKBOX, 2, 10, 299, 54, 65, STR_REAL_NAME, STR_REAL_NAME_TIP }, // Show 'real' names of guests + { WWT_CHECKBOX, 2, 10, 299, 69, 80, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, STR_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM_TIP }, // Allow loading with incorrect checksum + { WWT_CHECKBOX, 2, 10, 299, 84, 95, STR_SAVE_PLUGIN_DATA, STR_SAVE_PLUGIN_DATA_TIP }, // Export plug-in objects with saved games + { WWT_CHECKBOX, 2, 10, 299, 99, 110, STR_TEST_UNFINISHED_TRACKS, STR_TEST_UNFINISHED_TRACKS_TIP }, // test unfinished tracks + { WWT_CHECKBOX, 2, 10, 299, 114, 125, STR_ENABLE_DEBUGGING_TOOLS, STR_NONE }, // enable debugging tools + { WWT_CHECKBOX, 2, 10, 299, 129, 140, STR_STAY_CONNECTED_AFTER_DESYNC, STR_NONE }, // Do not disconnect after the client desynchronises with the server + { WWT_DROPDOWN, 1, 155, 299, 144, 155, STR_NONE, STR_NONE }, // autosave dropdown + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 145, 154, STR_DROPDOWN_GLYPH, STR_NONE }, // autosave dropdown button + { WWT_DROPDOWN, 1, 155, 299, 159, 170, STR_NONE, STR_NONE }, // title sequence dropdown + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 160, 169, STR_DROPDOWN_GLYPH, STR_NONE }, // title seqeuence dropdown button + { WWT_DROPDOWN_BUTTON, 1, 26, 185, 174, 185, STR_EDIT_TITLE_SEQUENCES_BUTTON, STR_NONE }, // Title sequences button + { WWT_CHECKBOX, 2, 10, 299, 189, 200, STR_AUTO_STAFF_PLACEMENT, STR_NONE }, // auto staff placement + { WWT_CHECKBOX, 2, 10, 299, 204, 215, STR_HANDYMEN_MOW_BY_DEFAULT, STR_NONE }, // handymen mow by default + { WWT_CHECKBOX, 2, 10, 299, 219, 230, STR_AUTO_OPEN_SHOPS, STR_AUTO_OPEN_SHOPS_TIP }, // Automatically open shops & stalls + { WWT_DROPDOWN, 1, 155, 299, 234, 245, STR_NONE, STR_NONE }, // default inspection time dropdown + { WWT_DROPDOWN_BUTTON, 1, 288, 298, 235, 244, STR_DROPDOWN_GLYPH, STR_NONE }, // default inspection time dropdown button { WIDGETS_END }, }; @@ -282,6 +326,7 @@ static rct_widget window_options_twitch_widgets[] = { rct_widget *window_options_page_widgets[] = { window_options_display_widgets, + window_options_rendering_widgets, window_options_culture_widgets, window_options_audio_widgets, window_options_controls_and_interface_widgets, @@ -291,8 +336,8 @@ rct_widget *window_options_page_widgets[] = { #pragma endregion -const int window_options_tab_animation_divisor[] = { 4, 8, 2, 2, 2, 1 }; -const int window_options_tab_animation_frames[] = { 16, 8, 16, 4, 16, 1 }; +const int window_options_tab_animation_divisor[] = { 4, 4, 8, 2, 2, 2, 1 }; +const int window_options_tab_animation_frames[] = { 16, 8, 8, 16, 4, 16, 1 }; static void window_options_set_page(rct_window *w, int page); static void window_options_set_pressed_tab(rct_window *w); @@ -354,7 +399,8 @@ static rct_window_event_list window_options_events = { (1 << WIDX_TAB_3) | \ (1 << WIDX_TAB_4) | \ (1 << WIDX_TAB_5) | \ - (1 << WIDX_TAB_6) + (1 << WIDX_TAB_6) | \ + (1 << WIDX_TAB_7) static uint32 window_options_page_enabled_widgets[] = { MAIN_OPTIONS_ENABLED_WIDGETS | @@ -366,15 +412,24 @@ static uint32 window_options_page_enabled_widgets[] = { (1 << WIDX_GRIDLINES_CHECKBOX) | (1 << WIDX_HARDWARE_DISPLAY_CHECKBOX) | (1 << WIDX_UNCAP_FPS_CHECKBOX) | + (1 << WIDX_SHOW_FPS_CHECKBOX) | (1 << WIDX_MINIMIZE_FOCUS_LOSS) | (1 << WIDX_STEAM_OVERLAY_PAUSE) | (1 << WIDX_SCALE) | (1 << WIDX_SCALE_UP) | (1 << WIDX_SCALE_DOWN) | + (1 << WIDX_SCALE_QUALITY) | + (1 << WIDX_SCALE_QUALITY_DROPDOWN) | + (1 << WIDX_SCALE_USE_NN_AT_INTEGER_SCALES_CHECKBOX), + + MAIN_OPTIONS_ENABLED_WIDGETS | + (1 << WIDX_TILE_SMOOTHING_CHECKBOX) | + (1 << WIDX_GRIDLINES_CHECKBOX) | (1 << WIDX_CONSTRUCTION_MARKER) | (1 << WIDX_CONSTRUCTION_MARKER_DROPDOWN) | (1 << WIDX_DAY_NIGHT_CHECKBOX) | - (1 << WIDX_UPPER_CASE_BANNERS_CHECKBOX), + (1 << WIDX_UPPER_CASE_BANNERS_CHECKBOX) | + (1 << WIDX_DISABLE_LIGHTNING_EFFECT_CHECKBOX), MAIN_OPTIONS_ENABLED_WIDGETS | (1 << WIDX_LANGUAGE) | @@ -401,6 +456,7 @@ static uint32 window_options_page_enabled_widgets[] = { MAIN_OPTIONS_ENABLED_WIDGETS | (1 << WIDX_SCREEN_EDGE_SCROLLING) | + (1 << WIDX_TRAP_CURSOR) | (1 << WIDX_INVERT_DRAG) | (1 << WIDX_HOTKEY_DROPDOWN) | (1 << WIDX_TOOLBAR_SHOW_FINANCES) | @@ -410,7 +466,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) | @@ -425,7 +484,10 @@ static uint32 window_options_page_enabled_widgets[] = { (1 << WIDX_TITLE_SEQUENCE_DROPDOWN) | (1 << WIDX_TITLE_SEQUENCE_BUTTON) | (1 << WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM) | - (1 << WIDX_STAY_CONNECTED_AFTER_DESYNC), + (1 << WIDX_STAY_CONNECTED_AFTER_DESYNC) | + (1 << WIDX_AUTO_OPEN_SHOPS) | + (1 << WIDX_DEFAULT_INSPECTION_INTERVAL) | + (1 << WIDX_DEFAULT_INSPECTION_INTERVAL_DROPDOWN), MAIN_OPTIONS_ENABLED_WIDGETS | (1 << WIDX_CHANNEL_BUTTON) | @@ -451,7 +513,7 @@ void window_options_open() if (w != NULL) return; - w = window_create_centred(WW, WH, &window_options_events, WC_OPTIONS, WF_RESIZABLE); + w = window_create_centred(WW, WH, &window_options_events, WC_OPTIONS, 0); w->widgets = window_options_display_widgets; w->enabled_widgets = window_options_page_enabled_widgets[WINDOW_OPTIONS_PAGE_DISPLAY]; w->page = WINDOW_OPTIONS_PAGE_DISPLAY; @@ -479,6 +541,7 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) case WIDX_TAB_4: case WIDX_TAB_5: case WIDX_TAB_6: + case WIDX_TAB_7: window_options_set_page(w, widgetIndex - WIDX_TAB_1); break; } @@ -486,25 +549,9 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) switch (w->page) { case WINDOW_OPTIONS_PAGE_DISPLAY: switch (widgetIndex) { - case WIDX_TILE_SMOOTHING_CHECKBOX: - gConfigGeneral.landscape_smoothing ^= 1; - config_save_default(); - gfx_invalidate_screen(); - break; - case WIDX_GRIDLINES_CHECKBOX: - gConfigGeneral.always_show_gridlines ^= 1; - config_save_default(); - gfx_invalidate_screen(); - if ((w = window_get_main()) != NULL) { - if (gConfigGeneral.always_show_gridlines) - w->viewport->flags |= VIEWPORT_FLAG_GRIDLINES; - else - w->viewport->flags &= ~VIEWPORT_FLAG_GRIDLINES; - } - break; case WIDX_HARDWARE_DISPLAY_CHECKBOX: gConfigGeneral.hardware_display ^= 1; -#ifdef _WIN32 +#ifdef __WINDOWS__ // Windows is apparently able to switch to hardware rendering on the fly although // using the same window in an unaccelerated and accelerated context is unsupported by SDL2 gHardwareDisplay = gConfigGeneral.hardware_display; @@ -522,6 +569,11 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) config_save_default(); window_invalidate(w); break; + case WIDX_SHOW_FPS_CHECKBOX: + gConfigGeneral.show_fps ^= 1; + config_save_default(); + window_invalidate(w); + break; case WIDX_MINIMIZE_FOCUS_LOSS: gConfigGeneral.minimize_fullscreen_focus_loss ^= 1; platform_refresh_video(); @@ -533,6 +585,33 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) config_save_default(); window_invalidate(w); break; + case WIDX_SCALE_USE_NN_AT_INTEGER_SCALES_CHECKBOX: + gConfigGeneral.use_nn_at_integer_scales ^= 1; + config_save_default(); + gfx_invalidate_screen(); + platform_trigger_resize(); + break; + } + break; + + case WINDOW_OPTIONS_PAGE_RENDERING: + switch (widgetIndex) { + case WIDX_TILE_SMOOTHING_CHECKBOX: + gConfigGeneral.landscape_smoothing ^= 1; + config_save_default(); + gfx_invalidate_screen(); + break; + case WIDX_GRIDLINES_CHECKBOX: + gConfigGeneral.always_show_gridlines ^= 1; + config_save_default(); + gfx_invalidate_screen(); + if ((w = window_get_main()) != NULL) { + if (gConfigGeneral.always_show_gridlines) + w->viewport->flags |= VIEWPORT_FLAG_GRIDLINES; + else + w->viewport->flags &= ~VIEWPORT_FLAG_GRIDLINES; + } + break; case WIDX_DAY_NIGHT_CHECKBOX: gConfigGeneral.day_night_cycle ^= 1; config_save_default(); @@ -543,6 +622,11 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) config_save_default(); window_invalidate(w); break; + case WIDX_DISABLE_LIGHTNING_EFFECT_CHECKBOX: + gConfigGeneral.disable_lightning_effect ^= 1; + config_save_default(); + window_invalidate(w); + break; } break; @@ -552,13 +636,14 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) case WINDOW_OPTIONS_PAGE_AUDIO: switch (widgetIndex) { case WIDX_SOUND_CHECKBOX: - audio_toggle_all_sounds(); + // audio_toggle_all_sounds(); + gConfigSound.sound_enabled = !gConfigSound.sound_enabled; config_save_default(); window_invalidate(w); break; case WIDX_MUSIC_CHECKBOX: - gConfigSound.ride_music = !gConfigSound.ride_music; - if (!gConfigSound.ride_music) { + gConfigSound.ride_music_enabled = !gConfigSound.ride_music_enabled; + if (!gConfigSound.ride_music_enabled) { audio_stop_ride_music(); } config_save_default(); @@ -582,6 +667,12 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) config_save_default(); window_invalidate(w); break; + case WIDX_TRAP_CURSOR: + gConfigGeneral.trap_cursor ^= 1; + config_save_default(); + SDL_SetWindowGrab(gWindow, gConfigGeneral.trap_cursor ? SDL_TRUE : SDL_FALSE); + window_invalidate(w); + break; case WIDX_TOOLBAR_SHOW_FINANCES: gConfigInterface.toolbar_show_finances ^= 1; config_save_default(); @@ -622,6 +713,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; @@ -630,8 +726,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; @@ -670,6 +765,11 @@ static void window_options_mouseup(rct_window *w, int widgetIndex) gConfigNetwork.stay_connected = !gConfigNetwork.stay_connected; config_save_default(); window_invalidate(w); + break; + case WIDX_AUTO_OPEN_SHOPS: + gConfigGeneral.auto_open_shops = !gConfigGeneral.auto_open_shops; + config_save_default(); + window_invalidate(w); } break; @@ -760,16 +860,6 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* dropdown_set_checked(gConfigGeneral.fullscreen_mode, true); break; - case WIDX_CONSTRUCTION_MARKER_DROPDOWN: - gDropdownItemsFormat[0] = 1142; - gDropdownItemsFormat[1] = 1142; - gDropdownItemsArgs[0] = STR_WHITE; - gDropdownItemsArgs[1] = STR_TRANSLUCENT; - - window_options_show_dropdown(w, widget, 2); - - dropdown_set_checked(gConfigGeneral.construction_marker_colour, true); - break; case WIDX_SCALE_UP: gConfigGeneral.window_scale += 0.25f; config_save_default(); @@ -783,6 +873,33 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* gfx_invalidate_screen(); platform_trigger_resize(); break; + case WIDX_SCALE_QUALITY_DROPDOWN: + gDropdownItemsFormat[0] = 1142; + gDropdownItemsFormat[1] = 1142; + gDropdownItemsFormat[2] = 1142; + gDropdownItemsArgs[0] = STR_SCALING_QUALITY_NN; + gDropdownItemsArgs[1] = STR_SCALING_QUALITY_LINEAR; + gDropdownItemsArgs[2] = STR_SCALING_QUALITY_ANISOTROPIC; + + window_options_show_dropdown(w, widget, 3); + + dropdown_set_checked(gConfigGeneral.scale_quality, true); + break; + } + break; + + case WINDOW_OPTIONS_PAGE_RENDERING: + switch (widgetIndex) { + case WIDX_CONSTRUCTION_MARKER_DROPDOWN: + gDropdownItemsFormat[0] = 1142; + gDropdownItemsFormat[1] = 1142; + gDropdownItemsArgs[0] = STR_WHITE; + gDropdownItemsArgs[1] = STR_TRANSLUCENT; + + window_options_show_dropdown(w, widget, 2); + + dropdown_set_checked(gConfigGeneral.construction_marker_colour, true); + break; } break; @@ -813,10 +930,12 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* case WIDX_DISTANCE_DROPDOWN: gDropdownItemsFormat[0] = 1142; gDropdownItemsFormat[1] = 1142; + gDropdownItemsFormat[2] = 1142; gDropdownItemsArgs[0] = STR_IMPERIAL; gDropdownItemsArgs[1] = STR_METRIC; + gDropdownItemsArgs[2] = STR_SI; - window_options_show_dropdown(w, widget, 2); + window_options_show_dropdown(w, widget, 3); dropdown_set_checked(gConfigGeneral.measurement_format, true); break; @@ -885,16 +1004,11 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* case WINDOW_OPTIONS_PAGE_CONTROLS_AND_INTERFACE: switch (widgetIndex) { case WIDX_THEMES_DROPDOWN: - num_items = gConfigThemes.num_presets; + num_items = (int)theme_manager_get_num_available_themes(); - gDropdownItemsFormat[0] = 2777; - gDropdownItemsArgs[0] = (uint32)&gConfigThemes.presets[1].name; - gDropdownItemsFormat[1] = 2777; - gDropdownItemsArgs[1] = (uint32)&gConfigThemes.presets[0].name; - - for (i = 2; i < num_items; i++) { + for (int i = 0; i < num_items; i++) { gDropdownItemsFormat[i] = 2777; - gDropdownItemsArgs[i] = (uint32)&gConfigThemes.presets[i].name; + gDropdownItemsArgs[i] = (uint32)theme_manager_get_available_theme_name(i); } window_dropdown_show_text_custom_width( @@ -905,13 +1019,31 @@ static void window_options_mousedown(int widgetIndex, rct_window*w, rct_widget* DROPDOWN_FLAG_STAY_OPEN, num_items, widget->right - widget->left - 3 - ); + ); - if (gCurrentTheme == 0 || gCurrentTheme == 1) { - dropdown_set_checked(gCurrentTheme ^ 1, true); - } else { - dropdown_set_checked(gCurrentTheme, true); - } + dropdown_set_checked(theme_manager_get_active_available_theme_index(), true); + widget_invalidate(w, WIDX_THEMES_DROPDOWN); + 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; @@ -935,18 +1067,26 @@ 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; + case WIDX_DEFAULT_INSPECTION_INTERVAL_DROPDOWN: + for (i = 0; i < 7; i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = STR_EVERY_10_MINUTES + i; + } + + window_options_show_dropdown(w, widget, 7); + dropdown_set_checked(gConfigGeneral.default_inspection_interval, true); + break; } break; @@ -991,6 +1131,19 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown gfx_invalidate_screen(); } break; + case WIDX_SCALE_QUALITY_DROPDOWN: + if (dropdownIndex != gConfigGeneral.scale_quality) { + gConfigGeneral.scale_quality = (uint8)dropdownIndex; + config_save_default(); + gfx_invalidate_screen(); + platform_trigger_resize(); + } + break; + } + break; + + case WINDOW_OPTIONS_PAGE_RENDERING: + switch (widgetIndex) { case WIDX_CONSTRUCTION_MARKER_DROPDOWN: if (dropdownIndex != gConfigGeneral.construction_marker_colour) { gConfigGeneral.construction_marker_colour = (uint8)dropdownIndex; @@ -1106,12 +1259,18 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown switch (widgetIndex) { case WIDX_THEMES_DROPDOWN: if (dropdownIndex != -1) { - if (dropdownIndex == 0 || dropdownIndex == 1) - dropdownIndex ^= 1; - theme_change_preset(dropdownIndex); + theme_manager_set_active_available_theme(dropdownIndex); } 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; @@ -1132,6 +1291,13 @@ static void window_options_dropdown(rct_window *w, int widgetIndex, int dropdown window_invalidate(w); } break; + case WIDX_DEFAULT_INSPECTION_INTERVAL_DROPDOWN: + if (dropdownIndex != gConfigGeneral.default_inspection_interval) { + gConfigGeneral.default_inspection_interval = (uint8)dropdownIndex; + config_save_default(); + window_invalidate(w); + } + break; } break; @@ -1160,9 +1326,9 @@ static void window_options_invalidate(rct_window *w) switch (w->page) { case WINDOW_OPTIONS_PAGE_DISPLAY: - RCT2_GLOBAL(0x013CE952 + 16, uint16) = (uint16)gConfigGeneral.fullscreen_width; - RCT2_GLOBAL(0x013CE952 + 18, uint16) = (uint16)gConfigGeneral.fullscreen_height; - RCT2_GLOBAL(0x013CE952 + 12, uint16) = 2773 + gConfigGeneral.fullscreen_mode; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 16, uint16) = (uint16)gConfigGeneral.fullscreen_width; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 18, uint16) = (uint16)gConfigGeneral.fullscreen_height; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 12, uint16) = 2773 + gConfigGeneral.fullscreen_mode; // disable resolution dropdown on "Fullscreen (desktop)" if (gConfigGeneral.fullscreen_mode == 2){ @@ -1174,46 +1340,78 @@ static void window_options_invalidate(rct_window *w) w->disabled_widgets &= ~(1 << WIDX_RESOLUTION); } - widget_set_checkbox_value(w, WIDX_TILE_SMOOTHING_CHECKBOX, (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE) == 0); - widget_set_checkbox_value(w, WIDX_GRIDLINES_CHECKBOX, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES); + if (gConfigGeneral.hardware_display == false) { + w->disabled_widgets |= (1 << WIDX_SCALE_QUALITY); + w->disabled_widgets |= (1 << WIDX_SCALE_QUALITY_DROPDOWN); + w->disabled_widgets |= (1 << WIDX_SCALE_USE_NN_AT_INTEGER_SCALES_CHECKBOX); + w->disabled_widgets |= (1 << WIDX_STEAM_OVERLAY_PAUSE); + } else { + w->disabled_widgets &= ~(1 << WIDX_SCALE_QUALITY); + w->disabled_widgets &= ~(1 << WIDX_SCALE_QUALITY_DROPDOWN); + w->disabled_widgets &= ~(1 << WIDX_SCALE_USE_NN_AT_INTEGER_SCALES_CHECKBOX); + w->disabled_widgets &= ~(1 << WIDX_STEAM_OVERLAY_PAUSE); + } + widget_set_checkbox_value(w, WIDX_HARDWARE_DISPLAY_CHECKBOX, gConfigGeneral.hardware_display); widget_set_checkbox_value(w, WIDX_UNCAP_FPS_CHECKBOX, gConfigGeneral.uncap_fps); + widget_set_checkbox_value(w, WIDX_SHOW_FPS_CHECKBOX, gConfigGeneral.show_fps); widget_set_checkbox_value(w, WIDX_MINIMIZE_FOCUS_LOSS, gConfigGeneral.minimize_fullscreen_focus_loss); widget_set_checkbox_value(w, WIDX_STEAM_OVERLAY_PAUSE, gConfigGeneral.steam_overlay_pause); - widget_set_checkbox_value(w, WIDX_DAY_NIGHT_CHECKBOX, gConfigGeneral.day_night_cycle); - widget_set_checkbox_value(w, WIDX_UPPER_CASE_BANNERS_CHECKBOX, gConfigGeneral.upper_case_banners); + widget_set_checkbox_value(w, WIDX_SCALE_USE_NN_AT_INTEGER_SCALES_CHECKBOX, gConfigGeneral.use_nn_at_integer_scales); - // construction marker: white/translucent - window_options_display_widgets[WIDX_CONSTRUCTION_MARKER].image = STR_WHITE + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_CONSTRUCTION_MARKER, uint8); + window_options_display_widgets[WIDX_SCALE_QUALITY].image = STR_SCALING_QUALITY_NN + gConfigGeneral.scale_quality; window_options_display_widgets[WIDX_RESOLUTION].type = WWT_DROPDOWN; window_options_display_widgets[WIDX_RESOLUTION_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_options_display_widgets[WIDX_FULLSCREEN].type = WWT_DROPDOWN; window_options_display_widgets[WIDX_FULLSCREEN_DROPDOWN].type = WWT_DROPDOWN_BUTTON; - window_options_display_widgets[WIDX_TILE_SMOOTHING_CHECKBOX].type = WWT_CHECKBOX; - window_options_display_widgets[WIDX_GRIDLINES_CHECKBOX].type = WWT_CHECKBOX; - window_options_display_widgets[WIDX_CONSTRUCTION_MARKER].type = WWT_DROPDOWN; - window_options_display_widgets[WIDX_CONSTRUCTION_MARKER_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_options_display_widgets[WIDX_HARDWARE_DISPLAY_CHECKBOX].type = WWT_CHECKBOX; window_options_display_widgets[WIDX_UNCAP_FPS_CHECKBOX].type = WWT_CHECKBOX; + window_options_display_widgets[WIDX_SHOW_FPS_CHECKBOX].type = WWT_CHECKBOX; window_options_display_widgets[WIDX_MINIMIZE_FOCUS_LOSS].type = WWT_CHECKBOX; window_options_display_widgets[WIDX_STEAM_OVERLAY_PAUSE].type = WWT_CHECKBOX; - window_options_display_widgets[WIDX_DAY_NIGHT_CHECKBOX].type = WWT_CHECKBOX; - window_options_display_widgets[WIDX_UPPER_CASE_BANNERS_CHECKBOX].type = WWT_CHECKBOX; + break; + + case WINDOW_OPTIONS_PAGE_RENDERING: + widget_set_checkbox_value(w, WIDX_TILE_SMOOTHING_CHECKBOX, (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_DISABLE_SMOOTH_LANDSCAPE) == 0); + widget_set_checkbox_value(w, WIDX_GRIDLINES_CHECKBOX, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_ALWAYS_SHOW_GRIDLINES); + widget_set_checkbox_value(w, WIDX_DAY_NIGHT_CHECKBOX, gConfigGeneral.day_night_cycle); + widget_set_checkbox_value(w, WIDX_UPPER_CASE_BANNERS_CHECKBOX, gConfigGeneral.upper_case_banners); + widget_set_checkbox_value(w, WIDX_DISABLE_LIGHTNING_EFFECT_CHECKBOX, gConfigGeneral.disable_lightning_effect); + + // construction marker: white/translucent + window_options_rendering_widgets[WIDX_CONSTRUCTION_MARKER].image = STR_WHITE + gConfigGeneral.construction_marker_colour; + + window_options_rendering_widgets[WIDX_TILE_SMOOTHING_CHECKBOX].type = WWT_CHECKBOX; + window_options_rendering_widgets[WIDX_GRIDLINES_CHECKBOX].type = WWT_CHECKBOX; + window_options_rendering_widgets[WIDX_CONSTRUCTION_MARKER].type = WWT_DROPDOWN; + window_options_rendering_widgets[WIDX_CONSTRUCTION_MARKER_DROPDOWN].type = WWT_DROPDOWN_BUTTON; + window_options_rendering_widgets[WIDX_DAY_NIGHT_CHECKBOX].type = WWT_CHECKBOX; + window_options_rendering_widgets[WIDX_UPPER_CASE_BANNERS_CHECKBOX].type = WWT_CHECKBOX; + window_options_rendering_widgets[WIDX_DISABLE_LIGHTNING_EFFECT_CHECKBOX].type = WWT_CHECKBOX; break; case WINDOW_OPTIONS_PAGE_CULTURE: // currency: pounds, dollars, etc. (10 total) - RCT2_GLOBAL(0x013CE952 + 12, uint16) = CurrencyDescriptors[gConfigGeneral.currency_format].stringId; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 12, uint16) = CurrencyDescriptors[gConfigGeneral.currency_format].stringId; - // distance: metric/imperial - RCT2_GLOBAL(0x013CE952 + 14, uint16) = STR_IMPERIAL + gConfigGeneral.measurement_format; + // distance: metric / imperial / si + { + rct_string_id stringId; + switch (gConfigGeneral.measurement_format) { + default: + case MEASUREMENT_FORMAT_IMPERIAL: stringId = STR_IMPERIAL; break; + case MEASUREMENT_FORMAT_METRIC: stringId = STR_METRIC; break; + case MEASUREMENT_FORMAT_SI: stringId = STR_SI; break; + } + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 14, uint16) = stringId; + } // temperature: celsius/fahrenheit - RCT2_GLOBAL(0x013CE952 + 20, uint16) = STR_CELSIUS + gConfigGeneral.temperature_format; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 20, uint16) = STR_CELSIUS + gConfigGeneral.temperature_format; // height: units/real values - RCT2_GLOBAL(0x013CE952 + 6, uint16) = gConfigGeneral.show_height_as_units ? STR_UNITS : STR_REAL_VALUES; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = gConfigGeneral.show_height_as_units ? STR_UNITS : STR_REAL_VALUES; window_options_culture_widgets[WIDX_LANGUAGE].type = WWT_DROPDOWN; window_options_culture_widgets[WIDX_LANGUAGE_DROPDOWN].type = WWT_DROPDOWN_BUTTON; @@ -1237,29 +1435,31 @@ static void window_options_invalidate(rct_window *w) RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_SOUND_NONE; } else { +#ifndef __LINUX__ if (currentSoundDevice == 0) RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = 5510; else +#endif // __LINUX__ RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = 1170; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = (uint32)gAudioDevices[currentSoundDevice].name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = (uint32)gAudioDevices[currentSoundDevice].name; } // music: on/off - RCT2_GLOBAL(0x013CE952 + 8, uint16) = STR_OFF + gConfigSound.ride_music; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint16) = STR_OFF + gConfigSound.ride_music_enabled; - widget_set_checkbox_value(w, WIDX_SOUND_CHECKBOX, gConfigSound.sound); - widget_set_checkbox_value(w, WIDX_MUSIC_CHECKBOX, gConfigSound.ride_music); + widget_set_checkbox_value(w, WIDX_SOUND_CHECKBOX, gConfigSound.sound_enabled); + widget_set_checkbox_value(w, WIDX_MUSIC_CHECKBOX, gConfigSound.ride_music_enabled); widget_set_checkbox_value(w, WIDX_AUDIO_FOCUS_CHECKBOX, gConfigSound.audio_focus); if(w->frame_no == 0){ // initialize only on first frame, otherwise the scrollbars wont be able to be modified - widget = &window_options_audio_widgets[WIDX_MASTER_VOLUME]; - w->scrolls[0].h_left = (sint16)ceil((gConfigSound.master_volume / 100.0f) * (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))); + widget = &window_options_audio_widgets[WIDX_SOUND_VOLUME]; + w->scrolls[0].h_left = (sint16)ceil((gConfigSound.sound_volume / 100.0f) * (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))); widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; - w->scrolls[1].h_left = (sint16)ceil((gConfigSound.music_volume / 100.0f) * (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))); + w->scrolls[1].h_left = (sint16)ceil((gConfigSound.ride_music_volume / 100.0f) * (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))); } - widget_scroll_update_thumbs(w, WIDX_MASTER_VOLUME); + widget_scroll_update_thumbs(w, WIDX_SOUND_VOLUME); widget_scroll_update_thumbs(w, WIDX_MUSIC_VOLUME); window_options_audio_widgets[WIDX_SOUND].type = WWT_DROPDOWN; @@ -1269,29 +1469,40 @@ static void window_options_invalidate(rct_window *w) window_options_audio_widgets[WIDX_AUDIO_FOCUS_CHECKBOX].type = WWT_CHECKBOX; window_options_audio_widgets[WIDX_TITLE_MUSIC].type = WWT_DROPDOWN; window_options_audio_widgets[WIDX_TITLE_MUSIC_DROPDOWN].type = WWT_DROPDOWN_BUTTON; - window_options_audio_widgets[WIDX_MASTER_VOLUME].type = WWT_SCROLL; + window_options_audio_widgets[WIDX_SOUND_VOLUME].type = WWT_SCROLL; window_options_audio_widgets[WIDX_MUSIC_VOLUME].type = WWT_SCROLL; break; case WINDOW_OPTIONS_PAGE_CONTROLS_AND_INTERFACE: widget_set_checkbox_value(w, WIDX_SCREEN_EDGE_SCROLLING, gConfigGeneral.edge_scrolling); + widget_set_checkbox_value(w, WIDX_TRAP_CURSOR, gConfigGeneral.trap_cursor); widget_set_checkbox_value(w, WIDX_INVERT_DRAG, gConfigGeneral.invert_viewport_drag); widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_FINANCES, gConfigInterface.toolbar_show_finances); widget_set_checkbox_value(w, WIDX_TOOLBAR_SHOW_RESEARCH, gConfigInterface.toolbar_show_research); 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; window_options_controls_and_interface_widgets[WIDX_THEMES_BUTTON].type = WWT_DROPDOWN_BUTTON; window_options_controls_and_interface_widgets[WIDX_SCREEN_EDGE_SCROLLING].type = WWT_CHECKBOX; + window_options_controls_and_interface_widgets[WIDX_TRAP_CURSOR].type = WWT_CHECKBOX; window_options_controls_and_interface_widgets[WIDX_HOTKEY_DROPDOWN].type = WWT_DROPDOWN_BUTTON; window_options_controls_and_interface_widgets[WIDX_TOOLBAR_SHOW_FINANCES].type = WWT_CHECKBOX; window_options_controls_and_interface_widgets[WIDX_TOOLBAR_SHOW_RESEARCH].type = WWT_CHECKBOX; 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: @@ -1300,7 +1511,7 @@ static void window_options_invalidate(rct_window *w) w->disabled_widgets |= (1ULL << WIDX_REAL_NAME_CHECKBOX); // save plugin data checkbox: visible or not - if (RCT2_GLOBAL(RCT2_ADDRESS_CUSTOM_OBJECTS_INSTALLED, uint8) == 1) + if (gNumInstalledCustomObjects == 0) window_options_misc_widgets[WIDX_SAVE_PLUGIN_DATA_CHECKBOX].type = WWT_EMPTY; else window_options_misc_widgets[WIDX_SAVE_PLUGIN_DATA_CHECKBOX].type = WWT_CHECKBOX; @@ -1313,6 +1524,7 @@ static void window_options_invalidate(rct_window *w) widget_set_checkbox_value(w, WIDX_DEBUGGING_TOOLS, gConfigGeneral.debugging_tools); widget_set_checkbox_value(w, WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM, gConfigGeneral.allow_loading_with_incorrect_checksum); widget_set_checkbox_value(w, WIDX_STAY_CONNECTED_AFTER_DESYNC, gConfigNetwork.stay_connected); + widget_set_checkbox_value(w, WIDX_AUTO_OPEN_SHOPS, gConfigGeneral.auto_open_shops); window_options_misc_widgets[WIDX_REAL_NAME_CHECKBOX].type = WWT_CHECKBOX; window_options_misc_widgets[WIDX_SAVE_PLUGIN_DATA_CHECKBOX].type = WWT_CHECKBOX; @@ -1327,6 +1539,9 @@ static void window_options_invalidate(rct_window *w) window_options_misc_widgets[WIDX_TITLE_SEQUENCE_BUTTON].type = WWT_DROPDOWN_BUTTON; window_options_misc_widgets[WIDX_ALLOW_LOADING_WITH_INCORRECT_CHECKSUM].type = WWT_CHECKBOX; window_options_misc_widgets[WIDX_STAY_CONNECTED_AFTER_DESYNC].type = WWT_CHECKBOX; + window_options_misc_widgets[WIDX_AUTO_OPEN_SHOPS].type = WWT_CHECKBOX; + window_options_misc_widgets[WIDX_DEFAULT_INSPECTION_INTERVAL].type = WWT_DROPDOWN; + window_options_misc_widgets[WIDX_DEFAULT_INSPECTION_INTERVAL_DROPDOWN].type = WWT_DROPDOWN_BUTTON; break; case WINDOW_OPTIONS_PAGE_TWITCH: @@ -1344,6 +1559,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) @@ -1354,19 +1578,19 @@ static void window_options_update(rct_window *w) rct_widget *widget; if (w->page == WINDOW_OPTIONS_PAGE_AUDIO) { - widget = &window_options_audio_widgets[WIDX_MASTER_VOLUME]; - uint8 master_volume = (uint8)(((float)w->scrolls[0].h_left / (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))) * 100); + widget = &window_options_audio_widgets[WIDX_SOUND_VOLUME]; + uint8 sound_volume = (uint8)(((float)w->scrolls[0].h_left / (w->scrolls[0].h_right - ((widget->right - widget->left) - 1))) * 100); widget = &window_options_audio_widgets[WIDX_MUSIC_VOLUME]; - uint8 music_volume = (uint8)(((float)w->scrolls[1].h_left / (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))) * 100); - if (master_volume != gConfigSound.master_volume) { - gConfigSound.master_volume = master_volume; + uint8 ride_music_volume = (uint8)(((float)w->scrolls[1].h_left / (w->scrolls[1].h_right - ((widget->right - widget->left) - 1))) * 100); + if (sound_volume != gConfigSound.sound_volume) { + gConfigSound.sound_volume = sound_volume; config_save_default(); } - if (music_volume != gConfigSound.music_volume) { - gConfigSound.music_volume = music_volume; + if (ride_music_volume != gConfigSound.ride_music_volume) { + gConfigSound.ride_music_volume = ride_music_volume; config_save_default(); } - widget_invalidate(w, WIDX_MASTER_VOLUME); + widget_invalidate(w, WIDX_SOUND_VOLUME); widget_invalidate(w, WIDX_MUSIC_VOLUME); } } @@ -1382,13 +1606,27 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) switch (w->page) { case WINDOW_OPTIONS_PAGE_DISPLAY: - gfx_draw_string_left(dpi, STR_DISPLAY_RESOLUTION, w, w->colours[1], w->x + 10, w->y + window_options_display_widgets[WIDX_RESOLUTION].top + 1); gfx_draw_string_left(dpi, STR_FULLSCREEN_MODE, w, w->colours[1], w->x + 10, w->y + window_options_display_widgets[WIDX_FULLSCREEN].top + 1); - gfx_draw_string_left(dpi, STR_CONSTRUCTION_MARKER, w, w->colours[1], w->x + 10, w->y + window_options_display_widgets[WIDX_CONSTRUCTION_MARKER].top + 1); + + int colour = w->colours[1]; + // disable resolution dropdown on "Fullscreen (desktop)" + if (gConfigGeneral.fullscreen_mode == 2) { + colour |= 0x40; + } + gfx_draw_string_left(dpi, STR_DISPLAY_RESOLUTION, w, colour, w->x + 10 + 15, w->y + window_options_display_widgets[WIDX_RESOLUTION].top + 1); gfx_draw_string_left(dpi, STR_UI_SCALING_DESC, w, w->colours[1], w->x + 10, w->y + window_options_display_widgets[WIDX_SCALE].top + 1); int scale = (int)(gConfigGeneral.window_scale * 100); gfx_draw_string_left(dpi, 3311, &scale, w->colours[1], w->x + w->widgets[WIDX_SCALE].left + 1, w->y + w->widgets[WIDX_SCALE].top + 1); + + colour = w->colours[1]; + if (gConfigGeneral.hardware_display == false) { + colour |= 0x40; + } + gfx_draw_string_left(dpi, STR_SCALING_QUALITY, w, colour, w->x + 25, w->y + window_options_display_widgets[WIDX_SCALE_QUALITY].top + 1); + break; + case WINDOW_OPTIONS_PAGE_RENDERING: + gfx_draw_string_left(dpi, STR_CONSTRUCTION_MARKER, w, w->colours[1], w->x + 10, w->y + window_options_rendering_widgets[WIDX_CONSTRUCTION_MARKER].top + 1); break; case WINDOW_OPTIONS_PAGE_CULTURE: gfx_draw_string_left(dpi, 2776, w, w->colours[1], w->x + 10, w->y + window_options_culture_widgets[WIDX_LANGUAGE].top + 1); @@ -1429,7 +1667,11 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) break; case WINDOW_OPTIONS_PAGE_CONTROLS_AND_INTERFACE: gfx_draw_string_left(dpi, STR_SHOW_TOOLBAR_BUTTONS_FOR, w, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_TOOLBAR_BUTTONS_GROUP].top + 15); - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&gConfigThemes.presets[gCurrentTheme].name; + + int activeAvailableThemeIndex = theme_manager_get_active_available_theme_index(); + const utf8 * activeThemeName = theme_manager_get_available_theme_name(activeAvailableThemeIndex); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)activeThemeName; + gfx_draw_string_left(dpi, 5238, NULL, w->colours[1], w->x + 10, w->y + window_options_controls_and_interface_widgets[WIDX_THEMES].top + 1); gfx_draw_string_left_clipped( dpi, @@ -1439,7 +1681,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); @@ -1463,6 +1717,16 @@ static void window_options_paint(rct_window *w, rct_drawpixelinfo *dpi) w->y + window_options_misc_widgets[WIDX_TITLE_SEQUENCE].top, window_options_misc_widgets[WIDX_TITLE_SEQUENCE_DROPDOWN].left - window_options_misc_widgets[WIDX_TITLE_SEQUENCE].left - 4 ); + + gfx_draw_string_left(dpi, STR_DEFAULT_INSPECTION_INTERVAL, w, w->colours[1], w->x + 10, w->y + window_options_misc_widgets[WIDX_DEFAULT_INSPECTION_INTERVAL].top + 1); + gfx_draw_string_left( + dpi, + STR_EVERY_10_MINUTES + gConfigGeneral.default_inspection_interval, + NULL, + w->colours[1], + w->x + window_options_misc_widgets[WIDX_DEFAULT_INSPECTION_INTERVAL].left + 1, + w->y + window_options_misc_widgets[WIDX_DEFAULT_INSPECTION_INTERVAL].top + ); break; } } @@ -1551,6 +1815,7 @@ static void window_options_draw_tab_image(rct_drawpixelinfo *dpi, rct_window *w, static void window_options_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) { window_options_draw_tab_image(dpi, w, WINDOW_OPTIONS_PAGE_DISPLAY, 5442); + window_options_draw_tab_image(dpi, w, WINDOW_OPTIONS_PAGE_RENDERING, 5221); window_options_draw_tab_image(dpi, w, WINDOW_OPTIONS_PAGE_CULTURE, 5229); window_options_draw_tab_image(dpi, w, WINDOW_OPTIONS_PAGE_AUDIO, 5335); window_options_draw_tab_image(dpi, w, WINDOW_OPTIONS_PAGE_CONTROLS_AND_INTERFACE, 5201); diff --git a/src/windows/park.c b/src/windows/park.c index 91be02ae90..7529258a6f 100644 --- a/src/windows/park.c +++ b/src/windows/park.c @@ -39,6 +39,7 @@ #include "../management/finance.h" #include "dropdown.h" #include "../interface/themes.h" +#include "../cheats.h" enum WINDOW_PARK_PAGE { WINDOW_PARK_PAGE_ENTRANCE, @@ -576,7 +577,7 @@ static void window_park_set_disabled_tabs(rct_window *w) static void window_park_prepare_window_title_text() { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id); - RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); } #pragma region Entrance page @@ -612,7 +613,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(); } @@ -645,7 +646,7 @@ static void window_park_entrance_mouseup(rct_window *w, int widgetIndex) window_scroll_to_viewport(w); break; case WIDX_RENAME: - RCT2_GLOBAL(0x013CE962, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 16, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); window_text_input_open(w, WIDX_RENAME, STR_PARK_NAME, STR_ENTER_PARK_NAME, RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id), 0, 32); break; case WIDX_CLOSE_LIGHT: @@ -689,10 +690,10 @@ static void window_park_entrance_mousedown(int widgetIndex, rct_window*w, rct_wi ); if (park_is_open()) { - gDropdownHighlightedIndex = 0; + gDropdownDefaultIndex = 0; dropdown_set_checked(1, true); } else { - gDropdownHighlightedIndex = 1; + gDropdownDefaultIndex = 1; dropdown_set_checked(0, true); } } @@ -949,7 +950,7 @@ static void window_park_entrance_invalidate(rct_window *w) // Set open / close park button state RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME, rct_string_id); - RCT2_GLOBAL(0x013CE952 + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_NAME_ARGS, uint32); window_park_entrance_widgets[WIDX_OPEN_OR_CLOSE].image = park_is_open() ? SPR_OPEN : SPR_CLOSED; window_park_entrance_widgets[WIDX_CLOSE_LIGHT].image = SPR_G2_RCT1_CLOSE_BUTTON_0 + !park_is_open() * 2 + widget_is_pressed(w, WIDX_CLOSE_LIGHT); window_park_entrance_widgets[WIDX_OPEN_LIGHT].image = SPR_G2_RCT1_OPEN_BUTTON_0 + park_is_open() * 2 + widget_is_pressed(w, WIDX_OPEN_LIGHT); @@ -978,7 +979,7 @@ static void window_park_entrance_invalidate(rct_window *w) window_park_entrance_widgets[WIDX_STATUS].top = w->height - 13; window_park_entrance_widgets[WIDX_STATUS].bottom = w->height - 3; - if (theme_get_preset()->features.rct1_park_lights) { + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_PARK) { window_park_entrance_widgets[WIDX_OPEN_OR_CLOSE].type = WWT_EMPTY; if (RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8) == OBJECTIVE_GUESTS_AND_RATING) { window_park_entrance_widgets[WIDX_CLOSE_LIGHT].type = WWT_FLATBTN; @@ -1038,7 +1039,7 @@ static void window_park_entrance_paint(rct_window *w, rct_drawpixelinfo *dpi) gfx_draw_string_centred_clipped( dpi, 1191, - (void*)0x013CE952, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + (labelWidget->left + labelWidget->right) / 2, w->y + labelWidget->top, @@ -1124,14 +1125,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 +1157,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 +1273,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(); @@ -1458,7 +1459,7 @@ static void window_park_price_invalidate(rct_window *w) // If the entry price is locked at free, disable the widget, unless the unlock_all_prices cheat is active. if ((RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY) - && (!gConfigCheat.unlock_all_prices)) { + && (!gCheatsUnlockAllPrices)) { window_park_price_widgets[WIDX_PRICE].type = WWT_12; window_park_price_widgets[WIDX_INCREASE_PRICE].type = WWT_EMPTY; window_park_price_widgets[WIDX_DECREASE_PRICE].type = WWT_EMPTY; @@ -1468,7 +1469,7 @@ static void window_park_price_invalidate(rct_window *w) window_park_price_widgets[WIDX_DECREASE_PRICE].type = WWT_DROPDOWN_BUTTON; } - RCT2_GLOBAL(0x013CE952 + 6, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint32) = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16); window_park_price_widgets[WIDX_PRICE].image = RCT2_GLOBAL(RCT2_ADDRESS_PARK_ENTRANCE_FEE, uint16) == 0 ? STR_FREE : 1429; window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_7); @@ -1489,8 +1490,6 @@ static void window_park_price_paint(rct_window *w, rct_drawpixelinfo *dpi) x = w->x + window_park_price_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_park_price_widgets[WIDX_PAGE_BACKGROUND].top + 30; - gfx_draw_string_left(dpi, STR_TOTAL_ADMISSIONS, (void*)RCT2_ADDRESS_TOTAL_ADMISSIONS, 0, x, y); - y += 10; gfx_draw_string_left(dpi, STR_INCOME_FROM_ADMISSIONS, (void*)RCT2_ADDRESS_INCOME_FROM_ADMISSIONS, 0, x, y); } @@ -1585,30 +1584,32 @@ static void window_park_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) // Draw park size parkSize = RCT2_GLOBAL(RCT2_ADDRESS_PARK_SIZE, uint16) * 10; stringIndex = STR_PARK_SIZE_METRIC_LABEL; - if (!RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, uint8)) { + if (gConfigGeneral.measurement_format == MEASUREMENT_FORMAT_IMPERIAL) { stringIndex = STR_PARK_SIZE_IMPERIAL_LABEL; parkSize = squaredmetres_to_squaredfeet(parkSize); } RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = parkSize; - gfx_draw_string_left(dpi, stringIndex, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, stringIndex, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 10; // Draw number of rides / attractions if (w->list_information_type != (uint16)-1) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = w->list_information_type; - gfx_draw_string_left(dpi, STR_NUMBER_OF_RIDES_LABEL, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, STR_NUMBER_OF_RIDES_LABEL, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } y += 10; // Draw number of staff if (w->var_48C != -1) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = w->var_48C; - gfx_draw_string_left(dpi, STR_STAFF_LABEL, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, STR_STAFF_LABEL, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } y += 10; // Draw number of guests in park gfx_draw_string_left(dpi, STR_GUESTS_IN_PARK_LABEL, (void*)RCT2_ADDRESS_GUESTS_IN_PARK, 0, x, y); + y += 10; + gfx_draw_string_left(dpi, STR_TOTAL_ADMISSIONS, (void*)RCT2_ADDRESS_TOTAL_ADMISSIONS, 0, x, y); } #pragma endregion @@ -1630,7 +1631,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(); @@ -1746,9 +1747,9 @@ static void window_park_objective_paint(rct_window *w, rct_drawpixelinfo *dpi) // Scenario description x = w->x + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_park_objective_widgets[WIDX_PAGE_BACKGROUND].top + 7; - safe_strncpy((char*)0x009BC677, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char), 256); + safe_strcpy((char*)0x009BC677, RCT2_ADDRESS(RCT2_ADDRESS_SCENARIO_DETAILS, char), 256); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = 3165; - y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 222, 1191, 0); + y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 222, 1191, 0); y += 5; // Your objective: @@ -1757,10 +1758,10 @@ static void window_park_objective_paint(rct_window *w, rct_drawpixelinfo *dpi) // Objective RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, short) = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_NUM_GUESTS, uint16); - RCT2_GLOBAL(0x013CE954, short) = date_get_total_months(MONTH_OCTOBER, RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8)); - RCT2_GLOBAL(0x013CE956, int) = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_CURRENCY, sint32); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, short) = date_get_total_months(MONTH_OCTOBER, RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_YEAR, uint8)); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, int) = RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_CURRENCY, sint32); - y += gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 221, 2385 + RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8), 0); + y += gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 221, 2385 + RCT2_GLOBAL(RCT2_ADDRESS_OBJECTIVE_TYPE, uint8), 0); y += 5; // Objective outcome @@ -1771,7 +1772,7 @@ static void window_park_objective_paint(rct_window *w, rct_drawpixelinfo *dpi) } else { // Objective completed RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, int) = RCT2_GLOBAL(RCT2_ADDRESS_COMPLETED_COMPANY_VALUE, money32); - gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x, y, 222, 2788, 0); + gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 222, 2788, 0); } } } @@ -1795,7 +1796,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 +1908,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 +1983,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; diff --git a/src/windows/player.c b/src/windows/player.c new file mode 100644 index 0000000000..dd94715a39 --- /dev/null +++ b/src/windows/player.c @@ -0,0 +1,649 @@ +/***************************************************************************** +* Copyright (c) 2014 Ted John, Duncan Frost +* 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 . +*****************************************************************************/ + +#include "../addresses.h" +#include "../config.h" +#include "../game.h" +#include "../input.h" +#include "../management/marketing.h" +#include "../network/network.h" +#include "../peep/peep.h" +#include "../peep/staff.h" +#include "../ride/ride.h" +#include "../ride/ride_data.h" +#include "../scenario.h" +#include "../localisation/localisation.h" +#include "../sprites.h" +#include "../interface/themes.h" +#include "../interface/viewport.h" +#include "../interface/widget.h" +#include "../interface/window.h" +#include "../util/util.h" +#include "../world/footpath.h" +#include "../world/map.h" +#include "../world/sprite.h" +#include "dropdown.h" +#include "error.h" + +enum WINDOW_PLAYER_PAGE { + WINDOW_PLAYER_PAGE_OVERVIEW, + WINDOW_PLAYER_PAGE_STATISTICS, +}; + +#pragma region Widgets + +enum WINDOW_PLAYER_WIDGET_IDX { + WIDX_BACKGROUND, + WIDX_TITLE, + WIDX_CLOSE, + WIDX_PAGE_BACKGROUND, + WIDX_TAB_1, + WIDX_TAB_2, + + WIDX_GROUP = 6, + WIDX_GROUP_DROPDOWN, + WIDX_LOCATE, + WIDX_KICK, + WIDX_VIEWPORT, +}; + +#define WINDOW_PLAYER_COMMON_WIDGETS \ + { WWT_FRAME, 0, 0, 191, 0, 156, 0x0FFFFFFFF, STR_NONE }, /* Panel / Background */ \ + { WWT_CAPTION, 0, 1, 190, 1, 14, 865, STR_WINDOW_TITLE_TIP }, /* Title */ \ + { WWT_CLOSEBOX, 0, 179, 189, 2, 13, 824, STR_CLOSE_WINDOW_TIP }, /* Close x button */ \ + { WWT_RESIZE, 1, 0, 191, 43, 156, 0x0FFFFFFFF, STR_NONE }, /* Resize */ \ + { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_NONE }, /* Tab 1 */ \ + { WWT_TAB, 1, 34, 64, 17, 43, 0x2000144E, STR_NONE } /* Tab 2 */ + +rct_widget window_player_overview_widgets[] = { + WINDOW_PLAYER_COMMON_WIDGETS, + { WWT_DROPDOWN, 1, 3, 177, 46, 57, 0x0FFFFFFFF, STR_NONE }, // Permission group + { WWT_DROPDOWN_BUTTON, 1, 167, 177, 47, 56, 876, STR_NONE }, // + { WWT_FLATBTN, 1, 179, 190, 45, 68, SPR_LOCATE, STR_LOCATE_PLAYER_TIP }, // Locate button + { WWT_FLATBTN, 1, 179, 190, 69, 92, SPR_DEMOLISH, STR_KICK_PLAYER_TIP }, // Kick button + { WWT_VIEWPORT, 1, 3, 177, 60, 120, 0x0FFFFFFFF, STR_NONE }, // Viewport + { WIDGETS_END }, +}; + +rct_widget window_player_statistics_widgets[] = { + WINDOW_PLAYER_COMMON_WIDGETS, + { WIDGETS_END }, +}; + +rct_widget *window_player_page_widgets[] = { + window_player_overview_widgets, + window_player_statistics_widgets +}; + +#pragma endregion + +#pragma region Events + +void window_player_overview_close(rct_window *w); +void window_player_overview_mouse_up(rct_window *w, int widgetIndex); +void window_player_overview_resize(rct_window *w); +void window_player_overview_mouse_down(int widgetIndex, rct_window *w, rct_widget *widget); +void window_player_overview_dropdown(rct_window *w, int widgetIndex, int dropdownIndex); +void window_player_overview_update(rct_window* w); +void window_player_overview_invalidate(rct_window *w); +void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi); + +static rct_window_event_list window_player_overview_events = { + window_player_overview_close, + window_player_overview_mouse_up, + window_player_overview_resize, + window_player_overview_mouse_down, + window_player_overview_dropdown, + NULL, + window_player_overview_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_player_overview_invalidate, + window_player_overview_paint, + NULL +}; + +void window_player_statistics_close(rct_window *w); +void window_player_statistics_mouse_up(rct_window *w, int widgetIndex); +void window_player_statistics_resize(rct_window *w); +void window_player_statistics_update(rct_window* w); +void window_player_statistics_invalidate(rct_window *w); +void window_player_statistics_paint(rct_window *w, rct_drawpixelinfo *dpi); + +static rct_window_event_list window_player_statistics_events = { + window_player_statistics_close, + window_player_statistics_mouse_up, + window_player_statistics_resize, + NULL, + NULL, + NULL, + window_player_statistics_update, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + window_player_statistics_invalidate, + window_player_statistics_paint, + NULL +}; + +static rct_window_event_list *window_player_page_events[] = { + &window_player_overview_events, + &window_player_statistics_events +}; + +#pragma endregion + +static void window_player_set_page(rct_window* w, int page); +static void window_player_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w); +static void window_player_update_viewport(rct_window *w, bool scroll); + +uint32 window_player_page_enabled_widgets[] = { + (1 << WIDX_CLOSE) | + (1 << WIDX_TAB_1) | + (1 << WIDX_TAB_2) | + (1 << WIDX_GROUP) | + (1 << WIDX_GROUP_DROPDOWN) | + (1 << WIDX_LOCATE) | + (1 << WIDX_KICK), + + (1 << WIDX_CLOSE) | + (1 << WIDX_TAB_1) | + (1 << WIDX_TAB_2) +}; + +void window_player_open(uint8 id) +{ + rct_window* window; + + int player = network_get_player_index(id); + window = window_bring_to_front_by_number(WC_PLAYER, id); + if (window == NULL) { + window = window_create_auto_pos(240, 170, &window_player_overview_events, WC_PLAYER, WF_RESIZABLE); + window->number = id; + window->page = 0; + window->viewport_focus_coordinates.y = 0; + window->frame_no = 0; + window->list_information_type = 0; + window->picked_peep_frame = 0; + window->highlighted_item = 0; + window->min_width = 210; + window->min_height = 134; + window->max_width = 500; + window->max_height = 450; + window->no_list_items = 0; + window->selected_list_item = -1; + + window->viewport_focus_coordinates.y = -1; + window->error.var_480 = user_string_allocate(128, network_get_player_name(player)); // repurposing var_480 to store this + } + + window->page = 0; + window_invalidate(window); + + window->widgets = window_player_page_widgets[WINDOW_PLAYER_PAGE_OVERVIEW]; + window->enabled_widgets = window_player_page_enabled_widgets[WINDOW_PLAYER_PAGE_OVERVIEW]; + window->hold_down_widgets = 0; + window->event_handlers = window_player_page_events[WINDOW_PLAYER_PAGE_OVERVIEW]; + window->pressed_widgets = 0; + + window_init_scroll_widgets(window); + window_player_set_page(window, WINDOW_PLAYER_PAGE_OVERVIEW); +} + +void window_player_overview_show_group_dropdown(rct_window *w, rct_widget *widget) +{ + rct_widget *dropdownWidget; + int numItems, i; + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + + dropdownWidget = widget - 1; + + numItems = network_get_num_groups(); + + window_dropdown_show_text_custom_width( + w->x + dropdownWidget->left, + w->y + dropdownWidget->top, + dropdownWidget->bottom - dropdownWidget->top + 1, + w->colours[1], + 0, + numItems, + widget->right - dropdownWidget->left + ); + + for (i = 0; i < network_get_num_groups(); i++) { + gDropdownItemsFormat[i] = 1142; + gDropdownItemsArgs[i] = network_get_group_name_string_id(i); + } + + dropdown_set_checked(network_get_group_index(network_get_player_group(player)), true); +} + +void window_player_overview_close(rct_window *w) +{ + if (w->error.var_480){ + user_string_free(w->error.var_480); + w->error.var_480 = 0; + } +} + +void window_player_overview_mouse_up(rct_window *w, int widgetIndex) +{ + switch(widgetIndex){ + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_TAB_1: + case WIDX_TAB_2: + window_player_set_page(w, widgetIndex - WIDX_TAB_1); + break; + case WIDX_LOCATE:{ + rct_window* mainWindow = window_get_main(); + if (mainWindow != NULL) { + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + rct_xyz16 coord = network_get_player_last_action_coord(player); + if (coord.x || coord.y || coord.z) { + window_scroll_to_location(mainWindow, coord.x, coord.y, coord.z); + } + } + }break; + case WIDX_KICK: + game_do_command(w->number, GAME_COMMAND_FLAG_APPLY, 0, 0, GAME_COMMAND_KICK_PLAYER, 0, 0); + break; + } +} + +void window_player_overview_mouse_down(int widgetIndex, rct_window *w, rct_widget *widget) +{ + switch(widgetIndex){ + case WIDX_GROUP_DROPDOWN: + window_player_overview_show_group_dropdown(w, widget); + break; + } +} + +void window_player_overview_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) +{ + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + if (dropdownIndex == -1) { + return; + } + int group = network_get_group_id(dropdownIndex); + game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, group, GAME_COMMAND_SET_PLAYER_GROUP, 0, 0); + window_invalidate(w); +} + +void window_player_overview_resize(rct_window *w) +{ + window_set_resize(w, 240, 170, 500, 300); +} + +void window_player_overview_update(rct_window* w) +{ + w->frame_no++; + widget_invalidate(w, WIDX_TAB_1 + w->page); + + if (network_get_player_index((uint8)w->number) == -1) { + window_close(w); + return; + } + + // Update viewport + bool scroll = true; + + // Use this spare window field for rotation check + if (w->var_4AE != get_current_rotation()) { + w->var_4AE = get_current_rotation(); + scroll = false; + } + window_player_update_viewport(w, scroll); +} + +void window_player_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); + window_player_draw_tab_images(dpi, w); + + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + + // Draw current group + int groupindex = network_get_group_index(network_get_player_group(player)); + if (groupindex != -1) { + rct_widget* widget = &window_player_overview_widgets[WIDX_GROUP]; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_group_name_string_id(groupindex); + + gfx_draw_string_centred_clipped( + dpi, + 1193, + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, + 0, + w->x + (widget->left + widget->right - 11) / 2, + w->y + widget->top, + widget->right - widget->left - 8 + ); + } + + // Draw ping + int x = w->x + 90; + int y = w->y + 24; + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_PING; + gfx_draw_string_left(dpi, STR_WINDOW_COLOUR_2_STRING, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); + char ping[64]; + sprintf(ping, "%d ms", network_get_player_ping(player)); + gfx_draw_string(dpi, ping, w->colours[2], x + 30, y); + + // Draw last action + x = w->x + (w->width / 2); + y = w->y + w->height - 13; + int width = w->width - 8; + int lastaction = network_get_player_last_action(player, 0); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_ACTION_NA; + if (lastaction != -999) { + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = network_get_action_name_string_id(lastaction); + } + gfx_draw_string_centred_clipped(dpi, STR_LAST_ACTION_RAN, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, width); + + if (w->viewport != NULL && w->var_492 != -1) { + window_draw_viewport(dpi, w); + } +} + +void window_player_overview_invalidate(rct_window *w) +{ + if (window_player_page_widgets[w->page] != w->widgets) { + w->widgets = window_player_page_widgets[w->page]; + window_init_scroll_widgets(w); + } + + colour_scheme_update(w); + + w->pressed_widgets &= ~(WIDX_TAB_1); + w->pressed_widgets &= ~(WIDX_TAB_2); + w->pressed_widgets |= 1ULL << (w->page + WIDX_TAB_1); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = w->error.var_480; // set title caption to player name + + w->widgets[WIDX_BACKGROUND].right = w->width - 1; + w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; + w->widgets[WIDX_PAGE_BACKGROUND].right =w->width - 1; + w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1; + w->widgets[WIDX_TITLE].right = w->width - 2; + w->widgets[WIDX_CLOSE].left = w->width - 13; + w->widgets[WIDX_CLOSE].right = w->width - 3; + w->widgets[WIDX_LOCATE].right = w->width - 2; + w->widgets[WIDX_LOCATE].left = w->width - 25; + w->widgets[WIDX_KICK].right = w->width - 2; + w->widgets[WIDX_KICK].left = w->width - 25; + w->widgets[WIDX_VIEWPORT].right = w->width - 26; + w->widgets[WIDX_VIEWPORT].bottom = w->height - 14; + + int groupDropdownWidth = w->widgets[WIDX_GROUP].right - w->widgets[WIDX_GROUP].left; + w->widgets[WIDX_GROUP].left = (w->width - groupDropdownWidth) / 2; + w->widgets[WIDX_GROUP].right = w->widgets[WIDX_GROUP].left + groupDropdownWidth; + w->widgets[WIDX_GROUP_DROPDOWN].left = w->widgets[WIDX_GROUP].right - 10; + w->widgets[WIDX_GROUP_DROPDOWN].right = w->widgets[WIDX_GROUP].right; + + window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_2); + + rct_viewport *viewport = w->viewport; + if (viewport != NULL) { + rct_widget *viewportWidget = &window_player_overview_widgets[WIDX_VIEWPORT]; + + viewport->x = w->x + viewportWidget->left; + viewport->y = w->y + viewportWidget->top; + viewport->width = viewportWidget->right - viewportWidget->left; + viewport->height = viewportWidget->bottom - viewportWidget->top; + viewport->view_width = viewport->width << viewport->zoom; + viewport->view_height = viewport->height << viewport->zoom; + } +} + +void window_player_statistics_close(rct_window *w) +{ + if (w->error.var_480) { + user_string_free(w->error.var_480); + w->error.var_480 = 0; + } +} + +void window_player_statistics_mouse_up(rct_window *w, int widgetIndex) +{ + switch (widgetIndex) { + case WIDX_CLOSE: + window_close(w); + break; + case WIDX_TAB_1: + case WIDX_TAB_2: + window_player_set_page(w, widgetIndex - WIDX_TAB_1); + break; + } +} + +void window_player_statistics_resize(rct_window *w) +{ + window_set_resize(w, 210, 80, 210, 80); +} + +void window_player_statistics_update(rct_window* w) +{ + w->frame_no++; + widget_invalidate(w, WIDX_TAB_1 + w->page); + + if (network_get_player_index((uint8)w->number) == -1) { + window_close(w); + } +} + +void window_player_statistics_invalidate(rct_window *w) +{ + if (window_player_page_widgets[w->page] != w->widgets) { + w->widgets = window_player_page_widgets[w->page]; + window_init_scroll_widgets(w); + } + + colour_scheme_update(w); + + w->pressed_widgets &= ~(WIDX_TAB_1); + w->pressed_widgets &= ~(WIDX_TAB_2); + w->pressed_widgets |= 1ULL << (w->page + WIDX_TAB_1); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = w->error.var_480; // set title caption to player name + + w->widgets[WIDX_BACKGROUND].right = w->width - 1; + w->widgets[WIDX_BACKGROUND].bottom = w->height - 1; + w->widgets[WIDX_PAGE_BACKGROUND].right = w->width - 1; + w->widgets[WIDX_PAGE_BACKGROUND].bottom = w->height - 1; + w->widgets[WIDX_TITLE].right = w->width - 2; + w->widgets[WIDX_CLOSE].left = w->width - 13; + w->widgets[WIDX_CLOSE].right = w->width - 3; + + window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_2); +} + +void window_player_statistics_paint(rct_window *w, rct_drawpixelinfo *dpi) +{ + window_draw_widgets(w, dpi); + window_player_draw_tab_images(dpi, w); + + int player = network_get_player_index((uint8)w->number); + if (player == -1) { + return; + } + + int x = w->x + window_player_overview_widgets[WIDX_PAGE_BACKGROUND].left + 4; + int y = w->y + window_player_overview_widgets[WIDX_PAGE_BACKGROUND].top + 4; + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = network_get_player_commands_ran(player); + gfx_draw_string_left(dpi, STR_COMMANDS_RAN, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0,x, y); + + y += 10; + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = network_get_player_money_spent(player); + gfx_draw_string_left(dpi, STR_MONEY_SPENT, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0,x, y); +} + +static void window_player_set_page(rct_window* w, int page) +{ + int originalPage = w->page; + + w->page = page; + w->frame_no = 0; + w->no_list_items = 0; + w->selected_list_item = -1; + + w->enabled_widgets = window_player_page_enabled_widgets[page]; + w->hold_down_widgets = 0; + w->event_handlers = window_player_page_events[page]; + w->pressed_widgets = 0; + w->widgets = window_player_page_widgets[page]; + window_invalidate(w); + window_event_resize_call(w); + window_event_invalidate_call(w); + window_init_scroll_widgets(w); + window_invalidate(w); + + if (page == WINDOW_PLAYER_PAGE_OVERVIEW) { + if (w->viewport == NULL) { + viewport_create(w, w->x, w->y, w->width, w->height, 0, 128 * 32, 128 * 32, 0, 1, -1); + w->flags |= WF_NO_SCROLLING; + window_event_invalidate_call(w); + window_player_update_viewport(w, false); + } else if (originalPage != page) { + window_event_invalidate_call(w); + window_player_update_viewport(w, false); + } + } else { + if (w->viewport != NULL) { + w->viewport->width = 0; + w->viewport = NULL; + } + } +} + +static void window_player_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) +{ + rct_widget *widget; + int x, y, imageId; + + // Tab 1 + if (!widget_is_disabled(w, WIDX_TAB_1)) { + widget = &w->widgets[WIDX_TAB_1]; + x = widget->left + w->x; + y = widget->top + w->y; + imageId = SPR_PEEP_LARGE_FACE_NORMAL; + gfx_draw_sprite(dpi, imageId, x, y, 0); + } + + // Tab 2 + if (!widget_is_disabled(w, WIDX_TAB_2)) { + widget = &w->widgets[WIDX_TAB_2]; + x = widget->left + w->x; + y = widget->top + w->y; + imageId = SPR_TAB_FINANCES_SUMMARY_0; + + if (w->page == WINDOW_PLAYER_PAGE_STATISTICS) { + imageId += (w->frame_no / 2) & 7; + } + + gfx_draw_sprite(dpi, imageId, x, y, 0); + } +} + +static void window_player_update_viewport(rct_window *w, bool scroll) +{ + int playerIndex = network_get_player_index((uint8)w->number); + if (playerIndex == -1) { + return; + } + + rct_viewport *viewport = w->viewport; + if (viewport != NULL) { + rct_xyz16 coord = network_get_player_last_action_coord(playerIndex); + if (coord.x != 0 || coord.y != 0 || coord.z != 0) { + int viewX, viewY; + center_2d_coordinates(coord.x, coord.y, coord.z, &viewX, &viewY, viewport); + + // Don't scroll if the view was originally undefined + if (w->var_492 == -1) { + scroll = false; + } + + if (!scroll || w->saved_view_x != viewX || w->saved_view_y != viewY) { + w->flags |= WF_SCROLLING_TO_LOCATION; + w->saved_view_x = viewX; + w->saved_view_y = viewY; + if (!scroll) { + w->viewport->view_x = viewX; + w->viewport->view_y = viewY; + } + widget_invalidate(w, WIDX_VIEWPORT); + } + + // Draw the viewport + w->var_492 = 0; + } else { + // Don't draw the viewport + w->var_492 = -1; + } + } +} diff --git a/src/windows/player_list.c b/src/windows/player_list.c deleted file mode 100644 index f482781f10..0000000000 --- a/src/windows/player_list.c +++ /dev/null @@ -1,322 +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 . - *****************************************************************************/ - -#include "../interface/themes.h" -#include "../interface/widget.h" -#include "../interface/window.h" -#include "../localisation/localisation.h" -#include "../network/network.h" -#include "../sprites.h" -#include "../windows/dropdown.h" -#include "../util/util.h" - -enum WINDOW_PLAYER_LIST_WIDGET_IDX { - WIDX_BACKGROUND, - WIDX_TITLE, - WIDX_CLOSE, - WIDX_CONTENT_PANEL, - WIDX_TAB1, - WIDX_LIST, -}; - -static rct_widget window_player_list_widgets[] = { - { WWT_FRAME, 0, 0, 339, 0, 239, 0x0FFFFFFFF, STR_NONE }, // panel / background - { WWT_CAPTION, 0, 1, 338, 1, 14, STR_PLAYER_LIST, STR_WINDOW_TITLE_TIP }, // title bar - { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button - { WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, STR_NONE }, // content panel - { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_NONE }, // tab - { WWT_SCROLL, 1, 3, 336, 60, 236, 2, STR_NONE }, // list - { WIDGETS_END }, -}; - -static void window_player_list_mouseup(rct_window *w, int widgetIndex); -static void window_player_list_resize(rct_window *w); -static void window_player_list_mousedown(int widgetIndex, rct_window* w, rct_widget* widget); -static void window_player_list_dropdown(rct_window *w, int widgetIndex, int dropdownIndex); -static void window_player_list_update(rct_window *w); -static void window_player_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height); -static void window_player_list_scrollmousedown(rct_window *w, int scrollIndex, int x, int y); -static void window_player_list_scrollmouseover(rct_window *w, int scrollIndex, int x, int y); -static void window_player_list_invalidate(rct_window *w); -static void window_player_list_paint(rct_window *w, rct_drawpixelinfo *dpi); -static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex); - -static rct_window_event_list window_player_list_events = { - NULL, - window_player_list_mouseup, - window_player_list_resize, - window_player_list_mousedown, - window_player_list_dropdown, - NULL, - window_player_list_update, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - window_player_list_scrollgetsize, - window_player_list_scrollmousedown, - NULL, - window_player_list_scrollmouseover, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - window_player_list_invalidate, - window_player_list_paint, - window_player_list_scrollpaint -}; - -enum { - DDIDX_KICK -}; - -static void window_player_list_refresh_list(rct_window *w); - -static int _dropdownPlayerId; - -void window_player_list_open() -{ - rct_window* window; - - // Check if window is already open - window = window_bring_to_front_by_class(WC_PLAYER_LIST); - if (window != NULL) - return; - - window = window_create_auto_pos(320, 144, &window_player_list_events, WC_PLAYER_LIST, WF_10 | WF_RESIZABLE); - - window->widgets = window_player_list_widgets; - window->enabled_widgets = 1 << WIDX_CLOSE; - window_init_scroll_widgets(window); - window->no_list_items = 0; - window->selected_list_item = -1; - window->frame_no = 0; - window->min_width = 320; - window->min_height = 124; - window->max_width = 500; - window->max_height = 450; - - window->page = 0; - window->list_information_type = 0; - window->colours[0] = 7; - window->colours[1] = 7; - window->colours[2] = 7; -} - -static void window_player_list_mouseup(rct_window *w, int widgetIndex) -{ - switch (widgetIndex) { - case WIDX_CLOSE: - window_close(w); - break; - } -} - -static void window_player_list_resize(rct_window *w) -{ - if (w->width < w->min_width) { - window_invalidate(w); - w->width = w->min_width; - } - if (w->height < w->min_height) { - window_invalidate(w); - w->height = w->min_height; - } - - window_player_list_refresh_list(w); -} - -static void window_player_list_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) -{ - switch (widgetIndex) { - case WIDX_TAB1: - if (w->page != widgetIndex - WIDX_TAB1) { - w->page = widgetIndex - WIDX_TAB1; - w->no_list_items = 0; - w->frame_no = 0; - w->selected_list_item = -1; - window_invalidate(w); - } - break; - } -} - -static void window_player_list_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) -{ - switch (dropdownIndex) { - case DDIDX_KICK: - network_kick_player(_dropdownPlayerId); - break; - } -} - -static void window_player_list_update(rct_window *w) -{ - widget_invalidate(w, WIDX_TAB1 + w->page); -} - -static void window_player_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height) -{ - int i; - - if (w->selected_list_item != -1) { - w->selected_list_item = -1; - window_invalidate(w); - } - - *height = network_get_num_players() * 10; - i = *height - window_player_list_widgets[WIDX_LIST].bottom + window_player_list_widgets[WIDX_LIST].top + 21; - if (i < 0) - i = 0; - if (i < w->scrolls[0].v_top) { - w->scrolls[0].v_top = i; - window_invalidate(w); - } -} - -static void window_player_list_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) -{ - if (network_get_mode() != NETWORK_MODE_SERVER) { - return; - } - - int index; - - index = y / 10; - if (index >= w->no_list_items) - return; - - w->selected_list_item = index; - window_invalidate(w); - - rct_widget *listWidget = &w->widgets[WIDX_LIST]; - int ddx = w->x + listWidget->left + x; - int ddy = w->y + listWidget->top + y; - - if (index == 0) { - return; - } - _dropdownPlayerId = network_get_player_id(index); - if (_dropdownPlayerId == network_get_current_player_id()) { - return; - } - - gDropdownItemsFormat[0] = STR_KICK_PLAYER; - window_dropdown_show_text(ddx, ddy, 0, 7, 0, 1); -} - -static void window_player_list_scrollmouseover(rct_window *w, int scrollIndex, int x, int y) -{ - int index; - - index = y / 10; - if (index >= w->no_list_items) - return; - - w->selected_list_item = index; - window_invalidate(w); -} - -static void window_player_list_invalidate(rct_window *w) -{ - for (int i = 0; i < 1; i++) - w->pressed_widgets &= ~(1 << (WIDX_TAB1 + i)); - w->pressed_widgets |= 1LL << (WIDX_TAB1 + w->page); - window_player_list_widgets[WIDX_BACKGROUND].right = w->width - 1; - window_player_list_widgets[WIDX_BACKGROUND].bottom = w->height - 1; - window_player_list_widgets[WIDX_CONTENT_PANEL].right = w->width - 1; - window_player_list_widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1; - window_player_list_widgets[WIDX_TITLE].right = w->width - 2; - window_player_list_widgets[WIDX_CLOSE].left = w->width - 2 - 0x0B; - window_player_list_widgets[WIDX_CLOSE].right = w->width - 2 - 0x0B + 0x0A; - window_player_list_widgets[WIDX_LIST].right = w->width - 4; - window_player_list_widgets[WIDX_LIST].bottom = w->height - 0x0F; -} - -static void window_player_list_paint(rct_window *w, rct_drawpixelinfo *dpi) -{ - window_draw_widgets(w, dpi); - gfx_draw_string_left(dpi, STR_PLAYER, w, w->colours[2], w->x + 6, 58 - 12 + w->y + 1); - gfx_draw_string_left(dpi, STR_PING, w, w->colours[2], w->x + 246, 58 - 12 + w->y + 1); - - gfx_draw_sprite(dpi, SPR_TAB_GUESTS_0, w->x + w->widgets[WIDX_TAB1].left, w->y + w->widgets[WIDX_TAB1].top, 0); -} - -static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) -{ - int y; - - gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ColourMapA[w->colours[1]].mid_light); - - y = 0; - for (int i = 0; i < network_get_num_players(); i++) { - if (y > dpi->y + dpi->height) { - break; - } - - if (y + 11 >= dpi->y) { - char buffer[300]; - char* lineCh = buffer; - int colour = 0; - if (i == w->selected_list_item) { - gfx_fill_rect(dpi, 0, y, 800, y + 9, 0x02000031); - safe_strncpy(&buffer[0], network_get_player_name(i), sizeof(buffer)); - colour = w->colours[2]; - } else { - if (network_get_player_flags(i) & NETWORK_PLAYER_FLAG_ISSERVER) { - lineCh = utf8_write_codepoint(lineCh, FORMAT_BABYBLUE); - } else { - lineCh = utf8_write_codepoint(lineCh, FORMAT_BLACK); - } - safe_strncpy(lineCh, network_get_player_name(i), sizeof(buffer) - (lineCh - buffer)); - } - gfx_clip_string(buffer, 230); - gfx_draw_string(dpi, buffer, colour, 0, y - 1); - lineCh = buffer; - int ping = network_get_player_ping(i); - if (ping <= 100) { - lineCh = utf8_write_codepoint(lineCh, FORMAT_GREEN); - } else - if (ping <= 250) { - lineCh = utf8_write_codepoint(lineCh, FORMAT_YELLOW); - } else { - lineCh = utf8_write_codepoint(lineCh, FORMAT_RED); - } - sprintf(lineCh, "%d ms", ping); - gfx_draw_string(dpi, buffer, colour, 240, y - 1); - } - y += 10; - } -} - -static void window_player_list_refresh_list(rct_window *w) -{ - w->no_list_items = network_get_num_players(); - w->list_item_positions[0] = 0; - - w->selected_list_item = -1; - window_invalidate(w); -} diff --git a/src/windows/publisher_credits.c b/src/windows/publisher_credits.c index 08eed0e41f..95a84411d9 100644 --- a/src/windows/publisher_credits.c +++ b/src/windows/publisher_credits.c @@ -184,4 +184,4 @@ static void window_publisher_credits_scrollpaint(rct_window *w, rct_drawpixelinf } -} \ No newline at end of file +} diff --git a/src/windows/research.c b/src/windows/research.c index 0c03911c09..4f3dd7b045 100644 --- a/src/windows/research.c +++ b/src/windows/research.c @@ -341,7 +341,7 @@ void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dp y += 15; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_UNKNOWN; - gfx_draw_string_left(dpi, STR_RESEARCH_EXPECTED_LABEL, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, STR_RESEARCH_EXPECTED_LABEL, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } else { // Research type stringId = STR_RESEARCH_UNKNOWN; @@ -350,7 +350,7 @@ void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dp if (RCT2_GLOBAL(RCT2_ADDRESS_RESEARH_PROGRESS_STAGE, uint8) != RESEARCH_STAGE_DESIGNING) { uint32 typeId = RCT2_GLOBAL(RCT2_ADDRESS_NEXT_RESEARCH_ITEM, uint32); if (typeId >= 0x10000) { - rct_ride_type *rideEntry = RCT2_GLOBAL(0x009ACFA4 + (typeId & 0xFF) * 4, rct_ride_type*); + rct_ride_entry *rideEntry = get_ride_entry(typeId & 0xFF); stringId = (rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) ? rideEntry->name : ((typeId >> 8) & 0xFF) + 2; @@ -373,11 +373,11 @@ void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dp uint16 expectedDay = RCT2_GLOBAL(RCT2_ADDRESS_NEXT_RESEARCH_EXPECTED_DAY, uint8); if (expectedDay != 255) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = 2289; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = STR_DATE_DAY_1 + expectedDay; - RCT2_GLOBAL(0x013CE952 + 4, uint16) = STR_MONTH_MARCH + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_RESEARCH_EXPECTED_MONTH, uint8); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = STR_DATE_DAY_1 + expectedDay; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = STR_MONTH_MARCH + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_RESEARCH_EXPECTED_MONTH, uint8); } } - gfx_draw_string_left(dpi, STR_RESEARCH_EXPECTED_LABEL, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, STR_RESEARCH_EXPECTED_LABEL, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); } // Last development @@ -388,7 +388,7 @@ void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dp int lastDevelopmentFormat; if (typeId != 0xFFFFFFFF) { if (typeId >= 0x10000) { - rct_ride_type *rideEntry = RCT2_GLOBAL(0x009ACFA4 + (typeId & 0xFF) * 4, rct_ride_type*); + rct_ride_entry *rideEntry = get_ride_entry(typeId & 0xFF); stringId = (rideEntry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) ? rideEntry->name : ((typeId >> 8) & 0xFF) + 2; diff --git a/src/windows/ride.c b/src/windows/ride.c index b68086446c..5a781dca83 100644 --- a/src/windows/ride.c +++ b/src/windows/ride.c @@ -333,9 +333,9 @@ static rct_widget window_ride_colour_widgets[] = { { WWT_SPINNER, 1, 3, 70, 47, 93, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN, 1, 74, 312, 49, 60, 872, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 301, 311, 50, 59, 876, STR_COLOUR_SCHEME_TO_CHANGE_TIP }, - { WWT_COLORBTN, 1, 79, 90, 74, 85, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, - { WWT_COLORBTN, 1, 99, 110, 74, 85, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, - { WWT_COLORBTN, 1, 119, 130, 74, 85, 0xFFFFFFFF, STR_SELECT_SUPPORT_STRUCTURE_COLOUR_TIP }, + { WWT_COLOURBTN, 1, 79, 90, 74, 85, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, + { WWT_COLOURBTN, 1, 99, 110, 74, 85, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, + { WWT_COLOURBTN, 1, 119, 130, 74, 85, 0xFFFFFFFF, STR_SELECT_SUPPORT_STRUCTURE_COLOUR_TIP }, { WWT_DROPDOWN, 1, 74, 312, 49, 60, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 301, 311, 50, 59, 876, STR_NONE }, { WWT_FLATBTN, 1, 289, 312, 68, 91, 5173, STR_PAINT_INDIVIDUAL_AREA_TIP }, @@ -347,9 +347,9 @@ static rct_widget window_ride_colour_widgets[] = { { WWT_DROPDOWN_BUTTON, 1, 301, 311, 158, 167, 876, STR_SELECT_VEHICLE_COLOUR_SCHEME_TIP }, { WWT_DROPDOWN, 1, 74, 312, 173, 184, 0xFFFFFFFF, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, 301, 311, 174, 183, 876, STR_SELECT_VEHICLE_TO_MODIFY_TIP }, - { WWT_COLORBTN, 1, 79, 90, 190, 201, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, - { WWT_COLORBTN, 1, 99, 110, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, - { WWT_COLORBTN, 1, 119, 130, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_2_TIP }, + { WWT_COLOURBTN, 1, 79, 90, 190, 201, 0xFFFFFFFF, STR_SELECT_MAIN_COLOUR_TIP }, + { WWT_COLOURBTN, 1, 99, 110, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_1_TIP }, + { WWT_COLOURBTN, 1, 119, 130, 190, 201, 0xFFFFFFFF, STR_SELECT_ADDITIONAL_COLOUR_2_TIP }, { WIDGETS_END }, }; @@ -951,6 +951,15 @@ static rct_window_event_list *window_ride_page_events[] = { #pragma endregion +// Cached overall view for each ride +// (Re)calculated when the ride window is opened +typedef struct ride_overall_view_t { + sint16 x, y, z; + uint8 zoom; +} ride_overall_view; + +ride_overall_view ride_overall_views[MAX_RIDES] = {0}; + const int window_ride_tab_animation_divisor[] = { 0, 0, 2, 2, 4, 2, 8, 8, 2, 0 }; const int window_ride_tab_animation_frames[] = { 0, 0, 4, 16, 8, 16, 8, 8, 8, 0 }; @@ -970,15 +979,15 @@ static void window_ride_draw_tab_image(rct_drawpixelinfo *dpi, rct_window *w, in /** * - * rct2: 0x006B2E88 + * rct2: 0x006B2E88 */ static void window_ride_draw_tab_main(rct_drawpixelinfo *dpi, rct_window *w) { int widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_MAIN; if (!(w->disabled_widgets & (1LL << widgetIndex))) { - int spriteIndex; - int rideType = GET_RIDE(w->number)->type; + int spriteIndex = 0; + int rideType = get_ride(w->number)->type; switch (gRideClassifications[rideType]) { case RIDE_CLASS_RIDE: @@ -1004,14 +1013,14 @@ static void window_ride_draw_tab_main(rct_drawpixelinfo *dpi, rct_window *w) /** * - * rct2: 0x006B2B68 + * rct2: 0x006B2B68 */ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w) { rct_ride *ride; rct_widget *widget; int widgetIndex, spriteIndex, x, y, width, height; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; vehicle_colour vehicleColour; widgetIndex = WIDX_TAB_1 + WINDOW_RIDE_PAGE_VEHICLE; @@ -1028,30 +1037,31 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w) x += w->x; y += w->y; - dpi = clip_drawpixelinfo(dpi, x, width, y, height); - if (dpi == NULL) + rct_drawpixelinfo clipDPI; + if (!clip_drawpixelinfo(&clipDPI, dpi, x, y, width, height)) { return; + } x = (widget->right - widget->left) / 2; y = (widget->bottom - widget->top) - 12; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); uint8 trainLayout[16]; ride_entry_get_train_layout(ride->subtype, ride->num_cars_per_train, trainLayout); - rideEntry = ride_get_entry(ride); + rideEntry = get_ride_entry_by_ride(ride); if (rideEntry->flags & RIDE_ENTRY_FLAG_0) { - dpi->zoom_level = 1; - dpi->width *= 2; - dpi->height *= 2; + clipDPI.zoom_level = 1; + clipDPI.width *= 2; + clipDPI.height *= 2; x *= 2; y *= 2; - dpi->x *= 2; - dpi->y *= 2; + clipDPI.x *= 2; + clipDPI.y *= 2; } - rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[rideEntry->tab_vehicle]]; + rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[rideEntry->tab_vehicle]]; height += rideVehicleEntry->tab_height; vehicleColour = ride_get_vehicle_colour(ride, 0); @@ -1059,21 +1069,20 @@ static void window_ride_draw_tab_vehicle(rct_drawpixelinfo *dpi, rct_window *w) spriteIndex = 32; if (w->page == WINDOW_RIDE_PAGE_VEHICLE) spriteIndex += w->frame_no; - spriteIndex /= (rideVehicleEntry->var_12 & 0x800) ? 4 : 2; + spriteIndex /= (rideVehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_11) ? 4 : 2; spriteIndex &= rideVehicleEntry->rotation_frame_mask; spriteIndex *= rideVehicleEntry->var_16; spriteIndex += rideVehicleEntry->base_image_id; spriteIndex |= (vehicleColour.additional_1 << 24) | (vehicleColour.main << 19); spriteIndex |= 0x80000000; - gfx_draw_sprite(dpi, spriteIndex, x, y, vehicleColour.additional_2); - rct2_free(dpi); + gfx_draw_sprite(&clipDPI, spriteIndex, x, y, vehicleColour.additional_2); } } /** * - * rct2: 0x006B2F42 + * rct2: 0x006B2F42 */ static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w) { @@ -1086,7 +1095,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; @@ -1096,7 +1105,7 @@ static void window_ride_draw_tab_customer(rct_drawpixelinfo *dpi, rct_window *w) /** * - * rct2: 0x006B2B35 + * rct2: 0x006B2B35 */ static void window_ride_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) { @@ -1119,27 +1128,30 @@ static void window_ride_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) void window_ride_disable_tabs(rct_window *w) { uint32 disabled_tabs = 0; - rct_ride *ride = GET_RIDE(w->number & 0xFF); + rct_ride *ride = get_ride(w->number & 0xFF); uint8 ride_type = ride->type; // ecx - if ((RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x200) == 0) + if (!ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_DATA_LOGGING)) disabled_tabs |= (1 << WIDX_TAB_8); // 0x800 if (ride_type == RIDE_TYPE_MINI_GOLF) disabled_tabs |= (1 << WIDX_TAB_2 | 1 << WIDX_TAB_3 | 1 << WIDX_TAB_4); // 0xE0 - if ((RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x2000) != 0) + if (ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_13)) disabled_tabs |= (1 << WIDX_TAB_2); // 0x20 if ( - !(RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x4000007) && + !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN) && + !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_ADDITIONAL) && + !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS) && + !ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_26) && !(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_HAS_ENTRANCE_EXIT) ) { disabled_tabs |= (1 << WIDX_TAB_5); // 0x100 } - if ((RCT2_GLOBAL(0x97CF40 + ride_type * 8, uint32) & 0x20000) != 0) + if (ride_type_has_flag(ride_type, RIDE_TYPE_FLAG_IS_SHOP)) disabled_tabs |= (1 << WIDX_TAB_3 | 1 << WIDX_TAB_4 | 1 << WIDX_TAB_7); // 0x4C0 if (!(RideData4[ride->type].flags & RIDE_TYPE_FLAG4_ALLOW_MUSIC)) { @@ -1154,17 +1166,68 @@ void window_ride_disable_tabs(rct_window *w) if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint32) & SCREEN_FLAGS_TRACK_DESIGNER) != 0) disabled_tabs |= (1 << WIDX_TAB_4 | 1 << WIDX_TAB_6 | 1 << WIDX_TAB_9 | 1 << WIDX_TAB_10); // 0x3280 - rct_ride_type *type = GET_RIDE_ENTRY(ride->subtype); + rct_ride_entry *type = get_ride_entry(ride->subtype); - if ((type->flags & RIDE_ENTRY_FLAG_19) != 0) + if (type == NULL) { + disabled_tabs |= 1 << WIDX_TAB_2 | 1 << WIDX_TAB_3 | 1 << WIDX_TAB_4 | 1 << WIDX_TAB_5 | 1 << WIDX_TAB_6 + | 1 << WIDX_TAB_7 | 1 << WIDX_TAB_8 | 1 << WIDX_TAB_9 | 1 << WIDX_TAB_10; + } else if ((type->flags & RIDE_ENTRY_FLAG_19) != 0) disabled_tabs |= (1 << WIDX_TAB_5); // 0x100 w->disabled_widgets = disabled_tabs; } +static void window_ride_update_overall_view(uint8 ride_index) { + // Calculate x, y, z bounds of the entire ride using its track elements + map_element_iterator it; + + map_element_iterator_begin(&it); + + int minx = INT_MAX, miny = INT_MAX, minz = INT_MAX; + int maxx = INT_MIN, maxy = INT_MIN, maxz = INT_MIN; + + while (map_element_iterator_next(&it)) { + if (map_element_get_type(it.element) != MAP_ELEMENT_TYPE_TRACK) + continue; + + if (it.element->properties.track.ride_index != ride_index) + continue; + + int x = it.x * 32; + int y = it.y * 32; + int z1 = it.element->base_height * 8; + int z2 = it.element->clearance_height * 8; + + minx = min(minx, x); + miny = min(miny, y); + minz = min(minz, z1); + + maxx = max(maxx, x); + maxy = max(maxy, y); + maxz = max(maxz, z2); + } + + ride_overall_view *view = &ride_overall_views[ride_index]; + view->x = (minx + maxx) / 2; + view->y = (miny + maxy) / 2; + view->z = (minz + maxz) / 2 + 8; + + // Calculate size to determine from how far away to view the ride + int dx = maxx - minx; + int dy = maxy - miny; + int dz = maxz - minz; + + int size = (int) sqrt(dx*dx + dy*dy + dz*dz); + + // Each farther zoom level shows twice as many tiles (log) + // Appropriate zoom is lowered by one to fill the entire view with the ride + double zoom = ceil(log(size / 80)) - 1; + view->zoom = (uint8)clamp(0, zoom, 3); +} + /** * - * rct2: 0x006AEAB4 + * rct2: 0x006AEAB4 */ rct_window *window_ride_open(int rideIndex) { @@ -1183,14 +1246,16 @@ rct_window *window_ride_open(int rideIndex) w->frame_no = 0; w->list_information_type = 0; w->var_492 = 0; - w->var_494 = 0; + w->ride_colour = 0; window_ride_disable_tabs(w); w->min_width = 316; w->min_height = 180; w->max_width = 500; w->max_height = 450; - ride = GET_RIDE(rideIndex); + window_ride_update_overall_view((uint8) rideIndex); + + ride = get_ride(rideIndex); numSubTypes = 0; rideEntryIndexPtr = get_ride_entry_indices_for_ride_type(ride->type); for (; *rideEntryIndexPtr != 0xFF; rideEntryIndexPtr++) { @@ -1207,7 +1272,7 @@ rct_window *window_ride_open(int rideIndex) /** * - * rct2: 0x006ACC28 + * rct2: 0x006ACC28 */ rct_window *window_ride_main_open(int rideIndex) { @@ -1219,7 +1284,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) ) { @@ -1246,7 +1311,7 @@ rct_window *window_ride_main_open(int rideIndex) /** * - * rct2: 0x006ACCCE + * rct2: 0x006ACCCE */ rct_window *window_ride_open_station(int rideIndex, int stationIndex) { @@ -1254,7 +1319,7 @@ rct_window *window_ride_open_station(int rideIndex, int stationIndex) rct_ride *ride; rct_window *w; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13)) return window_ride_main_open(rideIndex); @@ -1266,7 +1331,7 @@ rct_window *window_ride_open_station(int rideIndex, int stationIndex) } if ( - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint8) & 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 ) { @@ -1315,7 +1380,7 @@ rct_window *window_ride_open_track(rct_map_element *mapElement) /** * - * rct2: 0x006ACAC2 + * rct2: 0x006ACAC2 */ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle) { @@ -1328,7 +1393,7 @@ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle) headVehicle = vehicle_get_head(vehicle); headVehicleSpriteIndex = headVehicle->sprite_index; rideIndex = headVehicle->ride; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); // Get view index view = 1; @@ -1345,7 +1410,7 @@ rct_window *window_ride_open_vehicle(rct_vehicle *vehicle) window_invalidate(w); if ( - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint8) & 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 +1475,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(); @@ -1472,13 +1537,13 @@ static void window_ride_anchor_border_widgets(rct_window *w) /** * - * rct2: 0x006AF994 + * rct2: 0x006AF994 */ static void window_ride_init_viewport(rct_window *w) { if (w->page != WINDOW_RIDE_PAGE_MAIN) return; - rct_ride* ride = GET_RIDE(w->number); + rct_ride* ride = get_ride(w->number); int eax = w->viewport_focus_coordinates.var_480 - 1; union{ @@ -1486,6 +1551,9 @@ static void window_ride_init_viewport(rct_window *w) coordinate_focus coordinate; } focus; + focus.coordinate.x = 0; + focus.coordinate.y = 0; + focus.coordinate.z = 0; focus.sprite.sprite_id = -1; focus.coordinate.zoom = 0; focus.coordinate.rotation = get_current_rotation(); @@ -1494,7 +1562,7 @@ static void window_ride_init_viewport(rct_window *w) if (eax >= 0 && eax < ride->num_vehicles && ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK){ focus.sprite.sprite_id = ride->vehicles[eax]; - rct_ride_type* ride_entry = ride_get_entry(ride); + rct_ride_entry* ride_entry = get_ride_entry_by_ride(ride); if (ride_entry->tab_vehicle != 0){ rct_vehicle* vehicle = GET_VEHICLE(focus.sprite.sprite_id); focus.sprite.sprite_id = vehicle->next_vehicle_on_train; @@ -1521,15 +1589,15 @@ static void window_ride_init_viewport(rct_window *w) if (eax > 0){ w->viewport_focus_coordinates.var_480 = 0; } - focus.coordinate.x = (ride->overall_view & 0xFF) << 5; - focus.coordinate.y = (ride->overall_view & 0xFF00) >> 3; - focus.coordinate.x += 16; - focus.coordinate.y += 16; - focus.coordinate.z = map_element_height(focus.coordinate.x, focus.coordinate.y) & 0xFFFF; + + ride_overall_view *view = &ride_overall_views[w->number]; + + focus.coordinate.x = view->x; + focus.coordinate.y = view->y; + focus.coordinate.z = view->z; + focus.coordinate.zoom = view->zoom; + focus.sprite.type |= 0x40; - focus.coordinate.zoom = 1; - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15)) - focus.coordinate.zoom = 0; } focus.coordinate.var_480 = w->viewport_focus_coordinates.var_480; @@ -1593,36 +1661,24 @@ static void window_ride_init_viewport(rct_window *w) /** * - * rct2: 0x006B4971 - */ -void window_ride_construct(rct_window *w) -{ - // Window may be closed by close by class so - // make backup before calling. - uint8 rideIndex = (uint8)w->number; - window_close_by_class(WC_RIDE_CONSTRUCTION); - ride_construct(rideIndex); -} - -/** - * - * rct2: 0x006AF315 + * rct2: 0x006AF315 */ static void window_ride_rename(rct_window *w) { rct_ride *ride; - ride = GET_RIDE(w->number); - RCT2_GLOBAL(0x013CE962, uint32) = ride->name_arguments; + ride = get_ride(w->number); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 16, uint32) = ride->name_arguments; window_text_input_open(w, WIDX_RENAME, STR_RIDE_ATTRACTION_NAME, STR_ENTER_NEW_NAME_FOR_THIS_RIDE_ATTRACTION, ride->name, ride->name_arguments, 32); } /** * - * rct2: 0x006AF17E + * rct2: 0x006AF17E */ static void window_ride_main_mouseup(rct_window *w, int widgetIndex) { + uint8 rideIndex; rct_ride *ride; int status; @@ -1643,7 +1699,11 @@ static void window_ride_main_mouseup(rct_window *w, int widgetIndex) window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_CONSTRUCTION: - window_ride_construct(w); + rideIndex = (uint8)w->number; + ride_construct(rideIndex); + if (window_find_by_number(WC_RIDE_CONSTRUCTION, rideIndex) != NULL) { + window_close(w); + } break; case WIDX_RENAME: window_ride_rename(w); @@ -1658,7 +1718,7 @@ static void window_ride_main_mouseup(rct_window *w, int widgetIndex) case WIDX_TEST_LIGHT: case WIDX_OPEN_LIGHT: - ride = GET_RIDE(w->number); + ride = get_ride(w->number); switch (widgetIndex - WIDX_CLOSE_LIGHT) { case 0: @@ -1675,8 +1735,8 @@ static void window_ride_main_mouseup(rct_window *w, int widgetIndex) break; } - RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; ride_set_status(w->number, status); break; } @@ -1684,7 +1744,7 @@ static void window_ride_main_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006AF4A2 + * rct2: 0x006AF4A2 */ static void window_ride_main_resize(rct_window *w) { @@ -1693,8 +1753,8 @@ static void window_ride_main_resize(rct_window *w) w->flags |= WF_RESIZABLE; int minHeight = 180; - if (theme_get_preset()->features.rct1_ride_lights) - minHeight = 200 + RCT1_LIGHT_OFFSET - (ride_type_has_flag(GET_RIDE(w->number)->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 : 0); + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) + minHeight = 200 + RCT1_LIGHT_OFFSET - (ride_type_has_flag(get_ride(w->number)->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? 14 : 0); window_set_resize(w, 316, minHeight, 500, 450); viewport = w->viewport; @@ -1714,7 +1774,7 @@ static void window_ride_main_resize(rct_window *w) /** * - * rct2: 0x006AF825 + * rct2: 0x006AF825 */ static void window_ride_show_view_dropdown(rct_window *w, rct_widget *widget) { @@ -1723,7 +1783,7 @@ static void window_ride_show_view_dropdown(rct_window *w, rct_widget *widget) int numItems, currentItem, i, j, name; dropdownWidget = widget - 1; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); numItems = 1; if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_13)) { @@ -1777,14 +1837,14 @@ static void window_ride_show_view_dropdown(rct_window *w, rct_widget *widget) /** * - * rct2: 0x006AF64C + * rct2: 0x006AF64C */ static void window_ride_show_open_dropdown(rct_window *w, rct_widget *widget) { rct_ride *ride; - int numItems, highlightedIndex, checkedIndex; + int numItems, highlightedIndex = 0, checkedIndex; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); numItems = 0; gDropdownItemsFormat[numItems] = 1142; @@ -1848,12 +1908,12 @@ static void window_ride_show_open_dropdown(rct_window *w, rct_widget *widget) } dropdown_set_checked(checkedIndex, true); - gDropdownHighlightedIndex = highlightedIndex; + gDropdownDefaultIndex = highlightedIndex; } /** * - * rct2: 0x006AF1BD + * rct2: 0x006AF1BD */ static void window_ride_main_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { @@ -1869,18 +1929,18 @@ static void window_ride_main_mousedown(int widgetIndex, rct_window *w, rct_widge /** * - * rct2: 0x006AF300 + * rct2: 0x006AF300 */ static void window_ride_main_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { rct_ride *ride; - int status; + int status = 0; switch (widgetIndex) { case WIDX_VIEW_DROPDOWN: if (dropdownIndex == -1) { dropdownIndex = w->ride.view; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); dropdownIndex++; if (dropdownIndex != 0 && dropdownIndex <= ride->num_vehicles && !(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) dropdownIndex = ride->num_vehicles + 1; @@ -1897,7 +1957,7 @@ static void window_ride_main_dropdown(rct_window *w, int widgetIndex, int dropdo if (dropdownIndex == -1) dropdownIndex = gDropdownHighlightedIndex; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) && dropdownIndex != 0) dropdownIndex++; @@ -1916,8 +1976,8 @@ static void window_ride_main_dropdown(rct_window *w, int widgetIndex, int dropdo break; } - RCT2_GLOBAL(0x013CE952 + 6, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = ride->name_arguments; ride_set_status(w->number, status); break; } @@ -1925,7 +1985,7 @@ static void window_ride_main_dropdown(rct_window *w, int widgetIndex, int dropdo /** * - * rct2: 0x006AF40F + * rct2: 0x006AF40F */ static void window_ride_main_update(rct_window *w) { @@ -1940,7 +2000,7 @@ static void window_ride_main_update(rct_window *w) widget_invalidate(w, WIDX_TAB_1); // Update status - ride = GET_RIDE(w->number); + ride = get_ride(w->number); if (!(ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_MAIN)) { if (w->ride.view == 0) return; @@ -1969,7 +2029,7 @@ static void window_ride_main_update(rct_window *w) /** * - * rct2: 0x006AF2F9 + * rct2: 0x006AF2F9 */ static void window_ride_main_textinput(rct_window *w, int widgetIndex, char *text) { @@ -1981,7 +2041,7 @@ static void window_ride_main_textinput(rct_window *w, int widgetIndex, char *tex /** * - * rct2: 0x006AF55A + * rct2: 0x006AF55A */ static void window_ride_main_unknown_14(rct_window *w) { @@ -1990,7 +2050,7 @@ static void window_ride_main_unknown_14(rct_window *w) /** * - * rct2: 0x006AECF6 + * rct2: 0x006AECF6 */ static void window_ride_main_invalidate(rct_window *w) { @@ -2007,13 +2067,13 @@ static void window_ride_main_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - rct_ride *ride = GET_RIDE(w->number); + rct_ride *ride = get_ride(w->number); w->disabled_widgets &= ~((1 << 22) | (1 << 19)); if (ride->lifecycle_flags & (RIDE_LIFECYCLE_INDESTRUCTIBLE | RIDE_LIFECYCLE_INDESTRUCTIBLE_TRACK)) w->disabled_widgets |= (1 << 22); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; window_ride_main_widgets[WIDX_OPEN].image = SPR_CLOSED + ride->status; window_ride_main_widgets[WIDX_CLOSE_LIGHT].image = SPR_G2_RCT1_CLOSE_BUTTON_0 + (ride->status == RIDE_STATUS_CLOSED) * 2 + widget_is_pressed(w, WIDX_CLOSE_LIGHT); @@ -2034,7 +2094,7 @@ static void window_ride_main_invalidate(rct_window *w) window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); - if (theme_get_preset()->features.rct1_ride_lights) { + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) { window_ride_main_widgets[WIDX_OPEN].type = WWT_EMPTY; window_ride_main_widgets[WIDX_CLOSE_LIGHT].type = WWT_IMGBTN; window_ride_main_widgets[WIDX_TEST_LIGHT].type = (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_NO_TEST_MODE) ? WWT_EMPTY : WWT_IMGBTN); @@ -2075,7 +2135,7 @@ static void window_ride_main_invalidate(rct_window *w) /** * - * rct2: 0x006AF10A + * rct2: 0x006AF10A */ static rct_string_id window_ride_get_status_overall_view(rct_window *w, void *arguments) { @@ -2094,7 +2154,7 @@ static rct_string_id window_ride_get_status_overall_view(rct_window *w, void *ar /** * - * rct2: 0x006AEFEF + * rct2: 0x006AEFEF */ static rct_string_id window_ride_get_status_vehicle(rct_window *w, void *arguments) { @@ -2104,7 +2164,7 @@ static rct_string_id window_ride_get_status_vehicle(rct_window *w, void *argumen uint16 vehicleSpriteIndex; rct_string_id stringId; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); vehicleIndex = w->ride.view - 1; vehicleSpriteIndex = ride->vehicles[vehicleIndex]; @@ -2114,7 +2174,12 @@ static rct_string_id window_ride_get_status_vehicle(rct_window *w, void *argumen vehicle = &(g_sprite_list[vehicleSpriteIndex].vehicle); if (vehicle->status != VEHICLE_STATUS_CRASHING && vehicle->status != VEHICLE_STATUS_CRASHED) { int trackType = vehicle->track_type >> 2; - if (trackType == 216 || trackType == 123 || trackType == 9 || trackType == 63 || trackType == 147 || trackType == 155) { + if (trackType == 216 || + trackType == TRACK_ELEM_CABLE_LIFT_HILL || + trackType == TRACK_ELEM_25_DEG_UP_TO_FLAT || + trackType == TRACK_ELEM_60_DEG_UP_TO_FLAT || + trackType == TRACK_ELEM_DIAG_25_DEG_UP_TO_FLAT || + trackType == TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT) { if ((RCT2_ADDRESS(0x01357644, uint32)[ride->type] & 0x40) && vehicle->velocity == 0) { RCT2_GLOBAL((int)arguments + 0, uint16) = STR_STOPPED_BY_BLOCK_BRAKES; return 1191; @@ -2144,7 +2209,7 @@ static rct_string_id window_ride_get_status_vehicle(rct_window *w, void *argumen /** * - * rct2: 0x006AEF65 + * rct2: 0x006AEF65 */ static rct_string_id window_ride_get_status_station(rct_window *w, void *arguments) { @@ -2152,7 +2217,7 @@ static rct_string_id window_ride_get_status_station(rct_window *w, void *argumen int stationIndex, count, queueLength; rct_string_id stringId; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); count = w->ride.view - ride->num_vehicles - 1; stationIndex = -1; @@ -2192,11 +2257,11 @@ static rct_string_id window_ride_get_status_station(rct_window *w, void *argumen /** * - * rct2: 0x006AEE73 + * rct2: 0x006AEE73 */ static rct_string_id window_ride_get_status(rct_window *w, void *arguments) { - rct_ride *ride = GET_RIDE(w->number); + rct_ride *ride = get_ride(w->number); if (w->ride.view == 0) return window_ride_get_status_overall_view(w, arguments); @@ -2209,7 +2274,7 @@ static rct_string_id window_ride_get_status(rct_window *w, void *arguments) /** * - * rct2: 0x006AEE73 + * rct2: 0x006AEE73 */ static void window_ride_main_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -2228,15 +2293,15 @@ static void window_ride_main_paint(rct_window *w, rct_drawpixelinfo *dpi) } // View dropdown - ride = GET_RIDE(w->number); + ride = get_ride(w->number); stringId = STR_OVERALL_VIEW; if (w->ride.view != 0) { stringId = RideNameConvention[ride->type].vehicle_name + 6; if (w->ride.view > ride->num_vehicles) { - RCT2_GLOBAL(0x013CE952 + 2, uint16) = w->ride.view - ride->num_vehicles; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = w->ride.view - ride->num_vehicles; stringId = RideNameConvention[ride->type].station_name + 6; } else { - RCT2_GLOBAL(0x013CE952 + 2, uint16) = w->ride.view; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = w->ride.view; } } RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = stringId; @@ -2248,15 +2313,15 @@ static void window_ride_main_paint(rct_window *w, rct_drawpixelinfo *dpi) w->x + (widget->left + widget->right - 11) / 2, w->y + widget->top, 0, - (void*)0x013CE952 + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS ); // Status widget = &window_ride_main_widgets[WIDX_STATUS]; gfx_draw_string_centred_clipped( dpi, - window_ride_get_status(w, (void*)0x013CE952), - (void*)0x013CE952, + window_ride_get_status(w, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS), + (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + (widget->left + widget->right) / 2, w->y + widget->top, @@ -2270,13 +2335,13 @@ static void window_ride_main_paint(rct_window *w, rct_drawpixelinfo *dpi) /** * - * rct2: 0x006B272D + * rct2: 0x006B272D */ static void window_ride_vehicle_mouseup(rct_window *w, int widgetIndex) { rct_ride *ride; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); switch (widgetIndex) { case WIDX_CLOSE: @@ -2299,7 +2364,7 @@ static void window_ride_vehicle_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006B2ABB + * rct2: 0x006B2ABB */ static void window_ride_vehicle_resize(rct_window *w) { @@ -2308,20 +2373,20 @@ static void window_ride_vehicle_resize(rct_window *w) /** * - * rct2: 0x006B2748 + * rct2: 0x006B2748 */ static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { rct_widget *dropdownWidget = widget - 1; rct_ride *ride; - rct_ride_type *rideEntry, *currentRideEntry; + rct_ride_entry *rideEntry, *currentRideEntry; rct_string_id stringId; int i, minCars, maxCars, cars, numItems, quadIndex, bitIndex, rideEntryIndex, selectedIndex, rideTypeIterator, rideTypeIteratorMax; uint8 *rideEntryIndexPtr; bool selectionShouldBeExpanded; - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); if(gCheatsShowVehiclesFromOtherTrackTypes && !(ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE) || ride->type==RIDE_TYPE_MAZE || ride->type==RIDE_TYPE_MINI_GOLF)) { selectionShouldBeExpanded=true; @@ -2349,9 +2414,9 @@ static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_wi rideEntryIndexPtr = get_ride_entry_indices_for_ride_type(rideTypeIterator); - for (uint8 *currentRideEntryIndex = rideEntryIndexPtr; *currentRideEntryIndex != 0xFF; currentRideEntryIndex++) { + for (uint8 *currentRideEntryIndex = rideEntryIndexPtr; *currentRideEntryIndex != 0xFF && numItems <= 63; currentRideEntryIndex++) { rideEntryIndex = *currentRideEntryIndex; - currentRideEntry = GET_RIDE_ENTRY(rideEntryIndex); + currentRideEntry = get_ride_entry(rideEntryIndex); // Skip if vehicle has the same track type, but not same subtype, unless subtype switching is enabled if ((currentRideEntry->flags & (RIDE_ENTRY_FLAG_SEPARATE_RIDE | RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME)) && !(gConfigInterface.select_by_track_type || selectionShouldBeExpanded)) continue; @@ -2359,7 +2424,7 @@ static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_wi quadIndex = rideEntryIndex >> 5; bitIndex = rideEntryIndex & 0x1F; // Skip if vehicle type is not invented yet - if (!(RCT2_ADDRESS(0x01357424, uint32)[quadIndex] & (1 << bitIndex))) + if (!(RCT2_ADDRESS(0x01357424, uint32)[quadIndex] & (1u << bitIndex))) continue; if (ride->subtype == rideEntryIndex) @@ -2434,18 +2499,18 @@ static void window_ride_vehicle_mousedown(int widgetIndex, rct_window *w, rct_wi /** * - * rct2: 0x006B2767 + * rct2: 0x006B2767 */ static void window_ride_vehicle_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; if (dropdownIndex == -1) return; - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); switch (widgetIndex) { case WIDX_VEHICLE_TYPE_DROPDOWN: @@ -2463,7 +2528,7 @@ static void window_ride_vehicle_dropdown(rct_window *w, int widgetIndex, int dro /** * - * rct2: 0x006B2AA1 + * rct2: 0x006B2AA1 */ static void window_ride_vehicle_update(rct_window *w) { @@ -2474,13 +2539,13 @@ static void window_ride_vehicle_update(rct_window *w) /** * - * rct2: 0x006B222C + * rct2: 0x006B222C */ static void window_ride_vehicle_invalidate(rct_window *w) { rct_widget *widgets; rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_string_id stringId; int carsPerTrain; @@ -2494,11 +2559,11 @@ static void window_ride_vehicle_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; // Widget setup carsPerTrain = ride->num_cars_per_train - rideEntry->zero_cars; @@ -2535,12 +2600,12 @@ static void window_ride_vehicle_invalidate(rct_window *w) window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_DROPDOWN].type = WWT_EMPTY; } - RCT2_GLOBAL(0x013CE952 + 6, uint16) = carsPerTrain; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = carsPerTrain; stringId = RideNameConvention[ride->type].vehicle_name + 4; if (ride->num_vehicles > 1) stringId++; - RCT2_GLOBAL(0x013CE952 + 8, uint16) = stringId; - RCT2_GLOBAL(0x013CE952 + 10, uint16) = ride->num_vehicles; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint16) = stringId; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 10, uint16) = ride->num_vehicles; window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); @@ -2548,12 +2613,12 @@ static void window_ride_vehicle_invalidate(rct_window *w) /** * - * rct2: 0x006B23DC + * rct2: 0x006B23DC */ static void window_ride_vehicle_paint(rct_window *w, rct_drawpixelinfo *dpi) { rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_string_id stringId; int x, y; sint16 factor; @@ -2561,8 +2626,8 @@ static void window_ride_vehicle_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); x = w->x + 8; y = w->y + 64; @@ -2611,19 +2676,19 @@ rct_vehichle_paintinfo _sprites_to_draw[144]; /** * - * rct2: 0x006B2502 + * rct2: 0x006B2502 */ static void window_ride_vehicle_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_widget *widget; - int x, y, startX, startY, i, j, vehicleColourIndex, spriteIndex; + int x, y, startX, startY, i, j, vehicleColourIndex = 0, spriteIndex; rct_vehichle_paintinfo *nextSpriteToDraw, *current, tmp; vehicle_colour vehicleColour; - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); // Background gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width, dpi->y + dpi->height, 12); @@ -2635,7 +2700,7 @@ static void window_ride_vehicle_scrollpaint(rct_window *w, rct_drawpixelinfo *dp startX = max(2, ((widget->right - widget->left) - ((ride->num_vehicles - 1) * 36)) / 2 - 25); startY = widget->bottom - widget->top - 4; - rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[0]]; + rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[0]]; startY += rideVehicleEntry->tab_height; // For each train @@ -2646,9 +2711,9 @@ static void window_ride_vehicle_scrollpaint(rct_window *w, rct_drawpixelinfo *dp // For each car in train for (j = 0; j < ride->num_cars_per_train; j++) { - rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[j]]; - x += rideVehicleEntry->var_04 / 17432; - y -= (rideVehicleEntry->var_04 / 2) / 17432; + rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[j]]; + x += rideVehicleEntry->spacing / 17432; + y -= (rideVehicleEntry->spacing / 2) / 17432; // Get colour of vehicle switch (ride->colour_scheme_type & 3) { @@ -2665,7 +2730,7 @@ static void window_ride_vehicle_scrollpaint(rct_window *w, rct_drawpixelinfo *dp vehicleColour = ride_get_vehicle_colour(ride, vehicleColourIndex); spriteIndex = 16; - if (rideVehicleEntry->var_12 & 0x800) + if (rideVehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_11) spriteIndex /= 2; spriteIndex &= rideVehicleEntry->rotation_frame_mask; @@ -2680,8 +2745,8 @@ static void window_ride_vehicle_scrollpaint(rct_window *w, rct_drawpixelinfo *dp nextSpriteToDraw->tertiary_colour = vehicleColour.additional_2; nextSpriteToDraw++; - x += rideVehicleEntry->var_04 / 17432; - y -= (rideVehicleEntry->var_04 / 2) / 17432; + x += rideVehicleEntry->spacing / 17432; + y -= (rideVehicleEntry->spacing / 2) / 17432; } if (ride->type == RIDE_TYPE_REVERSER_ROLLER_COASTER) { @@ -2710,7 +2775,7 @@ static void set_operating_setting(int rideNumber, uint8 setting, uint8 value) static void window_ride_mode_tweak_set(rct_window *w, uint8 value) { - rct_ride *ride = GET_RIDE(w->number); + rct_ride *ride = get_ride(w->number); RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1362; if (ride->mode == RIDE_MODE_STATION_TO_STATION) @@ -2732,59 +2797,68 @@ static void window_ride_mode_tweak_set(rct_window *w, uint8 value) ) RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = 1868; - game_do_command(0, (value << 8) | 1, 0, (4 << 8) | w->number, GAME_COMMAND_SET_RIDE_SETTING, 0, 0); + set_operating_setting(w->number, RIDE_SETTING_OPERATION_OPTION, value); } /** * - * rct2: 0x006B11D5 + * rct2: 0x006B11D5 */ static void window_ride_mode_tweak_increase(rct_window *w) { - rct_ride *ride = GET_RIDE(w->number); - uint8 value = ride->operation_option; - //fast_lift_hill is the cheat that allows maxing out many limits on the Operating tab. - uint8 max_value = gConfigCheat.fast_lift_hill ? 255 : RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 5, uint8); + rct_ride *ride = get_ride(w->number); - //Allow 64 people in mazes under non-cheat settings. The old maximum of 16 was too little for even moderately big mazes. - if(ride->mode == RIDE_MODE_MAZE && !gConfigCheat.fast_lift_hill) - max_value = 64; + uint8 maxValue = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 5, uint8); + if (ride->mode == RIDE_MODE_MAZE) { + // Allow 64 people in mazes under non-cheat settings. The old maximum of 16 was too little for even moderately big mazes. + maxValue = 64; + } + if (gCheatsFastLiftHill) { + maxValue = 255; + } - if (value < max_value) - value += ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; - - window_ride_mode_tweak_set(w, value); + uint8 increment = ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; + uint8 newValue = ride->operation_option + increment; + if (newValue <= maxValue) { + window_ride_mode_tweak_set(w, newValue); + } } /** * - * rct2: 0x006B120A + * rct2: 0x006B120A */ static void window_ride_mode_tweak_decrease(rct_window *w) { - rct_ride *ride = GET_RIDE(w->number); - uint8 value = ride->operation_option; - if (value > RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 4, uint8)) - value -= ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; + rct_ride *ride = get_ride(w->number); - window_ride_mode_tweak_set(w, value); + uint8 minValue = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + (ride->type * 8) + 4, uint8); + if (gCheatsFastLiftHill) { + minValue = 0; + } + + uint8 decrement = ride->mode == RIDE_MODE_BUMPERCAR ? 10 : 1; + uint8 newValue = ride->operation_option - decrement; + if (newValue > minValue) { + window_ride_mode_tweak_set(w, newValue); + } } /** * - * rct2: 0x006B1631 + * rct2: 0x006B1631 */ static void window_ride_mode_dropdown(rct_window *w, rct_widget *widget) { - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_widget *dropdownWidget; rct_ride *ride; const uint8 *availableModes, *mode; int i, numAvailableModes; dropdownWidget = widget - 1; - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); // Seek to available modes for this ride availableModes = ride_seek_available_modes(ride); @@ -2831,7 +2905,7 @@ static void window_ride_mode_dropdown(rct_window *w, rct_widget *widget) /** * - * rct2: 0x006B15C0 + * rct2: 0x006B15C0 */ static void window_ride_load_dropdown(rct_window *w, rct_widget *widget) { @@ -2839,7 +2913,7 @@ static void window_ride_load_dropdown(rct_window *w, rct_widget *widget) int i; dropdownWidget = widget - 1; - rct_ride *ride = GET_RIDE(w->number); + rct_ride *ride = get_ride(w->number); for (i = 0; i < 5; i++) { gDropdownItemsFormat[i] = 1142; @@ -2860,13 +2934,13 @@ static void window_ride_load_dropdown(rct_window *w, rct_widget *widget) /** * - * rct2: 0x006B10A7 + * rct2: 0x006B10A7 */ static void window_ride_operating_mouseup(rct_window *w, int widgetIndex) { rct_ride *ride; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); switch (widgetIndex) { case WIDX_CLOSE: @@ -2885,26 +2959,26 @@ static void window_ride_operating_mouseup(rct_window *w, int widgetIndex) window_ride_set_page(w, widgetIndex - WIDX_TAB_1); break; case WIDX_LOAD_CHECKBOX: - set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_LOAD); + set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_LOAD); break; case WIDX_LEAVE_WHEN_ANOTHER_ARRIVES_CHECKBOX: - set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_LEAVE_WHEN_ANOTHER_ARRIVES); + set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_LEAVE_WHEN_ANOTHER_ARRIVES); break; case WIDX_MINIMUM_LENGTH_CHECKBOX: - set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH); + set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MINIMUM_LENGTH); break; case WIDX_MAXIMUM_LENGTH_CHECKBOX: - set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH); + set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_WAIT_FOR_MAXIMUM_LENGTH); break; case WIDX_SYNCHRONISE_WITH_ADJACENT_STATIONS_CHECKBOX: - set_operating_setting(w->number, 1, ride->depart_flags ^ RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS); + set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, ride->depart_flags ^ RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS); break; } } /** * - * rct2: 0x006B1715 + * rct2: 0x006B1715 */ static void window_ride_operating_resize(rct_window *w) { @@ -2913,12 +2987,12 @@ static void window_ride_operating_resize(rct_window *w) /** * - * rct2: 0x006B10F4 + * rct2: 0x006B10F4 */ static void window_ride_operating_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { - rct_ride *ride = GET_RIDE(w->number); - uint8 max_lift_hill_speed; + rct_ride *ride = get_ride(w->number); + uint8 parameter_check; switch (widgetIndex) { case WIDX_MODE_TWEAK_INCREASE: @@ -2928,28 +3002,24 @@ static void window_ride_operating_mousedown(int widgetIndex, rct_window *w, rct_ window_ride_mode_tweak_decrease(w); break; case WIDX_LIFT_HILL_SPEED_INCREASE: - - if(gConfigCheat.fast_lift_hill) - max_lift_hill_speed = 255; - else - max_lift_hill_speed = RCT2_GLOBAL(0x0097D7CA + (ride->type * 4), uint8); - - set_operating_setting(w->number, 8, min(ride->lift_hill_speed + 1, max_lift_hill_speed)); + parameter_check = gCheatsFastLiftHill ? 255 : RideLiftData[ride->type].maximum_speed; + set_operating_setting(w->number, RIDE_SETTING_LIFT_HILL_SPEED, min(ride->lift_hill_speed + 1, parameter_check)); break; case WIDX_LIFT_HILL_SPEED_DECREASE: - set_operating_setting(w->number, 8, max(RCT2_GLOBAL(0x0097D7C9 + (ride->type * 4), uint8), ride->lift_hill_speed - 1)); + parameter_check = gCheatsFastLiftHill ? 0 : RideLiftData[ride->type].minimum_speed; + set_operating_setting(w->number, RIDE_SETTING_LIFT_HILL_SPEED, max(ride->lift_hill_speed - 1, parameter_check)); break; case WIDX_MINIMUM_LENGTH_INCREASE: - set_operating_setting(w->number, 2, min(ride->min_waiting_time + 1, 250)); + set_operating_setting(w->number, RIDE_SETTING_MIN_WAITING_TIME, min(ride->min_waiting_time + 1, 250)); break; case WIDX_MINIMUM_LENGTH_DECREASE: - set_operating_setting(w->number, 2, max(0, ride->min_waiting_time - 1)); + set_operating_setting(w->number, RIDE_SETTING_MIN_WAITING_TIME, max(0, ride->min_waiting_time - 1)); break; case WIDX_MAXIMUM_LENGTH_INCREASE: - set_operating_setting(w->number, 3, min(ride->max_waiting_time + 1, 250)); + set_operating_setting(w->number, RIDE_SETTING_MAX_WAITING_TIME, min(ride->max_waiting_time + 1, 250)); break; case WIDX_MAXIMUM_LENGTH_DECREASE: - set_operating_setting(w->number, 3, max(0, ride->max_waiting_time - 1)); + set_operating_setting(w->number, RIDE_SETTING_MAX_WAITING_TIME, max(0, ride->max_waiting_time - 1)); break; case WIDX_MODE_DROPDOWN: window_ride_mode_dropdown(w, widget); @@ -2958,17 +3028,18 @@ static void window_ride_operating_mousedown(int widgetIndex, rct_window *w, rct_ window_ride_load_dropdown(w, widget); break; case WIDX_OPERATE_NUMBER_OF_CIRCUITS_INCREASE: - set_operating_setting(w->number, 9, min(ride->num_circuits + 1, 20)); + parameter_check = gCheatsFastLiftHill ? 255 : 20; + set_operating_setting(w->number, RIDE_SETTING_NUM_CIRCUITS, min(ride->num_circuits + 1, parameter_check)); break; case WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE: - set_operating_setting(w->number, 9, max(1, ride->num_circuits - 1)); + set_operating_setting(w->number, RIDE_SETTING_NUM_CIRCUITS, max(ride->num_circuits - 1, 1)); break; } } /** * - * rct2: 0x006B1165 + * rct2: 0x006B1165 */ static void window_ride_operating_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { @@ -2978,24 +3049,24 @@ static void window_ride_operating_dropdown(rct_window *w, int widgetIndex, int d if (dropdownIndex == -1) return; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); switch (widgetIndex) { case WIDX_MODE_DROPDOWN: // Seek to available modes for this ride availableModes = ride_seek_available_modes(ride); - set_operating_setting(w->number, 0, availableModes[dropdownIndex]); + set_operating_setting(w->number, RIDE_SETTING_MODE, availableModes[dropdownIndex]); break; case WIDX_LOAD_DROPDOWN: - set_operating_setting(w->number, 1, (ride->depart_flags & ~RIDE_DEPART_WAIT_FOR_LOAD_MASK) | dropdownIndex); + set_operating_setting(w->number, RIDE_SETTING_DEPARTURE, (ride->depart_flags & ~RIDE_DEPART_WAIT_FOR_LOAD_MASK) | dropdownIndex); break; } } /** * - * rct2: 0x006B178E + * rct2: 0x006B178E */ static void window_ride_operating_update(rct_window *w) { @@ -3005,7 +3076,7 @@ static void window_ride_operating_update(rct_window *w) window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_3); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_OPERATING) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_OPERATING; window_invalidate(w); @@ -3014,13 +3085,13 @@ static void window_ride_operating_update(rct_window *w) /** * - * rct2: 0x006B0B30 + * rct2: 0x006B0B30 */ static void window_ride_operating_invalidate(rct_window *w) { rct_widget *widgets; rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_string_id format, caption, tooltip; colour_scheme_update(w); @@ -3033,11 +3104,11 @@ static void window_ride_operating_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; // Widget setup w->pressed_widgets &= ~0x44700000; @@ -3048,7 +3119,7 @@ static void window_ride_operating_invalidate(rct_window *w) window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_DECREASE].type = WWT_DROPDOWN_BUTTON; - RCT2_GLOBAL(0x013CE966, uint16) = ride->lift_hill_speed; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 20, uint16) = ride->lift_hill_speed; } else { window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED_LABEL].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_LIFT_HILL_SPEED].type = WWT_EMPTY; @@ -3062,7 +3133,7 @@ static void window_ride_operating_invalidate(rct_window *w) window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS].type = WWT_SPINNER; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_DECREASE].type = WWT_DROPDOWN_BUTTON; - RCT2_GLOBAL(0x013CE968, uint16) = ride->num_circuits; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 22, uint16) = ride->num_circuits; } else { window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS_LABEL].type = WWT_EMPTY; window_ride_operating_widgets[WIDX_OPERATE_NUMBER_OF_CIRCUITS].type = WWT_EMPTY; @@ -3115,10 +3186,10 @@ static void window_ride_operating_invalidate(rct_window *w) window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_INCREASE].type = WWT_DROPDOWN_BUTTON; window_ride_operating_widgets[WIDX_MAXIMUM_LENGTH_DECREASE].type = WWT_DROPDOWN_BUTTON; - RCT2_GLOBAL(0x013CE952 + 10, uint16) = 1217; - RCT2_GLOBAL(0x013CE95E, uint16) = ride->min_waiting_time; - RCT2_GLOBAL(0x013CE960, uint16) = 1217; - RCT2_GLOBAL(0x013CE962, uint16) = ride->max_waiting_time; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 10, uint16) = 1217; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 12, uint16) = ride->min_waiting_time; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 14, uint16) = 1217; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 16, uint16) = ride->max_waiting_time; if (ride->depart_flags & RIDE_DEPART_WAIT_FOR_LOAD) w->pressed_widgets |= (1 << WIDX_LOAD_CHECKBOX); @@ -3148,25 +3219,25 @@ static void window_ride_operating_invalidate(rct_window *w) w->pressed_widgets |= (1 << WIDX_MAXIMUM_LENGTH_CHECKBOX); // Mode specific functionality - RCT2_GLOBAL(0x013CE964, uint16) = ride->operation_option; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 18, uint16) = ride->operation_option; switch (ride->mode) { case RIDE_MODE_POWERED_LAUNCH_PASSTROUGH: case RIDE_MODE_POWERED_LAUNCH: case RIDE_MODE_UPWARD_LAUNCH: case RIDE_MODE_POWERED_LAUNCH_BLOCK_SECTIONED: - RCT2_GLOBAL(0x013CE964, uint16) = (ride->launch_speed * 9) / 4; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 18, uint16) = (ride->launch_speed * 9) / 4; format = 1331; caption = STR_LAUNCH_SPEED; tooltip = STR_LAUNCH_SPEED_TIP; break; case RIDE_MODE_STATION_TO_STATION: - RCT2_GLOBAL(0x013CE964, uint16) = (ride->speed * 9) / 4; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 18, uint16) = (ride->speed * 9) / 4; format = 1331; caption = STR_SPEED; tooltip = STR_SPEED_TIP; break; case RIDE_MODE_RACE: - RCT2_GLOBAL(0x013CE964, uint16) = ride->num_laps; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 18, uint16) = ride->num_laps; format = 1736; caption = STR_NUMBER_OF_LAPS; tooltip = STR_NUMBER_OF_LAPS_TIP; @@ -3199,7 +3270,7 @@ static void window_ride_operating_invalidate(rct_window *w) if (format != 0) { if (ride->type == RIDE_TYPE_TWIST) - RCT2_GLOBAL(0x013CE964, uint16) *= 3; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 18, uint16) *= 3; window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].type = WWT_24; window_ride_operating_widgets[WIDX_MODE_TWEAK_LABEL].image = caption; @@ -3222,7 +3293,7 @@ static void window_ride_operating_invalidate(rct_window *w) /** * - * rct2: 0x006B1001 + * rct2: 0x006B1001 */ static void window_ride_operating_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -3232,7 +3303,7 @@ static void window_ride_operating_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); // Horizontal rule between mode settings and depart settings gfx_fill_rect_inset( @@ -3258,14 +3329,14 @@ static void window_ride_operating_paint(rct_window *w, rct_drawpixelinfo *dpi) /** * - * rct2: 0x006B1AE4 + * rct2: 0x006B1AE4 */ static void window_ride_locate_mechanic(rct_window *w) { rct_ride *ride; rct_peep *mechanic; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); // First check if there is a mechanic assigned mechanic = ride_get_assigned_mechanic(ride); @@ -3282,13 +3353,13 @@ static void window_ride_locate_mechanic(rct_window *w) /** * - * rct2: 0x006B7D08 + * rct2: 0x006B7D08 */ static void window_ride_maintenance_draw_bar(rct_window *w, rct_drawpixelinfo *dpi, int x, int y, int value, int unk) { gfx_fill_rect_inset(dpi, x, y, x + 149, y + 8, w->colours[1], 0x30); - if (unk & (1 << 31)) { - unk &= ~(1 << 31); + if (unk & (1u << 31)) { + unk &= ~(1u << 31); if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 && (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) & 8)) return; } @@ -3301,7 +3372,7 @@ static void window_ride_maintenance_draw_bar(rct_window *w, rct_drawpixelinfo *d /** * - * rct2: 0x006B1AAD + * rct2: 0x006B1AAD */ static void window_ride_maintenance_mouseup(rct_window *w, int widgetIndex) { @@ -3329,7 +3400,7 @@ static void window_ride_maintenance_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006B1D70 + * rct2: 0x006B1D70 */ static void window_ride_maintenance_resize(rct_window *w) { @@ -3338,20 +3409,23 @@ static void window_ride_maintenance_resize(rct_window *w) /** * - * rct2: 0x006B1ACE + * rct2: 0x006B1ACE */ static void window_ride_maintenance_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; rct_widget *dropdownWidget; int i, j, num_items; uint8 breakdownReason; dropdownWidget = widget; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); + if (ride_type == NULL) { + return; + } switch (widgetIndex) { case WIDX_INSPECTION_INTERVAL_DROPDOWN: @@ -3436,20 +3510,20 @@ static void window_ride_maintenance_mousedown(int widgetIndex, rct_window *w, rc /** * - * rct2: 0x006B1AD9 + * rct2: 0x006B1AD9 */ static void window_ride_maintenance_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; rct_vehicle *vehicle; int i, j, num_items; if (dropdownIndex == -1) return; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); switch (widgetIndex) { case WIDX_INSPECTION_INTERVAL_DROPDOWN: @@ -3468,7 +3542,7 @@ static void window_ride_maintenance_dropdown(rct_window *w, int widgetIndex, int do { vehicle = GET_VEHICLE(spriteId); vehicle->update_flags &= ~( - VEHICLE_UPDATE_FLAG_BROKEN_CAR | + VEHICLE_UPDATE_FLAG_BROKEN_CAR | VEHICLE_UPDATE_FLAG_7 | VEHICLE_UPDATE_FLAG_BROKEN_TRAIN ); @@ -3523,7 +3597,7 @@ static void window_ride_maintenance_dropdown(rct_window *w, int widgetIndex, int /** * - * rct2: 0x006B1D37 + * rct2: 0x006B1D37 */ static void window_ride_maintenance_update(rct_window *w) { @@ -3533,7 +3607,7 @@ static void window_ride_maintenance_update(rct_window *w) window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_4); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_MAINTENANCE) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_MAINTENANCE; window_invalidate(w); @@ -3542,7 +3616,7 @@ static void window_ride_maintenance_update(rct_window *w) /** * - * rct2: 0x006B17C8 + * rct2: 0x006B17C8 */ static void window_ride_maintenance_invalidate(rct_window *w) { @@ -3558,9 +3632,9 @@ static void window_ride_maintenance_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - rct_ride *ride = GET_RIDE(w->number); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + rct_ride *ride = get_ride(w->number); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; window_ride_maintenance_widgets[WIDX_INSPECTION_INTERVAL].image = STR_EVERY_10_MINUTES + ride->inspection_interval; @@ -3578,7 +3652,7 @@ static void window_ride_maintenance_invalidate(rct_window *w) /** * - * rct2: 0x006B1877 + * rct2: 0x006B1877 */ static void window_ride_maintenance_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -3592,7 +3666,7 @@ static void window_ride_maintenance_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); // Locate mechanic button image widget = &window_ride_maintenance_widgets[WIDX_LOCATE_MECHANIC]; @@ -3670,9 +3744,9 @@ static void window_ride_maintenance_paint(rct_window *w, rct_drawpixelinfo *dpi) } else { mechanicSprite = &(g_sprite_list[ride->mechanic].peep); if (peep_is_mechanic(mechanicSprite)) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = mechanicSprite->name_string_idx; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = mechanicSprite->id; - gfx_draw_string_left_wrapped(dpi, (void*)0x013CE952, x + 4, y, 280, stringId, 0); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = mechanicSprite->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = mechanicSprite->id; + gfx_draw_string_left_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x + 4, y, 280, stringId, 0); } } } @@ -3722,7 +3796,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->var_494)); + 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); @@ -3743,11 +3817,11 @@ static void window_ride_set_track_colour_scheme(rct_window *w, int x, int y) /** * - * rct2: 0x006B04FA + * rct2: 0x006B04FA */ 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) @@ -3761,7 +3835,7 @@ static void window_ride_colour_close(rct_window *w) /** * - * rct2: 0x006B02A1 + * rct2: 0x006B02A1 */ static void window_ride_colour_mouseup(rct_window *w, int widgetIndex) { @@ -3789,7 +3863,7 @@ static void window_ride_colour_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006B0AB6 + * rct2: 0x006B0AB6 */ static void window_ride_colour_resize(rct_window *w) { @@ -3798,7 +3872,7 @@ static void window_ride_colour_resize(rct_window *w) /** * - * rct2: 0x006B02C6 + * rct2: 0x006B02C6 */ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { @@ -3806,13 +3880,13 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid uint16 colourSchemeIndex; vehicle_colour vehicleColour; rct_widget *dropdownWidget; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; int i, numItems; rct_string_id stringId; - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); - colourSchemeIndex = *((uint16*)&w->var_494); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); + colourSchemeIndex = w->ride_colour; dropdownWidget = widget - 1; switch (widgetIndex) { @@ -3943,7 +4017,7 @@ static void window_ride_colour_mousedown(int widgetIndex, rct_window *w, rct_wid /** * - * rct2: 0x006B0331 + * rct2: 0x006B0331 */ static void window_ride_colour_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { @@ -3952,20 +4026,20 @@ static void window_ride_colour_dropdown(rct_window *w, int widgetIndex, int drop switch (widgetIndex) { case WIDX_TRACK_COLOUR_SCHEME_DROPDOWN: - *((uint16*)&w->var_494) = 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->var_494), 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->var_494), 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->var_494), 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->var_494), 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); @@ -3992,7 +4066,7 @@ static void window_ride_colour_dropdown(rct_window *w, int widgetIndex, int drop /** * - * rct2: 0x006B0A8F + * rct2: 0x006B0A8F */ static void window_ride_colour_update(rct_window *w) { @@ -4004,7 +4078,7 @@ static void window_ride_colour_update(rct_window *w) /** * - * rct2: 0x006B04EC + * rct2: 0x006B04EC */ static void window_ride_colour_tooldown(rct_window *w, int widgetIndex, int x, int y) { @@ -4014,7 +4088,7 @@ static void window_ride_colour_tooldown(rct_window *w, int widgetIndex, int x, i /** * - * rct2: 0x006B04F3 + * rct2: 0x006B04F3 */ static void window_ride_colour_tooldrag(rct_window *w, int widgetIndex, int x, int y) { @@ -4024,12 +4098,12 @@ static void window_ride_colour_tooldrag(rct_window *w, int widgetIndex, int x, i /** * - * rct2: 0x006AFB36 + * rct2: 0x006AFB36 */ static void window_ride_colour_invalidate(rct_window *w) { rct_widget *widgets; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_ride *ride; track_colour trackColour; vehicle_colour vehicleColour; @@ -4045,14 +4119,14 @@ static void window_ride_colour_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; // Track colours - int colourScheme = *((uint16*)&w->var_494); + int colourScheme = w->ride_colour; trackColour = ride_get_track_colour(ride, colourScheme); // Maze style @@ -4078,7 +4152,7 @@ static void window_ride_colour_invalidate(rct_window *w) // Track main colour if (window_ride_has_track_colour(ride, 0)) { - window_ride_colour_widgets[WIDX_TRACK_MAIN_COLOUR].type = WWT_COLORBTN; + window_ride_colour_widgets[WIDX_TRACK_MAIN_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_TRACK_MAIN_COLOUR].image = window_ride_get_colour_button_image(trackColour.main); } else { window_ride_colour_widgets[WIDX_TRACK_MAIN_COLOUR].type = WWT_EMPTY; @@ -4086,7 +4160,7 @@ static void window_ride_colour_invalidate(rct_window *w) // Track additional colour if (window_ride_has_track_colour(ride, 1)) { - window_ride_colour_widgets[WIDX_TRACK_ADDITIONAL_COLOUR].type = WWT_COLORBTN; + window_ride_colour_widgets[WIDX_TRACK_ADDITIONAL_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_TRACK_ADDITIONAL_COLOUR].image = window_ride_get_colour_button_image(trackColour.additional); } else { window_ride_colour_widgets[WIDX_TRACK_ADDITIONAL_COLOUR].type = WWT_EMPTY; @@ -4094,7 +4168,7 @@ static void window_ride_colour_invalidate(rct_window *w) // Track supports colour if (window_ride_has_track_colour(ride, 2) && ride->type != RIDE_TYPE_MAZE) { - window_ride_colour_widgets[WIDX_TRACK_SUPPORT_COLOUR].type = WWT_COLORBTN; + window_ride_colour_widgets[WIDX_TRACK_SUPPORT_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_TRACK_SUPPORT_COLOUR].image = window_ride_get_colour_button_image(trackColour.supports); } else { window_ride_colour_widgets[WIDX_TRACK_SUPPORT_COLOUR].type = WWT_EMPTY; @@ -4128,7 +4202,7 @@ static void window_ride_colour_invalidate(rct_window *w) vehicleColour = ride_get_vehicle_colour(ride, w->var_48C); window_ride_colour_widgets[WIDX_VEHICLE_PREVIEW].type = WWT_SCROLL; - window_ride_colour_widgets[WIDX_VEHICLE_MAIN_COLOUR].type = WWT_COLORBTN; + window_ride_colour_widgets[WIDX_VEHICLE_MAIN_COLOUR].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_VEHICLE_MAIN_COLOUR].image = window_ride_get_colour_button_image(vehicleColour.main); uint8 trainLayout[16]; @@ -4138,18 +4212,18 @@ static void window_ride_colour_invalidate(rct_window *w) for (int i = 0; i < ride->num_cars_per_train; i++) { uint8 vehicleTypeIndex = trainLayout[i]; - colourFlags |= rideEntry->vehicles[vehicleTypeIndex].var_14; + colourFlags |= rideEntry->vehicles[vehicleTypeIndex].flags_b; colourFlags = ror32(colourFlags, 16); - colourFlags |= rideEntry->vehicles[vehicleTypeIndex].var_12; + colourFlags |= rideEntry->vehicles[vehicleTypeIndex].flags_a; colourFlags = ror32(colourFlags, 16); } // Additional colours if (colourFlags & 1) { - window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].type = WWT_COLORBTN; + window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_1].image = window_ride_get_colour_button_image(vehicleColour.additional_1); if (colourFlags & 0x2000000) { - window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_COLORBTN; + window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_COLOURBTN; window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].image = window_ride_get_colour_button_image(vehicleColour.additional_2); } else { window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_EMPTY; @@ -4167,10 +4241,10 @@ static void window_ride_colour_invalidate(rct_window *w) window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME].type = WWT_EMPTY; window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_SCHEME_DROPDOWN].type = WWT_EMPTY; } - RCT2_GLOBAL(0x013CE952 + 6, uint16) = STR_ALL_VEHICLES_IN_SAME_COLOURS + vehicleColourSchemeType; - RCT2_GLOBAL(0x013CE952 + 8, uint16) = RideNameConvention[ride->type].vehicle_name; - RCT2_GLOBAL(0x013CE952 + 10, uint16) = RideNameConvention[ride->type].vehicle_name + 2; - RCT2_GLOBAL(0x013CE952 + 12, uint16) = w->var_48C + 1; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = STR_ALL_VEHICLES_IN_SAME_COLOURS + vehicleColourSchemeType; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint16) = RideNameConvention[ride->type].vehicle_name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 10, uint16) = RideNameConvention[ride->type].vehicle_name + 2; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 12, uint16) = w->var_48C + 1; // Vehicle index if (vehicleColourSchemeType != 0) { window_ride_colour_widgets[WIDX_VEHICLE_COLOUR_INDEX].type = WWT_DROPDOWN; @@ -4191,7 +4265,7 @@ static void window_ride_colour_invalidate(rct_window *w) window_ride_colour_widgets[WIDX_VEHICLE_ADDITIONAL_COLOUR_2].type = WWT_EMPTY; } - RCT2_GLOBAL(0x013CE960, uint16) = STR_MAIN_COLOUR_SCHEME + colourScheme; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 14, uint16) = STR_MAIN_COLOUR_SCHEME + colourScheme; window_ride_anchor_border_widgets(w); window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_10); @@ -4199,19 +4273,19 @@ static void window_ride_colour_invalidate(rct_window *w) /** * - * rct2: 0x006AFF3E + * rct2: 0x006AFF3E */ static void window_ride_colour_paint(rct_window *w, rct_drawpixelinfo *dpi) { - rct_drawpixelinfo *clippedDpi; + rct_drawpixelinfo clippedDpi; rct_widget *widget; rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; int x, y, spriteIndex, terniaryColour; track_colour trackColour; - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); @@ -4221,7 +4295,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->var_494)); + trackColour = ride_get_track_colour(ride, w->ride_colour); // if (rideEntry->shop_item == 0xFF) { @@ -4260,11 +4334,15 @@ static void window_ride_colour_paint(rct_window *w, rct_drawpixelinfo *dpi) trackColour = ride_get_track_colour(ride, 0); widget = &w->widgets[WIDX_ENTRANCE_PREVIEW]; if (widget->type != WWT_EMPTY) { - clippedDpi = clip_drawpixelinfo( - dpi, w->x + widget->left + 1, widget->right - widget->left, w->y + widget->top + 1, widget->bottom - widget->top - ); - if (clippedDpi != NULL) { - gfx_clear(clippedDpi, 0x0C0C0C0C); + if (clip_drawpixelinfo( + &clippedDpi, + dpi, + w->x + widget->left + 1, + w->y + widget->top + 1, + widget->right - widget->left, + widget->bottom - widget->top + )) { + gfx_clear(&clippedDpi, 0x0C0C0C0C); if (ride->entrance_style != RIDE_ENTRANCE_STYLE_NONE) { const rct_ride_entrance_definition *entranceStyle = &RideEntranceDefinitions[ride->entrance_style]; @@ -4279,35 +4357,33 @@ static void window_ride_colour_paint(rct_window *w, rct_drawpixelinfo *dpi) spriteIndex += RideEntranceDefinitions[ride->entrance_style].sprite_index; // Back - gfx_draw_sprite(clippedDpi, spriteIndex, 34, 20, terniaryColour); + gfx_draw_sprite(&clippedDpi, spriteIndex, 34, 20, terniaryColour); // Front - gfx_draw_sprite(clippedDpi, spriteIndex + 4, 34, 20, terniaryColour); + gfx_draw_sprite(&clippedDpi, spriteIndex + 4, 34, 20, terniaryColour); // ? if (terniaryColour != 0) - gfx_draw_sprite(clippedDpi, ((spriteIndex + 20) & 0x7FFFF) + terniaryColour, 34, 20, terniaryColour); + gfx_draw_sprite(&clippedDpi, ((spriteIndex + 20) & 0x7FFFF) + terniaryColour, 34, 20, terniaryColour); } - - rct2_free(clippedDpi); } } } /** * - * rct2: 0x006B0192 + * rct2: 0x006B0192 */ static void window_ride_colour_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_widget *vehiclePreviewWidget; int trainCarIndex, x, y, spriteIndex; vehicle_colour vehicleColour; - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); vehiclePreviewWidget = &window_ride_colour_widgets[WIDX_VEHICLE_PREVIEW]; vehicleColour = ride_get_vehicle_colour(ride, w->var_48C); @@ -4325,12 +4401,12 @@ static void window_ride_colour_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi trainCarIndex = (ride->colour_scheme_type & 3) == RIDE_COLOUR_SCHEME_DIFFERENT_PER_CAR ? w->var_48C : rideEntry->tab_vehicle; - rct_ride_type_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[trainCarIndex]]; + rct_ride_entry_vehicle* rideVehicleEntry = &rideEntry->vehicles[trainLayout[trainCarIndex]]; y += rideVehicleEntry->tab_height; // Draw the coloured spinning vehicle - spriteIndex = rideVehicleEntry->var_12 & 0x800 ? w->frame_no / 4 : w->frame_no / 2; + spriteIndex = rideVehicleEntry->flags_a & VEHICLE_ENTRY_FLAG_A_11 ? w->frame_no / 4 : w->frame_no / 2; spriteIndex &= rideVehicleEntry->rotation_frame_mask; spriteIndex *= rideVehicleEntry->var_16; spriteIndex += rideVehicleEntry->base_image_id; @@ -4379,11 +4455,11 @@ static uint8 window_ride_current_music_style_order[42]; /** * - * rct2: 0x006B215D + * rct2: 0x006B215D */ static void window_ride_toggle_music(rct_window *w) { - rct_ride *ride = GET_RIDE(w->number); + rct_ride *ride = get_ride(w->number); int activateMusic = (ride->lifecycle_flags & RIDE_LIFECYCLE_MUSIC) ? 0 : 1; @@ -4393,7 +4469,7 @@ static void window_ride_toggle_music(rct_window *w) /** * - * rct2: 0x006B1ED7 + * rct2: 0x006B1ED7 */ static void window_ride_music_mouseup(rct_window *w, int widgetIndex) { @@ -4421,7 +4497,7 @@ static void window_ride_music_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006AF4A2 + * rct2: 0x006AF4A2 */ static void window_ride_music_resize(rct_window *w) { @@ -4431,7 +4507,7 @@ static void window_ride_music_resize(rct_window *w) /** * - * rct2: 0x006B1EFC + * rct2: 0x006B1EFC */ static void window_ride_music_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { @@ -4442,7 +4518,7 @@ static void window_ride_music_mousedown(int widgetIndex, rct_window *w, rct_widg return; dropdownWidget = widget - 1; - rct_ride *ride = GET_RIDE(w->number); + rct_ride *ride = get_ride(w->number); int numItems = 0; if (ride->type == RIDE_TYPE_MERRY_GO_ROUND) { @@ -4481,7 +4557,7 @@ static void window_ride_music_mousedown(int widgetIndex, rct_window *w, rct_widg /** * - * rct2: 0x006B1F03 + * rct2: 0x006B1F03 */ static void window_ride_music_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { @@ -4491,7 +4567,7 @@ static void window_ride_music_dropdown(rct_window *w, int widgetIndex, int dropd if (widgetIndex != WIDX_MUSIC_DROPDOWN || dropdownIndex == -1) return; - ride = GET_RIDE(w->number); + ride = get_ride(w->number); musicStyle = window_ride_current_music_style_order[dropdownIndex]; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, uint16) = STR_CANT_CHANGE_OPERATING_MODE; game_do_command(0, (musicStyle << 8) | 1, 0, (7 << 8) | w->number, GAME_COMMAND_SET_RIDE_SETTING, 0, 0); @@ -4499,7 +4575,7 @@ static void window_ride_music_dropdown(rct_window *w, int widgetIndex, int dropd /** * - * rct2: 0x006B2198 + * rct2: 0x006B2198 */ static void window_ride_music_update(rct_window *w) { @@ -4510,7 +4586,7 @@ static void window_ride_music_update(rct_window *w) /** * - * rct2: 0x006B1DEA + * rct2: 0x006B1DEA */ static void window_ride_music_invalidate(rct_window *w) { @@ -4527,9 +4603,9 @@ static void window_ride_music_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - rct_ride *ride = GET_RIDE(w->number); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + rct_ride *ride = get_ride(w->number); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; // Set selected music window_ride_music_widgets[WIDX_MUSIC].image = STR_MUSIC_STYLE_START + ride->music; @@ -4552,7 +4628,7 @@ static void window_ride_music_invalidate(rct_window *w) /** * - * rct2: 0x006B1ECC + * rct2: 0x006B1ECC */ static void window_ride_music_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -4564,7 +4640,10 @@ static void window_ride_music_paint(rct_window *w, rct_drawpixelinfo *dpi) #pragma region Measurements -/* rct2: 0x006D2804 when al == 0*/ +/** + * + * rct2: 0x006D2804 + when al == 0*/ static void cancel_scenery_selection(){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) &= ~(1 << 2); RCT2_GLOBAL(0x9DEA6F, uint8) &= ~(1 << 0); @@ -4580,9 +4659,12 @@ static void cancel_scenery_selection(){ tool_cancel(); } -/* rct2: 0x006D27A3 */ +/** + * + * rct2: 0x006D27A3 + */ static void setup_scenery_selection(rct_window* w){ - rct_ride* ride = GET_RIDE(w->number); + rct_ride* ride = get_ride(w->number); if (RCT2_GLOBAL(0x009DEA6F, uint8) & 1){ cancel_scenery_selection(); @@ -4610,7 +4692,7 @@ static void setup_scenery_selection(rct_window* w){ /** * - * rct2: 0x006D3026 + * rct2: 0x006D3026 */ static void window_ride_measurements_design_reset() { @@ -4619,7 +4701,7 @@ static void window_ride_measurements_design_reset() /** * - * rct2: 0x006D303D + * rct2: 0x006D303D */ static void window_ride_measurements_design_select_nearby_scenery() { @@ -4628,7 +4710,7 @@ static void window_ride_measurements_design_select_nearby_scenery() /** * - * rct2: 0x006AD4DA + * rct2: 0x006AD4DA */ static void window_ride_measurements_design_cancel() { @@ -4638,7 +4720,7 @@ static void window_ride_measurements_design_cancel() /** * - * rct2: 0x006AD4CD + * rct2: 0x006AD4CD */ static void window_ride_measurements_design_save(rct_window *w) { @@ -4649,7 +4731,7 @@ static void window_ride_measurements_design_save(rct_window *w) /** * - * rct2: 0x006AD4DA + * rct2: 0x006AD4DA */ static void window_ride_measurements_close(rct_window *w) { @@ -4658,7 +4740,7 @@ static void window_ride_measurements_close(rct_window *w) /** * - * rct2: 0x006AD478 + * rct2: 0x006AD478 */ static void window_ride_measurements_mouseup(rct_window *w, int widgetIndex) { @@ -4695,7 +4777,7 @@ static void window_ride_measurements_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006AD564 + * rct2: 0x006AD564 */ static void window_ride_measurements_resize(rct_window *w) { @@ -4704,14 +4786,14 @@ static void window_ride_measurements_resize(rct_window *w) /** * - * rct2: 0x006AD4AB + * rct2: 0x006AD4AB */ static void window_ride_measurements_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { if (widgetIndex != WIDX_SAVE_TRACK_DESIGN) return; - rct_ride *ride = GET_RIDE(w->number); + rct_ride *ride = get_ride(w->number); gDropdownItemsFormat[0] = STR_SAVE_TRACK_DESIGN_ITEM; gDropdownItemsFormat[1] = STR_SAVE_TRACK_DESIGN_WITH_SCENERY_ITEM; @@ -4724,14 +4806,14 @@ static void window_ride_measurements_mousedown(int widgetIndex, rct_window *w, r 0, 2 ); - gDropdownHighlightedIndex = 0; + gDropdownDefaultIndex = 0; if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_DESIGNER) gDropdownItemsDisabled |= 2; } /** * - * rct2: 0x006AD4B2 + * rct2: 0x006AD4B2 */ static void window_ride_measurements_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { @@ -4749,7 +4831,7 @@ static void window_ride_measurements_dropdown(rct_window *w, int widgetIndex, in /** * - * rct2: 0x006AD5DD + * rct2: 0x006AD5DD */ static void window_ride_measurements_update(rct_window *w) { @@ -4760,7 +4842,7 @@ static void window_ride_measurements_update(rct_window *w) /** * - * rct2: 0x006D2AE7 + * rct2: 0x006D2AE7 */ static void window_ride_measurements_tooldown(rct_window *w, int widgetIndex, int x, int y) { @@ -4781,7 +4863,7 @@ static void window_ride_measurements_tooldown(rct_window *w, int widgetIndex, in /** * - * rct2: 0x006AD4DA + * rct2: 0x006AD4DA */ static void window_ride_measurements_toolabort(rct_window *w, int widgetIndex) { @@ -4790,7 +4872,7 @@ static void window_ride_measurements_toolabort(rct_window *w, int widgetIndex) /** * - * rct2: 0x006ACDBC + * rct2: 0x006ACDBC */ static void window_ride_measurements_invalidate(rct_window *w) { @@ -4806,9 +4888,9 @@ static void window_ride_measurements_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - rct_ride *ride = GET_RIDE(w->number); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + rct_ride *ride = get_ride(w->number); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; window_ride_measurements_widgets[WIDX_SAVE_TRACK_DESIGN].tooltip = STR_SAVE_TRACK_DESIGN_NOT_POSSIBLE; window_ride_measurements_widgets[WIDX_SAVE_TRACK_DESIGN].type = WWT_EMPTY; @@ -4841,7 +4923,7 @@ static void window_ride_measurements_invalidate(rct_window *w) /** * - * rct2: 0x006ACF07 + * rct2: 0x006ACF07 */ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -4866,22 +4948,22 @@ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi y = w->y + window_ride_measurements_widgets[WIDX_SELECT_NEARBY_SCENERY].bottom + 17; gfx_fill_rect_inset(dpi, x, y, w->x + 312, y + 1, w->colours[1], 0x20); } else { - ride = GET_RIDE(w->number); + ride = get_ride(w->number); x = w->x + window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_ride_measurements_widgets[WIDX_PAGE_BACKGROUND].top + 4; if (ride->lifecycle_flags & RIDE_LIFECYCLE_TESTED) { // Excitement - RCT2_GLOBAL(0x013CE952 + 0, uint32) = ride->excitement; - RCT2_GLOBAL(0x013CE952 + 4, uint16) = STR_RATING_LOW + min(ride->excitement >> 8, 5); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = ride->excitement; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = STR_RATING_LOW + min(ride->excitement >> 8, 5); stringId = ride->excitement == -1 ? STR_EXCITEMENT_RATING_NOT_YET_AVAILABLE : STR_EXCITEMENT_RATING; - gfx_draw_string_left(dpi, stringId, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 10; // Intensity - RCT2_GLOBAL(0x013CE952 + 0, uint32) = ride->intensity; - RCT2_GLOBAL(0x013CE952 + 4, uint16) = STR_RATING_LOW + min(ride->intensity >> 8, 5); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = ride->intensity; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = STR_RATING_LOW + min(ride->intensity >> 8, 5); stringId = STR_INTENSITY_RATING; if (ride->excitement == -1) @@ -4889,14 +4971,14 @@ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi else if (ride->intensity >= RIDE_RATING(10,00)) stringId = STR_INTENSITY_RATING_RED; - gfx_draw_string_left(dpi, stringId, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 10; // Nausea - RCT2_GLOBAL(0x013CE952 + 0, uint32) = ride->nausea; - RCT2_GLOBAL(0x013CE952 + 4, uint16) = STR_RATING_LOW + min(ride->nausea >> 8, 5); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = ride->nausea; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = STR_RATING_LOW + min(ride->nausea >> 8, 5); stringId = ride->excitement == -1 ? STR_NAUSEA_RATING_NOT_YET_AVAILABLE : STR_NAUSEA_RATING; - gfx_draw_string_left(dpi, stringId, (void*)0x013CE952, 0, x, y); + gfx_draw_string_left(dpi, stringId, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 20; // Horizontal rule @@ -4924,22 +5006,22 @@ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi for (i = 0; i < ride->num_stations; i++) { time = ride->time[numTimes]; if (time != 0) { - RCT2_GLOBAL(0x013CE952 + 0 + (numTimes * 4), uint16) = 1343; - RCT2_GLOBAL(0x013CE952 + 2 + (numTimes * 4), uint16) = time; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0 + (numTimes * 4), uint16) = 1343; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2 + (numTimes * 4), uint16) = time; numTimes++; } } if (numTimes == 0) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1343; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 1343; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = 0; numTimes++; } RCT2_GLOBAL(0x013CE94E + (numTimes * 4), uint16) = 1342; - RCT2_GLOBAL(0x013CE952 + 0 + (numTimes * 4), uint16) = 0; - RCT2_GLOBAL(0x013CE952 + 2 + (numTimes * 4), uint16) = 0; - RCT2_GLOBAL(0x013CE952 + 4 + (numTimes * 4), uint16) = 0; - RCT2_GLOBAL(0x013CE952 + 6 + (numTimes * 4), uint16) = 0; - gfx_draw_string_left_clipped(dpi, STR_RIDE_TIME, (void*)0x013CE952, 0, x, y, 308); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0 + (numTimes * 4), uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2 + (numTimes * 4), uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4 + (numTimes * 4), uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6 + (numTimes * 4), uint16) = 0; + gfx_draw_string_left_clipped(dpi, STR_RIDE_TIME, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, 308); y += 10; } @@ -4949,22 +5031,22 @@ static void window_ride_measurements_paint(rct_window *w, rct_drawpixelinfo *dpi length = ride->length[numLengths]; if (length != 0) { length >>= 16; - RCT2_GLOBAL(0x013CE952 + 0 + (numLengths * 4), uint16) = 1346; - RCT2_GLOBAL(0x013CE952 + 2 + (numLengths * 4), uint16) = (length & 0xFFFF); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0 + (numLengths * 4), uint16) = 1346; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2 + (numLengths * 4), uint16) = (length & 0xFFFF); numLengths++; } } if (numLengths == 0) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1346; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 1346; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = 0; numLengths++; } RCT2_GLOBAL(0x013CE94E + (numLengths * 4), uint16) = 1345; - RCT2_GLOBAL(0x013CE952 + 0 + (numLengths * 4), uint16) = 0; - RCT2_GLOBAL(0x013CE952 + 2 + (numLengths * 4), uint16) = 0; - RCT2_GLOBAL(0x013CE952 + 4 + (numLengths * 4), uint16) = 0; - RCT2_GLOBAL(0x013CE952 + 6 + (numLengths * 4), uint16) = 0; - gfx_draw_string_left_clipped(dpi, STR_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 308); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0 + (numLengths * 4), uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2 + (numLengths * 4), uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4 + (numLengths * 4), uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6 + (numLengths * 4), uint16) = 0; + gfx_draw_string_left_clipped(dpi, STR_RIDE_LENGTH, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, 308); y += 10; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_G_FORCES)) { @@ -5035,7 +5117,7 @@ enum { /** * - * rct2: 0x006AE8A6 + * rct2: 0x006AE8A6 */ static void window_ride_set_graph(rct_window *w, int type) { @@ -5050,7 +5132,7 @@ static void window_ride_set_graph(rct_window *w, int type) /** * - * rct2: 0x006AE85D + * rct2: 0x006AE85D */ static void window_ride_graphs_mouseup(rct_window *w, int widgetIndex) { @@ -5075,7 +5157,7 @@ static void window_ride_graphs_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006AE8DA + * rct2: 0x006AE8DA */ static void window_ride_graphs_resize(rct_window *w) { @@ -5084,7 +5166,7 @@ static void window_ride_graphs_resize(rct_window *w) /** * - * rct2: 0x006AE878 + * rct2: 0x006AE878 */ static void window_ride_graphs_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { @@ -5106,7 +5188,7 @@ static void window_ride_graphs_mousedown(int widgetIndex, rct_window *w, rct_wid /** * - * rct2: 0x006AE95D + * rct2: 0x006AE95D */ static void window_ride_graphs_update(rct_window *w) { @@ -5135,7 +5217,7 @@ static void window_ride_graphs_update(rct_window *w) /** * - * rct2: 0x006AEA75 + * rct2: 0x006AEA75 */ static void window_ride_graphs_scrollgetheight(rct_window *w, int scrollIndex, int *width, int *height) { @@ -5154,7 +5236,7 @@ static void window_ride_graphs_scrollgetheight(rct_window *w, int scrollIndex, i /** * - * rct2: 0x006AE953 + * rct2: 0x006AE953 */ static void window_ride_graphs_15(rct_window *w, int scrollIndex, int scrollAreaType) { @@ -5163,7 +5245,7 @@ static void window_ride_graphs_15(rct_window *w, int scrollIndex, int scrollArea /** * - * rct2: 0x006AEA05 + * rct2: 0x006AEA05 */ static void window_ride_graphs_tooltip(rct_window* w, int widgetIndex, rct_string_id *stringId) { @@ -5175,9 +5257,9 @@ static void window_ride_graphs_tooltip(rct_window* w, int widgetIndex, rct_strin RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = 3158; measurement = ride_get_measurement(w->number, &message); if (measurement != NULL && (measurement->flags & RIDE_MEASUREMENT_FLAG_RUNNING)) { - RCT2_GLOBAL(0x013CE952 + 4, uint16) = measurement->vehicle_index + 1; - ride = GET_RIDE(w->number); - RCT2_GLOBAL(0x013CE952 + 2, uint16) = RideNameConvention[ride->type].vehicle_name + 6; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = measurement->vehicle_index + 1; + ride = get_ride(w->number); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = RideNameConvention[ride->type].vehicle_name + 6; } else { *stringId = message; } @@ -5188,7 +5270,7 @@ static void window_ride_graphs_tooltip(rct_window* w, int widgetIndex, rct_strin /** * - * rct2: 0x006AE372 + * rct2: 0x006AE372 */ static void window_ride_graphs_invalidate(rct_window *w) { @@ -5206,10 +5288,10 @@ static void window_ride_graphs_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; // Set pressed graph button type w->pressed_widgets &= ~(1 << WIDX_GRAPH_VELOCITY); @@ -5250,7 +5332,7 @@ static void window_ride_graphs_invalidate(rct_window *w) /** * - * rct2: 0x006AE4BC + * rct2: 0x006AE4BC */ static void window_ride_graphs_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -5260,7 +5342,7 @@ static void window_ride_graphs_paint(rct_window *w, rct_drawpixelinfo *dpi) /** * - * rct2: 0x006AE4C7 + * rct2: 0x006AE4C7 */ static void window_ride_graphs_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) { @@ -5279,7 +5361,7 @@ static void window_ride_graphs_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi x = (widget->right - widget->left) / 2; y = (widget->bottom - widget->top) / 2 - 5; width = widget->right - widget->left - 2; - gfx_draw_string_centred_wrapped(dpi, (void*)0x013CE952, x, y, width, stringId, 0); + gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, width, stringId, 0); return; } @@ -5381,17 +5463,17 @@ static void window_ride_graphs_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi /** * - * rct2: 0x006ADEFD + * rct2: 0x006ADEFD */ static void window_ride_income_toggle_primary_price(rct_window *w) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; uint32 newFlags, shop_item; money16 price; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); if (ride->type == RIDE_TYPE_TOILETS) { shop_item = 0x1F; @@ -5413,12 +5495,12 @@ static void window_ride_income_toggle_primary_price(rct_window *w) else { if (shop_item < 32) { newFlags = RCT2_GLOBAL(0x01358838, uint32); - newFlags ^= (1 << shop_item); + newFlags ^= (1u << shop_item); game_do_command(0, 1, 0, (0x2 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); } else { newFlags = RCT2_GLOBAL(0x0135934C, uint32); - newFlags ^= (1 << (shop_item - 32)); + newFlags ^= (1u << (shop_item - 32)); game_do_command(0, 1, 0, (0x3 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); } } @@ -5428,17 +5510,17 @@ static void window_ride_income_toggle_primary_price(rct_window *w) /** * - * rct2: 0x006AE06E + * rct2: 0x006AE06E */ static void window_ride_income_toggle_secondary_price(rct_window *w) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; uint32 newFlags, shop_item; money16 price; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); shop_item = ride_type->shop_item_secondary; if (shop_item == 0xFF) @@ -5456,12 +5538,12 @@ static void window_ride_income_toggle_secondary_price(rct_window *w) else { if (shop_item < 32) { newFlags = RCT2_GLOBAL(0x01358838, uint32); - newFlags ^= (1 << shop_item); + newFlags ^= (1u << shop_item); game_do_command(0, 1, 0, (0x2 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); } else { newFlags = RCT2_GLOBAL(0x0135934C, uint32); - newFlags ^= (1 << (shop_item - 32)); + newFlags ^= (1u << (shop_item - 32)); game_do_command(0, 1, 0, (0x3 << 8), GAME_COMMAND_SET_PARK_OPEN, newFlags, shop_item); } } @@ -5471,19 +5553,19 @@ static void window_ride_income_toggle_secondary_price(rct_window *w) /** * - * rct2: 0x006AE1E4 + * rct2: 0x006AE1E4 */ static void window_ride_income_increase_primary_price(rct_window *w) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); if ((RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY) == 0) { if (ride->type != RIDE_TYPE_TOILETS && ride_type->shop_item == 0xFF) { - if (!gConfigCheat.unlock_all_prices) + if (!gCheatsUnlockAllPrices) return; } } @@ -5496,19 +5578,19 @@ static void window_ride_income_increase_primary_price(rct_window *w) /** * - * rct2: 0x006AE237 + * rct2: 0x006AE237 */ static void window_ride_income_decrease_primary_price(rct_window *w) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); if ((RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY) == 0) { if (ride->type != RIDE_TYPE_TOILETS && ride_type->shop_item == 0xFF) { - if (!gConfigCheat.unlock_all_prices) + if (!gCheatsUnlockAllPrices) return; } } @@ -5521,15 +5603,15 @@ static void window_ride_income_decrease_primary_price(rct_window *w) /** * - * rct2: 0x006AE269 + * rct2: 0x006AE269 */ static void window_ride_income_increase_secondary_price(rct_window *w) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); money16 price = ride->price_secondary; if (price < MONEY(20, 00)) @@ -5540,15 +5622,15 @@ static void window_ride_income_increase_secondary_price(rct_window *w) /** * - * rct2: 0x006AE28D + * rct2: 0x006AE28D */ static void window_ride_income_decrease_secondary_price(rct_window *w) { rct_ride *ride; - rct_ride_type *ride_type; + rct_ride_entry *ride_type; - ride = GET_RIDE(w->number); - ride_type = gRideTypeList[ride->subtype]; + ride = get_ride(w->number); + ride_type = get_ride_entry(ride->subtype); money16 price = ride->price_secondary; if (price > MONEY(0, 00)) @@ -5559,7 +5641,7 @@ static void window_ride_income_decrease_secondary_price(rct_window *w) /** * - * rct2: 0x006ADEA9 + * rct2: 0x006ADEA9 */ static void window_ride_income_mouseup(rct_window *w, int widgetIndex) { @@ -5590,7 +5672,7 @@ static void window_ride_income_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006AE2F8 + * rct2: 0x006AE2F8 */ static void window_ride_income_resize(rct_window *w) { @@ -5599,7 +5681,7 @@ static void window_ride_income_resize(rct_window *w) /** * - * rct2: 0x006ADED4 + * rct2: 0x006ADED4 */ static void window_ride_income_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { @@ -5621,7 +5703,7 @@ static void window_ride_income_mousedown(int widgetIndex, rct_window *w, rct_wid /** * - * rct2: 0x006AE2BF + * rct2: 0x006AE2BF */ static void window_ride_income_update(rct_window *w) { @@ -5631,7 +5713,7 @@ static void window_ride_income_update(rct_window *w) window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_9); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_INCOME) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_INCOME; window_invalidate(w); @@ -5640,12 +5722,12 @@ static void window_ride_income_update(rct_window *w) /** * - * rct2: 0x006ADAA3 + * rct2: 0x006ADAA3 */ static void window_ride_income_invalidate(rct_window *w) { rct_widget *widgets; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_string_id stringId; int primaryItem, secondaryItem; @@ -5659,11 +5741,11 @@ static void window_ride_income_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - rct_ride *ride = GET_RIDE(w->number); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + rct_ride *ride = get_ride(w->number); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; - rideEntry = ride_get_entry(ride); + rideEntry = get_ride_entry_by_ride(ride); // Primary item w->pressed_widgets &= ~(1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); @@ -5671,7 +5753,7 @@ static void window_ride_income_invalidate(rct_window *w) //If the park doesn't have free entry, lock the admission price, unless the cheat to unlock all prices is activated. if ((!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_PARK_FREE_ENTRY) && rideEntry->shop_item == 255 && ride->type != RIDE_TYPE_TOILETS) - && (!gConfigCheat.unlock_all_prices)) + && (!gCheatsUnlockAllPrices)) { w->disabled_widgets |= (1 << WIDX_PRIMARY_PRICE); } @@ -5681,7 +5763,7 @@ static void window_ride_income_invalidate(rct_window *w) window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_EMPTY; window_ride_income_widgets[WIDX_PRIMARY_PRICE].image = 1429; - RCT2_GLOBAL(0x013CE952 + 6, money32) = ride->price; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, money32) = ride->price; if (ride->price == 0) window_ride_income_widgets[WIDX_PRIMARY_PRICE].image = STR_FREE; @@ -5689,7 +5771,7 @@ static void window_ride_income_invalidate(rct_window *w) if (ride->type == RIDE_TYPE_TOILETS || ((primaryItem = (sint8)rideEntry->shop_item) != -1)) { window_ride_income_widgets[WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK].type = WWT_CHECKBOX; if (primaryItem < 32) { - if (RCT2_GLOBAL(0x01358838, uint32) & (1 << primaryItem)) + if (RCT2_GLOBAL(0x01358838, uint32) & (1u << primaryItem)) w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); if (primaryItem != 31) @@ -5697,7 +5779,7 @@ static void window_ride_income_invalidate(rct_window *w) } else { primaryItem -= 32; - if (RCT2_GLOBAL(0x0135934C, uint32) & (1 << primaryItem)) + if (RCT2_GLOBAL(0x0135934C, uint32) & (1u << primaryItem)) w->pressed_widgets |= (1 << WIDX_PRIMARY_PRICE_SAME_THROUGHOUT_PARK); window_ride_income_widgets[WIDX_PRIMARY_PRICE_LABEL].image = 2100 + primaryItem; @@ -5729,11 +5811,11 @@ static void window_ride_income_invalidate(rct_window *w) // Set same price throughout park checkbox w->pressed_widgets &= ~(1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK); if (secondaryItem < 32) { - if (RCT2_GLOBAL(0x01358838, uint32) & (1 << secondaryItem)) + if (RCT2_GLOBAL(0x01358838, uint32) & (1u << secondaryItem)) w->pressed_widgets |= (1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK); } else { secondaryItem -= 32; - if (RCT2_GLOBAL(0x0135934C, uint32) & (1 << secondaryItem)) + if (RCT2_GLOBAL(0x0135934C, uint32) & (1u << secondaryItem)) w->pressed_widgets |= (1 << WIDX_SECONDARY_PRICE_SAME_THROUGHOUT_PARK); } @@ -5746,7 +5828,7 @@ static void window_ride_income_invalidate(rct_window *w) // Set secondary item price window_ride_income_widgets[WIDX_SECONDARY_PRICE].image = 1799; - RCT2_GLOBAL(0x013CE952 + 10, money32) = ride->price_secondary; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 10, money32) = ride->price_secondary; if (ride->price_secondary == 0) window_ride_income_widgets[WIDX_SECONDARY_PRICE].image = STR_FREE; } @@ -5757,12 +5839,12 @@ static void window_ride_income_invalidate(rct_window *w) /** * - * rct2: 0x006ADCE5 + * rct2: 0x006ADCE5 */ static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi) { rct_ride *ride; - rct_ride_type *rideEntry; + rct_ride_entry *rideEntry; rct_string_id stringId; money32 profit, costPerHour; int x, y, primaryItem, secondaryItem; @@ -5770,8 +5852,8 @@ static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); - ride = GET_RIDE(w->number); - rideEntry = ride_get_entry(ride); + ride = get_ride(w->number); + rideEntry = get_ride_entry_by_ride(ride); x = w->x + window_ride_income_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_ride_income_widgets[WIDX_PAGE_BACKGROUND].top + 29; @@ -5782,9 +5864,7 @@ static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi) profit = ride->price; stringId = STR_PROFIT_PER_ITEM_SOLD; - profit -= primaryItem < 32 ? - RCT2_GLOBAL(0x00982164 + (primaryItem * 8), uint16) : - RCT2_GLOBAL(0x00982144 + (primaryItem * 8), uint16); + profit -= get_shop_item_cost(primaryItem); if (profit < 0) { profit *= -1; stringId = STR_LOSS_PER_ITEM_SOLD; @@ -5803,9 +5883,7 @@ static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi) profit = ride->price_secondary; stringId = STR_PROFIT_PER_ITEM_SOLD; - profit -= secondaryItem < 32 ? - RCT2_GLOBAL(0x00982164 + (secondaryItem * 8), uint16) : - RCT2_GLOBAL(0x00982144 + (secondaryItem * 8), uint16); + profit -= get_shop_item_cost(secondaryItem); if (profit < 0) { profit *= -1; stringId = STR_LOSS_PER_ITEM_SOLD; @@ -5844,7 +5922,7 @@ static void window_ride_income_paint(rct_window *w, rct_drawpixelinfo *dpi) /** * - * rct2: 0x006AD986 + * rct2: 0x006AD986 */ static void window_ride_customer_mouseup(rct_window *w, int widgetIndex) { @@ -5878,17 +5956,17 @@ static void window_ride_customer_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006ADA29 + * rct2: 0x006ADA29 */ static void window_ride_customer_resize(rct_window *w) { w->flags |= WF_RESIZABLE; - window_set_resize(w, 316, 139, 316, 139); + window_set_resize(w, 316, 149, 316, 149); } /** * - * rct2: 0x006AD9DD + * rct2: 0x006AD9DD */ static void window_ride_customer_update(rct_window *w) { @@ -5901,7 +5979,7 @@ static void window_ride_customer_update(rct_window *w) window_event_invalidate_call(w); widget_invalidate(w, WIDX_TAB_10); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); if (ride->window_invalidate_flags & RIDE_INVALIDATE_RIDE_CUSTOMER) { ride->window_invalidate_flags &= ~RIDE_INVALIDATE_RIDE_CUSTOMER; window_invalidate(w); @@ -5910,7 +5988,7 @@ static void window_ride_customer_update(rct_window *w) /** * - * rct2: 0x006AD5F8 + * rct2: 0x006AD5F8 */ static void window_ride_customer_invalidate(rct_window *w) { @@ -5926,9 +6004,9 @@ static void window_ride_customer_invalidate(rct_window *w) window_ride_set_pressed_tab(w); - rct_ride *ride = GET_RIDE(w->number); - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->name_arguments; + rct_ride *ride = get_ride(w->number); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; window_ride_customer_widgets[WIDX_SHOW_GUESTS_THOUGHTS].type = WWT_FLATBTN; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) { @@ -5945,7 +6023,7 @@ static void window_ride_customer_invalidate(rct_window *w) /** * - * rct2: 0x006AD6CD + * rct2: 0x006AD6CD */ static void window_ride_customer_paint(rct_window *w, rct_drawpixelinfo *dpi) { @@ -5959,14 +6037,19 @@ static void window_ride_customer_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); window_ride_draw_tab_images(dpi, w); - ride = GET_RIDE(w->number); + ride = get_ride(w->number); x = w->x + window_ride_customer_widgets[WIDX_PAGE_BACKGROUND].left + 4; y = w->y + window_ride_customer_widgets[WIDX_PAGE_BACKGROUND].top + 4; + // Customers currently on ride + if (gRideClassifications[ride->type] == RIDE_CLASS_RIDE) { + sint16 customersOnRide = ride->num_riders; + gfx_draw_string_left(dpi, STR_CUSTOMERS_ON_RIDE, &customersOnRide, 0, x, y); + y += 10; + } + // Customers per hour - customersPerHour = ride->var_124 + ride->var_126 + ride->var_128 + ride->var_12A + ride->var_12C + - ride->var_12E + ride->age + ride->running_cost + ride->var_134 + ride->var_136; - customersPerHour *= 12; + customersPerHour = ride_customers_per_hour(ride); gfx_draw_string_left(dpi, STR_CUSTOMERS_PER_HOUR, &customersPerHour, 0, x, y); y += 10; @@ -5993,28 +6076,30 @@ static void window_ride_customer_paint(rct_window *w, rct_drawpixelinfo *dpi) y += 10; // Queue time - queueTime = ride_get_max_queue_time(ride); - stringId = queueTime == 1 ? STR_QUEUE_TIME_MINUTE : STR_QUEUE_TIME_MINUTES; - y += gfx_draw_string_left_wrapped(dpi, &queueTime, x, y, 308, stringId, 0); - y += 5; + if (gRideClassifications[ride->type] == RIDE_CLASS_RIDE) { + queueTime = ride_get_max_queue_time(ride); + stringId = queueTime == 1 ? STR_QUEUE_TIME_MINUTE : STR_QUEUE_TIME_MINUTES; + y += gfx_draw_string_left_wrapped(dpi, &queueTime, x, y, 308, stringId, 0); + y += 5; + } // Primary shop items sold - shopItem = ride_get_entry(ride)->shop_item; + shopItem = get_ride_entry_by_ride(ride)->shop_item; if (shopItem != 0xFF) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ShopItemStringIds[shopItem].plural; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->no_primary_items_sold; - gfx_draw_string_left(dpi, STR_ITEMS_SOLD, (void*)0x013CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ShopItemStringIds[shopItem].plural; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->no_primary_items_sold; + gfx_draw_string_left(dpi, STR_ITEMS_SOLD, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 10; } // Secondary shop items sold / on-ride photos sold shopItem = ride->lifecycle_flags & RIDE_LIFECYCLE_ON_RIDE_PHOTO ? RCT2_GLOBAL(0x0097D7CB + (ride->type * 4), uint8) : - ride_get_entry(ride)->shop_item_secondary; + get_ride_entry_by_ride(ride)->shop_item_secondary; if (shopItem != 0xFF) { - RCT2_GLOBAL(0x013CE952 + 0, uint16) = ShopItemStringIds[shopItem].plural; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = ride->no_secondary_items_sold; - gfx_draw_string_left(dpi, STR_ITEMS_SOLD, (void*)0x013CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ShopItemStringIds[shopItem].plural; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->no_secondary_items_sold; + gfx_draw_string_left(dpi, STR_ITEMS_SOLD, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 10; } diff --git a/src/windows/ride_construction.c b/src/windows/ride_construction.c index 1ece93b7c2..ade6c79a44 100644 --- a/src/windows/ride_construction.c +++ b/src/windows/ride_construction.c @@ -21,6 +21,7 @@ #include "../addresses.h" #include "../audio/audio.h" #include "../cheats.h" +#include "../config.h" #include "../drawing/drawing.h" #include "../game.h" #include "../input.h" @@ -33,6 +34,7 @@ #include "../ride/ride_data.h" #include "../ride/track.h" #include "dropdown.h" +#include "../ride/track_data.h" /* move to ride.c */ void sub_6B2FA9(rct_windownumber number) @@ -451,9 +453,13 @@ static int _trackPlaceShiftStartScreenX; static int _trackPlaceShiftStartScreenY; static int _trackPlaceShiftZ; #define _trackPlaceZ RCT2_GLOBAL(0x00F44163, sint16) +static bool _autoOpeningShop; + +// This variable is updated separately from ride->num_stations because the latter +// is unreliable if currently in station construction mode +static bool _stationConstructed; +static bool _deferClose; -static void window_ride_construction_next_section(rct_window *w); -static void window_ride_construction_previous_section(rct_window *w); static void window_ride_construction_construct(rct_window *w); static void window_ride_construction_mouseup_demolish(rct_window* w); static void window_ride_construction_rotate(rct_window *w); @@ -493,12 +499,12 @@ static int ride_get_alternative_type(rct_ride *ride) { return _currentTrackCovered & 2 ? RCT2_ADDRESS(0x0097D4F5, uint8)[ride->type * 8] : - ride->type;; + ride->type; } /** * - * rct2: 0x006CB481 + * rct2: 0x006CB481 */ rct_window *window_ride_construction_open() { @@ -506,7 +512,10 @@ rct_window *window_ride_construction_open() sub_6B2FA9(rideIndex); rct_window *w; - rct_ride* ride = GET_RIDE(rideIndex); + rct_ride* ride = get_ride(rideIndex); + + _stationConstructed = ride->num_stations != 0; + _deferClose = false; if (ride->type == RIDE_TYPE_MAZE) return window_maze_construction_open(); @@ -554,6 +563,7 @@ rct_window *window_ride_construction_open() _rideConstructionState = RIDE_CONSTRUCTION_STATE_PLACE; _currentTrackSelectionFlags = 0; _rideConstructionArrowPulseTime = 0; + _autoOpeningShop = false; RCT2_GLOBAL(0x00F44159, uint8) = 0; RCT2_GLOBAL(0x00F4415C, uint8) = 0; colour_scheme_update(w); @@ -562,12 +572,10 @@ rct_window *window_ride_construction_open() /** * - * rct2: 0x006C845D + * rct2: 0x006C845D */ static void window_ride_construction_close(rct_window *w) { - rct_xy_element mapElement; - sub_6C9627(); viewport_set_visibility(0); @@ -584,7 +592,21 @@ static void window_ride_construction_close(rct_window *w) hide_gridlines(); uint8 rideIndex = _currentRideIndex; - if (sub_6CAF80(rideIndex, &mapElement) || network_get_mode() == NETWORK_MODE_CLIENT) { + if (ride_try_get_origin_element(rideIndex, NULL)) { + rct_ride *ride = get_ride(rideIndex); + // Auto open shops if required. + if (ride->mode == RIDE_MODE_SHOP_STALL && gConfigGeneral.auto_open_shops) { + // HACK: Until we find a good a way to defer the game command for opening the shop, stop this + // from getting stuck in an infinite loop as opening the ride will try to close this window + if (!_autoOpeningShop) { + _autoOpeningShop = true; + ride_set_status(rideIndex, RIDE_STATUS_OPEN); + _autoOpeningShop = false; + } + } + + ride_set_to_default_inspection_interval(rideIndex); + window_ride_main_open(rideIndex); } else { int eax = RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8); @@ -598,7 +620,7 @@ static void window_ride_construction_close(rct_window *w) /** * - * rct2: 0x006C6E14 + * rct2: 0x006C6E14 */ static void window_ride_construction_mouseup(rct_window *w, int widgetIndex) { @@ -635,7 +657,7 @@ static void window_ride_construction_mouseup(rct_window *w, int widgetIndex) /** * - * rct2: 0x006C7934 + * rct2: 0x006C7934 */ static void window_ride_construction_resize(rct_window *w) { @@ -645,7 +667,7 @@ static void window_ride_construction_resize(rct_window *w) w->enabled_widgets |= (1 << WIDX_CONSTRUCT); } - rct_ride *ride = GET_RIDE(_currentRideIndex); + rct_ride *ride = get_ride(_currentRideIndex); int rideType = ride_get_alternative_type(ride); uint64 disabledWidgets = 0; @@ -716,6 +738,12 @@ static void window_ride_construction_resize(rct_window *w) (1ULL << WIDX_BANK_STRAIGHT) | (1ULL << WIDX_BANK_RIGHT); } + // Disable banking if the start track is steep and the end of the track becomes flat. + if ((_previousTrackSlopeEnd == TRACK_SLOPE_DOWN_60 || _previousTrackSlopeEnd == TRACK_SLOPE_UP_60) && _currentTrackSlopeEnd == TRACK_SLOPE_NONE) { + disabledWidgets |= + (1ULL << WIDX_BANK_LEFT) | + (1ULL << WIDX_BANK_RIGHT); + } if (!is_track_enabled(TRACK_SLOPE) && !is_track_enabled(TRACK_SLOPE_STEEP)) { if (rideType != RIDE_TYPE_REVERSE_FREEFALL_COASTER && rideType != RIDE_TYPE_AIR_POWERED_VERTICAL_COASTER) { // Disable all slopes @@ -939,6 +967,11 @@ static void window_ride_construction_resize(rct_window *w) if (_currentTrackSlopeEnd == TRACK_SLOPE_UP_90 || _previousTrackSlopeEnd == TRACK_SLOPE_UP_90) { disabledWidgets |= (1ULL << WIDX_CHAIN_LIFT); } + if (!is_track_enabled(TRACK_LIFT_HILL_STEEP)) { + if (_previousTrackSlopeEnd == TRACK_SLOPE_UP_60 || _currentTrackSlopeEnd == TRACK_SLOPE_UP_60) { + disabledWidgets |= (1ULL << WIDX_CHAIN_LIFT); + } + } if (_previousTrackBankEnd == TRACK_BANK_UPSIDE_DOWN) { disabledWidgets |= (1ULL << WIDX_LEFT_CURVE_SMALL) | @@ -1196,11 +1229,11 @@ static void window_ride_construction_resize(rct_window *w) /** * - * rct2: 0x006C6E6A + * rct2: 0x006C6E6A */ static void window_ride_construction_mousedown(int widgetIndex, rct_window *w, rct_widget *widget) { - rct_ride *ride = GET_RIDE(_currentRideIndex); + rct_ride *ride = get_ride(_currentRideIndex); int rideType; window_ride_construction_update_enabled_track_pieces(); @@ -1447,7 +1480,7 @@ static void window_ride_construction_mousedown(int widgetIndex, rct_window *w, r uint8 maxBrakesSpeed = 30; if (RCT2_GLOBAL(0x00F440D3, uint8) != 1) { brakesSpeedPtr = (uint8*)0x00F440CE; - maxBrakesSpeed = RCT2_GLOBAL(0x0097CF40 + 6 + (ride->type * 8), uint8); + maxBrakesSpeed = RCT2_GLOBAL(RCT2_ADDRESS_RIDE_FLAGS + 6 + (ride->type * 8), uint8); } uint8 brakesSpeed = *brakesSpeedPtr + 2; if (brakesSpeed <= maxBrakesSpeed) { @@ -1523,7 +1556,7 @@ static void window_ride_construction_mousedown(int widgetIndex, rct_window *w, r /** * - * rct2: 0x006C78CD + * rct2: 0x006C78CD */ static void window_ride_construction_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { @@ -1553,7 +1586,7 @@ static void window_ride_construction_dropdown(rct_window *w, int widgetIndex, in /** * - * rct2: 0x006C9F72 + * rct2: 0x006C9F72 */ static void window_ride_construction_construct(rct_window *w) { @@ -1612,7 +1645,6 @@ static void window_ride_construction_construct(rct_window *w) // NOTE: the rest of this function (minus the network condition) is copied to game_command_callback_ride_construct_placed_front/back // Please update both ends if there are any changes here if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) { - RCT2_GLOBAL(0x00F441D2, uint8) = _currentRideIndex; trackDirection = _currentTrackPieceDirection ^ 2; x = _currentTrackBeginX; y = _currentTrackBeginY; @@ -1636,7 +1668,6 @@ static void window_ride_construction_construct(rct_window *w) _rideConstructionState = RIDE_CONSTRUCTION_STATE_0; } } else { - RCT2_GLOBAL(0x00F441D2, uint8) = _currentRideIndex; trackDirection = _currentTrackPieceDirection; x = _currentTrackBeginX; y = _currentTrackBeginY; @@ -1662,6 +1693,8 @@ static void window_ride_construction_construct(rct_window *w) } } + window_ride_construction_do_station_check(); + // returning early here makes it so that the construction window doesn't blink if (network_get_mode() == NETWORK_MODE_CLIENT) return; @@ -1671,7 +1704,7 @@ static void window_ride_construction_construct(rct_window *w) /** * - * rct2: 0x006C9BA5 + * rct2: 0x006C9BA5 */ static void window_ride_construction_mouseup_demolish(rct_window* w) { @@ -1758,6 +1791,8 @@ static void window_ride_construction_mouseup_demolish(rct_window* w) return; } + _stationConstructed = get_ride(w->number)->num_stations != 0; + if (network_get_mode() == NETWORK_MODE_CLIENT) { gRideRemoveTrackPieceCallbackX = x; gRideRemoveTrackPieceCallbackY = y; @@ -1788,7 +1823,7 @@ void window_ride_construction_mouseup_demolish_next_piece(int x, int y, int z, i b4 = _currentTrackLiftHill; ride_construction_set_default_next_piece(); sub_6C84CE(); - if (!sub_6CAF80(_currentRideIndex, NULL)) { + if (!ride_try_get_origin_element(_currentRideIndex, NULL)) { sub_6CC3FB(_currentRideIndex); _currentTrackPieceDirection = direction; if (!(slope & 0x100)) { @@ -1838,7 +1873,7 @@ void window_ride_construction_mouseup_demolish_next_piece(int x, int y, int z, i /** * - * rct2: 0x006C78AA + * rct2: 0x006C78AA */ static void window_ride_construction_rotate(rct_window *w) { @@ -1850,19 +1885,19 @@ static void window_ride_construction_rotate(rct_window *w) /** * - * rct2: 0x006C7802 + * rct2: 0x006C7802 */ static void window_ride_construction_entrance_click(rct_window *w) { if (tool_set(w, WIDX_ENTRANCE, 12)) { - if (!sub_6CAF80(_currentRideIndex, NULL)) { + if (!ride_try_get_origin_element(_currentRideIndex, NULL)) { sub_6CC3FB(_currentRideIndex); } } else { RCT2_GLOBAL(0x00F44191, uint8) = 0; RCT2_GLOBAL(0x00F44192, uint8) = w->number & 0xFF; RCT2_GLOBAL(0x00F44193, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint8) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; sub_6C9627(); if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) { RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState; @@ -1874,19 +1909,19 @@ static void window_ride_construction_entrance_click(rct_window *w) /** * - * rct2: 0x006C7866 + * rct2: 0x006C7866 */ static void window_ride_construction_exit_click(rct_window *w) { if (tool_set(w, WIDX_EXIT, 12)) { - if (!sub_6CAF80(_currentRideIndex, NULL)) { + if (!ride_try_get_origin_element(_currentRideIndex, NULL)) { sub_6CC3FB(_currentRideIndex); } } else { RCT2_GLOBAL(0x00F44191, uint8) = 1; RCT2_GLOBAL(0x00F44192, uint8) = w->number & 0xFF; RCT2_GLOBAL(0x00F44193, uint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_INPUT_FLAGS, uint8) |= INPUT_FLAG_6; + gInputFlags |= INPUT_FLAG_6; sub_6C9627(); if (_rideConstructionState != RIDE_CONSTRUCTION_STATE_ENTRANCE_EXIT) { RCT2_GLOBAL(0x00F440CC, uint8) = _rideConstructionState; @@ -1898,10 +1933,19 @@ static void window_ride_construction_exit_click(rct_window *w) /** * - * rct2: 0x006C8374 + * rct2: 0x006C8374 */ static void window_ride_construction_update(rct_window *w) { + rct_ride *ride = get_ride(_currentRideIndex); + + // Close construction window if ride is not closed, + // editing ride while open will cause many issues until properly handled + if (ride->status != RIDE_STATUS_CLOSED) { + window_close(w); + return; + } + switch (_currentTrackCurve) { case 429: case 376: @@ -1930,7 +1974,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(); @@ -1943,7 +1987,7 @@ static void window_ride_construction_update(rct_window *w) /** * - * rct2: 0x006CC538 + * rct2: 0x006CC538 */ static bool ride_get_place_position_from_screen_position(int screenX, int screenY, int *outX, int *outY) { @@ -1953,7 +1997,7 @@ static bool ride_get_place_position_from_screen_position(int screenX, int screen rct_viewport *viewport; if (!_trackPlaceCtrlState) { - if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 2) { + if (gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_COPY_Z) { get_map_coordinates_from_pos(screenX, screenY, 0xFCCA, &mapX, &mapY, &interactionType, &mapElement, &viewport); if (interactionType != 0) { _trackPlaceCtrlZ = mapElement->base_height * 8; @@ -1961,20 +2005,20 @@ static bool ride_get_place_position_from_screen_position(int screenX, int screen } } } else { - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 2)) { + if (!(gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_COPY_Z)) { _trackPlaceCtrlState = false; } } if (!_trackPlaceShiftState) { - if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 1) { + if (gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_SHIFT_Z) { _trackPlaceShiftState = true; _trackPlaceShiftStartScreenX = screenX; _trackPlaceShiftStartScreenY = screenY; _trackPlaceShiftZ = 0; } } else { - if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & 1) { + if (gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_SHIFT_Z) { _trackPlaceShiftZ = floor2(_trackPlaceShiftStartScreenY - screenY + 4, 8); screenX = _trackPlaceShiftStartScreenX; screenY = _trackPlaceShiftStartScreenY; @@ -2015,7 +2059,7 @@ static bool ride_get_place_position_from_screen_position(int screenX, int screen /** * - * rct2: 0x006C8229 + * rct2: 0x006C8229 */ static void window_ride_construction_toolupdate(rct_window* w, int widgetIndex, int x, int y) { @@ -2049,14 +2093,14 @@ static void window_ride_construction_tooldown(rct_window* w, int widgetIndex, in /** * - * rct2: 0x006C6AD5 + * rct2: 0x006C6AD5 */ static void window_ride_construction_invalidate(rct_window *w) { rct_ride *ride; rct_string_id stringId; - ride = GET_RIDE(_currentRideIndex); + ride = get_ride(_currentRideIndex); stringId = STR_RIDE_CONSTRUCTION_SPECIAL; if (_currentTrackCurve >= 256) { @@ -2067,26 +2111,26 @@ static void window_ride_construction_invalidate(rct_window *w) RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = stringId; if (RCT2_GLOBAL(0x00F440D3, uint8) == 1) - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ((RCT2_GLOBAL(0x00F440CD, uint8) * 9) >> 2) & 0xFFFF; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ((RCT2_GLOBAL(0x00F440CD, uint8) * 9) >> 2) & 0xFFFF; window_ride_construction_widgets[WIDX_SEAT_ROTATION_ANGLE_SPINNER].image = STR_RIDE_CONSTRUCTION_SEAT_ROTATION_ANGLE_NEG_180 + RCT2_GLOBAL(0x00F440CF, uint8); if (RCT2_GLOBAL(0x00F440D3, uint8) == 2) - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ((RCT2_GLOBAL(0x00F440CE, uint8) * 9) >> 2) & 0xFFFF; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ((RCT2_GLOBAL(0x00F440CE, uint8) * 9) >> 2) & 0xFFFF; // Set window title arguments - RCT2_GLOBAL(0x013CE952 + 4, uint16) = ride->name; - RCT2_GLOBAL(0x013CE952 + 6, uint32) = ride->name_arguments; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = ride->name; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint32) = ride->name_arguments; } /** * - * rct2: 0x006C6B86 + * rct2: 0x006C6B86 */ static void window_ride_construction_paint(rct_window *w, rct_drawpixelinfo *dpi) { - rct_drawpixelinfo *clipdpi; + rct_drawpixelinfo clipdpi; rct_widget *widget; int x, y, width, height; @@ -2105,10 +2149,8 @@ static void window_ride_construction_paint(rct_window *w, rct_drawpixelinfo *dpi y = w->y + widget->top + 1; width = widget->right - widget->left - 1; height = widget->bottom - widget->top - 1; - clipdpi = clip_drawpixelinfo(dpi, x, width, y, height); - if (clipdpi != NULL) { - window_ride_construction_draw_track_piece(w, clipdpi, rideIndex, trackType, trackDirection, edxRS16, width, height); - rct2_free(clipdpi); + if (clip_drawpixelinfo(&clipdpi, dpi, x, y, width, height)) { + window_ride_construction_draw_track_piece(w, &clipdpi, rideIndex, trackType, trackDirection, edxRS16, width, height); } // Draw cost @@ -2134,7 +2176,7 @@ static void window_ride_construction_draw_track_piece( const rct_preview_track *trackBlock; rct_ride *ride; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); trackBlock = get_track_def_from_ride(ride, trackType); while ((trackBlock + 1)->index != 0xFF) @@ -2212,7 +2254,7 @@ static rct_map_element *_backupMapElementArrays[5]; /** * - * rct2: 0x006CBCE2 + * rct2: 0x006CBCE2 * bh: trackDirection * dl: rideIndex * dh: trackType @@ -2234,7 +2276,7 @@ static void sub_6CBCE2( RCT2_GLOBAL(0x00EE7880, uint32) = 0x00F1A4CC; painter_setup(); - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); preserve_map_size_vars = RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, uint64); @@ -2336,7 +2378,7 @@ static void sub_6CBCE2( /** * - * rct2: 0x006C84CE + * rct2: 0x006C84CE */ void sub_6C84CE() { @@ -2367,39 +2409,248 @@ void sub_6C84CE() window_ride_construction_update_widgets(w); } -/** - * - * rct2: 0x006CA2DF - * bh: trackRotation (out) - * dl: ??? (out) - * dh: trackType (out) - * edx >> 16: ??? (out) - */ -static bool sub_6CA2DF(int *trackType, int *trackDirection, int *rideIndex, int *edxRS16, int *x, int *y, int *z, int *properties) -{ - int eax, ebx, ecx, edx, esi, edi, ebp; - if (RCT2_CALLFUNC_X(0x006CA2DF, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp) & 0x100) - return true; +static bool sub_6CA2DF_get_track_element(uint8 *trackElement) { + window_ride_construction_update_enabled_track_pieces(); + + uint8 startSlope = _previousTrackSlopeEnd; + uint8 endSlope = _currentTrackSlopeEnd; + uint8 startBank = _previousTrackBankEnd; + uint8 endBank = _currentTrackBankEnd; + + if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) { + startSlope = _currentTrackSlopeEnd; + endSlope = _previousTrackSlopeEnd; + startBank = _currentTrackBankEnd; + endBank = _previousTrackBankEnd; + } + + uint16 curve = _currentTrackCurve; + if (curve == 0xFFFF) { + return false; + } + + bool startsDiagonal = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) & (1 << 2); + if (curve == TRACK_CURVE_LEFT_LARGE || curve == TRACK_CURVE_RIGHT_LARGE) { + if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) { + startsDiagonal = !startsDiagonal; + } + } + + if (curve <= 8) { + for (int i = 0; i < 140; i++) { + track_descriptor trackDescriptor = gTrackDescriptors[i]; + if (trackDescriptor.track_curve != curve) continue; + if (trackDescriptor.starts_diagonal != startsDiagonal) continue; + if (trackDescriptor.slope_start != startSlope) continue; + if (trackDescriptor.slope_end != endSlope) continue; + if (trackDescriptor.bank_start != startBank) continue; + if (trackDescriptor.bank_end != endBank) continue; + + *trackElement = trackDescriptor.track_element; + return true; + } + + return false; + } + + *trackElement = curve & 0xFF; + switch (*trackElement) { + case TRACK_ELEM_END_STATION: + case TRACK_ELEM_S_BEND_LEFT: + case TRACK_ELEM_S_BEND_RIGHT: + if (startSlope != TRACK_SLOPE_NONE || endSlope != TRACK_SLOPE_NONE) { + return false; + } + + if (startBank != TRACK_BANK_NONE || endBank != TRACK_BANK_NONE) { + return false; + } + + return true; + + case TRACK_ELEM_LEFT_VERTICAL_LOOP: + case TRACK_ELEM_RIGHT_VERTICAL_LOOP: + if (startBank != TRACK_BANK_NONE || endBank != TRACK_BANK_NONE) { + return false; + } + + if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) { + if (endSlope != TRACK_SLOPE_DOWN_25) { + return false; + } + } else { + if (startSlope != TRACK_SLOPE_UP_25) { + return false; + } + } + + return true; + + default: + return true; + } +} + +/** + * rct2: 0x006CA2DF + * + * @param[out] _trackType (dh) + * @param[out] _trackDirection (bh) + * @param[out] _rideIndex (dl) + * @param[out] _edxRS16 (edxrs16) + * @param[out] _x (ax) + * @param[out] _y (cx) + * @param[out] _z (di) + * @param[out] _properties (edirs16) + * @return (CF) + */ +static bool sub_6CA2DF(int *_trackType, int *_trackDirection, int *_rideIndex, int *_edxRS16, int *_x, int *_y, int *_z, int *_properties) { + uint8 trackType, trackDirection, rideIndex; + uint16 z, x, y, edxRS16, properties; + + if (!sub_6CA2DF_get_track_element(&trackType)) { + return true; + } + + edxRS16 = 0; + rideIndex = _currentRideIndex; + if (_currentTrackLiftHill & 1) { + edxRS16 |= 0x1; + } + + if (_currentTrackCovered & (1 << 1)) { + edxRS16 |= 0x2; + } + + rct_ride *ride = get_ride(rideIndex); + + if (_enabledRidePiecesB & (1 << 8)) { + switch (trackType) { + case TRACK_ELEM_FLAT_TO_60_DEG_UP: + trackType = TRACK_ELEM_FLAT_TO_60_DEG_UP_LONG_BASE; + break; + + case TRACK_ELEM_60_DEG_UP_TO_FLAT: + trackType = TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE; + break; + + case TRACK_ELEM_FLAT_TO_60_DEG_DOWN: + trackType = TRACK_ELEM_60_DEG_UP_TO_FLAT_LONG_BASE_122; + break; + + case TRACK_ELEM_60_DEG_DOWN_TO_FLAT: + trackType = TRACK_ELEM_FLAT_TO_60_DEG_DOWN_LONG_BASE; + break; + + case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_UP: + case TRACK_ELEM_DIAG_60_DEG_UP_TO_FLAT: + case TRACK_ELEM_DIAG_FLAT_TO_60_DEG_DOWN: + case TRACK_ELEM_DIAG_60_DEG_DOWN_TO_FLAT: + return true; + } + } + + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_TRACK_ELEMENTS_HAVE_TWO_VARIETIES) && _currentTrackCovered & 1) { + if (ride->type != RIDE_TYPE_WATER_COASTER || trackType == TRACK_ELEM_FLAT || trackType == TRACK_ELEM_LEFT_QUARTER_TURN_5_TILES || trackType == TRACK_ELEM_RIGHT_QUARTER_TURN_5_TILES) { + trackType = RCT2_GLOBAL(0x00993D1C + trackType, uint8); + edxRS16 &= 0xFFFE; // unsets 0x1 + } + } + + const rct_track_coordinates *trackCoordinates = get_track_coord_from_ride(ride, trackType); + + x = _currentTrackBeginX; + y = _currentTrackBeginY; + z = _currentTrackBeginZ; + if (_rideConstructionState == 2) { + z -= trackCoordinates->z_end; + trackDirection = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) ^ 0x02; + trackDirection -= trackCoordinates->rotation_end; + trackDirection += trackCoordinates->rotation_begin; + trackDirection &= 0x03; + + if (trackCoordinates->rotation_begin & (1 << 2)) { + trackDirection |= 0x04; + } + + switch (trackDirection & 0x03) { + case 0: + x -= trackCoordinates->x; + y -= trackCoordinates->y; + break; + + case 1: + x -= trackCoordinates->y; + y += trackCoordinates->x; + break; + + case 2: + x += trackCoordinates->x; + y += trackCoordinates->y; + break; + + case 3: + x += trackCoordinates->y; + y -= trackCoordinates->x; + break; + } + } else { + z -= trackCoordinates->z_begin; + trackDirection = RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8); + } + + + bool do_loc_6CAF26 = false; + if (!(_enabledRidePiecesA & (1 << 5))) { + if (RCT2_ADDRESS(0x0099423C, uint16)[trackType] & 0x2000) { + do_loc_6CAF26 = true; + } + } + + if (!(RCT2_ADDRESS(0x0099423C, uint16)[trackType] & 0x1000)) { + do_loc_6CAF26 = true; + } + + if (do_loc_6CAF26) { + edxRS16 &= 0xFFFE; // unsets 0x1 + _currentTrackLiftHill &= 0xFE; + + if (trackType == TRACK_ELEM_LEFT_CURVED_LIFT_HILL || trackType == TRACK_ELEM_RIGHT_CURVED_LIFT_HILL) { + edxRS16 |= 0x1; + } + } + + + if (trackType == TRACK_ELEM_BRAKES) { + properties = RCT2_GLOBAL(0x00F440CD, uint8); + } else { + properties = _currentSeatRotationAngle << 12; + } + + + if (_trackType != NULL) *_trackType = trackType; + if (_trackDirection != NULL) *_trackDirection = trackDirection; + if (_rideIndex != NULL) *_rideIndex = rideIndex; + if (_edxRS16 != NULL) *_edxRS16 = edxRS16; + if (_x != NULL) *_x = x; + if (_y != NULL) *_y = y; + if (_z != NULL) *_z = z; + if (_properties != NULL) *_properties = properties; - if (trackType != NULL) *trackType = (edx >> 8) & 0xFF; - if (trackDirection != NULL) *trackDirection = (ebx >> 8) & 0xFF; - if (rideIndex != NULL) *rideIndex = edx & 0xFF; - if (edxRS16 != NULL) *edxRS16 = (edx >> 16) & 0xFFFF; - if (x != NULL) *x = eax & 0xFFFF; - if (y != NULL) *y = ecx & 0xFFFF; - if (z != NULL) *z = edi & 0xFFFF; - if (properties != NULL) *properties = (edi >> 16) & 0xFFFF; return false; } /** * - * rct2: 0x006C6A77 + * rct2: 0x006C6A77 */ static void window_ride_construction_update_enabled_track_pieces() { - rct_ride *ride = GET_RIDE(_currentRideIndex); - rct_ride_type *rideEntry = ride_get_entry(ride); + rct_ride *ride = get_ride(_currentRideIndex); + rct_ride_entry *rideEntry = get_ride_entry_by_ride(ride); + + if (rideEntry == NULL) + return; int rideType = _currentTrackCovered & 2 ? RCT2_ADDRESS(0x0097D4F5, uint8)[ride->type * 8] : ride->type; _enabledRidePiecesA = rideEntry->enabledTrackPiecesA & RCT2_ADDRESS(0x01357444, uint32)[rideType]; @@ -2408,7 +2659,7 @@ static void window_ride_construction_update_enabled_track_pieces() /** * - * rct2: 0x006CA162 + * rct2: 0x006CA162 */ money32 sub_6CA162(int rideIndex, int trackType, int trackDirection, int edxRS16, int x, int y, int z) { @@ -2416,7 +2667,7 @@ money32 sub_6CA162(int rideIndex, int trackType, int trackDirection, int edxRS16 money32 result; sub_6C96C0(); - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_MAZE) { result = game_do_command(x, 105 | (4 << 8), y, rideIndex | (trackType << 8) | (edxRS16 << 16), GAME_COMMAND_SET_MAZE_TRACK, z, 0); if (result == MONEY32_UNDEFINED) @@ -2456,7 +2707,7 @@ money32 sub_6CA162(int rideIndex, int trackType, int trackDirection, int edxRS16 /** * - * rct2: 0x006C94D8 + * rct2: 0x006C94D8 */ void sub_6C94D8() { @@ -2555,7 +2806,7 @@ void sub_6C94D8() /** * - * rct2: 0x006C84E2 + * rct2: 0x006C84E2 */ static void window_ride_construction_update_map_selection() { @@ -2588,14 +2839,14 @@ static void window_ride_construction_update_map_selection() break; } - ride = GET_RIDE(_currentRideIndex); + ride = get_ride(_currentRideIndex); window_ride_construction_select_map_tiles(ride, trackType, trackDirection, x, y); map_invalidate_map_selection_tiles(); } /** * - * rct2: 0x006C8648 + * rct2: 0x006C8648 */ static void window_ride_construction_update_possible_ride_configurations() { @@ -2603,7 +2854,7 @@ static void window_ride_construction_update_possible_ride_configurations() int trackType; int edx, edi; - ride = GET_RIDE(_currentRideIndex); + ride = get_ride(_currentRideIndex); RCT2_GLOBAL(0x00F440D3, uint8) = 0; if (_currentTrackCovered & 2) @@ -2686,16 +2937,16 @@ static void window_ride_construction_update_possible_ride_configurations() /** * - * rct2: 0x006C87F5 + * rct2: 0x006C87F5 */ static void window_ride_construction_update_widgets(rct_window *w) { uint8 rideIndex = _currentRideIndex; - rct_ride *ride = GET_RIDE(rideIndex); + rct_ride *ride = get_ride(rideIndex); int rideType = ride_get_alternative_type(ride); w->hold_down_widgets = 0; - if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_IS_SHOP)) { + if (ride_type_has_flag(rideType, RIDE_TYPE_FLAG_IS_SHOP) || !_stationConstructed) { window_ride_construction_widgets[WIDX_ENTRANCE_EXIT_GROUPBOX].type = WWT_EMPTY; window_ride_construction_widgets[WIDX_ENTRANCE].type = WWT_EMPTY; window_ride_construction_widgets[WIDX_EXIT].type = WWT_EMPTY; @@ -2869,6 +3120,10 @@ static void window_ride_construction_update_widgets(rct_window *w) window_ride_construction_widgets[WIDX_SLOPE_DOWN_STEEP].right = window_ride_construction_widgets[WIDX_SLOPE_DOWN].right; window_ride_construction_widgets[WIDX_SLOPE_DOWN].right = tmp; + tmp = window_ride_construction_widgets[WIDX_SLOPE_UP_STEEP].left; + window_ride_construction_widgets[WIDX_SLOPE_UP_STEEP].left = window_ride_construction_widgets[WIDX_SLOPE_UP].left; + window_ride_construction_widgets[WIDX_SLOPE_UP].left = tmp; + tmp = window_ride_construction_widgets[WIDX_SLOPE_UP_STEEP].right; window_ride_construction_widgets[WIDX_SLOPE_UP_STEEP].right = window_ride_construction_widgets[WIDX_SLOPE_UP].right; window_ride_construction_widgets[WIDX_SLOPE_UP].right = tmp; @@ -3180,21 +3435,22 @@ static void window_ride_construction_select_map_tiles(rct_ride *ride, int trackT /** * - * rct2: 0x006C776D + * rct2: 0x006C776D */ static void window_ride_construction_show_special_track_dropdown(rct_window *w, rct_widget *widget) { + int defaultIndex = -1; for (int i = 0; i < _numCurrentPossibleRideConfigurations; i++) { uint8 trackPiece = _currentPossibleRideConfigurations[i]; rct_string_id trackPieceStringId = RideConfigurationStringIds[trackPiece]; if (trackPieceStringId == STR_RAPIDS) { - rct_ride *ride = GET_RIDE(_currentRideIndex); + rct_ride *ride = get_ride(_currentRideIndex); if (ride->type == RIDE_TYPE_CAR_RIDE) trackPieceStringId = STR_LOG_BUMPS; } gDropdownItemsFormat[i] = trackPieceStringId; if ((trackPiece | 0x100) == _currentTrackCurve) { - gDropdownHighlightedIndex = i; + defaultIndex = i; } } @@ -3209,11 +3465,12 @@ static void window_ride_construction_show_special_track_dropdown(rct_window *w, ); gDropdownItemsDisabled = (uint64)RCT2_GLOBAL(0x00F4409C, uint32); + gDropdownDefaultIndex = defaultIndex; } /** * - * rct2: 0x006C7630 + * rct2: 0x006C7630 */ static void ride_selected_track_set_seat_rotation(int seatRotation) { @@ -3227,7 +3484,7 @@ static void ride_selected_track_set_seat_rotation(int seatRotation) /** * - * rct2: 0x006C7502 + * rct2: 0x006C7502 */ static void loc_6C7502(int al) { @@ -3243,7 +3500,7 @@ static void loc_6C7502(int al) /** * - * rct2: 0x006C76E9 + * rct2: 0x006C76E9 */ static void ride_construction_set_brakes_speed(int brakesSpeed) { @@ -3269,7 +3526,7 @@ static void ride_construction_set_brakes_speed(int brakesSpeed) /** * - * rct2: 0x006CC6A8 + * rct2: 0x006CC6A8 */ void ride_construction_toolupdate_construct(int screenX, int screenY) { @@ -3308,7 +3565,7 @@ void ride_construction_toolupdate_construct(int screenX, int screenY) return; } _currentTrackPieceType = trackType; - ride = GET_RIDE(_currentRideIndex); + ride = get_ride(_currentRideIndex); // Re-using this other code, very slight difference from original // - Original code checks for MSB mask instead of 255 on trackPart->var_00 @@ -3408,7 +3665,7 @@ void ride_construction_toolupdate_construct(int screenX, int screenY) /** * - * rct2: 0x006CD354 + * rct2: 0x006CD354 */ void ride_construction_toolupdate_entrance_exit(int screenX, int screenY) { @@ -3453,7 +3710,7 @@ void ride_construction_toolupdate_entrance_exit(int screenX, int screenY) /** * - * rct2: 0x006CCA73 + * rct2: 0x006CCA73 */ void ride_construction_tooldown_construct(int screenX, int screenY) { @@ -3496,7 +3753,7 @@ void ride_construction_tooldown_construct(int screenX, int screenY) tool_cancel(); - rct_ride *ride = GET_RIDE(_currentRideIndex); + rct_ride *ride = get_ride(_currentRideIndex); if (_trackPlaceZ == 0) { const rct_preview_track *trackBlock = get_track_def_from_ride(ride, _currentTrackPieceType); int bx = 0; @@ -3558,7 +3815,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; } @@ -3637,7 +3894,10 @@ void ride_construction_tooldown_construct(int screenX, int screenY) w = window_find_by_class(WC_RIDE_CONSTRUCTION); if (w != NULL) { if (ride_are_all_possible_entrances_and_exits_built(ride)) { - window_close(w); + // Clients don't necessarily have any ride built at this point + if (network_get_mode() != NETWORK_MODE_CLIENT) { + window_close(w); + } } else { window_event_mouse_up_call(w, WIDX_ENTRANCE); } @@ -3650,7 +3910,7 @@ void ride_construction_tooldown_construct(int screenX, int screenY) /** * - * rct2: 0x006CCA73 + * rct2: 0x006CCA73 */ static void ride_construction_tooldown_entrance_exit(int screenX, int screenY) { @@ -3667,6 +3927,7 @@ static void ride_construction_tooldown_entrance_exit(int screenX, int screenY) STR_CANT_BUILD_MOVE_ENTRANCE_FOR_THIS_RIDE_ATTRACTION : STR_CANT_BUILD_MOVE_EXIT_FOR_THIS_RIDE_ATTRACTION; + game_command_callback = game_command_callback_place_ride_entrance_or_exit; money32 cost = game_do_command( RCT2_GLOBAL(0x00F44188, uint16), (GAME_COMMAND_FLAG_APPLY) | ((RCT2_GLOBAL(0x00F44194, uint8) ^ 2) << 8), @@ -3676,10 +3937,10 @@ static void ride_construction_tooldown_entrance_exit(int screenX, int screenY) RCT2_GLOBAL(0x00F44193, uint8), 0 ); - if (cost == MONEY32_UNDEFINED) { - return; - } +} +void game_command_callback_place_ride_entrance_or_exit(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp) +{ audio_play_sound_at_location( SOUND_PLACE_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16), @@ -3687,10 +3948,10 @@ static void ride_construction_tooldown_entrance_exit(int screenX, int screenY) RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) ); - rct_ride *ride = GET_RIDE(RCT2_GLOBAL(0x00F44192, uint8)); + rct_ride *ride = get_ride(RCT2_GLOBAL(0x00F44192, uint8)); if (ride_are_all_possible_entrances_and_exits_built(ride)) { tool_cancel(); - if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_15)) { + if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_NO_TRACK)) { window_close_by_class(WC_RIDE_CONSTRUCTION); } } else { @@ -3700,3 +3961,32 @@ static void ride_construction_tooldown_entrance_exit(int screenX, int screenY) WIDX_ENTRANCE : WIDX_EXIT; } } + +void window_ride_construction_do_station_check() +{ + rct_ride *ride = get_ride(_currentRideIndex); + if (ride != NULL) { + _stationConstructed = ride->num_stations != 0; + } +} + +void window_ride_construction_do_entrance_exit_check() +{ + rct_window *w = window_find_by_class(WC_RIDE_CONSTRUCTION); + rct_ride *ride = get_ride(_currentRideIndex); + + if (w == NULL || ride == NULL) { + return; + } + + if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_0) { + w = window_find_by_class(WC_RIDE_CONSTRUCTION); + if (w != NULL) { + if (!ride_are_all_possible_entrances_and_exits_built(ride)) { + window_event_mouse_up_call(w, WIDX_ENTRANCE); + } else { + _deferClose = true; + } + } + } +} diff --git a/src/windows/ride_list.c b/src/windows/ride_list.c index b557ca0f1c..27a32e8e98 100644 --- a/src/windows/ride_list.c +++ b/src/windows/ride_list.c @@ -29,6 +29,8 @@ #include "../interface/window.h" #include "dropdown.h" #include "../interface/themes.h" +#include "../interface/themes.h" +#include "../localisation/date.h" enum { PAGE_RIDES, @@ -59,7 +61,7 @@ static rct_widget window_ride_list_widgets[] = { { WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button { WWT_RESIZE, 1, 0, 339, 43, 239, 0x0FFFFFFFF, 65535 }, // tab page background { WWT_FLATBTN, 1, 315, 338, 60, 83, SPR_TOGGLE_OPEN_CLOSE, STR_OPEN_OR_CLOSE_ALL_RIDES }, // open / close all toggle - { WWT_DROPDOWN, 1, 164, 273, 46, 57, 0x0FFFFFFFF, 65535 }, // current information type + { WWT_DROPDOWN, 1, 150, 273, 46, 57, 0x0FFFFFFFF, 65535 }, // current information type { WWT_DROPDOWN_BUTTON, 1, 262, 272, 47, 56, 876, STR_RIDE_LIST_INFORMATION_TYPE_TIP }, // information type dropdown button { WWT_DROPDOWN_BUTTON, 1, 280, 333, 46, 57, STR_SORT, STR_RIDE_LIST_SORT_TIP }, // sort button { WWT_TAB, 1, 3, 33, 17, 43, 0x2000144E, STR_LIST_RIDES_TIP }, // tab 1 @@ -120,11 +122,54 @@ enum { INFORMATION_TYPE_POPULARITY, INFORMATION_TYPE_SATISFACTION, INFORMATION_TYPE_PROFIT, + INFORMATION_TYPE_TOTAL_CUSTOMERS, + INFORMATION_TYPE_TOTAL_PROFIT, + INFORMATION_TYPE_CUSTOMERS, + INFORMATION_TYPE_AGE, + INFORMATION_TYPE_INCOME, + INFORMATION_TYPE_RUNNING_COST, INFORMATION_TYPE_QUEUE_LENGTH, INFORMATION_TYPE_QUEUE_TIME, INFORMATION_TYPE_RELIABILITY, INFORMATION_TYPE_DOWN_TIME, - INFORMATION_TYPE_GUESTS_FAVOURITE + INFORMATION_TYPE_GUESTS_FAVOURITE, + DROPDOWN_LIST_COUNT +}; + +uint32 ride_info_type_string_mapping[DROPDOWN_LIST_COUNT] = { + STR_STATUS, + STR_POPULARITY, + STR_SATISFACTION, + STR_PROFIT, + STR_RIDE_LIST_TOTAL_CUSTOMERS, + STR_RIDE_LIST_TOTAL_PROFIT, + STR_RIDE_LIST_CUSTOMERS_PER_HOUR, + STR_RIDE_LIST_AGE, + STR_RIDE_LIST_INCOME, + STR_RIDE_LIST_RUNNING_COST, + STR_QUEUE_LENGTH, + STR_QUEUE_TIME, + STR_RELIABILITY, + STR_DOWN_TIME, + STR_GUESTS_FAVOURITE +}; + +bool ride_info_type_money_mapping[DROPDOWN_LIST_COUNT] = { + false, + false, + false, + true, + false, + true, + false, + false, + true, + true, + false, + false, + false, + false, + false }; static int _window_ride_list_information_type; @@ -166,7 +211,7 @@ void window_ride_list_open() window->min_width = 340; window->min_height = 240; window->max_width = 400; - window->max_height = 450; + window->max_height = 700; } _window_ride_list_information_type = INFORMATION_TYPE_STATUS; window->list_information_type = 0; @@ -195,7 +240,7 @@ static void window_ride_list_mouseup(rct_window *w, int widgetIndex) w->no_list_items = 0; w->frame_no = 0; w->selected_list_item = -1; - if (w->page != PAGE_RIDES && _window_ride_list_information_type > INFORMATION_TYPE_PROFIT) { + if (w->page != PAGE_RIDES && _window_ride_list_information_type > INFORMATION_TYPE_RUNNING_COST) { _window_ride_list_information_type = INFORMATION_TYPE_STATUS; } window_invalidate(w); @@ -236,8 +281,6 @@ static void window_ride_list_resize(rct_window *w) */ static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { - int currentItem, lastItem, count; - if (widgetIndex == WIDX_OPEN_CLOSE_ALL) { gDropdownItemsFormat[0] = STR_CLOSE_ALL; gDropdownItemsFormat[1] = STR_OPEN_ALL; @@ -245,17 +288,28 @@ static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget } else if (widgetIndex == WIDX_INFORMATION_TYPE_DROPDOWN) { widget--; + int lastType; if (w->page == PAGE_RIDES) - lastItem = STR_GUESTS_FAVOURITE; + lastType = INFORMATION_TYPE_GUESTS_FAVOURITE; else - lastItem = STR_PROFIT; + lastType = INFORMATION_TYPE_RUNNING_COST; - for (count = 0, currentItem = STR_STATUS; currentItem <= lastItem; currentItem++) { - if ((RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) && (currentItem == STR_PROFIT)) - continue; - gDropdownItemsFormat[count] = 1142; - gDropdownItemsArgs[count] = currentItem; - count++; + int numItems = 0; + int selectedIndex = -1; + for (int type = INFORMATION_TYPE_STATUS; type <= lastType; type++) { + if ((RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { + if (ride_info_type_money_mapping[type]) { + continue; + } + } + + if (type == _window_ride_list_information_type) { + selectedIndex = numItems; + } + + gDropdownItemsFormat[numItems] = STR_DROPDOWN_MENU_LABEL; + gDropdownItemsArgs[numItems] = ride_info_type_string_mapping[type]; + numItems++; } window_dropdown_show_text_custom_width( @@ -264,10 +318,12 @@ static void window_ride_list_mousedown(int widgetIndex, rct_window*w, rct_widget widget->bottom - widget->top, w->colours[1], DROPDOWN_FLAG_STAY_OPEN, - count, + numItems, widget->right - widget->left - 3 ); - dropdown_set_checked(_window_ride_list_information_type, true); + if (selectedIndex != -1) { + dropdown_set_checked(selectedIndex, true); + } } } @@ -286,7 +342,15 @@ 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; + int informationType = INFORMATION_TYPE_STATUS; + uint32 arg = (uint32)gDropdownItemsArgs[dropdownIndex]; + for (int i = 0; i < countof(ride_info_type_string_mapping); i++) { + if (arg == ride_info_type_string_mapping[i]) { + informationType = i; + } + } + + _window_ride_list_information_type = informationType; window_invalidate(w); } } @@ -378,7 +442,7 @@ static void window_ride_list_invalidate(rct_window *w) colour_scheme_update(w); - window_ride_list_widgets[WIDX_CURRENT_INFORMATION_TYPE].image = STR_STATUS + _window_ride_list_information_type; + window_ride_list_widgets[WIDX_CURRENT_INFORMATION_TYPE].image = ride_info_type_string_mapping[_window_ride_list_information_type]; // Set correct active tab for (i = 0; i < 3; i++) @@ -403,7 +467,7 @@ static void window_ride_list_invalidate(rct_window *w) w->widgets[WIDX_OPEN_LIGHT].right = w->width - 7; w->widgets[WIDX_OPEN_LIGHT].left = w->width - 20; - if (theme_get_preset()->features.rct1_ride_lights) { + if (theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE) { w->widgets[WIDX_OPEN_CLOSE_ALL].type = WWT_EMPTY; w->widgets[WIDX_CLOSE_LIGHT].type = WWT_IMGBTN; w->widgets[WIDX_OPEN_LIGHT].type = WWT_IMGBTN; @@ -464,7 +528,7 @@ static void window_ride_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, } // Get ride - ride = &g_ride_list[w->list_item_positions[i]]; + ride = get_ride(w->list_item_positions[i]); // Ride name gfx_draw_string_left_clipped(dpi, format, &ride->name, 0, 0, y - 1, 159); @@ -474,59 +538,97 @@ static void window_ride_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, switch (_window_ride_list_information_type) { case INFORMATION_TYPE_STATUS: ride_get_status(w->list_item_positions[i], &formatSecondary, &argument); - RCT2_GLOBAL(0x013CE952 + 2, sint32) = argument; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, sint32) = argument; break; case INFORMATION_TYPE_POPULARITY: formatSecondary = STR_POPULARITY_UNKNOWN_LABEL; if (ride->popularity != 255) { formatSecondary = STR_POPULARITY_LABEL; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->popularity * 4; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride->popularity * 4; } break; case INFORMATION_TYPE_SATISFACTION: formatSecondary = STR_SATISFACTION_UNKNOWN_LABEL; if (ride->satisfaction != 255) { formatSecondary = STR_SATISFACTION_LABEL; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->satisfaction * 5; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride->satisfaction * 5; } break; case INFORMATION_TYPE_PROFIT: formatSecondary = 0; if (ride->profit != MONEY32_UNDEFINED) { formatSecondary = STR_PROFIT_LABEL; - RCT2_GLOBAL(0x013CE952 + 2, sint32) = ride->profit; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, sint32) = ride->profit; + } + break; + case INFORMATION_TYPE_TOTAL_CUSTOMERS: + formatSecondary = STR_RIDE_LIST_TOTAL_CUSTOMERS_LABEL; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->total_customers; + break; + case INFORMATION_TYPE_TOTAL_PROFIT: + formatSecondary = 0; + if (ride->total_profit != MONEY32_UNDEFINED) { + formatSecondary = STR_RIDE_LIST_TOTAL_PROFIT_LABEL; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, sint32) = ride->total_profit; + } + break; + case INFORMATION_TYPE_CUSTOMERS: + formatSecondary = STR_RIDE_LIST_CUSTOMERS_PER_HOUR_LABEL; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride_customers_per_hour(ride); + break; + case INFORMATION_TYPE_AGE:; + sint16 age = date_get_year(RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_MONTH_YEAR, uint16) - ride->build_date); + switch (age) { + case 0: formatSecondary = STR_RIDE_LIST_BUILT_THIS_YEAR_LABEL; break; + case 1: formatSecondary = STR_RIDE_LIST_BUILT_LAST_YEAR_LABEL; break; + default: formatSecondary = STR_RIDE_LIST_BUILT_X_YEARS_AGO_LABEL; break; + } + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, sint16) = age; + break; + case INFORMATION_TYPE_INCOME: + formatSecondary = 0; + if (ride->income_per_hour != MONEY32_UNDEFINED) { + formatSecondary = STR_RIDE_LIST_INCOME_LABEL; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, sint32) = ride->income_per_hour; + } + break; + case INFORMATION_TYPE_RUNNING_COST: + formatSecondary = STR_RIDE_LIST_RUNNING_COST_UNKNOWN; + if (ride->upkeep_cost != (money16)0xFFFF) { + formatSecondary = STR_RIDE_LIST_RUNNING_COST_LABEL; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, sint32) = ride->upkeep_cost * 16; } break; case INFORMATION_TYPE_QUEUE_LENGTH: - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride_get_total_queue_length(ride); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride_get_total_queue_length(ride); formatSecondary = STR_QUEUE_EMPTY; - if (RCT2_GLOBAL(0x013CE952 + 2, uint16) == 1) + if (RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) == 1) formatSecondary = STR_QUEUE_ONE_PERSON; - else if (RCT2_GLOBAL(0x013CE952 + 2, uint16) > 1) + else if (RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) > 1) formatSecondary = STR_QUEUE_PEOPLE; break; case INFORMATION_TYPE_QUEUE_TIME: - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride_get_max_queue_time(ride); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride_get_max_queue_time(ride); formatSecondary = STR_QUEUE_TIME_LABEL; - if (RCT2_GLOBAL(0x013CE952 + 2, uint16) > 1) + if (RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) > 1) formatSecondary = STR_QUEUE_TIME_PLURAL_LABEL; break; case INFORMATION_TYPE_RELIABILITY: // edx = RCT2_GLOBAL(0x009ACFA4 + (ride->var_001 * 4), uint32); - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->reliability >> 8; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride->reliability >> 8; formatSecondary = STR_RELIABILITY_LABEL; break; case INFORMATION_TYPE_DOWN_TIME: // edx = RCT2_GLOBAL(0x009ACFA4 + (ride->var_001 * 4), uint32); - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->downtime; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride->downtime; formatSecondary = STR_DOWN_TIME_LABEL; break; case INFORMATION_TYPE_GUESTS_FAVOURITE: formatSecondary = 0; if (RCT2_ADDRESS(0x0097C3AF, uint8)[ride->type] == PAGE_RIDES) { - RCT2_GLOBAL(0x013CE952 + 2, uint16) = ride->guests_favourite; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ride->guests_favourite; formatSecondary = ride->guests_favourite == 1 ? STR_GUESTS_FAVOURITE_LABEL : STR_GUESTS_FAVOURITE_PLURAL_LABEL; } break; @@ -537,7 +639,7 @@ static void window_ride_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, format = 1192; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = formatSecondary; - gfx_draw_string_left_clipped(dpi, format, (void*)0x013CE952, 0, 160, y - 1, 157); + gfx_draw_string_left_clipped(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 160, y - 1, 157); y += 10; } } @@ -613,7 +715,7 @@ static void window_ride_list_refresh_list(rct_window *w) bufferB = (char*)0x0141EF68; format_string_to_upper(bufferA, ride->name, &ride->name_arguments); while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); format_string_to_upper(bufferB, otherRide->name, &otherRide->name_arguments); if (strcmp(bufferA, bufferB) >= 0) break; @@ -623,7 +725,7 @@ static void window_ride_list_refresh_list(rct_window *w) break; case INFORMATION_TYPE_POPULARITY: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride->popularity * 4 <= otherRide->popularity * 4) break; @@ -632,7 +734,7 @@ static void window_ride_list_refresh_list(rct_window *w) break; case INFORMATION_TYPE_SATISFACTION: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride->satisfaction * 5 <= otherRide->satisfaction * 5) break; @@ -641,16 +743,70 @@ static void window_ride_list_refresh_list(rct_window *w) break; case INFORMATION_TYPE_PROFIT: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride->profit <= otherRide->profit) break; window_bubble_list_item(w, current_list_position); } break; + case INFORMATION_TYPE_TOTAL_CUSTOMERS: + while (--current_list_position >= 0) { + otherRide = get_ride(w->list_item_positions[current_list_position]); + if (ride->total_customers <= otherRide->total_customers) + break; + + window_bubble_list_item(w, current_list_position); + } + break; + case INFORMATION_TYPE_TOTAL_PROFIT: + while (--current_list_position >= 0) { + otherRide = get_ride(w->list_item_positions[current_list_position]); + if (ride->total_profit <= otherRide->total_profit) + break; + + window_bubble_list_item(w, current_list_position); + } + break; + case INFORMATION_TYPE_CUSTOMERS: + while (--current_list_position >= 0) { + otherRide = get_ride(w->list_item_positions[current_list_position]); + if (ride_customers_per_hour(ride) <= ride_customers_per_hour(otherRide)) + break; + + window_bubble_list_item(w, current_list_position); + } + break; + case INFORMATION_TYPE_AGE: + while (--current_list_position >= 0) { + otherRide = get_ride(w->list_item_positions[current_list_position]); + if (ride->build_date <= otherRide->build_date) + break; + + window_bubble_list_item(w, current_list_position); + } + break; + case INFORMATION_TYPE_INCOME: + while (--current_list_position >= 0) { + otherRide = get_ride(w->list_item_positions[current_list_position]); + if (ride->income_per_hour <= otherRide->income_per_hour) + break; + + window_bubble_list_item(w, current_list_position); + } + break; + case INFORMATION_TYPE_RUNNING_COST: + while (--current_list_position >= 0) { + otherRide = get_ride(w->list_item_positions[current_list_position]); + if (ride->upkeep_cost <= otherRide->upkeep_cost) + break; + + window_bubble_list_item(w, current_list_position); + } + break; case INFORMATION_TYPE_QUEUE_LENGTH: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride_get_total_queue_length(ride) <= ride_get_total_queue_length(otherRide)) break; @@ -659,7 +815,7 @@ static void window_ride_list_refresh_list(rct_window *w) break; case INFORMATION_TYPE_QUEUE_TIME: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride_get_max_queue_time(ride) <= ride_get_max_queue_time(otherRide)) break; @@ -668,7 +824,7 @@ static void window_ride_list_refresh_list(rct_window *w) break; case INFORMATION_TYPE_RELIABILITY: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride->reliability >> 8 <= otherRide->reliability >> 8) break; @@ -677,7 +833,7 @@ static void window_ride_list_refresh_list(rct_window *w) break; case INFORMATION_TYPE_DOWN_TIME: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride->downtime <= otherRide->downtime) break; @@ -686,7 +842,7 @@ static void window_ride_list_refresh_list(rct_window *w) break; case INFORMATION_TYPE_GUESTS_FAVOURITE: while (--current_list_position >= 0) { - otherRide = &g_ride_list[w->list_item_positions[current_list_position]]; + otherRide = get_ride(w->list_item_positions[current_list_position]); if (ride->guests_favourite <= otherRide->guests_favourite) break; @@ -712,8 +868,8 @@ static void window_ride_list_close_all(rct_window *w) continue; if (ride->status == RIDE_STATUS_CLOSED) continue; - RCT2_GLOBAL(0x013CE952 + 6, uint16) = w->scrolls[0].v_top; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = w->scrolls[0].v_bottom; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = w->scrolls[0].v_top; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = w->scrolls[0].v_bottom; ride_set_status(i, RIDE_STATUS_CLOSED); } @@ -729,8 +885,8 @@ static void window_ride_list_open_all(rct_window *w) continue; if (ride->status == RIDE_STATUS_OPEN) continue; - RCT2_GLOBAL(0x013CE952 + 6, uint16) = w->scrolls[0].v_top; - RCT2_GLOBAL(0x013CE952 + 8, uint32) = w->scrolls[0].v_bottom; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 6, uint16) = w->scrolls[0].v_top; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 8, uint32) = w->scrolls[0].v_bottom; ride_set_status(i, RIDE_STATUS_OPEN); } diff --git a/src/windows/save_prompt.c b/src/windows/save_prompt.c index 1b05645b3f..68f84e85db 100644 --- a/src/windows/save_prompt.c +++ b/src/windows/save_prompt.c @@ -23,12 +23,11 @@ #include "../config.h" #include "../game.h" #include "../localisation/localisation.h" +#include "../interface/themes.h" #include "../interface/widget.h" #include "../interface/window.h" #include "../openrct2.h" #include "../sprites.h" -#include "../tutorial.h" -#include "../interface/themes.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) { - RCT2_CALLPROC_EBPSAFE(0x0066EE54); - 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) { - RCT2_CALLPROC_EBPSAFE(0x0066EE54); - 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) @@ -278,4 +252,4 @@ static void window_save_prompt_callback(int result) if (result == MODAL_RESULT_OK) { game_load_or_quit_no_save_prompt(); } -} \ No newline at end of file +} diff --git a/src/windows/scenery.c b/src/windows/scenery.c index 8ca4deebd2..1328523eff 100644 --- a/src/windows/scenery.c +++ b/src/windows/scenery.c @@ -33,6 +33,8 @@ #include "../world/sprite.h" #include "dropdown.h" #include "../interface/themes.h" +#include "../network/network.h" +#include "error.h" #define WINDOW_SCENERY_WIDTH 634 #define WINDOW_SCENERY_HEIGHT 142 @@ -171,9 +173,9 @@ static rct_widget window_scenery_widgets[] = { { WWT_SCROLL, 1, 2, 608, 47, 126, 2, STR_NONE }, // 1000000 0x009DE418 { WWT_FLATBTN, 1, 609, 632, 44, 67, 5169, STR_ROTATE_OBJECTS_90 }, // 2000000 0x009DE428 { WWT_FLATBTN, 1, 609, 632, 68, 91, 5173, 3102 }, // 4000000 0x009DE438 - { WWT_COLORBTN, 1, 615, 626, 93, 104, 0xFFFFFFFF, STR_SELECT_COLOUR }, // 8000000 0x009DE448 - { WWT_COLORBTN, 1, 615, 626, 105, 116, 0xFFFFFFFF, STR_SELECT_SECONDARY_COLOUR }, // 10000000 0x009DE458 - { WWT_COLORBTN, 1, 615, 626, 117, 128, 0xFFFFFFFF, STR_SELECT_TERNARY_COLOUR }, // 20000000 0x009DE468 + { WWT_COLOURBTN, 1, 615, 626, 93, 104, 0xFFFFFFFF, STR_SELECT_COLOUR }, // 8000000 0x009DE448 + { WWT_COLOURBTN, 1, 615, 626, 105, 116, 0xFFFFFFFF, STR_SELECT_SECONDARY_COLOUR }, // 10000000 0x009DE458 + { WWT_COLOURBTN, 1, 615, 626, 117, 128, 0xFFFFFFFF, STR_SELECT_TERNARY_COLOUR }, // 20000000 0x009DE468 { WWT_FLATBTN, 1, 609, 632, 117, 140, 5172, 3225 }, // 40000000 0x009DE478 { WIDGETS_END }, }; @@ -473,7 +475,7 @@ void window_scenery_open() RCT2_GLOBAL(RCT2_ADDRESS_GHOST_SCENERY_TYPE, uint8) = 0; RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_COST, uint32) = MONEY32_UNDEFINED; RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_ROTATION, uint16) = 0; - window_scenery_is_repaint_scenery_tool_on = 0; // repaint colored scenery tool state + window_scenery_is_repaint_scenery_tool_on = 0; // repaint coloured scenery tool state window_scenery_is_build_cluster_tool_on = 0; // build cluster tool state window->min_width = WINDOW_SCENERY_WIDTH; @@ -488,9 +490,9 @@ void window_scenery_open() */ 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, rct_windownumber); + 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; @@ -547,13 +549,21 @@ static void window_scenery_mouseup(rct_window *w, int widgetIndex) window_invalidate(w); break; case WIDX_SCENERY_BUILD_CLUSTER_BUTTON: - window_scenery_is_build_cluster_tool_on ^= 1; + if (window_scenery_is_build_cluster_tool_on == 1) { + window_scenery_is_build_cluster_tool_on = 0; + } + else if (network_get_mode() != NETWORK_MODE_CLIENT || network_can_perform_command(network_get_current_player_group_index(), -2)) { + window_scenery_is_build_cluster_tool_on ^= 1; + } + else { + window_error_open(STR_CANT_DO_THIS, STR_PERMISSION_DENIED); + } window_invalidate(w); break; } } -/* +/** * * rct2: 0x006E1EB4 */ @@ -693,7 +703,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 +723,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; @@ -904,10 +914,10 @@ void window_scenery_invalidate(rct_window *w) window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_EMPTY; window_scenery_widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WWT_EMPTY; - if (window_scenery_is_repaint_scenery_tool_on & 1) { // repaint colored scenery tool is on - window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLORBTN; - window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLORBTN; - window_scenery_widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WWT_COLORBTN; + if (window_scenery_is_repaint_scenery_tool_on & 1) { // repaint coloured scenery tool is on + window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN; + window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLOURBTN; + window_scenery_widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WWT_COLOURBTN; window_scenery_widgets[WIDX_SCENERY_ROTATE_OBJECTS_BUTTON].type = WWT_EMPTY; } else if (tabSelectedSceneryId != -1) { rct_scenery_entry* sceneryEntry = NULL; @@ -916,36 +926,36 @@ void window_scenery_invalidate(rct_window *w) sceneryEntry = g_bannerSceneryEntries[tabSelectedSceneryId - 0x400]; if (sceneryEntry->banner.flags & 1) - window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN; } else if (tabSelectedSceneryId >= 0x300) { sceneryEntry = g_largeSceneryEntries[tabSelectedSceneryId - 0x300]; if (sceneryEntry->large_scenery.flags & 1) - window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN; if (sceneryEntry->large_scenery.flags & 2) - window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLOURBTN; } else if (tabSelectedSceneryId >= 0x200) { sceneryEntry = g_wallSceneryEntries[tabSelectedSceneryId - 0x200]; if (sceneryEntry->wall.flags & (WALL_SCENERY_FLAG1 | WALL_SCENERY_FLAG2)) { - window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN; if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) { - window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLOURBTN; if (sceneryEntry->wall.flags2 & WALL_SCENERY_FLAG1) window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_EMPTY; if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_TERNARY_COLOUR) - window_scenery_widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WWT_COLOURBTN; } } } else if (tabSelectedSceneryId < 0x100) { sceneryEntry = g_smallSceneryEntries[tabSelectedSceneryId]; if (sceneryEntry->small_scenery.flags & (SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR | SMALL_SCENERY_FLAG10)) { - window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WWT_COLOURBTN; if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_SECONDARY_COLOUR) - window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLORBTN; + window_scenery_widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WWT_COLOURBTN; } } } @@ -994,7 +1004,7 @@ void window_scenery_paint(rct_window *w, rct_drawpixelinfo *dpi) sint16 selectedSceneryEntryId = w->scenery.selected_scenery_id; if (selectedSceneryEntryId == -1) { - if (window_scenery_is_repaint_scenery_tool_on & 1) // repaint colored scenery tool is on + if (window_scenery_is_repaint_scenery_tool_on & 1) // repaint coloured scenery tool is on return; selectedSceneryEntryId = window_scenery_selected_scenery_by_tab[tabIndex]; @@ -1031,12 +1041,12 @@ void window_scenery_paint(rct_window *w, rct_drawpixelinfo *dpi) if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { // -14 - gfx_draw_string_right(dpi, STR_COST_LABEL, (void*)0x013CE952, 0, + gfx_draw_string_right(dpi, STR_COST_LABEL, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + w->width - 0x1A, w->y + w->height - 13); } RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = sceneryEntry->name; - gfx_draw_string_left_clipped(dpi, 0x4A7, (void*)0x013CE952, 0, + gfx_draw_string_left_clipped(dpi, 0x4A7, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + 3, w->y + w->height - 13, w->width - 19); } @@ -1091,8 +1101,8 @@ void window_scenery_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrol gfx_draw_sprite(dpi, imageId, left + 0x21, top, w->colours[1]); } else if (currentSceneryGlobalId >= 0x200) { sceneryEntry = g_wallSceneryEntries[currentSceneryGlobalId - 0x200]; - rct_drawpixelinfo* clipdpi = clip_drawpixelinfo(dpi, left + 1, 64, top + 1, 78); - if (clipdpi != NULL) { + rct_drawpixelinfo clipdpi; + if (clip_drawpixelinfo(&clipdpi, dpi, left + 1, top + 1, 64, 78)) { uint32 imageId = sceneryEntry->image; uint8 tertiaryColour = w->colours[1]; @@ -1102,11 +1112,11 @@ void window_scenery_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrol if (sceneryEntry->wall.flags & WALL_SCENERY_HAS_SECONDARY_COLOUR) { imageId |= (window_scenery_secondary_colour << 24) | 0x80000000; } - gfx_draw_sprite(clipdpi, imageId, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, + gfx_draw_sprite(&clipdpi, imageId, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, tertiaryColour); imageId = (sceneryEntry->image + 0x40000006) | ((window_scenery_primary_colour + 0x70) << 19); - gfx_draw_sprite(clipdpi, imageId, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, + gfx_draw_sprite(&clipdpi, imageId, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, tertiaryColour); } else { @@ -1121,17 +1131,14 @@ void window_scenery_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrol } } - gfx_draw_sprite(clipdpi, imageId, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, + gfx_draw_sprite(&clipdpi, imageId, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, tertiaryColour); if (sceneryEntry->wall.flags & WALL_SCENERY_FLAG5){ - gfx_draw_sprite(clipdpi, imageId + 1, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, + gfx_draw_sprite(&clipdpi, imageId + 1, 0x2F, (sceneryEntry->wall.height * 2) + 0x32, tertiaryColour); } } - - - rct2_free(clipdpi); } } else if (currentSceneryGlobalId >= 0x100) { sceneryEntry = g_pathBitSceneryEntries[currentSceneryGlobalId - 0x100]; @@ -1140,9 +1147,8 @@ void window_scenery_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrol gfx_draw_sprite(dpi, imageId, left + 0x0B, top + 0x10, w->colours[1]); } else { sceneryEntry = g_smallSceneryEntries[currentSceneryGlobalId]; - rct_drawpixelinfo* clipdpi = clip_drawpixelinfo(dpi, left + 1, SCENERY_BUTTON_WIDTH - 2, top + 1, SCENERY_BUTTON_HEIGHT - 2); - if (clipdpi != NULL) { - + rct_drawpixelinfo clipdpi; + if (clip_drawpixelinfo(&clipdpi, dpi, left + 1, top + 1, SCENERY_BUTTON_WIDTH - 2, SCENERY_BUTTON_HEIGHT - 2)) { uint32 imageId = sceneryEntry->image + window_scenery_rotation; if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR) { @@ -1160,21 +1166,19 @@ void window_scenery_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrol spriteTop -= 0x0C; } - gfx_draw_sprite(clipdpi, imageId, 0x20, spriteTop, w->colours[1]); + gfx_draw_sprite(&clipdpi, imageId, 0x20, spriteTop, w->colours[1]); if (sceneryEntry->small_scenery.flags & 0x200) { imageId = ((sceneryEntry->image + window_scenery_rotation) + 0x40000004) + ((window_scenery_primary_colour + 0x70) << 19); - gfx_draw_sprite(clipdpi, imageId, 0x20, spriteTop, w->colours[1]); + gfx_draw_sprite(&clipdpi, imageId, 0x20, spriteTop, w->colours[1]); } if (sceneryEntry->small_scenery.flags & SMALL_SCENERY_FLAG8) { imageId = (sceneryEntry->image + window_scenery_rotation) + 4; - gfx_draw_sprite(clipdpi, imageId, 0x20, spriteTop, w->colours[1]); + gfx_draw_sprite(&clipdpi, imageId, 0x20, spriteTop, w->colours[1]); } - - rct2_free(clipdpi); } } diff --git a/src/windows/server_list.c b/src/windows/server_list.c index 75b50e7634..a029c2661e 100644 --- a/src/windows/server_list.c +++ b/src/windows/server_list.c @@ -18,6 +18,7 @@ * along with this program. If not, see . *****************************************************************************/ +#include "../config.h" #include "../interface/colour.h" #include "../interface/themes.h" #include "../interface/widget.h" @@ -27,6 +28,7 @@ #include "../network/network.h" #include "../sprites.h" #include "../windows/dropdown.h" +#include "../windows/tooltip.h" #include "../util/util.h" #include "error.h" @@ -42,15 +44,16 @@ typedef struct { bool requiresPassword; utf8 *description; char *version; - bool favorite; + bool favourite; uint8 players; uint8 maxplayers; -} saved_server; +} server_entry; -char _playerName[32 + 1]; -saved_server *_savedServers = NULL; -int _numSavedServers = 0; -SDL_mutex *_mutex = 0; +static char _playerName[32 + 1]; +static server_entry *_severEntries = NULL; +static int _numServerEntries = 0; +static SDL_mutex *_mutex = 0; +static uint32 _numPlayersOnline = 0; enum { WIDX_BACKGROUND, @@ -126,18 +129,18 @@ static rct_window_event_list window_server_list_events = { enum { DDIDX_JOIN, - DDIDX_FAVORITE + DDIDX_FAVOURITE }; static int _hoverButtonIndex = -1; static void server_list_get_item_button(int buttonIndex, int x, int y, int width, int *outX, int *outY); -static void server_list_load_saved_servers(); -static void server_list_save_saved_servers(); -static void dispose_saved_server_list(); -static void dispose_saved_server(saved_server *serverInfo); -static saved_server* add_saved_server(char *address); -static void remove_saved_server(int index); +static void server_list_load_server_entries(); +static void server_list_save_server_entries(); +static void dispose_server_entry_list(); +static void dispose_server_entry(server_entry *serverInfo); +static server_entry* add_server_entry(char *address); +static void remove_server_entry(int index); static void join_server(char *address); static void fetch_servers(); #ifndef DISABLE_HTTP @@ -184,17 +187,17 @@ void window_server_list_open() window_set_resize(window, WWIDTH_MIN, WHEIGHT_MIN, WWIDTH_MAX, WHEIGHT_MAX); - safe_strncpy(_playerName, gConfigNetwork.player_name, sizeof(_playerName)); + safe_strcpy(_playerName, gConfigNetwork.player_name, sizeof(_playerName)); - server_list_load_saved_servers(); - window->no_list_items = _numSavedServers; + server_list_load_server_entries(); + window->no_list_items = _numServerEntries; fetch_servers(); } static void window_server_list_close(rct_window *w) { - dispose_saved_server_list(); + dispose_server_entry_list(); if (_mutex) { SDL_LockMutex(_mutex); SDL_DestroyMutex(_mutex); @@ -211,6 +214,13 @@ static void window_server_list_mouseup(rct_window *w, int widgetIndex) case WIDX_PLAYER_NAME_INPUT: window_start_textbox(w, widgetIndex, 1170, (uint32)_playerName, 63); break; + case WIDX_LIST:{ + int serverIndex = w->selected_list_item; + if (serverIndex >= 0 && serverIndex < _numServerEntries) { + char *serverAddress = _severEntries[serverIndex].address; + join_server(serverAddress); + } + }break; case WIDX_FETCH_SERVERS: fetch_servers(); break; @@ -232,17 +242,17 @@ static void window_server_list_dropdown(rct_window *w, int widgetIndex, int drop { int serverIndex = w->selected_list_item; if (serverIndex < 0) return; - if (serverIndex >= _numSavedServers) return; + if (serverIndex >= _numServerEntries) return; - char *serverAddress = _savedServers[serverIndex].address; + char *serverAddress = _severEntries[serverIndex].address; switch (dropdownIndex) { case DDIDX_JOIN: join_server(serverAddress); break; - case DDIDX_FAVORITE: - _savedServers[serverIndex].favorite = !_savedServers[serverIndex].favorite; - server_list_save_saved_servers(); + case DDIDX_FAVOURITE: + _severEntries[serverIndex].favourite = !_severEntries[serverIndex].favourite; + server_list_save_server_entries(); break; } } @@ -265,23 +275,25 @@ static void window_server_list_scroll_mousedown(rct_window *w, int scrollIndex, { int serverIndex = w->selected_list_item; if (serverIndex < 0) return; - if (serverIndex >= _numSavedServers) return; + if (serverIndex >= _numServerEntries) return; - char *serverAddress = _savedServers[serverIndex].address; + char *serverAddress = _severEntries[serverIndex].address; rct_widget *listWidget = &w->widgets[WIDX_LIST]; - int ddx = w->x + listWidget->left + x; - int ddy = w->y + listWidget->top + y; + int ddx = w->x + listWidget->left + x + 2 - w->scrolls[0].h_left; + int ddy = w->y + listWidget->top + y + 2 - w->scrolls[0].v_top; gDropdownItemsFormat[0] = STR_JOIN_GAME; - if (_savedServers[serverIndex].favorite) { - gDropdownItemsFormat[1] = STR_REMOVE_FROM_FAVORITES; + if (_severEntries[serverIndex].favourite) { + gDropdownItemsFormat[1] = STR_REMOVE_FROM_FAVOURITES; } else { - gDropdownItemsFormat[1] = STR_ADD_TO_FAVORITES; + gDropdownItemsFormat[1] = STR_ADD_TO_FAVOURITES; } window_dropdown_show_text(ddx, ddy, 0, COLOUR_GREY, 0, 2); } +char *gVersion = NULL; + static void window_server_list_scroll_mouseover(rct_window *w, int scrollIndex, int x, int y) { // Item @@ -305,9 +317,18 @@ static void window_server_list_scroll_mouseover(rct_window *w, int scrollIndex, } } + int width = w->widgets[WIDX_LIST].right - w->widgets[WIDX_LIST].left; + int right = width - 3 - 14 - 10; + if (x < right) + { + w->widgets[WIDX_LIST].tooltip = STR_NONE; + window_tooltip_close(); + } + if (w->selected_list_item != index || _hoverButtonIndex != hoverButtonIndex) { w->selected_list_item = index; _hoverButtonIndex = hoverButtonIndex; + window_tooltip_close(); window_invalidate(w); } } @@ -325,7 +346,7 @@ static void window_server_list_textinput(rct_window *w, int widgetIndex, char *t memset(_playerName, 0, sizeof(_playerName)); } else { memset(_playerName, 0, sizeof(_playerName)); - safe_strncpy(_playerName, text, sizeof(_playerName)); + safe_strcpy(_playerName, text, sizeof(_playerName)); } if (strlen(_playerName) > 0) { @@ -338,8 +359,8 @@ static void window_server_list_textinput(rct_window *w, int widgetIndex, char *t break; case WIDX_ADD_SERVER: - add_saved_server(text); - server_list_save_saved_servers(); + add_server_entry(text); + server_list_save_server_entries(); window_invalidate(w); break; } @@ -347,24 +368,33 @@ static void window_server_list_textinput(rct_window *w, int widgetIndex, char *t static void window_server_list_invalidate(rct_window *w) { + colour_scheme_update(w); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, char *) = gVersion; window_server_list_widgets[WIDX_BACKGROUND].right = w->width - 1; window_server_list_widgets[WIDX_BACKGROUND].bottom = w->height - 1; window_server_list_widgets[WIDX_TITLE].right = w->width - 2; window_server_list_widgets[WIDX_CLOSE].left = w->width - 2 - 11; window_server_list_widgets[WIDX_CLOSE].right = w->width - 2 - 11 + 10; + int margin = 6; + int buttonHeight = 11; + int buttonTop = w->height - margin - buttonHeight - 13; + int buttonBottom = buttonTop + buttonHeight; + int listBottom = buttonTop - margin; + window_server_list_widgets[WIDX_PLAYER_NAME_INPUT].right = w->width - 6; window_server_list_widgets[WIDX_LIST].left = 6; window_server_list_widgets[WIDX_LIST].right = w->width - 6; - window_server_list_widgets[WIDX_LIST].bottom = w->height - 6 - 11 - 6; - window_server_list_widgets[WIDX_FETCH_SERVERS].top = w->height - 6 - 11; - window_server_list_widgets[WIDX_FETCH_SERVERS].bottom = w->height - 6; - window_server_list_widgets[WIDX_ADD_SERVER].top = w->height - 6 - 11; - window_server_list_widgets[WIDX_ADD_SERVER].bottom = w->height - 6; - window_server_list_widgets[WIDX_START_SERVER].top = w->height - 6 - 11; - window_server_list_widgets[WIDX_START_SERVER].bottom = w->height - 6; + window_server_list_widgets[WIDX_LIST].bottom = listBottom; + window_server_list_widgets[WIDX_FETCH_SERVERS].top = buttonTop; + window_server_list_widgets[WIDX_FETCH_SERVERS].bottom = buttonBottom; + window_server_list_widgets[WIDX_ADD_SERVER].top = buttonTop; + window_server_list_widgets[WIDX_ADD_SERVER].bottom = buttonBottom; + window_server_list_widgets[WIDX_START_SERVER].top = buttonTop; + window_server_list_widgets[WIDX_START_SERVER].bottom = buttonBottom; - w->no_list_items = _numSavedServers; + w->no_list_items = _numServerEntries; } static void window_server_list_paint(rct_window *w, rct_drawpixelinfo *dpi) @@ -372,6 +402,10 @@ static void window_server_list_paint(rct_window *w, rct_drawpixelinfo *dpi) window_draw_widgets(w, dpi); gfx_draw_string_left(dpi, STR_PLAYER_NAME, NULL, COLOUR_WHITE, w->x + 6, w->y + w->widgets[WIDX_PLAYER_NAME_INPUT].top); + char *version = NETWORK_STREAM_ID; + gfx_draw_string_left(dpi, STR_NETWORK_VERSION, (void*)&version, COLOUR_WHITE, w->x + 324, w->y + w->widgets[WIDX_START_SERVER].top); + + gfx_draw_string_left(dpi, STR_X_PLAYERS_ONLINE, (void*)&_numPlayersOnline, COLOUR_WHITE, w->x + 8, w->y + w->height - 15); } static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex) @@ -385,31 +419,32 @@ static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi int width = w->widgets[WIDX_LIST].right - w->widgets[WIDX_LIST].left; int y = 0; + w->widgets[WIDX_LIST].tooltip = STR_NONE; for (int i = 0; i < w->no_list_items; i++) { if (y >= dpi->y + dpi->height) continue; // if (y + ITEM_HEIGHT < dpi->y) continue; - saved_server *serverDetails = &_savedServers[i]; + server_entry *serverDetails = &_severEntries[i]; bool highlighted = i == w->selected_list_item; // Draw hover highlight if (highlighted) { gfx_fill_rect(dpi, 0, y, width, y + ITEM_HEIGHT, 0x02000031); + gVersion = serverDetails->version; + w->widgets[WIDX_LIST].tooltip = STR_NETWORK_VERSION_TIP; } int colour = w->colours[1]; - if (serverDetails->favorite) { + if (serverDetails->favourite) { colour = COLOUR_YELLOW; } // Draw server information - if (highlighted) { - gfx_draw_string(dpi, serverDetails->address, colour, 3, y + 3); + if (highlighted && !str_is_null_or_empty(serverDetails->description)) { + gfx_draw_string(dpi, serverDetails->description, colour, 3, y + 3); } else { gfx_draw_string(dpi, serverDetails->name, colour, 3, y + 3); } - //gfx_draw_string(dpi, serverDetails->description, w->colours[1], 3, y + 14); - int right = width - 3 - 14; @@ -421,7 +456,7 @@ static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi compatibilitySpriteId = SPR_G2_RCT1_CLOSE_BUTTON_0; } else { // Server online... check version - bool correctVersion = strcmp(serverDetails->version, OPENRCT2_VERSION) == 0; + bool correctVersion = strcmp(serverDetails->version, NETWORK_STREAM_ID) == 0; compatibilitySpriteId = correctVersion ? SPR_G2_RCT1_OPEN_BUTTON_2 : SPR_G2_RCT1_CLOSE_BUTTON_2; } gfx_draw_sprite(dpi, compatibilitySpriteId, right, y + 1, 0); @@ -465,7 +500,7 @@ static char *freadstralloc(SDL_RWops *file) if (SDL_RWread(file, &c, 1, 1) != 1) break; if (c == 0) break; - if (length > capacity) { + if (length >= capacity) { capacity *= 2; buffer = realloc(buffer, capacity); } @@ -478,7 +513,7 @@ static char *freadstralloc(SDL_RWops *file) return buffer; } -static void server_list_load_saved_servers() +static void server_list_load_server_entries() { utf8 path[MAX_PATH]; SDL_RWops *file; @@ -492,22 +527,22 @@ static void server_list_load_saved_servers() } SDL_LockMutex(_mutex); - dispose_saved_server_list(); + dispose_server_entry_list(); - // Read number of saved servers - SDL_RWread(file, &_numSavedServers, sizeof(uint32), 1); - _savedServers = malloc(_numSavedServers * sizeof(saved_server)); + // Read number of server entries + SDL_RWread(file, &_numServerEntries, sizeof(uint32), 1); + _severEntries = malloc(_numServerEntries * sizeof(server_entry)); - // Load each saved server - for (int i = 0; i < _numSavedServers; i++) { - saved_server *serverInfo = &_savedServers[i]; + // Load each server entry + for (int i = 0; i < _numServerEntries; i++) { + server_entry *serverInfo = &_severEntries[i]; serverInfo->address = freadstralloc(file); serverInfo->name = freadstralloc(file); serverInfo->requiresPassword = false; serverInfo->description = freadstralloc(file); serverInfo->version = _strdup(""); - serverInfo->favorite = true; + serverInfo->favourite = true; serverInfo->players = 0; serverInfo->maxplayers = 0; } @@ -516,7 +551,7 @@ static void server_list_load_saved_servers() SDL_UnlockMutex(_mutex); } -static void server_list_save_saved_servers() +static void server_list_save_server_entries() { utf8 path[MAX_PATH]; SDL_RWops *file; @@ -532,19 +567,19 @@ static void server_list_save_saved_servers() SDL_LockMutex(_mutex); int count = 0; - for (int i = 0; i < _numSavedServers; i++) { - saved_server *serverInfo = &_savedServers[i]; - if (serverInfo->favorite) { + for (int i = 0; i < _numServerEntries; i++) { + server_entry *serverInfo = &_severEntries[i]; + if (serverInfo->favourite) { count++; } } - // Write number of saved servers + // Write number of server entries SDL_RWwrite(file, &count, sizeof(uint32), 1); - // Write each saved server - for (int i = 0; i < _numSavedServers; i++) { - saved_server *serverInfo = &_savedServers[i]; - if (serverInfo->favorite) { + // Write each server entry + for (int i = 0; i < _numServerEntries; i++) { + server_entry *serverInfo = &_severEntries[i]; + if (serverInfo->favourite) { SDL_RWwrite(file, serverInfo->address, strlen(serverInfo->address) + 1, 1); SDL_RWwrite(file, serverInfo->name, strlen(serverInfo->name) + 1, 1); SDL_RWwrite(file, serverInfo->description, strlen(serverInfo->description) + 1, 1); @@ -555,21 +590,21 @@ static void server_list_save_saved_servers() SDL_UnlockMutex(_mutex); } -static void dispose_saved_server_list() +static void dispose_server_entry_list() { SDL_LockMutex(_mutex); - if (_savedServers != NULL) { - for (int i = 0; i < _numSavedServers; i++) { - dispose_saved_server(&_savedServers[i]); + if (_severEntries != NULL) { + for (int i = 0; i < _numServerEntries; i++) { + dispose_server_entry(&_severEntries[i]); } - free(_savedServers); - _savedServers = NULL; + free(_severEntries); + _severEntries = NULL; } - _numSavedServers = 0; + _numServerEntries = 0; SDL_UnlockMutex(_mutex); } -static void dispose_saved_server(saved_server *serverInfo) +static void dispose_server_entry(server_entry *serverInfo) { SafeFree(serverInfo->address); SafeFree(serverInfo->name); @@ -577,46 +612,46 @@ static void dispose_saved_server(saved_server *serverInfo) SafeFree(serverInfo->version); } -static saved_server* add_saved_server(char *address) +static server_entry* add_server_entry(char *address) { SDL_LockMutex(_mutex); - for (int i = 0; i < _numSavedServers; i++) { - if (strcmp(_savedServers[i].address, address) == 0) { + for (int i = 0; i < _numServerEntries; i++) { + if (strcmp(_severEntries[i].address, address) == 0) { SDL_UnlockMutex(_mutex); - return &_savedServers[i]; + return &_severEntries[i]; } } - _numSavedServers++; - if (_savedServers == NULL) { - _savedServers = malloc(_numSavedServers * sizeof(saved_server)); + _numServerEntries++; + if (_severEntries == NULL) { + _severEntries = malloc(_numServerEntries * sizeof(server_entry)); } else { - _savedServers = realloc(_savedServers, _numSavedServers * sizeof(saved_server)); + _severEntries = realloc(_severEntries, _numServerEntries * sizeof(server_entry)); } - int index = _numSavedServers - 1; - saved_server* newserver = &_savedServers[index]; + int index = _numServerEntries - 1; + server_entry* newserver = &_severEntries[index]; newserver->address = _strdup(address); newserver->name = _strdup(address); newserver->requiresPassword = false; newserver->description = _strdup(""); newserver->version = _strdup(""); - newserver->favorite = false; + newserver->favourite = false; newserver->players = 0; newserver->maxplayers = 0; SDL_UnlockMutex(_mutex); return newserver; } -static void remove_saved_server(int index) +static void remove_server_entry(int index) { SDL_LockMutex(_mutex); - if (_numSavedServers > index) { - int serversToMove = _numSavedServers - index - 1; - memmove(&_savedServers[index], &_savedServers[index + 1], serversToMove * sizeof(saved_server)); + if (_numServerEntries > index) { + int serversToMove = _numServerEntries - index - 1; + memmove(&_severEntries[index], &_severEntries[index + 1], serversToMove * sizeof(server_entry)); - _numSavedServers--; - _savedServers = realloc(_savedServers, _numSavedServers * sizeof(saved_server)); + _numServerEntries--; + _severEntries = realloc(_severEntries, _numServerEntries * sizeof(server_entry)); } SDL_UnlockMutex(_mutex); } @@ -660,6 +695,16 @@ static void join_server(char *address) } } +static uint32 get_total_player_count() +{ + uint32 numPlayers = 0; + for (int i = 0; i < _numServerEntries; i++) { + server_entry *serverDetails = &_severEntries[i]; + numPlayers += serverDetails->players; + } + return numPlayers; +} + static void fetch_servers() { #ifndef DISABLE_HTTP @@ -669,9 +714,9 @@ static void fetch_servers() } SDL_LockMutex(_mutex); - for (int i = 0; i < _numSavedServers; i++) { - if (!_savedServers[i].favorite) { - remove_saved_server(i); + for (int i = 0; i < _numServerEntries; i++) { + if (!_severEntries[i].favourite) { + remove_server_entry(i); i = 0; } } @@ -733,17 +778,23 @@ static void fetch_servers_callback(http_json_response* response) json_t *ip6 = json_object_get(ip, "v6"); json_t *addressIp = json_array_get(ip4, 0); + if (name == NULL || version == NULL) + { + log_verbose("Cowardly refusing to add server without name or version specified."); + continue; + } + char address[256]; snprintf(address, sizeof(address), "%s:%d", json_string_value(addressIp), (int)json_integer_value(port)); SDL_LockMutex(_mutex); - saved_server* newserver = add_saved_server(address); + server_entry* newserver = add_server_entry(address); SafeFree(newserver->name); SafeFree(newserver->description); SafeFree(newserver->version); newserver->name = _strdup(json_string_value(name)); newserver->requiresPassword = json_boolean_value(requiresPassword); - newserver->description = _strdup(json_string_value(description)); + newserver->description = _strdup(description == NULL ? "" : json_string_value(description)); newserver->version = _strdup(json_string_value(version)); newserver->players = (uint8)json_integer_value(players); newserver->maxplayers = (uint8)json_integer_value(maxPlayers); @@ -751,6 +802,8 @@ static void fetch_servers_callback(http_json_response* response) } http_request_json_dispose(response); + _numPlayersOnline = get_total_player_count(); + rct_window *window = window_find_by_class(WC_SERVER_LIST); if (window != NULL) { window_invalidate(window); diff --git a/src/windows/server_start.c b/src/windows/server_start.c index 752c7efd4b..2c78733f8a 100644 --- a/src/windows/server_start.c +++ b/src/windows/server_start.c @@ -25,12 +25,13 @@ #include "../localisation/localisation.h" #include "../network/network.h" #include "../sprites.h" +#include "../title.h" #include "../util/util.h" #include "error.h" -char _port[7]; -char _name[65]; -char _password[33]; +static char _port[7]; +static char _name[65]; +static char _password[33]; enum { WIDX_BACKGROUND, @@ -43,7 +44,8 @@ enum { WIDX_MAXPLAYERS_INCREASE, WIDX_MAXPLAYERS_DECREASE, WIDX_ADVERTISE_CHECKBOX, - WIDX_START_SERVER + WIDX_START_SERVER, + WIDX_LOAD_SERVER }; #define WW 300 @@ -60,7 +62,8 @@ static rct_widget window_server_start_widgets[] = { { WWT_DROPDOWN_BUTTON, 1, WW-18, WW-8, 68, 72, STR_NUMERIC_UP, STR_NONE }, { WWT_DROPDOWN_BUTTON, 1, WW-18, WW-8, 72, 76, STR_NUMERIC_DOWN, STR_NONE }, { WWT_CHECKBOX, 1, 6, WW-8, 85, 91, STR_ADVERTISE, STR_NONE }, // advertise checkbox - { WWT_DROPDOWN_BUTTON, 1, 6, 106, WH-6-11, WH-6, STR_START_SERVER, STR_NONE }, // start server button + { WWT_DROPDOWN_BUTTON, 1, 6, 106, WH-6-11, WH-6, STR_NEW_GAME, STR_NONE }, // start server button + { WWT_DROPDOWN_BUTTON, 1, 112, 212, WH-6-11, WH-6, STR_LOAD_GAME, STR_NONE }, { WIDGETS_END }, }; @@ -123,7 +126,8 @@ void window_server_start_open() (1 << WIDX_MAXPLAYERS_INCREASE) | (1 << WIDX_MAXPLAYERS_DECREASE) | (1 << WIDX_ADVERTISE_CHECKBOX) | - (1 << WIDX_START_SERVER) + (1 << WIDX_START_SERVER) | + (1 << WIDX_LOAD_SERVER) ); window_init_scroll_widgets(window); window->no_list_items = 0; @@ -136,12 +140,9 @@ void window_server_start_open() window->page = 0; window->list_information_type = 0; - window->colours[0] = 1; - window->colours[1] = 26; - window->colours[2] = 26; - sprintf(_port, "%lu", gConfigNetwork.default_port); - safe_strncpy(_name, gConfigNetwork.server_name, sizeof(_name)); + sprintf(_port, "%u", gConfigNetwork.default_port); + safe_strcpy(_name, gConfigNetwork.server_name, sizeof(_name)); } static void window_server_start_close(rct_window *w) @@ -149,6 +150,23 @@ static void window_server_start_close(rct_window *w) } +static void window_server_start_scenarioselect_callback(const utf8 *path) +{ + network_set_password(_password); + if (scenario_load_and_play_from_path(path)) { + network_begin_server(gConfigNetwork.default_port); + } else { + title_load(); + } +} + +static void window_server_start_loadsave_callback(int result) +{ + if (result == MODAL_RESULT_OK) { + network_begin_server(gConfigNetwork.default_port); + } +} + static void window_server_start_mouseup(rct_window *w, int widgetIndex) { switch (widgetIndex) { @@ -184,8 +202,12 @@ static void window_server_start_mouseup(rct_window *w, int widgetIndex) window_invalidate(w); break; case WIDX_START_SERVER: + window_scenarioselect_open(window_server_start_scenarioselect_callback); + break; + case WIDX_LOAD_SERVER: network_set_password(_password); - window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME | LOADSAVETYPE_NETWORK, NULL); + window_loadsave_open(LOADSAVETYPE_LOAD | LOADSAVETYPE_GAME, NULL); + gLoadSaveCallback = window_server_start_loadsave_callback; break; } } @@ -210,7 +232,7 @@ static void window_server_start_textinput(rct_window *w, int widgetIndex, char * memset(_port, 0, sizeof(_port)); if (strlen(text) > 0) { - safe_strncpy(_port, text, sizeof(_port)); + safe_strcpy(_port, text, sizeof(_port)); } gConfigNetwork.default_port = atoi(_port); @@ -224,7 +246,7 @@ static void window_server_start_textinput(rct_window *w, int widgetIndex, char * memset(_name, 0, sizeof(_name)); if (strlen(text) > 0) { - safe_strncpy(_name, text, sizeof(_name)); + safe_strcpy(_name, text, sizeof(_name)); } if (strlen(_name) > 0) { @@ -241,7 +263,7 @@ static void window_server_start_textinput(rct_window *w, int widgetIndex, char * memset(_password, 0, sizeof(_password)); if (strlen(text) > 0) { - safe_strncpy(_password, text, sizeof(_password)); + safe_strcpy(_password, text, sizeof(_password)); } widget_invalidate(w, WIDX_PASSWORD_INPUT); @@ -251,8 +273,10 @@ static void window_server_start_textinput(rct_window *w, int widgetIndex, char * static void window_server_start_invalidate(rct_window *w) { + colour_scheme_update_by_class(w, WC_SERVER_LIST); + widget_set_checkbox_value(w, WIDX_ADVERTISE_CHECKBOX, gConfigNetwork.advertise); - RCT2_GLOBAL(0x013CE964, uint16) = gConfigNetwork.maxplayers; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 18, uint16) = gConfigNetwork.maxplayers; } static void window_server_start_paint(rct_window *w, rct_drawpixelinfo *dpi) diff --git a/src/windows/shortcut_key_change.c b/src/windows/shortcut_key_change.c index 912b1c8309..a5cb94bcac 100644 --- a/src/windows/shortcut_key_change.c +++ b/src/windows/shortcut_key_change.c @@ -121,6 +121,6 @@ static void window_shortcut_change_paint(rct_window *w, rct_drawpixelinfo *dpi) int x = w->x + 125; int y = w->y + 30; - RCT2_GLOBAL(0x13CE952, uint16) = ShortcutStringIds[RCT2_GLOBAL(0x009DE511, uint8)]; - gfx_draw_string_centred_wrapped(dpi, (void*)0x013CE952, x, y, 242, 2785, RCT2_GLOBAL(0x9DEB8D, uint8)); -} \ No newline at end of file + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = ShortcutStringIds[RCT2_GLOBAL(0x009DE511, uint8)]; + gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, 242, 2785, RCT2_GLOBAL(0x9DEB8D, uint8)); +} diff --git a/src/windows/shortcut_keys.c b/src/windows/shortcut_keys.c index db3db113e1..9bea79ad9c 100644 --- a/src/windows/shortcut_keys.c +++ b/src/windows/shortcut_keys.c @@ -132,6 +132,7 @@ const rct_string_id ShortcutStringIds[] = { STR_SHORTCUT_SCROLL_MAP_RIGHT, STR_SEND_MESSAGE, STR_SHORTCUT_QUICK_SAVE_GAME, + STR_SHORTCUT_SHOW_OPTIONS, }; /** @@ -258,9 +259,9 @@ static void window_shortcut_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, i char *templateString = (char*)language_get_string(templateStringId); keyboard_shortcut_format_string(templateString, gShortcutKeys[i]); - RCT2_GLOBAL(0x13CE952, uint16) = STR_SHORTCUT_ENTRY_FORMAT; - RCT2_GLOBAL(0x13CE954, uint16) = ShortcutStringIds[i]; - RCT2_GLOBAL(0x13CE956, uint16) = templateStringId; - gfx_draw_string_left(dpi, format, (void*)0x13CE952, 0, 0, y - 1); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = STR_SHORTCUT_ENTRY_FORMAT; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = ShortcutStringIds[i]; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint16) = templateStringId; + gfx_draw_string_left(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 0, y - 1); } } diff --git a/src/windows/sign.c b/src/windows/sign.c index 2599e7b256..3adf295347 100644 --- a/src/windows/sign.c +++ b/src/windows/sign.c @@ -44,20 +44,20 @@ enum WINDOW_SIGN_WIDGET_IDX { WIDX_VIEWPORT, WIDX_SIGN_TEXT, WIDX_SIGN_DEMOLISH, - WIDX_MAIN_COLOR, - WIDX_TEXT_COLOR + WIDX_MAIN_COLOUR, + WIDX_TEXT_COLOUR }; // 0x9AEE00 rct_widget window_sign_widgets[] = { - { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, 65535 }, // panel / background - { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_SIGN, 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_VIEWPORT, 1, 3, WW - 26, 17, WH - 20, 0x0FFFFFFFE, 65535 }, // Viewport - { WWT_FLATBTN, 1, WW - 25, WW - 2, 19, 42, 5168, STR_CHANGE_SIGN_TEXT_TIP }, // change sign button - { WWT_FLATBTN, 1, WW - 25, WW - 2, 67, 90, 5165, STR_DEMOLISH_SIGN_TIP }, // demolish button - { WWT_COLORBTN, 1, 5, 16, WH - 16, WH - 5, 0x0FFFFFFFF, STR_SELECT_MAIN_COLOR_TIP },// Main colour - { WWT_COLORBTN, 1, 17, 28, WH - 16, WH - 5, 0x0FFFFFFFF, STR_SELECT_TEXT_COLOR_TIP },// Text colour + { WWT_FRAME, 0, 0, WW - 1, 0, WH - 1, 0x0FFFFFFFF, 65535 }, // panel / background + { WWT_CAPTION, 0, 1, WW - 2, 1, 14, STR_SIGN, 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_VIEWPORT, 1, 3, WW - 26, 17, WH - 20, 0x0FFFFFFFE, 65535 }, // Viewport + { WWT_FLATBTN, 1, WW - 25, WW - 2, 19, 42, 5168, STR_CHANGE_SIGN_TEXT_TIP }, // change sign button + { WWT_FLATBTN, 1, WW - 25, WW - 2, 67, 90, 5165, STR_DEMOLISH_SIGN_TIP }, // demolish button + { WWT_COLOURBTN, 1, 5, 16, WH - 16, WH - 5, 0x0FFFFFFFF, STR_SELECT_MAIN_SIGN_COLOUR_TIP }, // Main colour + { WWT_COLOURBTN, 1, 17, 28, WH - 16, WH - 5, 0x0FFFFFFFF, STR_SELECT_TEXT_COLOUR_TIP }, // Text colour { WIDGETS_END }, }; @@ -159,8 +159,8 @@ void window_sign_open(rct_windownumber number) (1 << WIDX_CLOSE) | (1 << WIDX_SIGN_TEXT) | (1 << WIDX_SIGN_DEMOLISH) | - (1 << WIDX_MAIN_COLOR) | - (1 << WIDX_TEXT_COLOR); + (1 << WIDX_MAIN_COLOUR) | + (1 << WIDX_TEXT_COLOUR); w->number = number; window_init_scroll_widgets(w); @@ -214,7 +214,10 @@ void window_sign_open(rct_windownumber number) window_invalidate(w); } -/* rct2: 0x6B9765*/ +/** + * + * rct2: 0x6B9765 + */ static void window_sign_mouseup(rct_window *w, int widgetIndex) { rct_banner* banner = &gBanners[w->number]; @@ -254,8 +257,8 @@ static void window_sign_mouseup(rct_window *w, int widgetIndex) break; case WIDX_SIGN_TEXT: if (banner->flags&BANNER_FLAG_2){ - rct_ride* ride = GET_RIDE(banner->colour); - RCT2_GLOBAL(0x13CE962, uint32) = ride->name_arguments; + rct_ride* ride = get_ride(banner->colour); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 16, uint32) = ride->name_arguments; string_id = ride->name; } else @@ -267,29 +270,35 @@ static void window_sign_mouseup(rct_window *w, int widgetIndex) } } -/* rct2: 0x6B9784 & 0x6E6164 */ +/** + * + * rct2: 0x6B9784 + & 0x6E6164 */ static void window_sign_mousedown(int widgetIndex, rct_window*w, rct_widget* widget) { switch (widgetIndex) { - case WIDX_MAIN_COLOR: + case WIDX_MAIN_COLOUR: window_dropdown_show_colour(w, widget, w->colours[1] | 0x80, (uint8)w->list_information_type); break; - case WIDX_TEXT_COLOR: + case WIDX_TEXT_COLOUR: window_dropdown_show_colour(w, widget, w->colours[1] | 0x80, (uint8)w->var_492); break; } } -/* rct2: 0x6B979C */ +/** + * + * rct2: 0x6B979C + */ static void window_sign_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { switch (widgetIndex){ - case WIDX_MAIN_COLOR: + case WIDX_MAIN_COLOUR: if (dropdownIndex == -1) return; w->list_information_type = dropdownIndex; game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_SIGN_STYLE, w->var_492, 1); break; - case WIDX_TEXT_COLOR: + case WIDX_TEXT_COLOUR: if (dropdownIndex == -1) return; w->var_492 = dropdownIndex; game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, w->list_information_type, GAME_COMMAND_SET_SIGN_STYLE, dropdownIndex, 1); @@ -301,7 +310,10 @@ static void window_sign_dropdown(rct_window *w, int widgetIndex, int dropdownInd window_invalidate(w); } -/* rct2: 0x6B9791 & 0x6E6171*/ +/** + * + * rct2: 0x6B9791, 0x6E6171 + */ static void window_sign_textinput(rct_window *w, int widgetIndex, char *text) { if (widgetIndex == WIDX_SIGN_TEXT && text != NULL) { @@ -311,13 +323,16 @@ static void window_sign_textinput(rct_window *w, int widgetIndex, char *text) } } -/* rct2: 0x006B96F5 */ +/** + * + * rct2: 0x006B96F5 + */ static void window_sign_invalidate(rct_window *w) { colour_scheme_update(w); - rct_widget* main_colour_btn = &window_sign_widgets[WIDX_MAIN_COLOR]; - rct_widget* text_colour_btn = &window_sign_widgets[WIDX_TEXT_COLOR]; + rct_widget* main_colour_btn = &window_sign_widgets[WIDX_MAIN_COLOUR]; + rct_widget* text_colour_btn = &window_sign_widgets[WIDX_TEXT_COLOUR]; rct_scenery_entry* scenery_entry = g_largeSceneryEntries[w->var_48C]; @@ -325,17 +340,20 @@ static void window_sign_invalidate(rct_window *w) text_colour_btn->type = WWT_EMPTY; if (scenery_entry->large_scenery.flags&(1 << 0)){ - main_colour_btn->type = WWT_COLORBTN; + main_colour_btn->type = WWT_COLOURBTN; } if (scenery_entry->large_scenery.flags&(1 << 1)) { - text_colour_btn->type = WWT_COLORBTN; + text_colour_btn->type = WWT_COLOURBTN; } main_colour_btn->image = (w->list_information_type << 19) | 0x600013C3; text_colour_btn->image = (w->var_492 << 19) | 0x600013C3; } -/* rct2: 0x006B9754 & 0x006E6134 */ +/** + * + * rct2: 0x006B9754, 0x006E6134 + */ static void window_sign_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -346,7 +364,10 @@ static void window_sign_paint(rct_window *w, rct_drawpixelinfo *dpi) } } -/* rct2: 0x6B9A6C & 0x6E6424 */ +/** + * + * rct2: 0x6B9A6C, 0x6E6424 + */ static void window_sign_unknown_14(rct_window *w) { rct_viewport* view = w->viewport; @@ -382,7 +403,10 @@ static void window_sign_unknown_14(rct_window *w) } -/* rct2: 0x6E5F52 */ +/** + * + * rct2: 0x6E5F52 + */ void window_sign_small_open(rct_windownumber number){ rct_window* w; rct_widget *viewportWidget; @@ -399,8 +423,8 @@ void window_sign_small_open(rct_windownumber number){ (1 << WIDX_CLOSE) | (1 << WIDX_SIGN_TEXT) | (1 << WIDX_SIGN_DEMOLISH) | - (1 << WIDX_MAIN_COLOR) | - (1 << WIDX_TEXT_COLOR); + (1 << WIDX_MAIN_COLOUR) | + (1 << WIDX_TEXT_COLOUR); w->number = number; window_init_scroll_widgets(w); @@ -456,7 +480,10 @@ void window_sign_small_open(rct_windownumber number){ window_invalidate(w); } -/* rct2: 0x6E6145 */ +/** + * + * rct2: 0x6E6145 + */ static void window_sign_small_mouseup(rct_window *w, int widgetIndex) { rct_banner* banner = &gBanners[w->number]; @@ -494,8 +521,8 @@ static void window_sign_small_mouseup(rct_window *w, int widgetIndex) break; case WIDX_SIGN_TEXT: if (banner->flags&BANNER_FLAG_2){ - rct_ride* ride = GET_RIDE(banner->colour); - RCT2_GLOBAL(0x13CE962, uint32) = ride->name_arguments; + rct_ride* ride = get_ride(banner->colour); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 16, uint32) = ride->name_arguments; string_id = ride->name; } else @@ -507,18 +534,21 @@ static void window_sign_small_mouseup(rct_window *w, int widgetIndex) } } -/* rct2: 0x6E617C */ +/** + * + * rct2: 0x6E617C + */ static void window_sign_small_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { rct_banner* banner = &gBanners[w->number]; switch (widgetIndex){ - case WIDX_MAIN_COLOR: + case WIDX_MAIN_COLOUR: if (dropdownIndex == -1) return; w->list_information_type = dropdownIndex; game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, dropdownIndex, GAME_COMMAND_SET_SIGN_STYLE, w->var_492, 0); break; - case WIDX_TEXT_COLOR: + case WIDX_TEXT_COLOUR: if (dropdownIndex == -1) return; w->var_492 = dropdownIndex; game_do_command(1, GAME_COMMAND_FLAG_APPLY, w->number, w->list_information_type, GAME_COMMAND_SET_SIGN_STYLE, dropdownIndex, 0); @@ -530,13 +560,16 @@ static void window_sign_small_dropdown(rct_window *w, int widgetIndex, int dropd window_invalidate(w); } -/* rct2: 0x006E60D5 */ +/** + * + * rct2: 0x006E60D5 + */ static void window_sign_small_invalidate(rct_window *w) { colour_scheme_update(w); - rct_widget* main_colour_btn = &window_sign_widgets[WIDX_MAIN_COLOR]; - rct_widget* text_colour_btn = &window_sign_widgets[WIDX_TEXT_COLOR]; + rct_widget* main_colour_btn = &window_sign_widgets[WIDX_MAIN_COLOUR]; + rct_widget* text_colour_btn = &window_sign_widgets[WIDX_TEXT_COLOUR]; rct_scenery_entry* scenery_entry = g_wallSceneryEntries[w->var_48C]; @@ -544,10 +577,10 @@ static void window_sign_small_invalidate(rct_window *w) text_colour_btn->type = WWT_EMPTY; if (scenery_entry->wall.flags&(1 << 0)){ - main_colour_btn->type = WWT_COLORBTN; + main_colour_btn->type = WWT_COLOURBTN; } if (scenery_entry->wall.flags&(1 << 6)) { - text_colour_btn->type = WWT_COLORBTN; + text_colour_btn->type = WWT_COLOURBTN; } main_colour_btn->image = (w->list_information_type << 19) | 0x600013C3; diff --git a/src/windows/staff.c b/src/windows/staff.c index 9d4f41b29a..bc5209998a 100644 --- a/src/windows/staff.c +++ b/src/windows/staff.c @@ -309,8 +309,7 @@ rct_window *window_staff_open(rct_peep* peep) w->page = 0; w->viewport_focus_coordinates.y = 0; w->frame_no = 0; - - RCT2_GLOBAL((int*)w + 0x496, uint16) = 0; // missing, var_494 should perhaps be uint16? + w->highlighted_item = 0; window_staff_disable_widgets(w); @@ -366,11 +365,11 @@ void window_staff_disable_widgets(rct_window* w) /** * Same as window_peep_overview_close. - * rct2: 0x006BDFF8 + * rct2: 0x006BDFF8 */ 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(); @@ -379,11 +378,11 @@ void window_staff_overview_close(rct_window *w) /** * Mostly similar to window_peep_set_page. - * rct2: 0x006BE023 + * rct2: 0x006BE023 */ 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)) @@ -425,7 +424,10 @@ void window_staff_set_page(rct_window* w, int page) if (listen && w->viewport) w->viewport->flags |= VIEWPORT_FLAG_SOUND_ON; } -/** rct2: 0x006BDF55 */ +/** + * + * rct2: 0x006BDF55 + */ void window_staff_overview_mouseup(rct_window *w, int widgetIndex) { rct_peep* peep = GET_PEEP(w->number); @@ -447,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); @@ -466,7 +468,10 @@ void window_staff_overview_mouseup(rct_window *w, int widgetIndex) } } -/** rct2: 0x006BE558 */ +/** + * + * rct2: 0x006BE558 + */ void window_staff_overview_resize(rct_window *w) { window_staff_disable_widgets(w); @@ -516,7 +521,7 @@ void window_staff_overview_resize(rct_window *w) /** * Handle the dropdown of patrol button. - * rct2: 0x006BDF98 + * rct2: 0x006BDF98 */ void window_staff_overview_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) { @@ -532,7 +537,7 @@ void window_staff_overview_mousedown(int widgetIndex, rct_window* w, rct_widget* int y = widget->top + w->y; int extray = widget->bottom - widget->top + 1; window_dropdown_show_text(x, y, extray, w->colours[1], 0, 2); - gDropdownHighlightedIndex = 0; + gDropdownDefaultIndex = 0; rct_peep* peep = GET_PEEP(w->number); @@ -542,7 +547,10 @@ void window_staff_overview_mousedown(int widgetIndex, rct_window* w, rct_widget* } } -/** rct2: 0x006BDFA3 */ +/** + * + * rct2: 0x006BDFA3 + */ void window_staff_overview_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { if (widgetIndex != WIDX_PATROL) { @@ -575,7 +583,7 @@ void window_staff_overview_dropdown(rct_window *w, int widgetIndex, int dropdown /** * Update the animation frame of the tab icon. - * rct2: 0x6BE602 + * rct2: 0x6BE602 */ void window_staff_overview_update(rct_window* w) { @@ -588,7 +596,10 @@ void window_staff_overview_update(rct_window* w) widget_invalidate(w, WIDX_TAB_1); } -/** rct2: 0x006BE814 */ +/** + * + * rct2: 0x006BE814 + */ void window_staff_set_order(rct_window* w, int order_id) { rct_peep* peep = GET_PEEP(w->number); @@ -599,7 +610,10 @@ void window_staff_set_order(rct_window* w, int order_id) game_do_command(peep->x, flags, peep->y, w->number, GAME_COMMAND_SET_STAFF_ORDER, (int)peep, 0); } -/** rct2: 0x006BE7DB */ +/** + * + * rct2: 0x006BE7DB + */ void window_staff_options_mouseup(rct_window *w, int widgetIndex) { switch (widgetIndex) { @@ -620,14 +634,20 @@ void window_staff_options_mouseup(rct_window *w, int widgetIndex) } } -/** rct2: 0x006BE960 */ +/** + * + * rct2: 0x006BE960 + */ void window_staff_options_update(rct_window* w) { w->frame_no++; widget_invalidate(w, WIDX_TAB_2); } -/** rct2: 0x006BEBCF */ +/** + * + * rct2: 0x006BEBCF + */ void window_staff_stats_mouseup(rct_window *w, int widgetIndex) { switch (widgetIndex) { @@ -642,7 +662,10 @@ void window_staff_stats_mouseup(rct_window *w, int widgetIndex) } } -/** rct2: 0x006BEC1B and rct2: 0x006BE975 */ +/** + * + * rct2: 0x006BEC1B, 0x006BE975 + */ void window_staff_stats_resize(rct_window *w) { w->min_width = 190; @@ -671,7 +694,10 @@ void window_staff_stats_resize(rct_window *w) } } -/** rct2: 0x006BEBEA */ +/** + * + * rct2: 0x006BEBEA + */ void window_staff_stats_update(rct_window* w) { w->frame_no++; @@ -684,13 +710,19 @@ void window_staff_stats_update(rct_window* w) } } -/* rct2: 0x6BEC80, 0x6BE9DA */ +/** + * + * rct2: 0x6BEC80, 0x6BE9DA + */ void window_staff_unknown_05(rct_window *w) { widget_invalidate(w, WIDX_TAB_1); } -/* rct2: 0x006BE9E9 */ +/** + * + * rct2: 0x006BE9E9 + */ void window_staff_stats_invalidate(rct_window *w) { colour_scheme_update_by_class(w, (rct_windowclass)WC_STAFF); @@ -704,8 +736,8 @@ void window_staff_stats_invalidate(rct_window *w) rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; window_staff_stats_widgets[WIDX_BACKGROUND].right = w->width - 1; window_staff_stats_widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -722,7 +754,10 @@ void window_staff_stats_invalidate(rct_window *w) } -/* rct2: 0x006BE62B */ +/** + * + * rct2: 0x006BE62B + */ void window_staff_options_invalidate(rct_window *w) { colour_scheme_update_by_class(w, (rct_windowclass)WC_STAFF); @@ -736,8 +771,8 @@ void window_staff_options_invalidate(rct_window *w) rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; switch (peep->staff_type){ case STAFF_TYPE_ENTERTAINER: @@ -794,7 +829,10 @@ void window_staff_options_invalidate(rct_window *w) window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_3); } -/* rct2: 0x006BDD91 */ +/** + * + * rct2: 0x006BDD91 + */ void window_staff_overview_invalidate(rct_window *w) { colour_scheme_update_by_class(w, (rct_windowclass)WC_STAFF); @@ -808,8 +846,8 @@ void window_staff_overview_invalidate(rct_window *w) rct_peep* peep = GET_PEEP(w->number); - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; window_staff_overview_widgets[WIDX_BACKGROUND].right = w->width - 1; window_staff_overview_widgets[WIDX_BACKGROUND].bottom = w->height - 1; @@ -847,7 +885,10 @@ void window_staff_overview_invalidate(rct_window *w) window_align_tabs(w, WIDX_TAB_1, WIDX_TAB_3); } -/* rct2: 0x6BDEAF */ +/** + * + * rct2: 0x6BDEAF + */ void window_staff_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -869,16 +910,19 @@ void window_staff_overview_paint(rct_window *w, rct_drawpixelinfo *dpi) uint32 argument1, argument2; rct_peep* peep = GET_PEEP(w->number); get_arguments_from_action(peep, &argument1, &argument2); - RCT2_GLOBAL(0x13CE952, uint32) = argument1; - RCT2_GLOBAL(0x13CE952 + 4, uint32) = argument2; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = argument1; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = argument2; rct_widget* widget = &w->widgets[WIDX_BTM_LABEL]; int x = (widget->left + widget->right) / 2 + w->x; int y = w->y + widget->top; int width = widget->right - widget->left; - gfx_draw_string_centred_clipped(dpi, 1191, (void*)0x13CE952, 0, x, y, width); + gfx_draw_string_centred_clipped(dpi, 1191, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, width); } -/* rct2: 0x6BEC8F */ +/** + * + * rct2: 0x6BEC8F + */ void window_staff_options_tab_paint(rct_window* w, rct_drawpixelinfo* dpi) { if (w->disabled_widgets & (1 << WIDX_TAB_2)) return; @@ -896,7 +940,10 @@ void window_staff_options_tab_paint(rct_window* w, rct_drawpixelinfo* dpi) gfx_draw_sprite(dpi, image_id, x, y, 0); } -/* rct2: 0x6BECD3 */ +/** + * + * rct2: 0x6BECD3 + */ void window_staff_stats_tab_paint(rct_window* w, rct_drawpixelinfo* dpi) { if (w->disabled_widgets & (1 << WIDX_TAB_3)) return; @@ -929,8 +976,10 @@ void window_staff_overview_tab_paint(rct_window* w, rct_drawpixelinfo* dpi) int y = widget->top + 1 + w->y; if (w->page == WINDOW_STAFF_OVERVIEW) height++; - rct_drawpixelinfo* clip_dpi = clip_drawpixelinfo(dpi, x, width, y, height); - if (!clip_dpi) return; + rct_drawpixelinfo clip_dpi; + if (!clip_drawpixelinfo(&clip_dpi, dpi, x, y, width, height)) { + return; + } x = 14; y = 20; @@ -940,44 +989,45 @@ 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; if (w->page == WINDOW_STAFF_OVERVIEW){ - eax = w->var_494 >> 16; + eax = w->highlighted_item >> 16; eax &= 0xFFFC; } ebx += eax; int sprite_id = ebx | (peep->tshirt_colour << 19) | (peep->trousers_colour << 24) | 0xA0000000; - gfx_draw_sprite(clip_dpi, sprite_id, x, y, 0); + gfx_draw_sprite(&clip_dpi, sprite_id, x, y, 0); // If holding a balloon if (ebx >= 0x2A1D && ebx < 0x2A3D){ ebx += 32; ebx |= (peep->balloon_colour << 19) | 0x20000000; - gfx_draw_sprite(clip_dpi, ebx, x, y, 0); + gfx_draw_sprite(&clip_dpi, ebx, x, y, 0); } // If holding umbrella if (ebx >= 0x2BBD && ebx < 0x2BDD){ ebx += 32; ebx |= (peep->umbrella_colour << 19) | 0x20000000; - gfx_draw_sprite(clip_dpi, ebx, x, y, 0); + gfx_draw_sprite(&clip_dpi, ebx, x, y, 0); } // If wearing hat if (ebx >= 0x29DD && ebx < 0x29FD){ ebx += 32; ebx |= (peep->hat_colour << 19) | 0x20000000; - gfx_draw_sprite(clip_dpi, ebx, x, y, 0); + gfx_draw_sprite(&clip_dpi, ebx, x, y, 0); } - - rct2_free(clip_dpi); } -/* rct2: 0x6BE7C6 */ +/** + * + * rct2: 0x6BE7C6 + */ void window_staff_options_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -986,7 +1036,10 @@ void window_staff_options_paint(rct_window *w, rct_drawpixelinfo *dpi) window_staff_stats_tab_paint(w, dpi); } -/* rct2: 0x6BEA86 */ +/** + * + * rct2: 0x6BEA86 + */ void window_staff_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) { window_draw_widgets(w, dpi); @@ -1001,8 +1054,8 @@ void window_staff_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)){ - RCT2_GLOBAL(0x13CE952,uint32) = RCT2_ADDRESS(0x992A00,uint16)[peep->staff_type]; - gfx_draw_string_left(dpi, 2349, (void*)0x013CE952, 0,x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS,uint32) = RCT2_ADDRESS(0x992A00,uint16)[peep->staff_type]; + gfx_draw_string_left(dpi, 2349, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0,x, y); y += 10; } @@ -1034,13 +1087,32 @@ void window_staff_stats_paint(rct_window *w, rct_drawpixelinfo *dpi) } } -/* rct2: 0x006BDFD8 */ +/** + * + * rct2: 0x006BDFD8 + */ void window_staff_overview_tool_update(rct_window* w, int widgetIndex, int x, int y) { if (widgetIndex != WIDX_PICKUP) return; - RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_SPRITE, sint32) = -1; + map_invalidate_selection_rect(); + + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) &= ~(1 << 0); + + int map_x, map_y; + footpath_get_coordinates_from_pos(x, y + 16, &map_x, &map_y, NULL, NULL); + if (map_x != (sint16)0x8000) { + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_FLAGS, uint16) |= 1; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 4; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_X, sint16) = map_x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = map_x; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = map_y; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = map_y; + map_invalidate_selection_rect(); + } + + 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); @@ -1051,19 +1123,25 @@ 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; } -/* rct2: 0x006BDFC3 */ +/** + * + * rct2: 0x006BDFC3 + */ void window_staff_overview_tool_down(rct_window* w, int widgetIndex, int x, int y) { if (widgetIndex == WIDX_PICKUP) { @@ -1104,13 +1182,13 @@ 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; tool_cancel(); - RCT2_GLOBAL(0x9DE550, sint32) = -1; + RCT2_GLOBAL(RCT2_ADDRESS_PICKEDUP_PEEP_IMAGE, sint32) = -1; } else if (widgetIndex == WIDX_PATROL){ int dest_x, dest_y; @@ -1122,14 +1200,17 @@ void window_staff_overview_tool_down(rct_window* w, int widgetIndex, int x, int } } -/* rct2: 0x6BDFAE */ +/** + * + * rct2: 0x6BDFAE + */ void window_staff_overview_tool_abort(rct_window *w, int widgetIndex) { if (widgetIndex == WIDX_PICKUP) { 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){ @@ -1137,13 +1218,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(); @@ -1152,7 +1233,7 @@ void window_staff_overview_tool_abort(rct_window *w, int widgetIndex) } } -/* rct2:0x6BDFED */ +/* rct2: 0x6BDFED */ void window_staff_overview_text_input(rct_window *w, int widgetIndex, char *text) { if (widgetIndex != WIDX_RENAME) @@ -1167,13 +1248,19 @@ void window_staff_overview_text_input(rct_window *w, int widgetIndex, char *text game_do_command(0, GAME_COMMAND_FLAG_APPLY, w->number, *((int*)(text + 24)), GAME_COMMAND_SET_PEEP_NAME, *((int*)(text + 32)), *((int*)(text + 28))); } -/* rct2: 0x006BE5FC */ +/** + * + * rct2: 0x006BE5FC + */ void window_staff_overview_unknown_14(rct_window *w) { window_staff_viewport_init(w); } -/* rct2: 0x006BEDA3 */ +/** + * + * rct2: 0x006BEDA3 + */ void window_staff_viewport_init(rct_window* w){ if (w->page != WINDOW_STAFF_OVERVIEW) return; @@ -1296,7 +1383,10 @@ void window_staff_options_mousedown(int widgetIndex, rct_window* w, rct_widget* gDropdownItemsChecked = item_checked; } -/** rct2: 0x6BE809 */ +/** + * + * rct2: 0x6BE809 + */ void window_staff_options_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { if (widgetIndex != WIDX_COSTUME_BTN) { diff --git a/src/windows/staff_fire_prompt.c b/src/windows/staff_fire_prompt.c index 564888159c..1384e206f0 100644 --- a/src/windows/staff_fire_prompt.c +++ b/src/windows/staff_fire_prompt.c @@ -138,11 +138,11 @@ static void window_staff_fire_paint(rct_window *w, rct_drawpixelinfo *dpi) rct_peep* peep = &g_sprite_list[w->number].peep; - RCT2_GLOBAL(0x13CE952, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x13CE954, uint32) = peep->id; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; int x = w->x + WW / 2; int y = w->y + (WH / 2) - 3; - gfx_draw_string_centred_wrapped(dpi, (void*)0x13CE952, x, y, WW - 4, STR_FIRE_STAFF_ID, 0); + gfx_draw_string_centred_wrapped(dpi, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, x, y, WW - 4, STR_FIRE_STAFF_ID, 0); } diff --git a/src/windows/staff_list.c b/src/windows/staff_list.c index 797531f490..3af406fcf3 100644 --- a/src/windows/staff_list.c +++ b/src/windows/staff_list.c @@ -102,28 +102,33 @@ enum WINDOW_STAFF_LIST_WIDGET_IDX { WIDX_STAFF_LIST_SECURITY_TAB, WIDX_STAFF_LIST_ENTERTAINERS_TAB, WIDX_STAFF_LIST_LIST, - WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER, + WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER, WIDX_STAFF_LIST_HIRE_BUTTON, + WIDX_STAFF_LIST_QUICK_FIRE, WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON, WIDX_STAFF_LIST_MAP, - WIDX_STAFF_LIST_QUICK_FIRE, }; +#define WW 320 +#define WH 270 +#define MAX_WW 500 +#define MAX_WH 450 + static rct_widget window_staff_list_widgets[] = { - { WWT_FRAME, 0, 0, 319, 0, 269, 0x0FFFFFFFF, STR_NONE }, // panel / background - { WWT_CAPTION, 0, 1, 318, 1, 14, STR_STAFF, STR_WINDOW_TITLE_TIP }, // title bar - { WWT_CLOSEBOX, 0, 307, 317, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close button - { WWT_RESIZE, 1, 0, 319, 43, 269, 0x0FFFFFFFF, STR_NONE }, // tab content panel - { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_STAFF_HANDYMEN_TAB_TIP }, // handymen tab - { WWT_TAB, 1, 34, 64, 17, 43, 0x02000144E, STR_STAFF_MECHANICS_TAB_TIP }, // mechanics tab - { WWT_TAB, 1, 65, 95, 17, 43, 0x02000144E, STR_STAFF_SECURITY_TAB_TIP }, // security guards tab - { WWT_TAB, 1, 96, 126, 17, 43, 0x02000144E, STR_STAFF_ENTERTAINERS_TAB_TIP }, // entertainers tab - { WWT_SCROLL, 1, 3, 316, 72, 266, 3, STR_NONE }, // staff list - { WWT_COLORBTN, 1, 130, 141, 58, 69, STR_NONE, STR_UNIFORM_COLOUR_TIP }, // uniform color picker - { WWT_DROPDOWN_BUTTON, 0, 165, 309, 17, 29, STR_NONE, STR_HIRE_STAFF_TIP }, // hire button - { WWT_FLATBTN, 1, 267, 290, 46, 69, 5175, STR_SHOW_PATROL_AREA_TIP }, // show staff patrol area tool - { WWT_FLATBTN, 1, 291, 314, 46, 69, 5192, STR_SHOW_STAFF_ON_MAP_TIP }, // show staff on map button - { WWT_FLATBTN, 1, 243, 266, 46, 69, SPR_DEMOLISH, 5300 }, // quick fire staff + { WWT_FRAME, 0, 0, 319, 0, 269, 0x0FFFFFFFF, STR_NONE }, // panel / background + { WWT_CAPTION, 0, 1, 318, 1, 14, STR_STAFF, STR_WINDOW_TITLE_TIP }, // title bar + { WWT_CLOSEBOX, 0, 307, 317, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close button + { WWT_RESIZE, 1, 0, 319, 43, 269, 0x0FFFFFFFF, STR_NONE }, // tab content panel + { WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_STAFF_HANDYMEN_TAB_TIP }, // handymen tab + { WWT_TAB, 1, 34, 64, 17, 43, 0x02000144E, STR_STAFF_MECHANICS_TAB_TIP }, // mechanics tab + { WWT_TAB, 1, 65, 95, 17, 43, 0x02000144E, STR_STAFF_SECURITY_TAB_TIP }, // security guards tab + { WWT_TAB, 1, 96, 126, 17, 43, 0x02000144E, STR_STAFF_ENTERTAINERS_TAB_TIP }, // entertainers tab + { WWT_SCROLL, 1, 3, 316, 72, 266, 3, STR_NONE }, // staff list + { WWT_COLOURBTN, 1, 130, 141, 58, 69, STR_NONE, STR_UNIFORM_COLOUR_TIP }, // uniform colour picker + { WWT_DROPDOWN_BUTTON, 0, WW - 155, WW - 11, 17, 29, STR_NONE, STR_HIRE_STAFF_TIP }, // hire button + { WWT_FLATBTN, 1, WW - 77, WW - 54, 46, 69, SPR_DEMOLISH, 5300 }, // quick fire staff + { WWT_FLATBTN, 1, WW - 53, WW - 30, 46, 69, 5175, STR_SHOW_PATROL_AREA_TIP }, // show staff patrol area tool + { WWT_FLATBTN, 1, WW - 29, WW - 6, 46, 69, 5192, STR_SHOW_STAFF_ON_MAP_TIP }, // show staff on map button { WIDGETS_END }, }; @@ -152,7 +157,7 @@ void window_staff_list_open() if (window != NULL) return; - window = window_create_auto_pos(320, 270, &window_staff_list_events, WC_STAFF_LIST, WF_10 | WF_RESIZABLE); + window = window_create_auto_pos(WW, WH, &window_staff_list_events, WC_STAFF_LIST, WF_10 | WF_RESIZABLE); window->widgets = window_staff_list_widgets; window->enabled_widgets = (1 << WIDX_STAFF_LIST_CLOSE) | @@ -161,7 +166,7 @@ void window_staff_list_open() (1 << WIDX_STAFF_LIST_SECURITY_TAB) | (1 << WIDX_STAFF_LIST_ENTERTAINERS_TAB) | (1 << WIDX_STAFF_LIST_HIRE_BUTTON) | - (1 << WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER) | + (1 << WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER) | (1 << WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON) | (1 << WIDX_STAFF_LIST_MAP) | (1 << WIDX_STAFF_LIST_QUICK_FIRE); @@ -170,18 +175,18 @@ void window_staff_list_open() RCT2_GLOBAL(RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX, short) = -1; window->list_information_type = 0; - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER].type = WWT_EMPTY; - window->min_width = 320; - window->min_height = 270; - window->max_width = 500; - window->max_height = 450; + window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WWT_EMPTY; + window->min_width = WW; + window->min_height = WH; + window->max_width = MAX_WW; + window->max_height = MAX_WH; _quick_fire_mode = false; } 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(); } @@ -240,8 +245,8 @@ static void window_staff_list_mouseup(rct_window *w, int widgetIndex) */ static void window_staff_list_resize(rct_window *w) { - w->min_width = 320; - w->min_height = 270; + w->min_width = WW; + w->min_height = WH; if (w->width < w->min_width) { w->width = w->min_width; window_invalidate(w); @@ -274,7 +279,7 @@ static void window_staff_list_mousedown(int widgetIndex, rct_window* w, rct_widg w->scrolls[0].v_top = 0; window_staff_list_cancel_tools(w); break; - case WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER: + case WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER: window_dropdown_show_colour(w, widget, w->colours[1], RCT2_ADDRESS(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8)[RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)]); break; } @@ -288,7 +293,7 @@ static void window_staff_list_mousedown(int widgetIndex, rct_window* w, rct_widg */ static void window_staff_list_dropdown(rct_window *w, int widgetIndex, int dropdownIndex) { - if (widgetIndex == WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER && dropdownIndex != -1) { + if (widgetIndex == WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER && dropdownIndex != -1) { update_staff_colour(RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8), dropdownIndex); } } @@ -308,13 +313,11 @@ void window_staff_list_update(rct_window *w) } else { widget_invalidate(w, WIDX_STAFF_LIST_HANDYMEN_TAB + RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)); 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; + FOR_ALL_STAFF(spriteIndex, peep) { + peep->flags &= ~(SPRITE_FLAGS_PEEP_FLASHING); - if (peep->staff_type == RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)) { - peep->var_0C |= 0x200; - } + if (peep->staff_type == RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)) { + peep->flags |= SPRITE_FLAGS_PEEP_FLASHING; } } } @@ -350,7 +353,7 @@ static void window_staff_list_tooldown(rct_window *w, int widgetIndex, int x, in if (!(gStaffModes[peep->staff_id] & 2)) { continue; } - if (!mechanic_is_location_in_patrol(peep, x, y)) { + if (!staff_is_location_in_patrol(peep, x, y)) { continue; } } @@ -401,8 +404,8 @@ void window_staff_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, rct_peep *peep; uint16 staffCount = 0; - FOR_ALL_PEEPS(spriteIndex, peep) { - if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)) + FOR_ALL_STAFF(spriteIndex, peep) { + if (peep->staff_type == RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)) staffCount++; } @@ -435,10 +438,7 @@ void window_staff_list_scrollmousedown(rct_window *w, int scrollIndex, int x, in rct_peep *peep; i = y / 10; - FOR_ALL_PEEPS(spriteIndex, peep) { - if (peep->type != PEEP_TYPE_STAFF) - continue; - + FOR_ALL_STAFF(spriteIndex, peep) { if (peep->staff_type != RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8)) continue; @@ -490,20 +490,20 @@ void window_staff_list_invalidate(rct_window *w) uint8 tabIndex = RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8); uint8 widgetIndex = tabIndex + 4; - w->pressed_widgets = pressed_widgets | (1 << widgetIndex); + w->pressed_widgets = pressed_widgets | (1ULL << widgetIndex); window_staff_list_widgets[WIDX_STAFF_LIST_HIRE_BUTTON].image = STR_HIRE_HANDYMAN + tabIndex; - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER].type = WWT_EMPTY; + window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WWT_EMPTY; if (tabIndex < 3) { - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER].type = WWT_COLORBTN; - window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER].image = + window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].type = WWT_COLOURBTN; + window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].image = ((uint32)RCT2_ADDRESS(RCT2_ADDRESS_HANDYMAN_COLOUR, uint8)[tabIndex] << 19) + 0x600013C3; } if (_quick_fire_mode) - w->pressed_widgets |= (1 << WIDX_STAFF_LIST_QUICK_FIRE); + w->pressed_widgets |= (1ULL << WIDX_STAFF_LIST_QUICK_FIRE); else - w->pressed_widgets &= ~(1 << WIDX_STAFF_LIST_QUICK_FIRE); + w->pressed_widgets &= ~(1ULL << WIDX_STAFF_LIST_QUICK_FIRE); window_staff_list_widgets[WIDX_STAFF_LIST_BACKGROUND].right = w->width - 1; window_staff_list_widgets[WIDX_STAFF_LIST_BACKGROUND].bottom = w->height - 1; @@ -514,6 +514,14 @@ void window_staff_list_invalidate(rct_window *w) window_staff_list_widgets[WIDX_STAFF_LIST_CLOSE].right = w->width - 2 - 0x0B + 0x0A; window_staff_list_widgets[WIDX_STAFF_LIST_LIST].right = w->width - 4; window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom = w->height - 0x0F; + window_staff_list_widgets[WIDX_STAFF_LIST_QUICK_FIRE].left = w->width - 77; + window_staff_list_widgets[WIDX_STAFF_LIST_QUICK_FIRE].right = w->width - 54; + window_staff_list_widgets[WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON].left = w->width - 53; + window_staff_list_widgets[WIDX_STAFF_LIST_SHOW_PATROL_AREA_BUTTON].right = w->width - 30; + window_staff_list_widgets[WIDX_STAFF_LIST_MAP].left = w->width - 29; + window_staff_list_widgets[WIDX_STAFF_LIST_MAP].right = w->width - 6; + window_staff_list_widgets[WIDX_STAFF_LIST_HIRE_BUTTON].left = w->width - 155; + window_staff_list_widgets[WIDX_STAFF_LIST_HIRE_BUTTON].right = w->width - 11; } /** @@ -566,36 +574,28 @@ void window_staff_list_paint(rct_window *w, rct_drawpixelinfo *dpi) window_staff_list_widgets[WIDX_STAFF_LIST_SECURITY_TAB].bottom - 6 + w->y, 0 ); - rct_drawpixelinfo* sprite_dpi = clip_drawpixelinfo( + rct_drawpixelinfo sprite_dpi; + if (clip_drawpixelinfo( + &sprite_dpi, dpi, window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].left + w->x + 1, - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].right - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].left - 1, window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].top + w->y + 1, + window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].right - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].left - 1, window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].bottom - window_staff_list_widgets[WIDX_STAFF_LIST_ENTERTAINERS_TAB].top - 1 - ); - - - - if (sprite_dpi != NULL) { + )) { // Entertainers tab image i = (selectedTab == 3 ? w->list_information_type & 0x0FFFFFFFC : 0); i += RCT2_ADDRESS(RCT2_GLOBAL(0x00982738, int), int)[0] + 1; - gfx_draw_sprite( - sprite_dpi, - i, - 0x0F, - 0x17, 0 - ); - rct2_free(sprite_dpi); + gfx_draw_sprite(&sprite_dpi, i, 0x0F, 0x17, 0); } if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) { RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = RCT2_ADDRESS(0x00992A00, uint16)[selectedTab]; - gfx_draw_string_left(dpi, 1858, (void*)0x013CE952, 0, w->x + 0xA5, w->y + 0x20); + gfx_draw_string_left(dpi, 1858, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + w->width - 155, w->y + 0x20); } if (selectedTab < 3) { - gfx_draw_string_left(dpi, STR_UNIFORM_COLOUR, w, 0, w->x + 6, window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOR_PICKER].top + w->y + 1); + gfx_draw_string_left(dpi, STR_UNIFORM_COLOUR, w, 0, w->x + 6, window_staff_list_widgets[WIDX_STAFF_LIST_UNIFORM_COLOUR_PICKER].top + w->y + 1); } int staffTypeStringId = 1859 + selectedTab; @@ -605,9 +605,9 @@ void window_staff_list_paint(rct_window *w, rct_drawpixelinfo *dpi) } RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = _window_staff_list_selected_type_count; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = staffTypeStringId; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = staffTypeStringId; - gfx_draw_string_left(dpi, STR_STAFF_LIST_COUNTER, (void*)0x013CE952, 0, w->x + 4, window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom + w->y + 2); + gfx_draw_string_left(dpi, STR_STAFF_LIST_COUNTER, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, w->x + 4, window_staff_list_widgets[WIDX_STAFF_LIST_LIST].bottom + w->y + 2); } /** @@ -626,8 +626,8 @@ void window_staff_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int sc y = 0; i = 0; selectedTab = RCT2_GLOBAL(RCT2_ADDRESS_WINDOW_STAFF_LIST_SELECTED_TAB, uint8); - FOR_ALL_PEEPS(spriteIndex, peep) { - if (peep->type == PEEP_TYPE_STAFF && peep->staff_type == selectedTab) { + FOR_ALL_STAFF(spriteIndex, peep) { + if (peep->staff_type == selectedTab) { if (y > dpi->y + dpi->height) { break; } @@ -641,13 +641,13 @@ void window_staff_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int sc } RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint16) = peep->name_string_idx; - RCT2_GLOBAL(0x013CE952 + 2, uint32) = peep->id; - gfx_draw_string_left_clipped(dpi, format, (void*)0x013CE952, 0, 0, y - 1, 107); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = peep->id; + gfx_draw_string_left_clipped(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 0, y - 1, 107); get_arguments_from_action(peep, &argument_1, &argument_2); RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS, uint32) = argument_1; - RCT2_GLOBAL(0x013CE952 + 4, uint32) = argument_2; - gfx_draw_string_left_clipped(dpi, format, (void*)0x013CE952, 0, 175, y - 1, 305); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 4, uint32) = argument_2; + gfx_draw_string_left_clipped(dpi, format, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, 175, y - 1, 305); // True if a patrol path is set for the worker if (RCT2_ADDRESS(RCT2_ADDRESS_STAFF_MODE_ARRAY, uint8)[peep->staff_id] & 2) { diff --git a/src/windows/text_input.c b/src/windows/text_input.c index 48cbef83d6..d9404443ae 100644 --- a/src/windows/text_input.c +++ b/src/windows/text_input.c @@ -111,21 +111,21 @@ void window_text_input_open(rct_window* call_w, int call_widget, rct_string_id t // Enter in the the text input buffer any existing // text. - if (existing_text != (rct_string_id)STR_NONE) + if (existing_text != STR_NONE) format_string(text_input, existing_text, &existing_args); // In order to prevent strings that exceed the maxLength // from crashing the game. text_input[maxLength - 1] = '\0'; - utf8_remove_format_codes(text_input); + utf8_remove_format_codes(text_input, false); // This is the text displayed above the input box input_text_description = description; // Work out the existing size of the window char wrapped_string[512]; - safe_strncpy(wrapped_string, text_input, 512); + safe_strcpy(wrapped_string, text_input, 512); int no_lines = 0, font_height = 0; @@ -175,7 +175,7 @@ void window_text_input_raw_open(rct_window* call_w, int call_widget, rct_string_ // Enter in the the text input buffer any existing // text. if (existing_text != NULL) - safe_strncpy(text_input, existing_text, maxLength); + safe_strcpy(text_input, existing_text, maxLength); // In order to prevent strings that exceed the maxLength // from crashing the game. @@ -186,7 +186,7 @@ void window_text_input_raw_open(rct_window* call_w, int call_widget, rct_string_ // Work out the existing size of the window char wrapped_string[512]; - safe_strncpy(wrapped_string, text_input, 512); + safe_strcpy(wrapped_string, text_input, 512); int no_lines = 0, font_height = 0; @@ -273,7 +273,7 @@ static void window_text_input_paint(rct_window *w, rct_drawpixelinfo *dpi) RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_FLAGS, uint16) = 0; char wrapped_string[512]; - safe_strncpy(wrapped_string, text_input, 512); + safe_strcpy(wrapped_string, text_input, 512); // String length needs to add 12 either side of box // +13 for cursor when max length. @@ -293,19 +293,19 @@ static void window_text_input_paint(rct_window *w, rct_drawpixelinfo *dpi) int string_length = get_string_size(wrap_pointer) - 1; - if (!cur_drawn && (gTextInputCursorPosition <= char_count + string_length)) { + if (!cur_drawn && (gTextInput.selection_offset <= (size_t)(char_count + string_length))) { // Make a copy of the string for measuring the width. char temp_string[512] = { 0 }; - memcpy(temp_string, wrap_pointer, gTextInputCursorPosition - char_count); + memcpy(temp_string, wrap_pointer, gTextInput.selection_offset - char_count); cursorX = w->x + 13 + gfx_get_string_width(temp_string); cursorY = y; int width = 6; - if ((uint32)gTextInputCursorPosition < strlen(text_input)){ + if ((uint32)gTextInput.selection_offset < strlen(text_input)){ // Make a new 1 character wide string for measuring the width // of the character that the cursor is under. temp_string[1] = '\0'; - temp_string[0] = text_input[gTextInputCursorPosition]; + temp_string[0] = text_input[gTextInput.selection_offset]; width = max(gfx_get_string_width(temp_string) - 2, 4); } @@ -389,7 +389,7 @@ static void window_text_input_invalidate(rct_window *w) { // Work out the existing size of the window char wrapped_string[512]; - safe_strncpy(wrapped_string, text_input, 512); + safe_strcpy(wrapped_string, text_input, 512); int no_lines = 0, font_height = 0; diff --git a/src/windows/themes.c b/src/windows/themes.c index 51694d493d..53971bf842 100644 --- a/src/windows/themes.c +++ b/src/windows/themes.c @@ -114,7 +114,7 @@ enum WINDOW_STAFF_LIST_WIDGET_IDX { WIDX_THEMES_DUPLICATE_BUTTON, WIDX_THEMES_DELETE_BUTTON, WIDX_THEMES_RENAME_BUTTON, - WIDX_THEMES_COLORBTN_MASK, + WIDX_THEMES_COLOURBTN_MASK, WIDX_THEMES_LIST, WIDX_THEMES_RCT1_RIDE_LIGHTS, WIDX_THEMES_RCT1_PARK_LIGHTS, @@ -140,7 +140,7 @@ static rct_widget window_themes_widgets[] = { { WWT_DROPDOWN_BUTTON, 1, 10, 100, 82, 93, 5239, 5257 }, // Duplicate button { WWT_DROPDOWN_BUTTON, 1, 110, 200, 82, 93, 3349, 5258 }, // Delete button { WWT_DROPDOWN_BUTTON, 1, 210, 300, 82, 93, 3348, 5259 }, // Rename button - { WWT_COLORBTN, 1, 0, 0, 0, 0, STR_NONE, STR_NONE }, // color button mask + { WWT_COLOURBTN, 1, 0, 0, 0, 0, STR_NONE, STR_NONE }, // colour button mask { WWT_SCROLL, 1, 3, 316, 60, 103, 2, STR_NONE }, // staff list { WWT_CHECKBOX, 1, 10, 299, 54, 65, 5282, STR_NONE }, // rct1 ride lights { WWT_CHECKBOX, 1, 10, 299, 69, 80, 5283, STR_NONE }, // rct1 park lights @@ -238,12 +238,17 @@ static rct_windowclass window_themes_tab_5_classes[] = { static rct_windowclass window_themes_tab_6_classes[] = { WC_CHEATS, + WC_TILE_INSPECTOR, WC_THEMES, WC_TITLE_EDITOR, WC_OPTIONS, WC_KEYBOARD_SHORTCUT_LIST, WC_CHANGE_KEYBOARD_SHORTCUT, - WC_LOADSAVE + WC_LOADSAVE, + WC_CHANGELOG, + WC_SERVER_LIST, + WC_MULTIPLAYER, + WC_PLAYER, }; static rct_windowclass window_themes_tab_7_classes[] = { @@ -251,12 +256,24 @@ static rct_windowclass window_themes_tab_7_classes[] = { WC_DEMOLISH_RIDE_PROMPT, WC_FIRE_PROMPT, WC_TRACK_DELETE_PROMPT, - WC_LOADSAVE_OVERWRITE_PROMPT + WC_LOADSAVE_OVERWRITE_PROMPT, + WC_NETWORK_STATUS, +}; + +static rct_windowclass *window_themes_tab_classes[] = { + NULL, + window_themes_tab_1_classes, + window_themes_tab_2_classes, + window_themes_tab_3_classes, + window_themes_tab_4_classes, + window_themes_tab_5_classes, + window_themes_tab_6_classes, + window_themes_tab_7_classes, }; static uint8 _selected_tab = 0; -static sint16 _color_index_1 = -1; -static sint8 _color_index_2 = -1; +static sint16 _colour_index_1 = -1; +static sint8 _colour_index_2 = -1; static const uint8 _row_height = 32; static const uint8 _button_offset_x = 220; static const uint8 _button_offset_y = 3; @@ -267,57 +284,10 @@ void window_themes_init_vars() _selected_tab = WINDOW_THEMES_TAB_SETTINGS; } -static theme_window_definition* get_colour_scheme_tab_definition() +static rct_windowclass get_window_class_tab_index(int index) { - switch (_selected_tab) { - case 1: return theme_window_definition_get_by_class(window_themes_tab_1_classes[_color_index_1]); - case 2: return theme_window_definition_get_by_class(window_themes_tab_2_classes[_color_index_1]); - case 3: return theme_window_definition_get_by_class(window_themes_tab_3_classes[_color_index_1]); - case 4: return theme_window_definition_get_by_class(window_themes_tab_4_classes[_color_index_1]); - case 5: return theme_window_definition_get_by_class(window_themes_tab_5_classes[_color_index_1]); - case 6: return theme_window_definition_get_by_class(window_themes_tab_6_classes[_color_index_1]); - case 7: return theme_window_definition_get_by_class(window_themes_tab_7_classes[_color_index_1]); - } - return NULL; -} -static theme_window_definition* get_colour_scheme_tab_definition_by_index(int index) -{ - switch (_selected_tab) { - case 1: return theme_window_definition_get_by_class(window_themes_tab_1_classes[index]); - case 2: return theme_window_definition_get_by_class(window_themes_tab_2_classes[index]); - case 3: return theme_window_definition_get_by_class(window_themes_tab_3_classes[index]); - case 4: return theme_window_definition_get_by_class(window_themes_tab_4_classes[index]); - case 5: return theme_window_definition_get_by_class(window_themes_tab_5_classes[index]); - case 6: return theme_window_definition_get_by_class(window_themes_tab_6_classes[index]); - case 7: return theme_window_definition_get_by_class(window_themes_tab_7_classes[index]); - } - return NULL; -} -static theme_window* get_colour_scheme_tab() -{ - switch (_selected_tab) { - case 1: return theme_window_get_by_class(window_themes_tab_1_classes[_color_index_1]); - case 2: return theme_window_get_by_class(window_themes_tab_2_classes[_color_index_1]); - case 3: return theme_window_get_by_class(window_themes_tab_3_classes[_color_index_1]); - case 4: return theme_window_get_by_class(window_themes_tab_4_classes[_color_index_1]); - case 5: return theme_window_get_by_class(window_themes_tab_5_classes[_color_index_1]); - case 6: return theme_window_get_by_class(window_themes_tab_6_classes[_color_index_1]); - case 7: return theme_window_get_by_class(window_themes_tab_7_classes[_color_index_1]); - } - return NULL; -} -static theme_window* get_colour_scheme_tab_by_index(int index) -{ - switch (_selected_tab) { - case 1: return theme_window_get_by_class(window_themes_tab_1_classes[index]); - case 2: return theme_window_get_by_class(window_themes_tab_2_classes[index]); - case 3: return theme_window_get_by_class(window_themes_tab_3_classes[index]); - case 4: return theme_window_get_by_class(window_themes_tab_4_classes[index]); - case 5: return theme_window_get_by_class(window_themes_tab_5_classes[index]); - case 6: return theme_window_get_by_class(window_themes_tab_6_classes[index]); - case 7: return theme_window_get_by_class(window_themes_tab_7_classes[index]); - } - return NULL; + rct_windowclass * classes = window_themes_tab_classes[_selected_tab]; + return classes[index]; } static int get_colour_scheme_tab_count() @@ -334,19 +304,6 @@ static int get_colour_scheme_tab_count() return 0; } -/*static int get_colour_scheme_index() { - switch (_selected_tab) { - case 1: return theme_window_get_index_by_class(window_themes_tab_1_classes[_color_index_1]); - case 2: return theme_window_get_index_by_class(window_themes_tab_2_classes[_color_index_1]); - case 3: return theme_window_get_index_by_class(window_themes_tab_3_classes[_color_index_1]); - case 4: return theme_window_get_index_by_class(window_themes_tab_4_classes[_color_index_1]); - case 5: return theme_window_get_index_by_class(window_themes_tab_5_classes[_color_index_1]); - case 6: return theme_window_get_index_by_class(window_themes_tab_6_classes[_color_index_1]); - case 7: return theme_window_get_index_by_class(window_themes_tab_7_classes[_color_index_1]); - } - return -1; -}*/ - static void window_themes_draw_tab_images(rct_drawpixelinfo *dpi, rct_window *w) { int sprite_idx; @@ -381,7 +338,7 @@ void window_themes_open() (1 << WIDX_THEMES_MISC_TAB) | (1 << WIDX_THEMES_PROMPTS_TAB) | (1 << WIDX_THEMES_FEATURES_TAB) | - (1 << WIDX_THEMES_COLORBTN_MASK) | + (1 << WIDX_THEMES_COLOURBTN_MASK) | (1 << WIDX_THEMES_PRESETS) | (1 << WIDX_THEMES_PRESETS_DROPDOWN) | (1 << WIDX_THEMES_DUPLICATE_BUTTON) | @@ -395,8 +352,8 @@ void window_themes_open() window_init_scroll_widgets(window); window->list_information_type = 0; - _color_index_1 = -1; - _color_index_2 = -1; + _colour_index_1 = -1; + _colour_index_2 = -1; window->min_width = 320; window->min_height = 107; window->max_width = 320; @@ -405,27 +362,32 @@ void window_themes_open() static void window_themes_mouseup(rct_window *w, int widgetIndex) { + int activeAvailableThemeIndex; + const utf8 * activeThemeName; + switch (widgetIndex) { case WIDX_THEMES_CLOSE: window_close(w); break; - case WIDX_THEMES_DUPLICATE_BUTTON: - window_text_input_open(w, widgetIndex, 5239, 5240, 1170, (uint32)&gConfigThemes.presets[gCurrentTheme].name, 64); + case WIDX_THEMES_DUPLICATE_BUTTON:; + activeAvailableThemeIndex = theme_manager_get_active_available_theme_index(); + activeThemeName = theme_manager_get_available_theme_name(activeAvailableThemeIndex); + window_text_input_open(w, widgetIndex, 5239, 5240, 1170, (uint32)activeThemeName, 64); break; case WIDX_THEMES_DELETE_BUTTON: - if (gCurrentTheme >= 2) { - theme_delete_preset(gCurrentTheme); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_delete(); } break; case WIDX_THEMES_RENAME_BUTTON: - if (gCurrentTheme >= 2) { - window_text_input_open(w, widgetIndex, 3348, 5240, 1170, (uint32)&gConfigThemes.presets[gCurrentTheme].name, 64); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + activeAvailableThemeIndex = theme_manager_get_active_available_theme_index(); + activeThemeName = theme_manager_get_available_theme_name(activeAvailableThemeIndex); + window_text_input_open(w, widgetIndex, 3348, 5240, 1170, (uint32)activeThemeName, 64); } break; } @@ -507,7 +469,7 @@ static void window_themes_resize(rct_window *w) static void window_themes_mousedown(int widgetIndex, rct_window* w, rct_widget* widget) { short newSelectedTab; - int num_items, i; + int num_items; switch (widgetIndex) { case WIDX_THEMES_SETTINGS_TAB: @@ -529,19 +491,15 @@ static void window_themes_mousedown(int widgetIndex, rct_window* w, rct_widget* window_invalidate(w); break; case WIDX_THEMES_PRESETS_DROPDOWN: - num_items = gConfigThemes.num_presets; + theme_manager_load_available_themes(); + num_items = (int)theme_manager_get_num_available_themes(); widget--; - gDropdownItemsFormat[0] = 2777; - gDropdownItemsArgs[0] = (uint32)&gConfigThemes.presets[1].name; - gDropdownItemsFormat[1] = 2777; - gDropdownItemsArgs[1] = (uint32)&gConfigThemes.presets[0].name; - - for (i = 2; i < num_items; i++) { + for (int i = 0; i < num_items; i++) { gDropdownItemsFormat[i] = 2777; - gDropdownItemsArgs[i] = (uint32)&gConfigThemes.presets[i].name; + gDropdownItemsArgs[i] = (uint32)theme_manager_get_available_theme_name(i); } - + window_dropdown_show_text_custom_width( w->x + widget->left, w->y + widget->top, @@ -550,42 +508,35 @@ static void window_themes_mousedown(int widgetIndex, rct_window* w, rct_widget* DROPDOWN_FLAG_STAY_OPEN, num_items, widget->right - widget->left - 3 - ); + ); - if (gCurrentTheme == 0 || gCurrentTheme == 1) { - dropdown_set_checked(gCurrentTheme ^ 1, true); - } else { - dropdown_set_checked(gCurrentTheme, true); - } + dropdown_set_checked(theme_manager_get_active_available_theme_index(), true); break; case WIDX_THEMES_RCT1_RIDE_LIGHTS: - if (gCurrentTheme >= 2) { - theme_get_preset()->features.rct1_ride_lights ^= 1; - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_set_flags(theme_get_flags() ^ UITHEME_FLAG_USE_LIGHTS_RIDE); + theme_save(); + window_invalidate_all(); } break; case WIDX_THEMES_RCT1_PARK_LIGHTS: - if (gCurrentTheme >= 2) { - theme_get_preset()->features.rct1_park_lights ^= 1; - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_set_flags(theme_get_flags() ^ UITHEME_FLAG_USE_LIGHTS_PARK); + theme_save(); + window_invalidate_all(); } break; case WIDX_THEMES_RCT1_SCENARIO_FONT: - if (gCurrentTheme >= 2) { - theme_get_preset()->features.rct1_scenario_font ^= 1; - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, STR_NONE); + } else { + theme_set_flags(theme_get_flags() ^ UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT); + theme_save(); + window_invalidate_all(); } break; } @@ -596,22 +547,22 @@ static void window_themes_dropdown(rct_window *w, int widgetIndex, int dropdownI switch (widgetIndex) { case WIDX_THEMES_LIST: if (dropdownIndex != -1) { - get_colour_scheme_tab()->colours[_color_index_2] = dropdownIndex | (get_colour_scheme_tab()->colours[_color_index_2] & 0x80); + rct_windowclass wc = get_window_class_tab_index(_colour_index_1); + uint8 colour = theme_get_colour(wc, _colour_index_2); + colour = (colour & COLOUR_FLAG_TRANSLUCENT) | dropdownIndex; + theme_set_colour(wc, _colour_index_2, colour); window_invalidate_all(); - _color_index_1 = -1; - _color_index_2 = -1; + _colour_index_1 = -1; + _colour_index_2 = -1; - if (gCurrentTheme >= 2) - themes_save_preset(gCurrentTheme); + // if (gCurrentTheme >= 2) + // themes_save_preset(gCurrentTheme); } break; case WIDX_THEMES_PRESETS_DROPDOWN: if (dropdownIndex != -1) { - if (dropdownIndex == 0 || dropdownIndex == 1) - dropdownIndex ^= 1; - theme_change_preset(dropdownIndex); + theme_manager_set_active_available_theme(dropdownIndex); } - config_save_default(); break; } @@ -649,35 +600,39 @@ void window_themes_scrollmousedown(rct_window *w, int scrollIndex, int x, int y) { if (y / _row_height < get_colour_scheme_tab_count()) { int y2 = y % _row_height; - _color_index_1 = y / _row_height; - _color_index_2 = ((x - _button_offset_x) / 12); - if (_color_index_2 < get_colour_scheme_tab_definition()->num_colours) { + _colour_index_1 = y / _row_height; + _colour_index_2 = ((x - _button_offset_x) / 12); + + rct_windowclass wc = get_window_class_tab_index(_colour_index_1); + int numColours = theme_desc_get_num_colours(wc); + if (_colour_index_2 < numColours) { if (x >= _button_offset_x && x < _button_offset_x + 12 * 6 && y2 >= _button_offset_y && y2 < _button_offset_y + 11) { - if (gCurrentTheme >= 2) { - window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].left = _button_offset_x + _color_index_2 * 12 + window_themes_widgets[WIDX_THEMES_LIST].left; - window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].top = _color_index_1 * _row_height + _button_offset_y - w->scrolls[0].v_top + window_themes_widgets[WIDX_THEMES_LIST].top; - window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].right = window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].left + 12; - window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].bottom = window_themes_widgets[WIDX_THEMES_COLORBTN_MASK].top + 12; - window_dropdown_show_colour(w, &(window_themes_widgets[WIDX_THEMES_COLORBTN_MASK]), w->colours[1], get_colour_scheme_tab()->colours[_color_index_2]); - widget_invalidate(w, WIDX_THEMES_LIST); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, 5256); + } else { + window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].type = WWT_COLOURBTN; + window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].left = _button_offset_x + _colour_index_2 * 12 + window_themes_widgets[WIDX_THEMES_LIST].left; + window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].top = _colour_index_1 * _row_height + _button_offset_y - w->scrolls[0].v_top + window_themes_widgets[WIDX_THEMES_LIST].top; + window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].right = window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].left + 12; + window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].bottom = window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].top + 12; + + uint8 colour = theme_get_colour(wc, _colour_index_2); + window_dropdown_show_colour(w, &(window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK]), w->colours[1], colour); + widget_invalidate(w, WIDX_THEMES_LIST); } } else if (x >= _button_offset_x && x < _button_offset_x + 12 * 6 - 1 && y2 >= _check_offset_y && y2 < _check_offset_y + 11) { - if (gCurrentTheme >= 2) { - if (get_colour_scheme_tab()->colours[_color_index_2] & 0x80) { - get_colour_scheme_tab()->colours[_color_index_2] &= 0x7F; - } - else { - get_colour_scheme_tab()->colours[_color_index_2] |= 0x80; - } - themes_save_preset(gCurrentTheme); - window_invalidate_all(); - } - else { + if (theme_get_flags() & UITHEME_FLAG_PREDEFINED) { window_error_open(5241, 5256); + } else { + uint8 colour = theme_get_colour(wc, _colour_index_2); + if (colour & COLOUR_FLAG_TRANSLUCENT) { + colour &= ~COLOUR_FLAG_TRANSLUCENT; + } else { + colour |= COLOUR_FLAG_TRANSLUCENT; + } + theme_set_colour(wc, _colour_index_2, colour); + window_invalidate_all(); } } } @@ -700,25 +655,26 @@ static void window_themes_textinput(rct_window *w, int widgetIndex, char *text) case WIDX_THEMES_RENAME_BUTTON: if (filename_valid_characters(text)) { bool nameTaken = false; - for (int i = 0; i < gConfigThemes.num_presets; i++) { - if (strcmp(gConfigThemes.presets[i].name, text) == 0) { - window_error_open(5242, STR_NONE); + int numAvailableThemes = (int)theme_manager_get_num_available_themes(); + for (int i = 0; i < numAvailableThemes; i++) { + const utf8 * themeName = theme_manager_get_available_theme_name(i); + if (strcmp(themeName, text) == 0) { + if (widgetIndex != WIDX_THEMES_RENAME_BUTTON) { + window_error_open(5242, STR_NONE); + } nameTaken = true; break; } } if (!nameTaken) { if (widgetIndex == WIDX_THEMES_DUPLICATE_BUTTON) { - theme_create_preset(gCurrentTheme, text); + theme_duplicate(text); + } else { + theme_rename(text); } - else { - theme_rename_preset(gCurrentTheme, text); - } - config_save_default(); window_invalidate(w); } - } - else { + } else { window_error_open(5243, STR_NONE); } break; @@ -740,8 +696,8 @@ void window_themes_invalidate(rct_window *w) w->pressed_widgets = pressed_widgets | (1 << widgetIndex); if (window_find_by_class(WC_DROPDOWN) == NULL) { - _color_index_1 = -1; - _color_index_2 = -1; + _colour_index_1 = -1; + _colour_index_2 = -1; } window_themes_widgets[WIDX_THEMES_BACKGROUND].right = w->width - 1; @@ -764,6 +720,7 @@ void window_themes_invalidate(rct_window *w) window_themes_widgets[WIDX_THEMES_RENAME_BUTTON].type = WWT_EMPTY; window_themes_widgets[WIDX_THEMES_PRESETS].type = WWT_EMPTY; window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].type = WWT_EMPTY; + window_themes_widgets[WIDX_THEMES_COLOURBTN_MASK].type = WWT_EMPTY; if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS) { window_themes_widgets[WIDX_THEMES_LIST].type = WWT_EMPTY; @@ -787,9 +744,9 @@ void window_themes_invalidate(rct_window *w) window_themes_widgets[WIDX_THEMES_PRESETS].type = WWT_EMPTY; window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].type = WWT_EMPTY; - widget_set_checkbox_value(w, WIDX_THEMES_RCT1_RIDE_LIGHTS, theme_get_preset()->features.rct1_ride_lights); - widget_set_checkbox_value(w, WIDX_THEMES_RCT1_PARK_LIGHTS, theme_get_preset()->features.rct1_park_lights); - widget_set_checkbox_value(w, WIDX_THEMES_RCT1_SCENARIO_FONT, theme_get_preset()->features.rct1_scenario_font); + widget_set_checkbox_value(w, WIDX_THEMES_RCT1_RIDE_LIGHTS, theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_RIDE); + widget_set_checkbox_value(w, WIDX_THEMES_RCT1_PARK_LIGHTS, theme_get_flags() & UITHEME_FLAG_USE_LIGHTS_PARK); + widget_set_checkbox_value(w, WIDX_THEMES_RCT1_SCENARIO_FONT, theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT); } else { window_themes_widgets[WIDX_THEMES_LIST].type = WWT_SCROLL; @@ -811,7 +768,9 @@ void window_themes_paint(rct_window *w, rct_drawpixelinfo *dpi) window_themes_draw_tab_images(dpi, w); if (_selected_tab == WINDOW_THEMES_TAB_SETTINGS) { - RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)&gConfigThemes.presets[gCurrentTheme].name; + int activeAvailableThemeIndex = theme_manager_get_active_available_theme_index(); + const utf8 * activeThemeName = theme_manager_get_available_theme_name(activeAvailableThemeIndex); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = (uint32)activeThemeName; gfx_draw_string_left(dpi, 5238, NULL, w->colours[1], w->x + 10, w->y + window_themes_widgets[WIDX_THEMES_PRESETS].top + 1); gfx_draw_string_left_clipped( dpi, @@ -821,7 +780,7 @@ void window_themes_paint(rct_window *w, rct_drawpixelinfo *dpi) w->x + window_themes_widgets[WIDX_THEMES_PRESETS].left + 1, w->y + window_themes_widgets[WIDX_THEMES_PRESETS].top, w->x + window_themes_widgets[WIDX_THEMES_PRESETS_DROPDOWN].left - window_themes_widgets[WIDX_THEMES_PRESETS].left - 4 - ); + ); } else if (_selected_tab == WINDOW_THEMES_TAB_FEATURES) { @@ -869,18 +828,20 @@ void window_themes_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scroll } } - for (int j = 0; j < get_colour_scheme_tab_definition_by_index(i)->num_colours; j++) { + rct_windowclass wc = get_window_class_tab_index(i); + int numColours = theme_desc_get_num_colours(wc); + for (uint8 j = 0; j < numColours; j++) { + gfx_draw_string_left(dpi, theme_desc_get_name(wc), NULL, w->colours[1], 2, y + 4); - gfx_draw_string_left(dpi, get_colour_scheme_tab_definition_by_index(i)->name, NULL, w->colours[1], 2, y + 4); - - uint32 image = ((get_colour_scheme_tab_by_index(i)->colours[j] & 0x7F) << 19) + 0x600013C3; - if (i == _color_index_1 && j == _color_index_2) { - image = ((get_colour_scheme_tab_by_index(i)->colours[j] & 0x7F) << 19) + 0x600013C4; + uint8 colour = theme_get_colour(wc, j); + uint32 image = ((colour & ~COLOUR_FLAG_TRANSLUCENT) << 19) + 0x600013C3; + if (i == _colour_index_1 && j == _colour_index_2) { + image = ((colour & ~COLOUR_FLAG_TRANSLUCENT) << 19) + 0x600013C4; } gfx_draw_sprite(dpi, image, _button_offset_x + 12 * j, y + _button_offset_y, 0); gfx_fill_rect_inset(dpi, _button_offset_x + 12 * j, y + _check_offset_y, _button_offset_x + 12 * j + 9, y + _check_offset_y + 10, w->colours[1], 0xE0); - if (get_colour_scheme_tab_by_index(i)->colours[j] & 0x80) { + if (colour & COLOUR_FLAG_TRANSLUCENT) { RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = -1; gfx_draw_string(dpi, (char*)CheckBoxMarkString, w->colours[1] & 0x7F, _button_offset_x + 12 * j, y + _check_offset_y); } diff --git a/src/windows/tile_inspector.c b/src/windows/tile_inspector.c index e6e8122b24..aed3c67cea 100644 --- a/src/windows/tile_inspector.c +++ b/src/windows/tile_inspector.c @@ -20,37 +20,83 @@ #include "../addresses.h" #include "../localisation/localisation.h" +#include "../interface/themes.h" #include "../interface/widget.h" #include "../interface/window.h" #include "../interface/viewport.h" #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 +104,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 +124,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 +134,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 +168,14 @@ 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; @@ -148,7 +196,55 @@ void corrupt_element(int x, int y) { mapElement--; mapElement = map_element_insert(x, y, mapElement->base_height, 0); + assert(mapElement != NULL); mapElement->type = (8 << 2); + map_invalidate_tile_full(x, y); +} + +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--; + map_invalidate_tile_full(window_tile_inspector_tile_x, window_tile_inspector_tile_y); +} + +// 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; + } + map_invalidate_tile_full(window_tile_inspector_tile_x, window_tile_inspector_tile_y); } static void window_tile_inspector_mouseup(rct_window *w, int widgetIndex) @@ -159,9 +255,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 +295,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 +354,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,42 +374,120 @@ 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) { + colour_scheme_update(w); + window_tile_inspector_widgets[WIDX_BACKGROUND].right = w->width - 1; 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 +496,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 +511,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 +539,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( @@ -390,26 +604,26 @@ static void window_tile_inspector_scrollpaint(rct_window *w, rct_drawpixelinfo * ); type_name = buffer; break; + case MAP_ELEMENT_TYPE_CORRUPT: + // fall-through + default: + sprintf(buffer, "Unknown (type %d)", type); + 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++)); - } diff --git a/src/windows/title_editor.c b/src/windows/title_editor.c index 41c2974acd..d7aa42bc68 100644 --- a/src/windows/title_editor.c +++ b/src/windows/title_editor.c @@ -360,7 +360,7 @@ static void window_title_editor_mouseup(rct_window *w, int widgetIndex) case WIDX_TITLE_EDITOR_LOAD: if (w->selected_list_item != -1) { if (gConfigTitleSequences.presets[gCurrentTitleSequence].path[0]) { - safe_strncpy(path, gConfigTitleSequences.presets[gCurrentTitleSequence].path, MAX_PATH); + safe_strcpy(path, gConfigTitleSequences.presets[gCurrentTitleSequence].path, MAX_PATH); } else { platform_get_user_directory(path, "title sequences"); diff --git a/src/windows/title_logo.c b/src/windows/title_logo.c index 9e338a8e63..cbc1615a5c 100644 --- a/src/windows/title_logo.c +++ b/src/windows/title_logo.c @@ -144,4 +144,4 @@ static void window_title_logo_draw_expansion_packs(rct_drawpixelinfo *dpi) packs = packs >> 1; names += 128; } -} \ No newline at end of file +} diff --git a/src/windows/title_menu.c b/src/windows/title_menu.c index ddc684d58f..a45316b7c8 100644 --- a/src/windows/title_menu.c +++ b/src/windows/title_menu.c @@ -22,28 +22,29 @@ #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 "../title.h" #include "dropdown.h" -#include "../interface/themes.h" enum { WIDX_START_NEW_GAME, WIDX_CONTINUE_SAVED_GAME, + WIDX_MULTIPLAYER, WIDX_SHOW_TUTORIAL, - WIDX_GAME_TOOLS, - WIDX_MULTIPLAYER + WIDX_GAME_TOOLS }; static rct_widget window_title_menu_widgets[] = { - { WWT_IMGBTN, 2, 0, 81, 0, 81, SPR_MENU_NEW_GAME, STR_START_NEW_GAME_TIP }, - { WWT_IMGBTN, 2, 82, 163, 0, 81, SPR_MENU_LOAD_GAME, STR_CONTINUE_SAVED_GAME_TIP }, - { WWT_IMGBTN, 2, 164, 245, 0, 81, SPR_MENU_TUTORIAL, STR_SHOW_TUTORIAL_TIP }, - { WWT_IMGBTN, 2, 246, 327, 0, 81, SPR_MENU_TOOLBOX, STR_GAME_TOOLS }, - { WWT_DROPDOWN_BUTTON, 2, 82, 245, 88, 99, STR_MULTIPLAYER, STR_NONE }, + { WWT_IMGBTN, 2, 0, 0, 0, 81, SPR_MENU_NEW_GAME, STR_START_NEW_GAME_TIP }, + { WWT_IMGBTN, 2, 0, 0, 0, 81, SPR_MENU_LOAD_GAME, STR_CONTINUE_SAVED_GAME_TIP }, + { WWT_IMGBTN, 2, 0, 0, 0, 81, SPR_G2_MENU_MULTIPLAYER, STR_SHOW_MULTIPLAYER_TIP }, + { WWT_IMGBTN, 2, 0, 0, 0, 81, SPR_MENU_TUTORIAL, STR_SHOW_TUTORIAL_TIP }, + { WWT_IMGBTN, 2, 0, 0, 0, 81, SPR_MENU_TOOLBOX, STR_GAME_TOOLS }, { WIDGETS_END }, }; @@ -94,8 +95,8 @@ void window_title_menu_open() rct_window* window; window = window_create( - (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 328) / 2, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 142, - 328, 100, + 0, RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 142, + 0, 100, &window_title_menu_events, WC_TITLE_MENU, WF_STICK_TO_BACK | WF_TRANSPARENT | WF_NO_BACKGROUND @@ -104,27 +105,45 @@ void window_title_menu_open() window->enabled_widgets = ( (1 << WIDX_START_NEW_GAME) | (1 << WIDX_CONTINUE_SAVED_GAME) | - (1 << WIDX_SHOW_TUTORIAL) | - (1 << WIDX_GAME_TOOLS) | - (1 << WIDX_MULTIPLAYER) +#ifndef DISABLE_NETWORK + (1 << WIDX_MULTIPLAYER) | +#endif + // Disable tutorial + // (1 << WIDX_SHOW_TUTORIAL) | + (1 << WIDX_GAME_TOOLS) ); - // Disable tutorial button - window->disabled_widgets = (1 << WIDX_SHOW_TUTORIAL); + int i = 0; + int x = 0; + for (rct_widget *widget = window->widgets; widget->type != WWT_LAST; widget++) { + if (widget_is_enabled(window, i)) { + widget->left = x; + widget->right = x + 81; -#if DISABLE_NETWORK - // Disable multiplayer - window->widgets[WIDX_MULTIPLAYER].type = WWT_EMPTY; -#endif + x += 82; + } else { + widget->type = WWT_EMPTY; + } + i++; + } + window->width = x; + window->x = (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - window->width) / 2; window_init_scroll_widgets(window); } +static void window_title_menu_scenarioselect_callback(const utf8 *path) +{ + if (!scenario_load_and_play_from_path(path)) { + title_load(); + } +} + static void window_title_menu_mouseup(rct_window *w, int widgetIndex) { switch (widgetIndex) { case WIDX_START_NEW_GAME: - window_scenarioselect_open(); + window_scenarioselect_open(window_title_menu_scenarioselect_callback); break; case WIDX_CONTINUE_SAVED_GAME: game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 0, 0); @@ -137,19 +156,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; @@ -167,9 +174,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(); @@ -189,24 +194,12 @@ 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) { gfx_fill_rect(dpi, w->x, w->y, w->x + w->width - 1, w->y + 82 - 1, 0x2000000 | 51); - - rct_widget *multiplayerButtonWidget = &window_title_menu_widgets[WIDX_MULTIPLAYER]; - if (multiplayerButtonWidget->type != WWT_EMPTY) { - gfx_fill_rect( - dpi, - w->x + multiplayerButtonWidget->left, - w->y + multiplayerButtonWidget->top, - w->x + multiplayerButtonWidget->right, - w->y + multiplayerButtonWidget->bottom, - 0x2000000 | 51 - ); - } window_draw_widgets(w, dpi); } diff --git a/src/windows/title_scenarioselect.c b/src/windows/title_scenarioselect.c index cc20a5ca8c..d266a1bd86 100644 --- a/src/windows/title_scenarioselect.c +++ b/src/windows/title_scenarioselect.c @@ -28,8 +28,32 @@ #include "../interface/widget.h" #include "../interface/window.h" #include "../interface/themes.h" +#include "../title.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 +64,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 +100,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,13 +130,25 @@ 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); + +static scenarioselect_callback _callback; +static bool _showLockedInformation = false; + /** * * rct2: 0x006781B5 */ -void window_scenarioselect_open() +void window_scenarioselect_open(scenarioselect_callback callback) { rct_window* window; + int windowWidth; + int windowHeight = 334; + + _callback = callback; if (window_bring_to_front_by_class(WC_SCENARIO_SELECT) != NULL) return; @@ -113,46 +156,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_TAB6) | (1 << WIDX_TAB7) | (1 << WIDX_TAB8); + + window_scenarioselect_init_tabs(window); + initialise_list_items(window); - window->enabled_widgets = 0x04 | 0x10 | 0x20 | 0x40 | 0x80 | 0x100; window_init_scroll_widgets(window); window->viewport_focus_coordinates.var_480 = -1; - window->var_494 = 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; } @@ -164,17 +223,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->var_494 = 0; + w->highlighted_scenario = NULL; + initialise_list_items(w); window_invalidate(w); window_event_resize_call(w); window_event_invalidate_call(w); @@ -185,65 +251,79 @@ 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; } -/* rct2: 0x6780FE */ +/** + * + * rct2: 0x6780FE + */ 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); + _callback(listItem->scenario.scenario->path); + } + break; + } + if (y < 0) { + break; + } } } -/* rct2: 0x678162 */ +/** + * + * rct2: 0x678162 + */ 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; + bool originalShowLockedInformation = _showLockedInformation; + _showLockedInformation = false; + 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) { + if (listItem->scenario.is_locked) { + _showLockedInformation = true; + } else { + selected = listItem->scenario.scenario; + } + } + break; + } + if (y < 0) { + break; + } } - if (w->var_494 != (uint32)selected) { - w->var_494 = (uint32)selected; + + if (w->highlighted_scenario != selected) { + w->highlighted_scenario = selected; + window_invalidate(w); + } else if (_showLockedInformation != originalShowLockedInformation) { window_invalidate(w); } } @@ -252,112 +332,353 @@ static void window_scenarioselect_invalidate(rct_window *w) { colour_scheme_update(w); - w->pressed_widgets &= ~(0x10 | 0x20 | 0x40 | 0x80 | 0x100); + w->pressed_widgets &= ~( (1 << WIDX_CLOSE) | (1 << WIDX_TAB1) | (1 << WIDX_TAB2) + | (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; + format = (theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_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->var_494; - if (scenario == NULL) + scenario = w->highlighted_scenario; + if (scenario == NULL) { + if (_showLockedInformation) { + // Show locked information + x = w->x + window_scenarioselect_widgets[WIDX_SCENARIOLIST].right + 4; + y = w->y + window_scenarioselect_widgets[WIDX_TABCONTENT].top + 5; + gfx_draw_string_centred_clipped(dpi, STR_SCENARIO_LOCKED, NULL, 0, x + 85, y, 170); + y += 15; + y += gfx_draw_string_left_wrapped(dpi, NULL, x, y, 170, STR_SCENARIO_LOCKED_DESC, 0) + 5; + } return; + } + + // Scenario path + if (gConfigGeneral.debugging_tools) { + utf8 path[MAX_PATH]; + + RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = 224; + 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); + safe_strcpy((char*)0x009BC677, scenario->name, 64); + 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; + safe_strcpy((char*)0x009BC677, scenario->details, 256); + 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_strcpy((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_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_FONT) ? 5139 : 1193; + int unhighlighted_format = (theme_get_flags() & UITHEME_FLAG_USE_ALTERNATIVE_SCENARIO_SELECT_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->var_494 == (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_strcpy((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; + if (isDisabled) RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, sint16) = -1; + 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_strcpy((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 != 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; +} diff --git a/src/windows/tooltip.c b/src/windows/tooltip.c index 724e42e331..0e77880917 100644 --- a/src/windows/tooltip.c +++ b/src/windows/tooltip.c @@ -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); @@ -92,7 +93,7 @@ void window_tooltip_show(rct_string_id id, int x, int y) RCT2_GLOBAL(0x0142006C, sint32) = -1; char* buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, char); - format_string(buffer, id, (void*)0x013CE952); + format_string(buffer, id, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS); RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_FONT_SPRITE_BASE, uint16) = FONT_SPRITE_BASE_MEDIUM; int tooltip_text_width; @@ -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,11 +154,11 @@ 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) + if (window_event_tooltip_call(widgetWindow, widgetIndex) == STR_NONE) return; window_tooltip_show(widget->tooltip, x, y); @@ -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; } /** diff --git a/src/windows/tooltip.h b/src/windows/tooltip.h index b5b649463c..9c6f6e2d33 100644 --- a/src/windows/tooltip.h +++ b/src/windows/tooltip.h @@ -28,4 +28,4 @@ void window_tooltip_show(rct_string_id id, int x, int y); void window_tooltip_open(rct_window *widgetWindow, int widgetIndex, int x, int y); void window_tooltip_close(); -#endif \ No newline at end of file +#endif diff --git a/src/windows/top_toolbar.c b/src/windows/top_toolbar.c index 881c4a845c..e73bc4332f 100644 --- a/src/windows/top_toolbar.c +++ b/src/windows/top_toolbar.c @@ -19,27 +19,28 @@ *****************************************************************************/ #include "../addresses.h" +#include "../audio/audio.h" #include "../cheats.h" #include "../config.h" #include "../editor.h" #include "../game.h" #include "../input.h" -#include "../sprites.h" -#include "../audio/audio.h" +#include "../interface/console.h" #include "../interface/screenshot.h" +#include "../interface/themes.h" +#include "../interface/viewport.h" #include "../interface/widget.h" #include "../interface/window.h" -#include "../interface/viewport.h" #include "../localisation/localisation.h" #include "../network/network.h" #include "../network/twitch.h" #include "../scenario.h" +#include "../title.h" +#include "../sprites.h" #include "../util/util.h" -#include "../world/scenery.h" #include "../world/banner.h" +#include "../world/scenery.h" #include "dropdown.h" -#include "../interface/themes.h" -#include "../interface/console.h" enum { WIDX_PAUSE, @@ -73,19 +74,20 @@ enum { }; typedef enum { - DDIDX_LOAD_GAME = 0, - DDIDX_SAVE_GAME = 1, - DDIDX_SAVE_GAME_AS = 2, + DDIDX_NEW_GAME = 0, + DDIDX_LOAD_GAME = 1, + DDIDX_SAVE_GAME = 2, + DDIDX_SAVE_GAME_AS = 3, // separator - DDIDX_ABOUT = 4, - DDIDX_OPTIONS = 5, - DDIDX_SCREENSHOT = 6, - DDIDX_GIANT_SCREENSHOT = 7, + DDIDX_ABOUT = 5, + DDIDX_OPTIONS = 6, + DDIDX_SCREENSHOT = 7, + DDIDX_GIANT_SCREENSHOT = 8, // separator - DDIDX_QUIT_TO_MENU = 9, - DDIDX_EXIT_OPENRCT2 = 10, + DDIDX_QUIT_TO_MENU = 10, + DDIDX_EXIT_OPENRCT2 = 11, // separator - DDIDX_ENABLE_TWITCH = 12 + DDIDX_ENABLE_TWITCH = 13 } FILE_MENU_DDIDX; typedef enum { @@ -110,7 +112,7 @@ typedef enum { } TOP_TOOLBAR_DEBUG_DDIDX; typedef enum { - DDIDX_PLAYER_LIST = 0 + DDIDX_MULTIPLAYER = 0 } TOP_TOOLBAR_NETWORK_DDIDX; enum { @@ -120,6 +122,16 @@ enum { DDIDX_DISABLE_SUPPORT_LIMITS }; +enum { + DDIDX_SHOW_MAP, + DDIDX_OPEN_VIEWPORT, +}; + +enum { + DDIDX_ROTATE_CLOCKWISE, + DDIDX_ROTATE_ANTI_CLOCKWISE, +}; + #pragma region Toolbar_widget_ordering // from left to right @@ -310,7 +322,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; @@ -381,26 +393,27 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg gDropdownItemsFormat[9] = STR_EXIT_OPENRCT2; numItems = 10; } else { - gDropdownItemsFormat[0] = STR_LOAD_GAME; - gDropdownItemsFormat[1] = STR_SAVE_GAME; - gDropdownItemsFormat[2] = STR_SAVE_GAME_AS; - gDropdownItemsFormat[3] = 0; - gDropdownItemsFormat[4] = STR_ABOUT; - gDropdownItemsFormat[5] = STR_OPTIONS; - gDropdownItemsFormat[6] = STR_SCREENSHOT; - gDropdownItemsFormat[7] = STR_GIANT_SCREENSHOT; - gDropdownItemsFormat[8] = 0; - gDropdownItemsFormat[9] = STR_QUIT_TO_MENU; - gDropdownItemsFormat[10] = STR_EXIT_OPENRCT2; - numItems = 11; + gDropdownItemsFormat[0] = STR_NEW_GAME; + gDropdownItemsFormat[1] = STR_LOAD_GAME; + gDropdownItemsFormat[2] = STR_SAVE_GAME; + gDropdownItemsFormat[3] = STR_SAVE_GAME_AS; + gDropdownItemsFormat[4] = 0; + gDropdownItemsFormat[5] = STR_ABOUT; + gDropdownItemsFormat[6] = STR_OPTIONS; + gDropdownItemsFormat[7] = STR_SCREENSHOT; + gDropdownItemsFormat[8] = STR_GIANT_SCREENSHOT; + gDropdownItemsFormat[9] = 0; + gDropdownItemsFormat[10] = STR_QUIT_TO_MENU; + gDropdownItemsFormat[11] = STR_EXIT_OPENRCT2; + numItems = 12; #ifndef DISABLE_TWITCH if (gConfigTwitch.channel != NULL && gConfigTwitch.channel[0] != 0) { _menuDropdownIncludesTwitch = true; - gDropdownItemsFormat[11] = 0; - gDropdownItemsFormat[12] = 1156; - gDropdownItemsArgs[12] = STR_TWITCH_ENABLE; - numItems = 13; + gDropdownItemsFormat[12] = 0; + gDropdownItemsFormat[13] = 1156; + gDropdownItemsArgs[13] = STR_TWITCH_ENABLE; + numItems = 14; } #endif } @@ -415,7 +428,7 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg #ifndef DISABLE_TWITCH if (_menuDropdownIncludesTwitch && gTwitchEnable) { - dropdown_set_checked(11, true); + dropdown_set_checked(13, true); } #endif break; @@ -446,7 +459,7 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg if (gCheatsDisableSupportLimits) { dropdown_set_checked(DDIDX_DISABLE_SUPPORT_LIMITS, true); } - RCT2_GLOBAL(0x009DEBA2, uint16) = 0; + gDropdownDefaultIndex = DDIDX_CHEATS; break; case WIDX_VIEW_MENU: top_toolbar_init_view_menu(w, widget); @@ -469,7 +482,7 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg 0, numItems ); - RCT2_GLOBAL(0x009DEBA2, uint16) = 0; + gDropdownDefaultIndex = DDIDX_SHOW_MAP; break; case WIDX_FASTFORWARD: top_toolbar_init_fastforward_menu(w, widget); @@ -486,6 +499,13 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg } } +static void window_top_toolbar_scenarioselect_callback(const utf8 *path) +{ + if (!scenario_load_and_play_from_path(path)) { + title_load(); + } +} + /** * * rct2: 0x0066C9EA @@ -495,6 +515,10 @@ static void window_top_toolbar_dropdown(rct_window *w, int widgetIndex, int drop switch (widgetIndex) { case WIDX_FILE_MENU: + // New game is only available in the normal game. Skip one position to avoid incorrect mappings in the menus of the other modes. + if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_SCENARIO_EDITOR)) + dropdownIndex += 1; + // Quicksave is only available in the normal game. Skip one position to avoid incorrect mappings in the menus of the other modes. if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_SCENARIO_EDITOR) && dropdownIndex > DDIDX_LOAD_GAME) dropdownIndex += 1; @@ -504,6 +528,9 @@ static void window_top_toolbar_dropdown(rct_window *w, int widgetIndex, int drop dropdownIndex += DDIDX_ABOUT; switch (dropdownIndex) { + case DDIDX_NEW_GAME: + window_scenarioselect_open(window_top_toolbar_scenarioselect_callback); + break; case DDIDX_LOAD_GAME: game_do_command(0, 1, 0, 0, GAME_COMMAND_LOAD_OR_QUIT, 0, 0); break; @@ -549,19 +576,18 @@ static void window_top_toolbar_dropdown(rct_window *w, int widgetIndex, int drop } break; case WIDX_CHEATS: - if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x009DEBA2, uint16); switch (dropdownIndex) { case DDIDX_CHEATS: window_cheats_open(); break; case DDIDX_ENABLE_SANDBOX_MODE: - gCheatsSandboxMode = !gCheatsSandboxMode; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_SANDBOXMODE, 0, GAME_COMMAND_CHEAT, 0, 0); break; case DDIDX_DISABLE_CLEARANCE_CHECKS: - gCheatsDisableClearanceChecks = !gCheatsDisableClearanceChecks; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_DISABLECLEARANCECHECKS, 0, GAME_COMMAND_CHEAT, 0, 0); break; case DDIDX_DISABLE_SUPPORT_LIMITS: - gCheatsDisableSupportLimits = !gCheatsDisableSupportLimits; + game_do_command(0, GAME_COMMAND_FLAG_APPLY, CHEAT_DISABLESUPPORTLIMITS, 0, GAME_COMMAND_CHEAT, 0, 0); break; } break; @@ -569,9 +595,6 @@ static void window_top_toolbar_dropdown(rct_window *w, int widgetIndex, int drop top_toolbar_view_menu_dropdown(dropdownIndex); break; case WIDX_MAP: - if (dropdownIndex == -1) - dropdownIndex = RCT2_GLOBAL(0x009DEBA2, uint16); - switch (dropdownIndex) { case 0: window_map_open(); @@ -682,15 +705,16 @@ static void window_top_toolbar_invalidate(rct_window *w) window_top_toolbar_widgets[WIDX_NEWS].type = WWT_EMPTY; switch (network_get_mode()) { - case NETWORK_MODE_SERVER: - window_top_toolbar_widgets[WIDX_FASTFORWARD].type = WWT_EMPTY; + case NETWORK_MODE_NONE: + window_top_toolbar_widgets[WIDX_NETWORK].type = WWT_EMPTY; break; case NETWORK_MODE_CLIENT: window_top_toolbar_widgets[WIDX_PAUSE].type = WWT_EMPTY; + // Fall-through + case NETWORK_MODE_SERVER: window_top_toolbar_widgets[WIDX_FASTFORWARD].type = WWT_EMPTY; + window_top_toolbar_widgets[WIDX_DEBUG].type = WWT_EMPTY; break; - default: - window_top_toolbar_widgets[WIDX_NETWORK].type = WWT_EMPTY; } } @@ -861,7 +885,10 @@ static void window_top_toolbar_paint(rct_window *w, rct_drawpixelinfo *dpi) } } -/* rct2: 0x006E3158 */ +/** + * + * rct2: 0x006E3158 + */ static void repaint_scenery_tool_down(sint16 x, sint16 y, sint16 widgetIndex){ // ax, cx, bl sint16 grid_x, grid_y; @@ -968,7 +995,9 @@ static void repaint_scenery_tool_down(sint16 x, sint16 y, sint16 widgetIndex){ } } -/* rct2: 0x006E1F34 +/** + * + * rct2: 0x006E1F34 * Outputs * eax : grid_x * ebx : parameter_1 @@ -1003,11 +1032,10 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin if (type == 0 && !gCheatsDisableSupportLimits) { RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_CTRL_PRESSED, uint8) = 0; RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) = 0; - } - else{ - if (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_CTRL_PRESSED, uint8) == 0){ - // CTRL pressed - if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & (1 << 1)){ + } else { + if (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_CTRL_PRESSED, uint8) == 0) { + if (gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_COPY_Z) { + // CTRL pressed rct_map_element* map_element; uint16 flags = VIEWPORT_INTERACTION_MASK_TERRAIN & @@ -1024,17 +1052,16 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin RCT2_GLOBAL(RCT2_ADDRESS_CTRL_PRESS_Z_COORDINATE, uint16) = map_element->base_height * 8; } } - } - else{ - // CTRL not pressed - if (!(RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & (1 << 1))){ + } else { + if (!(gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_COPY_Z)) { + // CTRL not pressed RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_CTRL_PRESSED, uint8) = 0; } } if (RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) == 0){ - // SHIFT pressed - if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & (1 << 0)){ + if (gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_SHIFT_Z) { + // SHIFT pressed RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) = 1; RCT2_GLOBAL(RCT2_ADDRESS_SHIFT_PRESS_X_COORDINATE, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_SHIFT_PRESS_Y_COORDINATE, uint16) = y; @@ -1042,15 +1069,14 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin } } else{ - // SHIFT pressed - if (RCT2_GLOBAL(RCT2_ADDRESS_PLACE_OBJECT_MODIFIER, uint8) & (1 << 0)){ + if (gInputPlaceObjectModifier & PLACE_OBJECT_MODIFIER_SHIFT_Z) { + // SHIFT pressed RCT2_GLOBAL(RCT2_ADDRESS_SHIFT_PRESS_Z_VECTOR, sint16) = (RCT2_GLOBAL(RCT2_ADDRESS_SHIFT_PRESS_Y_COORDINATE, sint16) - y + 4) & 0xFFF8; x = RCT2_GLOBAL(RCT2_ADDRESS_SHIFT_PRESS_X_COORDINATE, sint16); y = RCT2_GLOBAL(RCT2_ADDRESS_SHIFT_PRESS_Y_COORDINATE, sint16); - } - else{ + } else { // SHIFT not pressed RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_TOOL_SHIFT_PRESSED, uint8) = 0; } @@ -1125,7 +1151,7 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin // Also places it in lower but think thats for clobering *parameter_1 = (selected_scenery & 0xFF) << 8; - *parameter_2 = cl ^ (1 << 1) | (window_scenery_primary_colour << 8); + *parameter_2 = (cl ^ (1 << 1)) | (window_scenery_primary_colour << 8); *parameter_3 = rotation | (window_scenery_secondary_colour << 16); return; } @@ -1396,6 +1422,15 @@ void sub_6E1F34(sint16 x, sint16 y, uint16 selected_scenery, sint16* grid_x, sin } } +void game_command_callback_place_banner(int eax, int ebx, int ecx, int edx, int esi, int edi, int ebp) +{ + if (ebx != MONEY32_UNDEFINED) { + int bannerId = edi; + + audio_play_sound_at_location(SOUND_PLACE_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16), RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16), RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16)); + window_banner_open(bannerId); + } +} /** * * rct2: 0x006E2CC6 @@ -1426,10 +1461,10 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window *w case SCENERY_TYPE_SMALL: { int quantity = 1; - if (window_scenery_is_build_cluster_tool_on) { + bool isCluster = window_scenery_is_build_cluster_tool_on && (network_get_mode() != NETWORK_MODE_CLIENT || network_can_perform_command(network_get_current_player_group_index(), -2)); + if (isCluster) { quantity = 35; } - int successfulPlacements = 0; for (int q = 0; q < quantity; q++) { int zCoordinate = RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_Z_COORDINATE, sint16); @@ -1438,7 +1473,7 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window *w sint16 cur_grid_x = gridX; sint16 cur_grid_y = gridY; - if (window_scenery_is_build_cluster_tool_on){ + if (isCluster){ if (!(scenery->small_scenery.flags & SMALL_SCENERY_FLAG_FULL_TILE)){ parameter_2 &= 0xFF00; parameter_2 |= util_rand() & 3; @@ -1610,13 +1645,8 @@ static void window_top_toolbar_scenery_tool_down(short x, short y, rct_window *w .esi = GAME_COMMAND_PLACE_BANNER, .edi = parameter_3 }; - money32 cost = game_do_command_p(GAME_COMMAND_PLACE_BANNER, ®s.eax, ®s.ebx, ®s.ecx, ®s.edx, ®s.esi, ®s.edi, ®s.ebp); - if (cost != MONEY32_UNDEFINED) { - int bannerId = regs.edi; - - audio_play_sound_at_location(SOUND_PLACE_ITEM, RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16), RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16), RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16)); - window_banner_open(bannerId); - } + game_command_callback = game_command_callback_place_banner; + game_do_command_p(GAME_COMMAND_PLACE_BANNER, ®s.eax, ®s.ebx, ®s.ecx, ®s.edx, ®s.esi, ®s.edi, ®s.ebp); break; } } @@ -2076,7 +2106,9 @@ void top_toolbar_tool_update_water(sint16 x, sint16 y){ } } -/* rct2: 0x006E24F6 +/** + * + * rct2: 0x006E24F6 * On failure returns MONEY32_UNDEFINED * On success places ghost scenery and returns cost to place proper */ @@ -2360,7 +2392,7 @@ void top_toolbar_tool_update_scenery(sint16 x, sint16 y){ RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_A_Y, sint16) = mapTile.y; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_X, sint16) = mapTile.x; RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_B_Y, sint16) = mapTile.y; - RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 10 + parameter2 & 0xFF; + RCT2_GLOBAL(RCT2_ADDRESS_MAP_SELECTION_TYPE, uint16) = 10 + (parameter2 & 0xFF); map_invalidate_selection_rect(); @@ -2520,7 +2552,8 @@ static void window_top_toolbar_tool_update(rct_window* w, int widgetIndex, int x } /** - * rct2: 0x0066CB73 + * + * rct2: 0x0066CB73 */ static void window_top_toolbar_tool_down(rct_window* w, int widgetIndex, int x, int y) { @@ -2633,27 +2666,21 @@ void window_top_toolbar_land_tool_drag(short x, short y) sint16 tile_height = -16 / (1 << viewport->zoom); - int y_diff = y - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16); - + int y_diff = y - gInputDragLastY; if (y_diff <= tile_height) { - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) += tile_height; + gInputDragLastY += tile_height; selection_raise_land(GAME_COMMAND_FLAG_APPLY); RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = MONEY32_UNDEFINED; RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = MONEY32_UNDEFINED; - return; - } - - if (y_diff >= -tile_height) { - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) -= tile_height; + } else if (y_diff >= -tile_height) { + gInputDragLastY -= tile_height; selection_lower_land(GAME_COMMAND_FLAG_APPLY); RCT2_GLOBAL(RCT2_ADDRESS_LAND_RAISE_COST, uint32) = MONEY32_UNDEFINED; RCT2_GLOBAL(RCT2_ADDRESS_LAND_LOWER_COST, uint32) = MONEY32_UNDEFINED; - - return; } } @@ -2679,10 +2706,10 @@ void window_top_toolbar_water_tool_drag(short x, short y) sint16 dx = 0xFFF0; dx >>= viewport->zoom; - y -= RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16); + y -= gInputDragLastY; if (y <= dx) { - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) += dx; + gInputDragLastY += dx; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = STR_CANT_RAISE_WATER_LEVEL_HERE; @@ -2704,7 +2731,7 @@ void window_top_toolbar_water_tool_drag(short x, short y) dx = -dx; if (y >= dx) { - RCT2_GLOBAL(RCT2_ADDRESS_CURSOR_DRAG_LAST_Y, uint16) += dx; + gInputDragLastY += dx; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TITLE, rct_string_id) = STR_CANT_LOWER_WATER_LEVEL_HERE; @@ -2858,14 +2885,18 @@ void top_toolbar_init_fastforward_menu(rct_window* w, rct_widget* widget) { dropdown_set_checked(5, true); } - if (gConfigGeneral.debugging_tools) - RCT2_GLOBAL(0x9DEBA2, uint16) = (gGameSpeed == 8 ? 0 : gGameSpeed); - else - RCT2_GLOBAL(0x9DEBA2, uint16) = (gGameSpeed >= 4 ? 0 : gGameSpeed); + if (gConfigGeneral.debugging_tools) { + gDropdownDefaultIndex = (gGameSpeed == 8 ? 0 : gGameSpeed); + } else { + gDropdownDefaultIndex = (gGameSpeed >= 4 ? 0 : gGameSpeed); + } + if (gDropdownDefaultIndex == 4) { + gDropdownDefaultIndex = 5; + } } -void top_toolbar_fastforward_menu_dropdown(short dropdownIndex) { - if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16); +void top_toolbar_fastforward_menu_dropdown(short dropdownIndex) +{ rct_window* w = window_get_main(); if (w) { if (dropdownIndex >= 0 && dropdownIndex <= 5) { @@ -2877,7 +2908,8 @@ void top_toolbar_fastforward_menu_dropdown(short dropdownIndex) { } } -void top_toolbar_init_rotate_menu(rct_window* w, rct_widget* widget) { +void top_toolbar_init_rotate_menu(rct_window* w, rct_widget* widget) +{ gDropdownItemsFormat[0] = STR_ROTATE_CLOCKWISE; gDropdownItemsFormat[1] = STR_ROTATE_ANTI_CLOCKWISE; @@ -2888,13 +2920,13 @@ void top_toolbar_init_rotate_menu(rct_window* w, rct_widget* widget) { w->colours[1] | 0x80, 0, 2 - ); + ); - RCT2_GLOBAL(0x9DEBA2, uint16) = 0; + gDropdownDefaultIndex = DDIDX_ROTATE_CLOCKWISE; } -void top_toolbar_rotate_menu_dropdown(short dropdownIndex) { - if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16); +void top_toolbar_rotate_menu_dropdown(short dropdownIndex) +{ rct_window* w = window_get_main(); if (w) { if (dropdownIndex == 0) { @@ -2908,7 +2940,8 @@ void top_toolbar_rotate_menu_dropdown(short dropdownIndex) { } } -void top_toolbar_init_debug_menu(rct_window* w, rct_widget* widget) { +void top_toolbar_init_debug_menu(rct_window* w, rct_widget* widget) +{ gDropdownItemsFormat[0] = STR_DEBUG_DROPDOWN_CONSOLE; gDropdownItemsFormat[1] = STR_DEBUG_DROPDOWN_TILE_INSPECTOR; gDropdownItemsFormat[2] = STR_DEBUG_DROPDOWN_OBJECT_SELECTION; @@ -2920,15 +2953,16 @@ void top_toolbar_init_debug_menu(rct_window* w, rct_widget* widget) { w->y + widget->top, widget->bottom - widget->top + 1, w->colours[0] | 0x80, - 0, + DROPDOWN_FLAG_STAY_OPEN, 5 ); - RCT2_GLOBAL(0x9DEBA2, uint16) = 0; + gDropdownDefaultIndex = DDIDX_CONSOLE; } -void top_toolbar_init_network_menu(rct_window* w, rct_widget* widget) { - gDropdownItemsFormat[0] = STR_PLAYER_LIST; +void top_toolbar_init_network_menu(rct_window* w, rct_widget* widget) +{ + gDropdownItemsFormat[0] = STR_MULTIPLAYER; window_dropdown_show_text( w->x + widget->left, @@ -2939,11 +2973,11 @@ void top_toolbar_init_network_menu(rct_window* w, rct_widget* widget) { 1 ); - RCT2_GLOBAL(0x9DEBA2, uint16) = 0; + gDropdownDefaultIndex = DDIDX_MULTIPLAYER; } -void top_toolbar_debug_menu_dropdown(short dropdownIndex) { - if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16); +void top_toolbar_debug_menu_dropdown(short dropdownIndex) +{ rct_window* w = window_get_main(); if (w) { switch (dropdownIndex) { @@ -2967,13 +3001,13 @@ void top_toolbar_debug_menu_dropdown(short dropdownIndex) { } } -void top_toolbar_network_menu_dropdown(short dropdownIndex) { - if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16); +void top_toolbar_network_menu_dropdown(short dropdownIndex) +{ rct_window* w = window_get_main(); if (w) { switch (dropdownIndex) { - case DDIDX_PLAYER_LIST: - window_player_list_open(); + case DDIDX_MULTIPLAYER: + window_multiplayer_open(); break; } } @@ -3040,15 +3074,15 @@ void top_toolbar_init_view_menu(rct_window* w, rct_widget* widget) { if (mainViewport->flags & VIEWPORT_FLAG_PATH_HEIGHTS) dropdown_set_checked(11, true); - RCT2_GLOBAL(0x9DEBA2, uint16) = 0; + gDropdownDefaultIndex = DDIDX_UNDERGROUND_INSIDE; } /** * * rct2: 0x0066CF8A */ -void top_toolbar_view_menu_dropdown(short dropdownIndex) { - if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16); +void top_toolbar_view_menu_dropdown(short dropdownIndex) +{ rct_window* w = window_get_main(); if (w) { switch (dropdownIndex) { @@ -3105,16 +3139,16 @@ void toggle_footpath_window() /** * - * rct2: 0x0066CD54 + * rct2: 0x0066CD54 */ 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, uint8) == 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(); } @@ -3122,16 +3156,16 @@ void toggle_land_window(rct_window *topToolbar, int widgetIndex) /** * - * rct2: 0x0066CD0C + * rct2: 0x0066CD0C */ 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, uint8) == 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(); } @@ -3139,16 +3173,16 @@ void toggle_clear_scenery_window(rct_window *topToolbar, int widgetIndex) /** * - * rct2: 0x0066CD9C + * rct2: 0x0066CD9C */ 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, uint8) == 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(); } @@ -3160,11 +3194,11 @@ 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; - if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, sint16) != WIDX_LAND) + if (RCT2_GLOBAL(RCT2_ADDRESS_TOOL_WIDGETINDEX, uint16) != WIDX_LAND) return false; return true; } diff --git a/src/windows/track_list.c b/src/windows/track_list.c index fedc79a3e7..988c685e6f 100644 --- a/src/windows/track_list.c +++ b/src/windows/track_list.c @@ -30,7 +30,6 @@ #include "error.h" #include "../interface/themes.h" #include "../rct1.h" -#include "../network/network.h" enum { WIDX_BACKGROUND, @@ -146,13 +145,6 @@ void window_track_list_open(ride_list_item item) RCT2_GLOBAL(RCT2_ADDRESS_TRACK_DESIGN_SCENERY_TOGGLE, uint8) = 0; window_push_others_right(w); RCT2_GLOBAL(RCT2_ADDRESS_TRACK_PREVIEW_ROTATION, uint8) = 2; - -#ifndef NETWORK_DISABLE - // TODO: FIX NETWORK TRACKS - // Until tracks work with the network this will disable them - if (network_get_mode() != NETWORK_MODE_NONE) - RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, utf8)[0] = 0; -#endif } /** @@ -191,7 +183,7 @@ static void window_track_list_select(rct_window *w, int index) 1); char track_path[MAX_PATH] = { 0 }; - subsitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem); + substitute_path(track_path, (char*)RCT2_ADDRESS_TRACKS_PATH, trackDesignItem); if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TRACK_MANAGER) { window_track_manage_open(); @@ -345,12 +337,12 @@ static void window_track_list_tooltip(rct_window* w, int widgetIndex, rct_string */ static void window_track_list_invalidate(rct_window *w) { - rct_ride_type *entry; + rct_ride_entry *entry; rct_string_id stringId; colour_scheme_update(w); - entry = GET_RIDE_ENTRY(_window_track_list_item.entry_index); + entry = get_ride_entry(_window_track_list_item.entry_index); stringId = entry->name; if (!(entry->flags & RIDE_ENTRY_FLAG_SEPARATE_RIDE_NAME) || rideTypeShouldLoseSeparateFlag(entry)) @@ -395,7 +387,7 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi) uint16 holes, speed, drops, dropHeight, inversions; fixed32_2dp rating; int trackIndex, x, y, colour, gForces, airTime; - rct_g1_element tmpElement, *subsituteElement; + rct_g1_element tmpElement, *substituteElement; window_draw_widgets(w, dpi); @@ -420,16 +412,16 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi) rct_track_td6* track_td6 = &trackDesign->track_td6; - subsituteElement = &g1Elements[0]; - tmpElement = *subsituteElement; - subsituteElement->offset = image; - subsituteElement->width = 370; - subsituteElement->height = 217; - subsituteElement->x_offset = 0; - subsituteElement->y_offset = 0; - subsituteElement->flags = G1_FLAG_BMP; + substituteElement = &g1Elements[0]; + tmpElement = *substituteElement; + substituteElement->offset = image; + substituteElement->width = 370; + substituteElement->height = 217; + substituteElement->x_offset = 0; + substituteElement->y_offset = 0; + substituteElement->flags = G1_FLAG_BMP; gfx_draw_sprite(dpi, 0, x, y, 0); - *subsituteElement = tmpElement; + *substituteElement = tmpElement; x = w->x + (widget->left + widget->right) / 2; y = w->y + widget->bottom - 12; @@ -491,9 +483,9 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi) } // Ride length - RCT2_GLOBAL(0x013CE952 + 0, uint16) = 1345; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->ride_length; - gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)0x013CE952, 0, x, y, 214); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = 1345; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->ride_length; + gfx_draw_string_left_clipped(dpi, STR_TRACK_LIST_RIDE_LENGTH, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y, 214); y += 10; } @@ -548,9 +540,9 @@ static void window_track_list_paint(rct_window *w, rct_drawpixelinfo *dpi) if (track_td6->space_required_x != 0xFF) { // Space required - RCT2_GLOBAL(0x013CE952 + 0, uint16) = track_td6->space_required_x; - RCT2_GLOBAL(0x013CE952 + 2, uint16) = track_td6->space_required_y; - gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)0x013CE952, 0, x, y); + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = track_td6->space_required_x; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint16) = track_td6->space_required_y; + gfx_draw_string_left(dpi, STR_TRACK_LIST_SPACE_REQUIRED, (void*)RCT2_ADDRESS_COMMON_FORMAT_ARGS, 0, x, y); y += 10; } diff --git a/src/windows/track_manage.c b/src/windows/track_manage.c index 4b1ac29344..0f8f87ea1e 100644 --- a/src/windows/track_manage.c +++ b/src/windows/track_manage.c @@ -185,7 +185,7 @@ static void window_track_manage_close(rct_window *w) */ static void window_track_manage_mouseup(rct_window *w, int widgetIndex) { - uint8 *trackDesignList = (uint8*)0x00F441EC; + char *trackDesignList = RCT2_ADDRESS(RCT2_ADDRESS_TRACK_LIST, char); rct_window *trackDesignListWindow; char *dst, *src; @@ -253,7 +253,7 @@ static void window_track_delete_prompt_open() w = window_create( max(28, (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 250) / 2), - (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_WIDTH, uint16) - 44) / 2, + (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_HEIGHT, uint16) - 44) / 2, 250, 74, &window_track_delete_prompt_events, @@ -309,4 +309,4 @@ static void window_track_delete_prompt_paint(rct_window *w, rct_drawpixelinfo *d gfx_draw_string_centred_wrapped( dpi, &stringId, w->x + 125, w->y + 28, 246, STR_ARE_YOU_SURE_YOU_WANT_TO_PERMANENTLY_DELETE_TRACK, 0 ); -} \ No newline at end of file +} diff --git a/src/windows/track_place.c b/src/windows/track_place.c index e52fedbafb..0567f9722e 100644 --- a/src/windows/track_place.c +++ b/src/windows/track_place.c @@ -30,6 +30,7 @@ #include "../ride/track.h" #include "../ride/track_data.h" #include "../interface/themes.h" +#include "../cheats.h" #define TRACK_MINI_PREVIEW_WIDTH 168 #define TRACK_MINI_PREVIEW_HEIGHT 78 @@ -239,8 +240,8 @@ static void window_track_place_draw_mini_preview() if (track_coordinate->rotation_end & 4) rotation |= 4; if (!(rotation & 4)) { - originX += RCT2_GLOBAL(0x00993CCC + (rotation * 4), sint16); - originY += RCT2_GLOBAL(0x00993CCE + (rotation * 4), sint16); + originX += TileDirectionDelta[rotation].x; + originY += TileDirectionDelta[rotation].y; } trackElement++; } @@ -389,7 +390,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 +450,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); } @@ -485,7 +486,7 @@ static void window_track_place_toolupdate(rct_window* w, int widgetIndex, int x, // Get base Z position mapZ = window_track_place_get_base_z(mapX, mapY); - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gCheatsBuildInPauseMode) { window_track_place_clear_provisional(); // Try increasing Z until a feasible placement is found @@ -595,26 +596,23 @@ static void window_track_place_invalidate(rct_window *w) */ static void window_track_place_paint(rct_window *w, rct_drawpixelinfo *dpi) { - rct_drawpixelinfo *clippedDpi; - rct_g1_element tmpElement, *subsituteElement; + rct_drawpixelinfo clippedDpi; + rct_g1_element tmpElement, *substituteElement; window_draw_widgets(w, dpi); // Draw mini tile preview - clippedDpi = clip_drawpixelinfo(dpi, w->x + 4, 168, w->y + 18, 78); - if (clippedDpi != NULL) { - subsituteElement = &g1Elements[0]; - tmpElement = *subsituteElement; - subsituteElement->offset = _window_track_place_mini_preview; - subsituteElement->width = TRACK_MINI_PREVIEW_WIDTH; - subsituteElement->height = TRACK_MINI_PREVIEW_HEIGHT; - subsituteElement->x_offset = 0; - subsituteElement->y_offset = 0; - subsituteElement->flags = 0; - gfx_draw_sprite(clippedDpi, 0, 0, 0, 0); - *subsituteElement = tmpElement; - - rct2_free(clippedDpi); + if (clip_drawpixelinfo(&clippedDpi, dpi, w->x + 4, w->y + 18, 168, 78)) { + substituteElement = &g1Elements[0]; + tmpElement = *substituteElement; + substituteElement->offset = _window_track_place_mini_preview; + substituteElement->width = TRACK_MINI_PREVIEW_WIDTH; + substituteElement->height = TRACK_MINI_PREVIEW_HEIGHT; + substituteElement->x_offset = 0; + substituteElement->y_offset = 0; + substituteElement->flags = 0; + gfx_draw_sprite(&clippedDpi, 0, 0, 0, 0); + *substituteElement = tmpElement; } // Price diff --git a/src/windows/viewport.c b/src/windows/viewport.c index 9a09015bb0..33a09aac9c 100644 --- a/src/windows/viewport.c +++ b/src/windows/viewport.c @@ -221,7 +221,7 @@ static void window_viewport_invalidate(rct_window *w) } // Set title - RCT2_GLOBAL(0x013CE952 + 0, uint32) = w->number; + RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint32) = w->number; // Set disabled widgets w->disabled_widgets = 0; diff --git a/src/windows/water.c b/src/windows/water.c index 85ccc87f36..8a8b98dd08 100644 --- a/src/windows/water.c +++ b/src/windows/water.c @@ -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; diff --git a/src/world/balloon.c b/src/world/balloon.c index 1d05313edc..22659e3aa4 100644 --- a/src/world/balloon.c +++ b/src/world/balloon.c @@ -32,7 +32,7 @@ void balloon_pop(rct_balloon *balloon) /** * - * rct: 0x0067342C + * rct2: 0x0067342C */ void balloon_update(rct_balloon *balloon) { @@ -70,7 +70,7 @@ void balloon_press(rct_balloon *balloon) return; uint32 random = util_rand(); - if ((balloon->var_0A & 7) || (random & 0xFFFF) < 0x2000) { + if ((balloon->sprite_index & 7) || (random & 0xFFFF) < 0x2000) { balloon_pop(balloon); return; } diff --git a/src/world/banner.c b/src/world/banner.c index 44521c90f2..f244ead699 100644 --- a/src/world/banner.c +++ b/src/world/banner.c @@ -29,7 +29,7 @@ rct_banner *gBanners = (rct_banner*)0x0135A124; /** * - * rct2: 0x006B9CB0 + * rct2: 0x006B9CB0 */ void banner_init() { @@ -101,7 +101,7 @@ static int banner_get_ride_index_at(int x, int y, int z) continue; rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_IS_SHOP)) continue; diff --git a/src/world/banner.h b/src/world/banner.h index 7b836d0815..e53cf053e6 100644 --- a/src/world/banner.h +++ b/src/world/banner.h @@ -41,7 +41,7 @@ enum{ BANNER_FLAG_NO_ENTRY = (1 << 0), BANNER_FLAG_1 = (1 << 1), BANNER_FLAG_2 = (1 << 2) -} BANNER_FLAGS; +}; extern rct_banner *gBanners; diff --git a/src/world/climate.c b/src/world/climate.c index 787438bf90..c180645c58 100644 --- a/src/world/climate.c +++ b/src/world/climate.c @@ -29,6 +29,7 @@ #include "../interface/window.h" #include "../util/util.h" #include "climate.h" +#include "../cheats.h" enum { THUNDER_STATUS_NULL = 0, @@ -84,12 +85,8 @@ int climate_celsius_to_fahrenheit(int celsius) return (celsius * 29) / 16 + 32; } -// cheats -extern int g_climate_locked; -extern void toggle_climate_lock(); - /** - * Set climate and determine start weather. + * Set climate and determine start weather. * rct2: 0x006C45ED */ void climate_reset(int climate) @@ -124,18 +121,11 @@ sint8 step_weather_level(sint8 cur_weather_level, sint8 next_weather_level) { } } - -//for cheats -void toggle_climate_lock() -{ - g_climate_locked = !g_climate_locked; -} - /** * Weather & climate update iteration. * Gradually changes the weather parameters towards their determined next values. * - * rct2: 0x006C46B1 + * rct2: 0x006C46B1 */ void climate_update() { @@ -147,7 +137,7 @@ void climate_update() cur_rain = RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_RAIN_LEVEL, sint8), next_rain = _climateNextRainLevel; - if (g_climate_locked) //for cheats + if (gCheatsFreezeClimate) //for cheats return; if (screen_flags & (~SCREEN_FLAGS_PLAYING)) // only normal play mode gets climate @@ -185,6 +175,19 @@ void climate_update() RCT2_GLOBAL(RCT2_ADDRESS_BTM_TOOLBAR_DIRTY_FLAGS, uint32) |= BTM_TB_DIRTY_FLAG_CLIMATE; } } + + if (_thunderTimer != 0) { + climate_update_lightning(); + climate_update_thunder(); + } else if (_climateCurrentWeatherEffect == 2) { + // Create new thunder and lightning + unsigned int randomNumber = util_rand(); + if ((randomNumber & 0xFFFF) <= 0x1B4) { + randomNumber >>= 16; + _thunderTimer = 43 + (randomNumber % 64); + _lightningTimer = randomNumber % 32; + } + } } void climate_force_weather(uint8 weather){ @@ -206,7 +209,7 @@ void climate_force_weather(uint8 weather){ * for next_weather. The other weather parameters are then looked up depending only on the * next weather. * - * rct2: 0x006C461C + * rct2: 0x006C461C */ static void climate_determine_future_weather(int randomDistribution) { @@ -229,7 +232,7 @@ static void climate_determine_future_weather(int randomDistribution) /** * - * rct2: 0x006BCB91 + * rct2: 0x006BCB91 */ void climate_update_sound() { @@ -237,7 +240,7 @@ void climate_update_sound() return; if (gGameSoundsOff) return; - if (!gConfigSound.sound) + if (!gConfigSound.sound_enabled) return; if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_TITLE_DEMO) return; @@ -282,17 +285,6 @@ static void climate_update_thunder_sound() // Play thunder on right side _thunderStereoEcho = 0; climate_play_thunder(1, _thunderSoundId, _thunderVolume, 10000); - } else if (_thunderTimer != 0) { - climate_update_lightning(); - climate_update_thunder(); - } else if (_climateCurrentWeatherEffect == 2) { - // Create new thunder and lightning - unsigned int randomNumber = scenario_rand(); - if ((randomNumber & 0xFFFF) <= 0x1B4) { - randomNumber >>= 16; - _thunderTimer = 43 + (randomNumber % 64); - _lightningTimer = randomNumber % 32; - } } // Stop thunder sounds if they have finished @@ -312,10 +304,12 @@ static void climate_update_lightning() if (_lightningTimer == 0) return; - _lightningTimer--; - if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) == 0) - if ((scenario_rand() & 0xFFFF) <= 0x2000) - RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) = 1; + if (!gConfigGeneral.disable_lightning_effect) { + _lightningTimer--; + if (RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) == 0) + if ((util_rand() & 0xFFFF) <= 0x2000) + RCT2_GLOBAL(RCT2_ADDRESS_LIGHTNING_ACTIVE, uint16) = 1; + } } static void climate_update_thunder() @@ -324,7 +318,7 @@ static void climate_update_thunder() if (_thunderTimer != 0) return; - unsigned int randomNumber = scenario_rand(); + unsigned int randomNumber = util_rand(); if (randomNumber & 0x10000) { if (_thunderStatus[0] == THUNDER_STATUS_NULL && _thunderStatus[1] == THUNDER_STATUS_NULL) { // Play thunder on left side diff --git a/src/world/climate.h b/src/world/climate.h index 147b6445ac..d7d995edf4 100644 --- a/src/world/climate.h +++ b/src/world/climate.h @@ -53,10 +53,6 @@ typedef struct { extern const rct_weather climate_weather_data[6]; -// cheats -int g_climate_locked; -void toggle_climate_lock(); - int climate_celsius_to_fahrenheit(int celsius); void climate_reset(int climate); void climate_update(); diff --git a/src/world/duck.c b/src/world/duck.c index 1e500247ca..6218339b59 100644 --- a/src/world/duck.c +++ b/src/world/duck.c @@ -79,7 +79,7 @@ void create_duck(int targetX, int targetY) /** * - * rct: 0x006740E8 + * rct2: 0x006740E8 */ void duck_update(rct_duck *duck) { @@ -109,7 +109,7 @@ static void duck_invalidate(rct_duck *duck) /** * - * rct: 0x00674108 + * rct2: 0x00674108 */ static void duck_update_fly_to_water(rct_duck *duck) { @@ -163,11 +163,11 @@ static void duck_update_fly_to_water(rct_duck *duck) /** * - * rct: 0x00674282 + * rct2: 0x00674282 */ static void duck_update_swim(rct_duck *duck) { - if ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + duck->var_0A) & 3) + if ((RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) + duck->sprite_index) & 3) return; uint32 randomNumber = scenario_rand(); @@ -225,7 +225,7 @@ static void duck_update_swim(rct_duck *duck) /** * - * rct: 0x00674357 + * rct2: 0x00674357 */ static void duck_update_drink(rct_duck *duck) { @@ -241,7 +241,7 @@ static void duck_update_drink(rct_duck *duck) /** * - * rct: 0x00674372 + * rct2: 0x00674372 */ static void duck_update_double_drink(rct_duck *duck) { @@ -257,7 +257,7 @@ static void duck_update_double_drink(rct_duck *duck) /** * - * rct: 0x0067438D + * rct2: 0x0067438D */ static void duck_update_fly_away(rct_duck *duck) { @@ -277,14 +277,14 @@ static void duck_update_fly_away(rct_duck *duck) return; } - int z = z = min(duck->z + 2, 496); + int z = min(duck->z + 2, 496); sprite_move(x, y, z, (rct_sprite*)duck); duck_invalidate(duck); } /** * - * rct: 0x006E895D + * rct2: 0x006E895D */ void duck_press(rct_duck *duck) { @@ -293,7 +293,7 @@ void duck_press(rct_duck *duck) /** * - * rct: 0x00674576 + * rct2: 0x00674576 */ void duck_remove_all() { diff --git a/src/world/entrance.h b/src/world/entrance.h index 291a14f905..2be3e6c3b7 100644 --- a/src/world/entrance.h +++ b/src/world/entrance.h @@ -30,4 +30,4 @@ typedef struct { uint8 text_height; // 0x07 } rct_entrance_type; -#endif \ No newline at end of file +#endif diff --git a/src/world/footpath.c b/src/world/footpath.c index ee57d5e0b4..4a262feb34 100644 --- a/src/world/footpath.c +++ b/src/world/footpath.c @@ -24,6 +24,7 @@ #include "../game.h" #include "../localisation/localisation.h" #include "../management/finance.h" +#include "../network/network.h" #include "../util/util.h" #include "footpath.h" #include "map.h" @@ -157,14 +158,7 @@ static money32 footpath_element_insert(int type, int x, int y, int z, int slope, zHigh += 2; } - RCT2_GLOBAL(0x00F3EF84, uint16) = x; - RCT2_GLOBAL(0x00F3EF86, uint16) = y; - - // Ugh, hack until 0x006A6733 is written - // 0x006A6733 expects the flags to be at (*0xF3EF7C) + 8 - RCT2_GLOBAL(0x00F3EF7C, uint32) = (uint32)(&flags - 2); - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, (void*)0x006A6733, bl)) + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &map_place_non_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F3EFD9, money32))) return MONEY32_UNDEFINED; RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8); @@ -180,6 +174,7 @@ static money32 footpath_element_insert(int type, int x, int y, int z, int slope, if (flags & GAME_COMMAND_FLAG_APPLY) { mapElement = map_element_insert(x / 32, y / 32, z, 0x0F); + assert(mapElement != NULL); mapElement->type = MAP_ELEMENT_TYPE_PATH; mapElement->clearance_height = z + 4 + (slope & 4 ? 2 : 0); mapElement->properties.path.type = (type << 4) | (slope & 7); @@ -210,7 +205,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 +244,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 +262,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 +290,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); @@ -310,7 +308,7 @@ static money32 footpath_place_real(int type, int x, int y, int z, int slope, int RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z * 8; - if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -347,6 +345,14 @@ static money32 footpath_place_real(int type, int x, int y, int z, int slope, int // Force ride construction to recheck area RCT2_GLOBAL(0x00F440B0, uint8) |= 8; + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + footpath_provisional_remove(); mapElement = map_get_footpath_element_slope((x / 32), (y / 32), z, slope); if (mapElement == NULL) { @@ -356,7 +362,10 @@ static money32 footpath_place_real(int type, int x, int y, int z, int slope, int } } -/* rct2: 0x006BA23E */ +/** + * + * rct2: 0x006BA23E + */ void remove_banners_at_element(int x, int y, rct_map_element* mapElement){ while (!map_element_is_last_for_tile(mapElement++)){ if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH)return; @@ -376,7 +385,7 @@ money32 footpath_remove_real(int x, int y, int z, int flags) RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z * 8; - if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -391,6 +400,14 @@ money32 footpath_remove_real(int x, int y, int z, int flags) mapElement = map_get_footpath_element(x / 32, y / 32, z); if (mapElement != NULL && (flags & GAME_COMMAND_FLAG_APPLY)) { + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + RCT2_GLOBAL(0x00F3EFF4, uint32) = 0x00F3EFF8; remove_banners_at_element(x, y, mapElement); footpath_remove_edges_at(x, y, mapElement); @@ -428,7 +445,7 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z * 8; - if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -470,14 +487,7 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop zHigh += 2; } - RCT2_GLOBAL(0x00F3EF84, uint16) = x; - RCT2_GLOBAL(0x00F3EF86, uint16) = y; - - // Ugh, hack until 0x006A6733 is written - // 0x006A6733 expects the flags to be at (*0xF3EF7C) + 8 - RCT2_GLOBAL(0x00F3EF7C, uint32) = (uint32)(&flags - 2); - - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, (void*)0x006A6733, bl)) + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(x, y, z, zHigh, &map_place_non_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F3EFD9, money32))) return MONEY32_UNDEFINED; RCT2_GLOBAL(0x00F3EFA4, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8); @@ -492,7 +502,16 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop RCT2_GLOBAL(0x00F3EFD9, money32) += supportHeight < 0 ? MONEY(20, 00) : (supportHeight / 2) * MONEY(5, 00); if (flags & GAME_COMMAND_FLAG_APPLY) { + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + mapElement = map_element_insert(x / 32, y / 32, z, 0x0F); + assert(mapElement != NULL); mapElement->type = MAP_ELEMENT_TYPE_PATH; mapElement->clearance_height = z + 4 + (slope & 4 ? 2 : 0); mapElement->properties.path.type = (type << 4) | (slope & 7); @@ -509,8 +528,9 @@ static money32 footpath_place_from_track(int type, int x, int y, int z, int slop return RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY ? 0 : RCT2_GLOBAL(0x00F3EFD9, money32); } -/* - * rct2: 0x006A68AE +/** + * + * rct2: 0x006A68AE */ void game_command_place_footpath_from_track(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { @@ -604,9 +624,9 @@ void footpath_provisional_update() } /** - * Determines the location of the footpath at which we point with the cursor. If no footpath is underneath the cursor, - * then return the location of the ground tile. Besides the location it also computes the direction of the yellow arrow - * when we are going to build a footpath bridge/tunnel. + * Determines the location of the footpath at which we point with the cursor. If no footpath is underneath the cursor, + * then return the location of the ground tile. Besides the location it also computes the direction of the yellow arrow + * when we are going to build a footpath bridge/tunnel. * rct2: 0x00689726 * In: * screenX: eax @@ -799,7 +819,10 @@ void footpath_interrupt_peeps(int x, int y, int z) } } -/* rct2: 0x006E59DC */ +/** + * + * rct2: 0x006E59DC + */ bool fence_in_the_way(int x, int y, int z0, int z1, int direction) { rct_map_element *mapElement; @@ -1112,7 +1135,7 @@ static void loc_6A6D7E( break; case MAP_ELEMENT_TYPE_TRACK: if (z == mapElement->base_height) { - rct_ride *ride = GET_RIDE(mapElement->properties.track.ride_index); + rct_ride *ride = get_ride(mapElement->properties.track.ride_index); if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE)) { continue; } @@ -1203,7 +1226,7 @@ static void loc_6A6C85( } if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK) { - rct_ride *ride = GET_RIDE(mapElement->properties.track.ride_index); + rct_ride *ride = get_ride(mapElement->properties.track.ride_index); if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE)) { return; } @@ -1283,7 +1306,7 @@ void footpath_connect_edges(int x, int y, rct_map_element *mapElement, int flags void footpath_chain_ride_queue(int rideIndex, int entranceIndex, int x, int y, rct_map_element *mapElement, int direction) { rct_map_element *lastPathElement, *lastQueuePathElement; - int lastPathX, lastPathY, lastPathDirection; + int lastPathX = x, lastPathY = y, lastPathDirection = direction; lastPathElement = NULL; lastQueuePathElement = NULL; @@ -1348,6 +1371,8 @@ void footpath_chain_ride_queue(int rideIndex, int entranceIndex, int x, int y, r mapElement->properties.path.additions &= 0x8F; mapElement->properties.path.additions |= (entranceIndex & 7) << 4; + map_invalidate_element(x, y, mapElement); + if (lastQueuePathElement == NULL) { lastQueuePathElement = mapElement; } @@ -1396,7 +1421,7 @@ void sub_6A759F() for (esi = (uint8*)0x00F3EFF8; esi < RCT2_GLOBAL(0x00F3EFF4, uint8*); esi++) { rideIndex = *esi; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (ride->type == RIDE_TYPE_NULL) continue; @@ -1572,7 +1597,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; } @@ -1587,6 +1612,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 @@ -1918,7 +1982,7 @@ void footpath_remove_edges_at(int x, int y, rct_map_element *mapElement) if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_TRACK) { int rideIndex = mapElement->properties.track.ride_index; - ride = GET_RIDE(rideIndex); + ride = get_ride(rideIndex); if (!ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE)) return; } diff --git a/src/world/footpath.h b/src/world/footpath.h index 05c5ad43ad..7f67b982af 100644 --- a/src/world/footpath.h +++ b/src/world/footpath.h @@ -70,9 +70,16 @@ void footpath_bridge_get_info_from_pos(int screenX, int screenY, int *x, int *y, int footpath_is_connected_to_map_edge(int x, int y, int z, int direction, int flags); bool footpath_element_is_sloped(rct_map_element *mapElement); -int footpath_element_get_slope_direction(rct_map_element *mapElement); +uint8 footpath_element_get_slope_direction(rct_map_element *mapElement); bool footpath_element_is_queue(rct_map_element *mapElement); bool footpath_element_is_wide(rct_map_element *mapElement); +uint8 footpath_element_get_type(rct_map_element *mapElement); +bool footpath_element_has_path_scenery(rct_map_element *mapElement); +uint8 footpath_element_get_path_scenery(rct_map_element *mapElement); +void footpath_element_set_path_scenery(rct_map_element *mapElement, uint8 pathSceneryType); +uint8 footpath_element_get_path_scenery_index(rct_map_element *mapElement); +bool footpath_element_path_scenery_is_ghost(rct_map_element *mapElement); +void footpath_scenery_set_is_ghost(rct_map_element *mapElement, bool isGhost); void footpath_remove_edges_at(int x, int y, rct_map_element *mapElement); #endif diff --git a/src/world/fountain.c b/src/world/fountain.c index 3c720c9474..f7ea3e78d8 100644 --- a/src/world/fountain.c +++ b/src/world/fountain.c @@ -24,6 +24,7 @@ #include "map.h" #include "scenery.h" #include "sprite.h" +#include "footpath.h" enum { PATTERN_CYCLIC_SQUARES, @@ -191,7 +192,7 @@ void jumping_fountain_create(int type, int x, int y, int z, int direction, int f jumpingFountain->iteration = iteration; jumpingFountain->var_2E = direction; - jumpingFountain->flags = flags; + jumpingFountain->fountain_flags = flags; jumpingFountain->sprite_direction = direction << 3; jumpingFountain->var_14 = 33; jumpingFountain->var_09 = 36; @@ -206,8 +207,8 @@ void jumping_fountain_create(int type, int x, int y, int z, int direction, int f /** * - * rct: 0x006733CB (water) - * rct: 0x00673407 (snow) + * rct2: 0x006733CB (water) + * rct2: 0x00673407 (snow) */ void jumping_fountain_update(rct_jumping_fountain *jumpingFountain) { @@ -221,10 +222,10 @@ void jumping_fountain_update(rct_jumping_fountain *jumpingFountain) switch (jumpingFountain->misc_identifier) { case SPRITE_MISC_JUMPING_FOUNTAIN_WATER: - if (jumpingFountain->var_26b == 11 && (jumpingFountain->flags & FOUNTAIN_FLAG_FAST)) + if (jumpingFountain->var_26b == 11 && (jumpingFountain->fountain_flags & FOUNTAIN_FLAG_FAST)) jumping_fountain_continue(jumpingFountain); - if (jumpingFountain->var_26b == 16 && !(jumpingFountain->flags & FOUNTAIN_FLAG_FAST)) + if (jumpingFountain->var_26b == 16 && !(jumpingFountain->fountain_flags & FOUNTAIN_FLAG_FAST)) jumping_fountain_continue(jumpingFountain); break; case SPRITE_MISC_JUMPING_FOUNTAIN_SNOW: @@ -262,20 +263,20 @@ static void jumping_fountain_continue(rct_jumping_fountain *jumpingFountain) if (availableDirections == 0) return; - if (jumpingFountain->flags & FOUNTAIN_FLAG_TERMINATE) + if (jumpingFountain->fountain_flags & FOUNTAIN_FLAG_TERMINATE) return; - if (jumpingFountain->flags & FOUNTAIN_FLAG_GOTO_EDGE) { + if (jumpingFountain->fountain_flags & FOUNTAIN_FLAG_GOTO_EDGE) { jumping_fountain_goto_edge(jumpingFountain, x, y, z, availableDirections); return; } - if (jumpingFountain->flags & FOUNTAIN_FLAG_BOUNCE) { + if (jumpingFountain->fountain_flags & FOUNTAIN_FLAG_BOUNCE) { jumping_fountain_bounce(jumpingFountain, x, y, z, availableDirections); return; } - if (jumpingFountain->flags & FOUNTAIN_FLAG_SPLIT) { + if (jumpingFountain->fountain_flags & FOUNTAIN_FLAG_SPLIT) { jumping_fountain_split(jumpingFountain, x, y, z, availableDirections); return; } @@ -297,14 +298,14 @@ static bool is_jumping_fountain(int type, int x, int y, int z) continue; if (mapElement->base_height != z) continue; - if (mapElement->properties.path.additions & 0x80) + if (footpath_element_path_scenery_is_ghost(mapElement)) continue; - int additions = mapElement->properties.path.additions & 0x0F; - if (additions == 0) + if (!footpath_element_has_path_scenery(mapElement)) continue; - rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + uint8 additionIndex = footpath_element_get_path_scenery_index(mapElement); + rct_scenery_entry *sceneryEntry = g_pathBitSceneryEntries[additionIndex]; if (!(sceneryEntry->path_bit.var_06 & pathBitFlagMask)) continue; @@ -316,7 +317,7 @@ static bool is_jumping_fountain(int type, int x, int y, int z) /** * - * rct: 0x00673B6E + * rct2: 0x00673B6E */ static void jumping_fountain_goto_edge(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections) { @@ -336,7 +337,7 @@ static void jumping_fountain_goto_edge(rct_jumping_fountain *jumpingFountain, in if ((randomIndex & 0xFFFF) < 0x3333) return; - if (jumpingFountain->flags & FOUNTAIN_FLAG_SPLIT) { + if (jumpingFountain->fountain_flags & FOUNTAIN_FLAG_SPLIT) { jumping_fountain_split(jumpingFountain, x, y, z, availableDirections); return; } @@ -350,7 +351,7 @@ static void jumping_fountain_goto_edge(rct_jumping_fountain *jumpingFountain, in /** * - * rct: 0x00673B45 + * rct2: 0x00673B45 */ static void jumping_fountain_bounce(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections) { @@ -371,7 +372,7 @@ static void jumping_fountain_bounce(rct_jumping_fountain *jumpingFountain, int x /** * - * rct: 0x00673ACE + * rct2: 0x00673ACE */ static void jumping_fountain_split(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections) { @@ -393,7 +394,7 @@ static void jumping_fountain_split(rct_jumping_fountain *jumpingFountain, int x, type, x, y, z, direction >> 1, - jumpingFountain->flags & ~FOUNTAIN_FLAG_7, + jumpingFountain->fountain_flags & ~FOUNTAIN_FLAG_7, jumpingFountain->iteration + 1 ); } @@ -403,7 +404,7 @@ static void jumping_fountain_split(rct_jumping_fountain *jumpingFountain, int x, type, x, y, z, direction >> 1, - jumpingFountain->flags | FOUNTAIN_FLAG_7, + jumpingFountain->fountain_flags | FOUNTAIN_FLAG_7, jumpingFountain->iteration + 1 ); } @@ -412,7 +413,7 @@ static void jumping_fountain_split(rct_jumping_fountain *jumpingFountain, int x, /** * - * rct: 0x00673AAC + * rct2: 0x00673AAC */ static void jumping_fountain_random(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int availableDirections) { @@ -429,11 +430,11 @@ static void jumping_fountain_random(rct_jumping_fountain *jumpingFountain, int x /** * - * rct: 0x00673B45 + * rct2: 0x00673B45 */ static void jumping_fountain_create_next(rct_jumping_fountain *jumpingFountain, int x, int y, int z, int direction) { - int flags = jumpingFountain->flags & ~FOUNTAIN_FLAG_7; + int flags = jumpingFountain->fountain_flags & ~FOUNTAIN_FLAG_7; if (direction & 1) flags |= FOUNTAIN_FLAG_7; @@ -442,4 +443,4 @@ static void jumping_fountain_create_next(rct_jumping_fountain *jumpingFountain, JUMPING_FOUNTAIN_TYPE_WATER; jumping_fountain_create(type, x, y, z, direction >> 1, flags, jumpingFountain->iteration); -} \ No newline at end of file +} diff --git a/src/world/map.c b/src/world/map.c index 6af8a11c14..366de4feed 100644 --- a/src/world/map.c +++ b/src/world/map.c @@ -28,6 +28,7 @@ #include "../localisation/date.h" #include "../localisation/localisation.h" #include "../management/finance.h" +#include "../network/network.h" #include "../openrct2.h" #include "../ride/ride_data.h" #include "../ride/track.h" @@ -41,7 +42,9 @@ #include "park.h" #include "scenery.h" -/* Replaces 0x00993CCC & 0x00993CCE */ +/** + * Replaces 0x00993CCC, 0x00993CCE + */ const rct_xy16 TileDirectionDelta[] = { { -32, 0 }, { 0, +32 }, @@ -178,22 +181,22 @@ void map_set_tile_elements(int x, int y, rct_map_element *elements) TILE_MAP_ELEMENT_POINTER(x + y * 256) = elements; } -int map_element_is_last_for_tile(rct_map_element *element) +int map_element_is_last_for_tile(const rct_map_element *element) { return element->flags & MAP_ELEMENT_FLAG_LAST_TILE; } -int map_element_get_type(rct_map_element *element) +int map_element_get_type(const rct_map_element *element) { return element->type & MAP_ELEMENT_TYPE_MASK; } -int map_element_get_direction(rct_map_element *element) +int map_element_get_direction(const rct_map_element *element) { return element->type & MAP_ELEMENT_DIRECTION_MASK; } -int map_element_get_terrain(rct_map_element *element) +int map_element_get_terrain(const rct_map_element *element) { int terrain = (element->properties.surface.terrain >> 5) & 7; if (element->type & 1) @@ -201,7 +204,7 @@ int map_element_get_terrain(rct_map_element *element) return terrain; } -int map_element_get_terrain_edge(rct_map_element *element) +int map_element_get_terrain_edge(const rct_map_element *element) { int terrain_edge = (element->properties.surface.slope >> 5) & 7; if (element->type & 128) @@ -360,9 +363,9 @@ void map_update_tile_pointers() /** * Return the absolute height of an element, given its (x,y) coordinates * - * ax: x - * cx: y - * dx: return remember to & with 0xFFFF if you don't want water affecting results + * ax: x + * cx: y + * dx: return remember to & with 0xFFFF if you don't want water affecting results * rct2: 0x00662783 */ int map_element_height(int x, int y) @@ -389,7 +392,7 @@ int map_element_height(int x, int y) // Remove the extra height bit slope &= 0xF; - sint8 quad, quad_extra; // which quadrant the element is in? + sint8 quad = 0, quad_extra = 0; // which quadrant the element is in? // quad_extra is for extra height tiles uint8 xl, yl; // coordinates across this tile @@ -643,15 +646,18 @@ int map_is_location_owned(int x, int y, int z) { rct_map_element *mapElement; + // This check is to avoid throwing lots of messages in logs. if (x < (256 * 32) && y < (256 * 32)) { mapElement = map_get_surface_element_at(x / 32, y / 32); - if (mapElement->properties.surface.ownership & OWNERSHIP_OWNED) - return 1; - - if (mapElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) { - z /= 8; - if (z < mapElement->base_height || z - 2 > mapElement->base_height) + if (mapElement != NULL) { + if (mapElement->properties.surface.ownership & OWNERSHIP_OWNED) return 1; + + if (mapElement->properties.surface.ownership & OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED) { + z /= 8; + if (z < mapElement->base_height || z - 2 > mapElement->base_height) + return 1; + } } } @@ -706,14 +712,20 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es money32 cost; rct_scenery_entry *entry = g_smallSceneryEntries[scenery_type]; + if (entry == (rct_scenery_entry *)0xFFFFFFFF) + { + log_warning("Invalid game command for scenery removal, scenery_type = %u", scenery_type); + *ebx = MONEY32_UNDEFINED; + return; + } cost = entry->small_scenery.removal_price * 10; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = x + 16; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = y + 16; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = base_height * 8; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x + 16; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = base_height * 8; - if (!(flags & GAME_COMMAND_FLAG_GHOST) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (!(flags & GAME_COMMAND_FLAG_GHOST) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -759,6 +771,14 @@ void game_command_remove_scenery(int* eax, int* ebx, int* ecx, int* edx, int* es // Remove element if (flags & GAME_COMMAND_FLAG_APPLY) { + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + map_invalidate_tile_full(x, y); map_element_remove(map_element); } @@ -783,7 +803,7 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - if (!(flags & GAME_COMMAND_FLAG_GHOST) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (!(flags & GAME_COMMAND_FLAG_GHOST) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -791,6 +811,12 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i bool element_found = false; rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + if (map_element == NULL) + { + log_warning("Invalid game command for scenery removal, x = %d, y = %d", x, y); + *ebx = MONEY32_UNDEFINED; + return; + } do { if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) continue; @@ -894,8 +920,16 @@ void game_command_remove_large_scenery(int* eax, int* ebx, int* ecx, int* edx, i } } + if (flags & GAME_COMMAND_FLAG_APPLY && RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + *ebx = scenery_entry->large_scenery.removal_price * 10; - if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY || + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY || calculate_cost == false){ *ebx = 0; } @@ -919,7 +953,7 @@ void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; - if(!(flags & GAME_COMMAND_FLAG_GHOST) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + if(!(flags & GAME_COMMAND_FLAG_GHOST) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -942,6 +976,14 @@ void game_command_remove_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi rct_scenery_entry *scenery_entry = g_bannerSceneryEntries[banner->type]; if (flags & GAME_COMMAND_FLAG_APPLY) { + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + map_element_remove_banner_entry(map_element); map_invalidate_tile_zoom1(x, y, z, z + 32); map_element_remove(map_element); @@ -965,9 +1007,11 @@ void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int int y = *ecx; uint8 base_height = *edx; uint8 scenery_type = *edx >> 8; - uint8 color1 = *ebp; - uint8 color2 = *ebp >> 8; + uint8 colour1 = *ebp; + uint8 colour2 = *ebp >> 8; uint8 flags = *ebx & 0xFF; + // Note this function is passed type. + uint8 quadrant = ((*ebx >> 8) & 0xFF) >> 6; int z = base_height * 8; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; @@ -980,10 +1024,9 @@ void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int } } - // Previously it would do a search for type of bh (set from calling function) instead of just small scenery - // Unsure if this was a mistake. - rct_map_element* map_element = map_get_small_scenery_element_at(x, y, base_height, scenery_type); - + bool found = false; + rct_map_element *map_element = map_get_small_scenery_element_at(x, y, base_height, scenery_type, quadrant); + if (map_element == NULL) { *ebx = 0; return; @@ -996,9 +1039,9 @@ void game_command_set_scenery_colour(int* eax, int* ebx, int* ecx, int* edx, int if(flags & GAME_COMMAND_FLAG_APPLY){ map_element->properties.scenery.colour_1 &= 0xE0; - map_element->properties.scenery.colour_1 |= color1; + map_element->properties.scenery.colour_1 |= colour1; map_element->properties.scenery.colour_2 &= 0xE0; - map_element->properties.scenery.colour_2 |= color2; + map_element->properties.scenery.colour_2 |= colour2; map_invalidate_tile_full(x, y); } @@ -1016,9 +1059,9 @@ void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* int y = *ecx; uint8 map_element_direction = *edx; uint8 base_height = *edx >> 8; - uint8 color1 = *ebx >> 8; - uint8 color2 = *ebp; - uint8 color3 = *ebp >> 8; + uint8 colour1 = *ebx >> 8; + uint8 colour2 = *ebp; + uint8 colour3 = *ebp >> 8; uint8 flags = *ebx & 0xFF; int z = base_height * 8; @@ -1050,14 +1093,14 @@ void game_command_set_fence_colour(int* eax, int* ebx, int* ecx, int* edx, int* if(flags & GAME_COMMAND_FLAG_APPLY){ rct_scenery_entry* scenery_entry = g_wallSceneryEntries[map_element->properties.fence.type]; map_element->properties.fence.item[1] &= 0xE0; - map_element->properties.fence.item[1] |= color1; - map_element->properties.fence.item[1] &= 0x1F; + map_element->properties.fence.item[1] |= colour1; + map_element->properties.fence.item[1] &= 0x1F; map_element->flags &= 0x9F; - map_element->properties.fence.item[1] |= (color2 & 0x7) * 32; - map_element->flags |= (color2 & 0x18) * 4; + map_element->properties.fence.item[1] |= (colour2 & 0x7) * 32; + map_element->flags |= (colour2 & 0x18) * 4; if(scenery_entry->wall.flags & 0x80){ - map_element->properties.fence.item[0] = color3; + map_element->properties.fence.item[0] = colour3; } map_invalidate_tile_zoom1(x, y, z, z + 72); } @@ -1078,8 +1121,8 @@ void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* ed uint8 flags = *ebx & 0xFF; uint8 base_height = *edx; uint8 tileIndex = *edx >> 8; - uint8 color1 = *ebp; - uint8 color2 = *ebp >> 8; + uint8 colour1 = *ebp; + uint8 colour2 = *ebp >> 8; int z = map_element_height(x, y); RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; @@ -1091,13 +1134,13 @@ void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* ed *ebx = 0; return; } - + if((flags & GAME_COMMAND_FLAG_GHOST) && !(map_element->flags & MAP_ELEMENT_FLAG_GHOST)){ *ebx = 0; return; } - rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[map_element->properties.scenerymultiple.type & 0x3FF]; + rct_scenery_entry *scenery_entry = g_largeSceneryEntries[map_element->properties.scenerymultiple.type & 0x3FF]; // Work out the base tile coordinates (Tile with index 0) rct_xyz16 baseTile = { @@ -1132,16 +1175,16 @@ void game_command_set_large_scenery_colour(int* eax, int* ebx, int* ecx, int* ed if(flags & GAME_COMMAND_FLAG_APPLY){ rct_map_element* mapElement = map_get_large_scenery_segment( - currentTile.x, - currentTile.y, - base_height, - map_element_direction, + currentTile.x, + currentTile.y, + base_height, + map_element_direction, i); mapElement->properties.scenerymultiple.colour[0] &= 0xE0; - mapElement->properties.scenerymultiple.colour[0] |= color1; + mapElement->properties.scenerymultiple.colour[0] |= colour1; mapElement->properties.scenerymultiple.colour[1] &= 0xE0; - mapElement->properties.scenerymultiple.colour[1] |= color2; + mapElement->properties.scenerymultiple.colour[1] |= colour2; map_invalidate_tile_full(currentTile.x, currentTile.y); } @@ -1160,7 +1203,7 @@ void game_command_set_banner_colour(int* eax, int* ebx, int* ecx, int* edx, int* int y = *ecx; uint8 base_height = *edx; uint8 banner_position = *edx >> 8; - uint8 color = *ebp; + uint8 colour = *ebp; int z = (base_height * 8); RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; @@ -1197,7 +1240,7 @@ void game_command_set_banner_colour(int* eax, int* ebx, int* ecx, int* edx, int* if(window){ window_invalidate(window); } - gBanners[map_element->properties.banner.index].colour = color; + gBanners[map_element->properties.banner.index].colour = colour; map_invalidate_tile_zoom1(x, y, z, z + 32); } @@ -1299,7 +1342,8 @@ restart_from_beginning: return totalCost; } -/* Function to clear the flag that is set to prevent cost duplication +/** + * Function to clear the flag that is set to prevent cost duplication * when using the clear scenery tool with large scenery. */ void map_reset_clear_large_scenery_flag(){ @@ -1353,6 +1397,14 @@ money32 map_clear_scenery(int x0, int y0, int x1, int y1, int clear, int flags) } } + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && flags & GAME_COMMAND_FLAG_APPLY) { + rct_xyz16 coord; + coord.x = ((x0 + x1) / 2) + 16; + coord.y = ((y0 + y1) / 2) + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + if (clear & (1 << 1)) { map_reset_clear_large_scenery_flag(); } @@ -1376,7 +1428,10 @@ void game_command_clear_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi ); } -/* rct2: 0x00663CCD */ +/** + * + * rct2: 0x00663CCD + */ money32 map_change_surface_style(int x0, int y0, int x1, int y1, uint8 surfaceStyle, uint8 edgeStyle, uint8 flags) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; @@ -1400,7 +1455,7 @@ money32 map_change_surface_style(int x0, int y0, int x1, int y1, uint8 surfaceSt money32 cost = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { cost += RCT2_GLOBAL(0x009E32B4, uint32); return (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) ? 0 : cost; } @@ -1479,12 +1534,23 @@ money32 map_change_surface_style(int x0, int y0, int x1, int y1, uint8 surfaceSt } } + if (flags & GAME_COMMAND_FLAG_APPLY && RCT2_GLOBAL(0x009A8C28, uint8) == 1) { + rct_xyz16 coord; + coord.x = ((x0 + x1) / 2) + 16; + coord.y = ((y0 + y1) / 2) + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + cost *= 100; cost += RCT2_GLOBAL(0x009E32B4, uint32); return (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) ? 0 : cost; } -/* rct2: 0x00663CCD */ +/** + * + * rct2: 0x00663CCD + */ void game_command_change_surface_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { *ebx = map_change_surface_style( @@ -1516,9 +1582,25 @@ const uint8 map_element_lower_styles[5][32] = { { 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x0D, 0x0E, 0x00 }, }; +/** + * + * rct2: 0x00663CB9 + */ +int map_set_land_height_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price) { + if (map_element_get_type(*map_element) == MAP_ELEMENT_TYPE_SURFACE) + return 0; + + if (map_element_get_type(*map_element) == MAP_ELEMENT_TYPE_SCENERY) + return 0; + + return 1; +} + static money32 map_set_land_height(int flags, int x, int y, int height, int style, int selectionType) { - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + rct_map_element *mapElement; + + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; return MONEY32_UNDEFINED; } @@ -1559,9 +1641,150 @@ static money32 map_set_land_height(int flags, int x, int y, int height, int styl } } - int eax = x, ebx = flags, ecx = y, edx = (style << 8) | height, esi = 0, edi = selectionType << 5, ebp = 0; - RCT2_CALLFUNC_X(0x006639FE, &eax, &ebx, &ecx, &edx, &esi, &edi, &ebp); - return ebx; + RCT2_GLOBAL(0x9E2E18, money32) = MONEY(0, 0); + if(flags & GAME_COMMAND_FLAG_APPLY) + { + footpath_remove_litter(x, y, map_element_height(x, y)); + if(!gCheatsDisableClearanceChecks) + map_remove_walls_at(x, y, height * 8 - 16, height * 8 + 32); + } + RCT2_GLOBAL(0x9E2E18, money32) += MONEY(20, 0); + + if (!gCheatsDisableClearanceChecks) { + //Check for obstructing scenery + mapElement = map_get_first_element_at(x / 32, y / 32); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY) + continue; + if (height > mapElement->clearance_height) + continue; + if (height + 4 < mapElement->base_height) + continue; + rct_scenery_entry *sceneryEntry = g_smallSceneryEntries[mapElement->properties.scenery.type]; //sceneryEntry = eax + if (sceneryEntry->small_scenery.height > 64 && RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_TREE_REMOVAL) + { + map_obstruction_set_error_text(mapElement); + return MONEY32_UNDEFINED; + } + RCT2_GLOBAL(0x9E2E18, money32) += MONEY(sceneryEntry->small_scenery.removal_price, 0); + if (flags & GAME_COMMAND_FLAG_APPLY) + map_element_remove(mapElement--); + } while (!map_element_is_last_for_tile(mapElement++)); + } + + //Check for ride support limits + if(gCheatsDisableSupportLimits==false) + { + mapElement = map_get_first_element_at(x / 32, y / 32); + do{ + if(map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) + continue; + int rideIndex = mapElement->properties.track.ride_index; + int maxHeight = get_ride_entry_by_ride(get_ride(rideIndex))->max_height; + if(maxHeight == 0) + maxHeight = RCT2_GLOBAL(0x97D218 + 8 * get_ride(rideIndex)->type, uint8); + int zDelta = mapElement->clearance_height - height; + if(zDelta >= 0 && zDelta/2 > maxHeight) + { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_SUPPORTS_CANT_BE_EXTENDED; + return MONEY32_UNDEFINED; + } + }while(!map_element_is_last_for_tile(mapElement++)); + } + + uint8 zCorner = height; //z position of highest corner of tile + rct_map_element *surfaceElement = map_get_surface_element_at(x / 32, y / 32); + if(surfaceElement->type & MAP_ELEMENT_TYPE_FLAG_HIGHLIGHT) + { + int waterHeight = surfaceElement->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK; + if(waterHeight != 0) + { + if(style & 0x1F) + { + zCorner += 2; + if(style & 0x10) + { + zCorner += 2; + } + } + if(zCorner > waterHeight * 2 - 2) + { + surfaceElement++; + map_obstruction_set_error_text(surfaceElement); + return MONEY32_UNDEFINED; + } + } + } + + zCorner = height; + if(style & 0xF) + { + zCorner += 2; + if(style & 0x10) + { + zCorner += 2; + } + } + + if (!gCheatsDisableClearanceChecks) { + if (!map_can_construct_with_clear_at(x, y, height, zCorner, &map_set_land_height_clear_func, 0xF, 0, NULL)) { + return MONEY32_UNDEFINED; + } + } + + if (!gCheatsDisableClearanceChecks) { + mapElement = map_get_first_element_at(x / 32, y / 32); + do { + int elementType = map_element_get_type(mapElement); + + if (elementType == MAP_ELEMENT_TYPE_FENCE) + continue; + if (elementType == MAP_ELEMENT_TYPE_SCENERY) + continue; + if (mapElement->flags & 0x10) + continue; + if (mapElement == surfaceElement) + continue; + if (mapElement > surfaceElement) + { + if (zCorner > mapElement->base_height) + { + map_obstruction_set_error_text(mapElement); + return MONEY32_UNDEFINED; + } + continue; + } + if (height < mapElement->clearance_height) + { + map_obstruction_set_error_text(mapElement); + return MONEY32_UNDEFINED; + } + } while (!map_element_is_last_for_tile(mapElement++)); + } + + if(flags & GAME_COMMAND_FLAG_APPLY) + { + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + + surfaceElement = map_get_surface_element_at(x / 32, y / 32); + surfaceElement->base_height = height; + surfaceElement->clearance_height = height; + surfaceElement->properties.surface.slope &= MAP_ELEMENT_SLOPE_EDGE_STYLE_MASK; + surfaceElement->properties.surface.slope |= style; + int slope = surfaceElement->properties.surface.terrain & MAP_ELEMENT_SLOPE_MASK; + if(slope != 0 && slope <= height / 2) + surfaceElement->properties.surface.terrain &= MAP_ELEMENT_SURFACE_TERRAIN_MASK; + map_invalidate_tile_full(x, y); + } + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY) + return 0; + return RCT2_GLOBAL(0x9E2E18, money32); } void game_command_set_land_height(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) @@ -1584,6 +1807,11 @@ money32 map_set_land_ownership(uint8 flags, sint16 x1, sint16 y1, sint16 x2, sin RCT2_GLOBAL(0x009E2E28, uint8) = 0; + // Clamp to maximum addressable element to prevent long loop spamming the log + x1 = clamp(0, x1, RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16)); + y1 = clamp(0, y1, RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16)); + x2 = min(x2, RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16)); + y2 = min(y2, RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16)); for (sint16 y = y1; y <= y2; y += 32) { for (sint16 x = x1; x <= x2; x += 32) { if (x > RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16)) @@ -1610,7 +1838,10 @@ money32 map_set_land_ownership(uint8 flags, sint16 x1, sint16 y1, sint16 x2, sin return 0; } -/* rct2: 0x006648E3*/ +/** + * + * rct2: 0x006648E3 + */ void game_command_set_land_ownership(int *eax, int *ebx, int *ecx, int *edx, int *esi, int *edi, int *ebp) { *ebx = map_set_land_ownership( @@ -1628,6 +1859,12 @@ money32 raise_land(int flags, int x, int y, int z, int ax, int ay, int bx, int b { money32 cost = 0; + if (selectionType < 0 || selectionType >= countof(map_element_raise_styles)) + { + log_warning("Invalid selection type %d for raising land", selectionType); + return MONEY32_UNDEFINED; + } + if ((flags & GAME_COMMAND_FLAG_APPLY) && RCT2_GLOBAL(0x009A8C28, uint8) == 1) { audio_play_sound_at_location(SOUND_PLACE_ITEM, x, y, z); } @@ -1674,9 +1911,9 @@ money32 raise_land(int flags, int x, int y, int z, int ax, int ay, int bx, int b RCT2_GLOBAL(0x00F440B0, uint8) |= 8; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = x; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = y; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = z; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; return cost; } @@ -1688,6 +1925,12 @@ money32 lower_land(int flags, int x, int y, int z, int ax, int ay, int bx, int b audio_play_sound_at_location(SOUND_PLACE_ITEM, x, y, z); } + if (selectionType < 0 || selectionType >= 5) + { + log_warning("Improper selection type %d", selectionType); + return MONEY32_UNDEFINED; + } + uint8 max_height = 0; ax = max(ax, 32); @@ -1741,15 +1984,16 @@ money32 lower_land(int flags, int x, int y, int z, int ax, int ay, int bx, int b RCT2_GLOBAL(0x00F440B0, uint8) |= 8; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = x; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = y; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = z; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; return cost; } money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags) { money32 cost = 0; + bool waterHeightChanged = false; uint8 max_height = 0xFF; @@ -1791,6 +2035,7 @@ money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags) return MONEY32_UNDEFINED; cost += tileCost; + waterHeightChanged = true; } } } @@ -1805,10 +2050,19 @@ money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags) z = water_height_z; if (z != 0) z = base_height_z; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = x; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = y; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = z; - audio_play_sound_at_location(SOUND_LAYING_OUT_WATER, x, y, z); + + rct_xyz16 coord; + coord.x = x; + coord.y = y; + coord.z = z; + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; + if (waterHeightChanged) { + audio_play_sound_at_location(SOUND_LAYING_OUT_WATER, x, y, z); + } } // Force ride construction to recheck area @@ -1820,6 +2074,7 @@ money32 raise_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags) money32 lower_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags) { money32 cost = 0; + bool waterHeightChanged = false; uint8 min_height = 0; @@ -1856,6 +2111,7 @@ money32 lower_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags) if (tileCost == MONEY32_UNDEFINED) return MONEY32_UNDEFINED; cost += tileCost; + waterHeightChanged = true; } } } @@ -1870,10 +2126,19 @@ money32 lower_water(sint16 x0, sint16 y0, sint16 x1, sint16 y1, uint8 flags) z = water_height_z; if (z == 0) z = base_height_z; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = x; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = y; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = z; - audio_play_sound_at_location(SOUND_LAYING_OUT_WATER, x, y, z); + + rct_xyz16 coord; + coord.x = x; + coord.y = y; + coord.z = z; + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = z; + if (waterHeightChanged) { + audio_play_sound_at_location(SOUND_LAYING_OUT_WATER, x, y, z); + } } // Force ride construction to recheck area @@ -1977,6 +2242,11 @@ static money32 smooth_land_tile(int direction, uint8 flags, int x, int y, int ta // Get height of tile rct_map_element *mapElement = map_get_surface_element_at(x >> 5, y >> 5); + if (mapElement == NULL) + { + log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", x, y); + return MONEY32_UNDEFINED; + } int baseZ = map_get_corner_height(mapElement, direction); // Check if tile is same height as target tile @@ -2020,8 +2290,8 @@ money32 smooth_land(int flags, int centreX, int centreY, int mapLeft, int mapTop // Cap bounds to map mapLeft = max(mapLeft, 32); mapTop = max(mapTop, 32); - mapRight = min(mapRight, 255 * 32); - mapBottom = min(mapBottom, 255 * 32); + mapRight = clamp(0, mapRight, 255 * 32); + mapBottom = clamp(0, mapBottom, 255 * 32); int commandType; int centreZ = map_element_height(centreX, centreY); @@ -2049,6 +2319,20 @@ money32 smooth_land(int flags, int centreX, int centreY, int mapLeft, int mapTop x = mapLeft; y = mapTop; mapElement = map_get_surface_element_at(x >> 5, y >> 5); + if (mapElement == NULL) + { + log_warning("Invalid coordinates for land smoothing, x = %d, y = %d", x, y); + return MONEY32_UNDEFINED; + } + + if (flags & GAME_COMMAND_FLAG_APPLY) { + rct_xyz16 coord; + coord.x = centreX + 16; + coord.y = centreY + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + int slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; if (slope != 0) { commandType = command == 0xFFFF ? GAME_COMMAND_RAISE_LAND : GAME_COMMAND_LOWER_LAND; @@ -2063,9 +2347,9 @@ money32 smooth_land(int flags, int centreX, int centreY, int mapLeft, int mapTop slope = mapElement->properties.surface.slope & MAP_ELEMENT_SLOPE_MASK; if (slope != 0) { RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = centreX; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = centreY; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = centreZ; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = centreX; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = centreY; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = centreZ; return totalCost * 4; } } @@ -2219,9 +2503,9 @@ money32 smooth_land(int flags, int centreX, int centreY, int mapLeft, int mapTop } RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = centreX; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = centreY; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = centreZ; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = centreX; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = centreY; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = centreZ; return totalCost * 4; } @@ -2285,7 +2569,7 @@ void game_command_set_water_height(int* eax, int* ebx, int* ecx, int* edx, int* RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, sint16) = x + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, sint16) = y + 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = base_height * 8; - if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -2322,7 +2606,8 @@ void game_command_set_water_height(int* eax, int* ebx, int* ecx, int* edx, int* if(*ebx & GAME_COMMAND_FLAG_APPLY){ int element_height = map_element_height(x, y); footpath_remove_litter(x, y, element_height); - map_remove_walls_at_z(x, y, element_height); + if(!gCheatsDisableClearanceChecks) + map_remove_walls_at_z(x, y, element_height); } rct_map_element* map_element = map_get_surface_element_at(x / 32, y / 32); @@ -2337,7 +2622,7 @@ void game_command_set_water_height(int* eax, int* ebx, int* ecx, int* edx, int* zLow = temp; } - if(map_can_construct_at(x, y, zLow, zHigh, 0xFF)){ + if (gCheatsDisableClearanceChecks || map_can_construct_at(x, y, zLow, zHigh, 0xFF)) { if(map_element->type & 0x40){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 0; *ebx = MONEY32_UNDEFINED; @@ -2372,7 +2657,7 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, uint8 direction = *edx; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + if(!(*ebx & 0x40) && RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -2398,6 +2683,14 @@ void game_command_remove_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, return; } + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + map_element_remove_banner_entry(map_element); map_invalidate_tile_zoom1(x, y, map_element->base_height * 8, (map_element->base_height * 8) + 72); map_element_remove(map_element); @@ -2416,76 +2709,179 @@ void game_command_place_banner(int* eax, int* ebx, int* ecx, int* edx, int* esi, uint8 edge = *edx >> 8; uint8 colour = *edi; uint8 type = *ebx >> 8; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint32) = x + 16; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint32) = y + 16; - RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint32) = base_height * 16; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x + 16; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y + 16; + RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, uint16) = base_height * 16; RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; - if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode){ - if(sub_68B044() && x < 8192 && y < 8192){ - rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); - int dl = base_height * 2; - int ch = (base_height - 1) * 2; - while(map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH || - (map_element->base_height != dl && map_element->base_height != ch) || - !(map_element->properties.path.edges & (1 << edge))){ - map_element++; - if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; - *ebx = MONEY32_UNDEFINED; - return; - } - } - if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_owned(x, y, base_height * 16)){ - *ebx = MONEY32_UNDEFINED; - return; - } - map_element = map_get_first_element_at(x / 32, y / 32); - dl = (base_height + 1) * 2; - while(map_element->type != MAP_ELEMENT_TYPE_BANNER || - map_element->base_height != dl || - (map_element->properties.banner.position & 0x3) != edge){ - map_element++; - if((map_element - 1)->flags & MAP_ELEMENT_FLAG_LAST_TILE){ - int banner_index = create_new_banner(*ebx); - if(banner_index == BANNER_NULL){ - *ebx = MONEY32_UNDEFINED; - return; - } - *edi = banner_index; - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0); - gBanners[banner_index].type = type; - gBanners[banner_index].colour = colour; - gBanners[banner_index].x = x / 32; - gBanners[banner_index].y = y / 32; - new_map_element->type = MAP_ELEMENT_TYPE_BANNER; - new_map_element->clearance_height = new_map_element->base_height + 2; - new_map_element->properties.banner.position = edge; - new_map_element->properties.banner.flags = 0xFF; - new_map_element->properties.banner.unused = 0; - new_map_element->properties.banner.index = banner_index; - if(*ebx & 0x40){ - new_map_element->flags |= 0x10; - } - map_invalidate_tile_full(x, y); - map_animation_create(0x0A, x, y, new_map_element->base_height); - } - rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[type]; - *ebx = scenery_entry->banner.price; - if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ - *ebx = 0; - } - return; - } - } - RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_BANNER_SIGN_IN_THE_WAY; - *ebx = MONEY32_UNDEFINED; - return; - } - }else{ + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; + *ebx = MONEY32_UNDEFINED; + return; } - *ebx = MONEY32_UNDEFINED; + + if (!sub_68B044()) { + *ebx = MONEY32_UNDEFINED; + return; + } + + if (x >= 8192 || y >= 8192) { + *ebx = MONEY32_UNDEFINED; + return; + } + + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); + int dl = base_height * 2; + int ch = (base_height - 1) * 2; + + bool pathFound = false; + do { + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_PATH) + continue; + + if (map_element->base_height != dl && map_element->base_height != ch) + continue; + + if (!(map_element->properties.path.edges & (1 << edge))) + continue; + + pathFound = true; + break; + } while (!map_element_is_last_for_tile(map_element++)); + + if (pathFound == false) { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CAN_ONLY_BE_BUILT_ACROSS_PATHS; + *ebx = MONEY32_UNDEFINED; + return; + } + + if(!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode && !map_is_location_owned(x, y, base_height * 16)){ + *ebx = MONEY32_UNDEFINED; + return; + } + map_element = map_get_first_element_at(x / 32, y / 32); + dl = (base_height + 1) * 2; + + // Check to see if there is a banner in the way + do { + if (map_element_get_type(map_element) != MAP_ELEMENT_TYPE_BANNER) + continue; + + if (map_element->base_height != dl) + continue; + + if ((map_element->properties.banner.position & 0x3) != edge) + continue; + + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_BANNER_SIGN_IN_THE_WAY; + *ebx = MONEY32_UNDEFINED; + return; + } while (!map_element_is_last_for_tile(map_element++)); + + int banner_index = create_new_banner(*ebx); + if(banner_index == BANNER_NULL){ + *ebx = MONEY32_UNDEFINED; + return; + } + *edi = banner_index; + if(*ebx & GAME_COMMAND_FLAG_APPLY){ + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + + rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, (base_height + 1) * 2, 0); + assert(new_map_element != NULL); + gBanners[banner_index].type = type; + gBanners[banner_index].colour = colour; + gBanners[banner_index].x = x / 32; + gBanners[banner_index].y = y / 32; + new_map_element->type = MAP_ELEMENT_TYPE_BANNER; + new_map_element->clearance_height = new_map_element->base_height + 2; + new_map_element->properties.banner.position = edge; + new_map_element->properties.banner.flags = 0xFF; + new_map_element->properties.banner.unused = 0; + new_map_element->properties.banner.index = banner_index; + if(*ebx & GAME_COMMAND_FLAG_GHOST){ + new_map_element->flags |= MAP_ELEMENT_FLAG_GHOST; + } + map_invalidate_tile_full(x, y); + map_animation_create(0x0A, x, y, new_map_element->base_height); + } + rct_scenery_entry *scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_BANNERS].chunks[type]; + *ebx = scenery_entry->banner.price; + if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ + *ebx = 0; + } +} + +/** + * + * rct2: 0x006E0D6E, 0x006B8D88 + */ +int map_place_scenery_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price) { + if (map_element_get_type(*map_element) != MAP_ELEMENT_TYPE_SCENERY) + return 1; + + if (!(flags & GAME_COMMAND_FLAG_7)) + return 1; + + rct_scenery_entry* scenery = g_smallSceneryEntries[(*map_element)->properties.scenery.type]; + + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_TREE_REMOVAL) { + if (scenery->small_scenery.height > 64) + return 1; + } + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) + *price += scenery->small_scenery.removal_price * 10; + + if (flags & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(flags & GAME_COMMAND_FLAG_APPLY)) + return 0; + + map_invalidate_tile(x, y, (*map_element)->base_height * 8, (*map_element)->clearance_height * 8); + + map_element_remove(*map_element); + + (*map_element)--; + return 0; +} + +/** + * + * rct2: 0x006C5A4F, 0x006CDE57, 0x006A6733, 0x0066637E + */ +int map_place_non_scenery_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price) { + if (map_element_get_type(*map_element) != MAP_ELEMENT_TYPE_SCENERY) + return 1; + + rct_scenery_entry* scenery = g_smallSceneryEntries[(*map_element)->properties.scenery.type]; + + if (RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_FORBID_TREE_REMOVAL) { + if (scenery->small_scenery.height > 64) + return 1; + } + + if (!(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY)) + *price += scenery->small_scenery.removal_price * 10; + + if (flags & GAME_COMMAND_FLAG_GHOST) + return 0; + + if (!(flags & GAME_COMMAND_FLAG_APPLY)) + return 0; + + map_invalidate_tile(x, y, (*map_element)->base_height * 8, (*map_element)->clearance_height * 8); + + map_element_remove(*map_element); + + (*map_element)--; + return 0; } /** @@ -2497,12 +2893,14 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LANDSCAPING * 4; int x = (uint16)*eax; int y = (uint16)*ecx; - uint8 color2 = *edi >> 16; + uint8 colour2 = *edi >> 16; uint8 rotation = *edi; int z = *ebp; uint8 scenery_type = *ebx >> 8; + uint8 flags = *ebx & 0xFF; uint8 quadrant = *edx; - uint8 color1 = *edx >> 8; + uint8 colour1 = *edx >> 8; + RCT2_GLOBAL(0x00F64F26, money32) = 0; int F64F1D = 0; int F64EC8 = z; int base_height = map_element_height(x, y); @@ -2518,7 +2916,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi } RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) += 16; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) += 16; - if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode){ + if(RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gCheatsBuildInPauseMode){ if(sub_68B044()){ if(RCT2_GLOBAL(0x009D8150, uint8) & 1 || (x <= RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAX_XY, uint16) && y <= RCT2_GLOBAL(RCT2_ADDRESS_MAP_MAX_XY, uint16))){ rct_scenery_entry* scenery_entry = (rct_scenery_entry*)object_entry_groups[OBJECT_TYPE_SMALL_SCENERY].chunks[scenery_type]; @@ -2550,7 +2948,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi *ebx = MONEY32_UNDEFINED; return; } - if(*ebx & GAME_COMMAND_FLAG_APPLY && !(*ebx & 0x40)){ + if(flags & GAME_COMMAND_FLAG_APPLY && !(flags & 0x40)){ footpath_remove_litter(x, y, F64EC8); if(!gCheatsDisableClearanceChecks && (scenery_entry->small_scenery.flags & SMALL_SCENERY_FLAG_ALLOW_WALLS)) { map_remove_walls_at(x, y, F64EC8, F64EC8 + scenery_entry->small_scenery.height); @@ -2621,14 +3019,20 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi if(z == 0){ bl |= 0xF0; } - RCT2_GLOBAL(0x00F64F22, uint16) = x; - RCT2_GLOBAL(0x00F64F24, uint16) = y; - RCT2_GLOBAL(0x00F64F1E, uint32) = (uint32)(ebx - 1); //0x006E0D6E uses [F64F1E+4] to read ebx value - if(gCheatsDisableClearanceChecks || map_can_construct_with_clear_at(x, y, zLow, zHigh, (void*)0x006E0D6E, bl)){ + + if(gCheatsDisableClearanceChecks || map_can_construct_with_clear_at(x, y, zLow, zHigh, &map_place_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F64F26, money32))){ RCT2_GLOBAL(0x00F64F14, uint8) = RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 0x3; - if(*ebx & GAME_COMMAND_FLAG_APPLY){ - int flags = (bl & 0xf); - rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, zLow, flags); + if(flags & GAME_COMMAND_FLAG_APPLY){ + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(flags & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + int collisionQuadrants = (bl & 0xf); + rct_map_element* new_map_element = map_element_insert(x / 32, y / 32, zLow, collisionQuadrants); + assert(new_map_element != NULL); RCT2_GLOBAL(RCT2_ADDRESS_SCENERY_MAP_ELEMENT, rct_map_element*) = new_map_element; uint8 type = quadrant << 6; type |= MAP_ELEMENT_TYPE_SCENERY; @@ -2636,13 +3040,13 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi new_map_element->type = type; new_map_element->properties.scenery.type = scenery_type; new_map_element->properties.scenery.age = 0; - new_map_element->properties.scenery.colour_1 = color1; - new_map_element->properties.scenery.colour_2 = color2; + new_map_element->properties.scenery.colour_1 = colour1; + new_map_element->properties.scenery.colour_2 = colour2; new_map_element->clearance_height = new_map_element->base_height + ((scenery_entry->small_scenery.height + 7) / 8); if(z != 0){ new_map_element->properties.scenery.colour_1 |= 0x20; } - if(*ebx & 0x40){ + if(flags & 0x40){ new_map_element->flags |= 0x10; } map_invalidate_tile_full(x, y); @@ -2650,7 +3054,7 @@ void game_command_place_scenery(int* eax, int* ebx, int* ecx, int* edx, int* esi map_animation_create(2, x, y, new_map_element->base_height); } } - *ebx = (scenery_entry->small_scenery.price * 10); + *ebx = (scenery_entry->small_scenery.price * 10) + RCT2_GLOBAL(0x00F64F26, money32); if(RCT2_GLOBAL(RCT2_ADDRESS_PARK_FLAGS, uint32) & PARK_FLAGS_NO_MONEY){ *ebx = 0; } @@ -2696,7 +3100,7 @@ static bool map_place_fence_check_obstruction_with_track(rct_scenery_entry *wall int sequence = trackElement->properties.track.sequence & 0x0F; int typeAndSequence = (trackType << 4) | sequence; direction = (edge - trackElement->type) & 3; - rct_ride *ride = GET_RIDE(trackElement->properties.track.ride_index); + rct_ride *ride = get_ride(trackElement->properties.track.ride_index); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE)) { if (RCT2_ADDRESS(0x0099AA94, uint8)[typeAndSequence] & (1 << direction)) { @@ -2720,7 +3124,7 @@ static bool map_place_fence_check_obstruction_with_track(rct_scenery_entry *wall return false; } - rct_ride_type *rideEntry = GET_RIDE_ENTRY(ride->subtype); + rct_ride_entry *rideEntry = get_ride_entry(ride->subtype); if (rideEntry->flags & RIDE_ENTRY_FLAG_16) { return false; } @@ -2885,7 +3289,7 @@ void game_command_place_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Z, sint16) = map_element_height(position.x, position.y) & 0xFFFF; } - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode){ + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode){ RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; @@ -3056,7 +3460,16 @@ void game_command_place_fence(int* eax, int* ebx, int* ecx, int* edx, int* esi, } if (flags & GAME_COMMAND_FLAG_APPLY){ + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = position.x + 16; + coord.y = position.y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + map_element = map_element_insert(position.x / 32, position.y / 32, position.z / 8, 0); + assert(map_element != NULL); map_animation_create(MAP_ANIMATION_TYPE_WALL, position.x, position.y, position.z / 8); @@ -3122,8 +3535,8 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in int x = (sint16)*eax; int y = (sint16)*ecx; int z = (sint16)*ebp; - uint8 color1 = *edx; - uint8 color2 = *edx >> 8; + uint8 colour1 = *edx; + uint8 colour2 = *edx >> 8; uint8 flags = *ebx; uint8 rotation = *ebx >> 8; uint8 entry_index = *edi; @@ -3137,18 +3550,31 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in // Supports cost RCT2_GLOBAL(0x00F4389A, money32) = 0; - if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gConfigCheat.build_in_pause_mode) { + if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) != 0 && !gCheatsBuildInPauseMode) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; *ebx = MONEY32_UNDEFINED; return; } + if (entry_index >= 128) + { + log_warning("Invalid game command for scenery placement, entry_index = %u", entry_index); + *ebx = MONEY32_UNDEFINED; + return; + } + if (!sub_68B044()) { *ebx = MONEY32_UNDEFINED; return; } - rct_scenery_entry* scenery_entry = RCT2_ADDRESS(RCT2_ADDRESS_LARGE_SCENERY_ENTRIES, rct_scenery_entry*)[entry_index]; + rct_scenery_entry *scenery_entry = g_largeSceneryEntries[entry_index]; + if (scenery_entry == (rct_scenery_entry *)0xFFFFFFFF) + { + log_warning("Invalid game command for scenery placement, entry_index = %u", entry_index); + *ebx = MONEY32_UNDEFINED; + return; + } if(scenery_entry->large_scenery.var_11 != 0xFF){ banner_id = create_new_banner(flags); @@ -3172,7 +3598,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in } } - + sint16 maxHeight = 0xFFFF; for (rct_large_scenery_tile* tile = scenery_entry->large_scenery.tiles; tile->x_offset != -1; @@ -3184,7 +3610,7 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in }; rotate_map_coordinates(&curTile.x, &curTile.y, rotation); - + curTile.x += x; curTile.y += y; @@ -3243,12 +3669,12 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in RCT2_GLOBAL(0x00F43892, sint16) = curTile.x; RCT2_GLOBAL(0x00F43894, sint16) = curTile.y; RCT2_GLOBAL(0x00F43896, uint32) = (uint32)(ebx - 3); // this is how ebx flags var is passed to 0x006B8D88 - if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(curTile.x, curTile.y, zLow, zHigh, (void*)0x006B8D88, bl)) { + if (!gCheatsDisableClearanceChecks && !map_can_construct_with_clear_at(curTile.x, curTile.y, zLow, zHigh, &map_place_scenery_clear_func, bl, flags, RCT2_ADDRESS(0x00F4389A, money32))) { *ebx = MONEY32_UNDEFINED; return; } - if ((RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) || (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & 2)) { + if ((RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERWATER) || (RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) & ELEMENT_IS_UNDERGROUND)) { *ebx = MONEY32_UNDEFINED; return; } @@ -3283,18 +3709,27 @@ void game_command_place_large_scenery(int* eax, int* ebx, int* ecx, int* edx, in map_remove_walls_at(curTile.x, curTile.y, zLow * 8, zHigh * 8); } } + if (RCT2_GLOBAL(0x009A8C28, uint8) == 1 && !(*ebx & GAME_COMMAND_FLAG_GHOST)) { + rct_xyz16 coord; + coord.x = x + 16; + coord.y = y + 16; + coord.z = map_element_height(coord.x, coord.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + } + rct_map_element *new_map_element = map_element_insert(curTile.x / 32, curTile.y / 32, zLow, F43887); + assert(new_map_element != NULL); map_animation_create(MAP_ANIMATION_TYPE_LARGE_SCENERY, curTile.x, curTile.y, zLow); new_map_element->clearance_height = zHigh; new_map_element->type = MAP_ELEMENT_TYPE_SCENERY_MULTIPLE | rotation; - new_map_element->properties.scenerymultiple.type = - (tile_num << 10) | + new_map_element->properties.scenerymultiple.type = + (tile_num << 10) | entry_index; - new_map_element->properties.scenerymultiple.colour[0] = color1; - new_map_element->properties.scenerymultiple.colour[1] = color2; + new_map_element->properties.scenerymultiple.colour[0] = colour1; + new_map_element->properties.scenerymultiple.colour[1] = colour2; if (banner_id != 0xFF) { new_map_element->type |= banner_id & 0xC0; @@ -3463,7 +3898,7 @@ void map_reorganise_elements() { platform_set_cursor(CURSOR_ZZZ); - rct_map_element* new_map_elements = rct2_malloc(0x30000 * sizeof(rct_map_element)); + rct_map_element* new_map_elements = malloc(0x30000 * sizeof(rct_map_element)); rct_map_element* new_elements_pointer = new_map_elements; if (new_map_elements == NULL || new_map_elements == (rct_map_element*)-1){ @@ -3489,7 +3924,7 @@ void map_reorganise_elements() memcpy(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element), new_map_elements, num_elements * sizeof(rct_map_element)); memset(RCT2_ADDRESS(RCT2_ADDRESS_MAP_ELEMENTS, rct_map_element) + num_elements, 0, (0x30000 - num_elements) * sizeof(rct_map_element)); - rct2_free(new_map_elements); + free(new_map_elements); map_update_tile_pointers(); } @@ -3527,7 +3962,10 @@ rct_map_element *map_element_insert(int x, int y, int z, int flags) { rct_map_element *originalMapElement, *newMapElement, *insertedElement; - sub_68B044(); + if (!sub_68B044()) { + log_error("Cannot insert new element"); + return NULL; + } newMapElement = RCT2_GLOBAL(RCT2_ADDRESS_NEXT_FREE_MAP_ELEMENT, rct_map_element*); originalMapElement = TILE_MAP_ELEMENT_POINTER(y * 256 + x); @@ -3556,7 +3994,7 @@ rct_map_element *map_element_insert(int x, int y, int z, int flags) newMapElement->base_height = z; newMapElement->flags = flags; newMapElement->clearance_height = z; - *((uint32*)&newMapElement->properties) = 0; + memset(&newMapElement->properties, 0, sizeof(newMapElement->properties)); newMapElement++; // Insert rest of map elements above insert height @@ -3593,7 +4031,7 @@ static void map_obstruction_set_error_text(rct_map_element *mapElement) errorStringId = STR_FOOTPATH_IN_THE_WAY; break; case MAP_ELEMENT_TYPE_TRACK: - ride = GET_RIDE(mapElement->properties.track.ride_index); + ride = get_ride(mapElement->properties.track.ride_index); errorStringId = STR_X_IN_THE_WAY; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 0, uint16) = ride->name; RCT2_GLOBAL(RCT2_ADDRESS_COMMON_FORMAT_ARGS + 2, uint32) = ride->name_arguments; @@ -3634,11 +4072,15 @@ static void map_obstruction_set_error_text(rct_map_element *mapElement) /** * * rct2: 0x0068B932 + * ax = x + * cx = y + * dl = zLow + * dh = zHigh + * ebp = clearFunc + * bl = bl */ -int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl) +int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUNC *clearFunc, uint8 bl, uint8 flags, money32 *price) { - // return (RCT2 CALLPROC X(0x0068B932, x, bl, y, (zHigh << 8) | zLow, 0, 0, (int)clearFunc) & 0x100) == 0; - RCT2_GLOBAL(0x00F1AD40, void*) = clearFunc; RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) = 1; if (x >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16) || y >= RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16) || x < 32 || y < 32) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = STR_OFF_EDGE_OF_MAP; @@ -3656,7 +4098,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle } int water_height = ((map_element->properties.surface.terrain & MAP_ELEMENT_WATER_HEIGHT_MASK) * 2); if (water_height && water_height > zLow && map_element->base_height < zHigh) { - RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) |= 4; + RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) |= ELEMENT_IS_UNDERWATER; if (water_height < zHigh) { goto loc_68BAE6; } @@ -3674,7 +4116,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle if ((bl & 0xF0) != 0xF0) { if (map_element->base_height >= zHigh) { // loc_68BA81 - RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) |= 2; + RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) |= ELEMENT_IS_UNDERGROUND; RCT2_GLOBAL(RCT2_ADDRESS_ELEMENT_LOCATION_COMPARED_TO_GROUND_AND_WATER, uint8) &= 0xFE; } else { int al = map_element->base_height; @@ -3710,9 +4152,9 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle continue; } loc_68BABC: - if (RCT2_GLOBAL(0x00F1AD40, void*) != (void*)0xFFFFFFFF) { + if (clearFunc != NULL) { int zero = 0; - if (!(RCT2_CALLFUNC_X((int)RCT2_GLOBAL(0x00F1AD40, void*), &zero, &zero, &zero, &zero, (int*)&map_element, &zero, &zero) & 0x100)) { + if (!clearFunc(&map_element, x, y, flags, price)) { continue; } } @@ -3721,9 +4163,9 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle } return false; loc_68BAE6: - if (RCT2_GLOBAL(0x00F1AD40, void*) != (void*)0xFFFFFFFF) { + if (clearFunc != NULL) { int zero = 0; - if (!(RCT2_CALLFUNC_X((int)RCT2_GLOBAL(0x00F1AD40, void*), &zero, &zero, &zero, &zero, (int*)&map_element, &zero, &zero) & 0x100)) { + if (!clearFunc(&map_element, x, y, flags, price)) { goto loc_68B9B7; } } @@ -3743,7 +4185,7 @@ int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *cle */ int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl) { - return map_can_construct_with_clear_at(x, y, zLow, zHigh, (void*)0xFFFFFFFF, bl); + return map_can_construct_with_clear_at(x, y, zLow, zHigh, NULL, bl, 0, NULL); } /** @@ -3828,9 +4270,8 @@ static void map_update_grass_length(int x, int y, rct_map_element *mapElement) return; } - // Grass can't grow any further - if (grassLength == GRASS_LENGTH_CLUMPS_2) - return; + // Grass can't grow any further than CLUMPS_2 but this code also cuts grass + // if there is an object placed ontop of it. int z0 = mapElement->base_height; int z1 = mapElement->base_height + 2; @@ -3842,17 +4283,22 @@ static void map_update_grass_length(int x, int y, rct_map_element *mapElement) for (;;) { if (mapElementAbove->flags & MAP_ELEMENT_FLAG_LAST_TILE) { // Grow grass - if (mapElement->properties.surface.grass_length < 0xF0) { + + // Check interim grass lengths + uint8 lengthNibble = (mapElement->properties.surface.grass_length & 0xF0) >> 4; + if (lengthNibble < 0xF) { mapElement->properties.surface.grass_length += 0x10; } else { + // Zeros the length nibble mapElement->properties.surface.grass_length += 0x10; mapElement->properties.surface.grass_length ^= 8; if (mapElement->properties.surface.grass_length & 8) { - // Random growth rate + // Random growth rate (length nibble) mapElement->properties.surface.grass_length |= scenario_rand() & 0x70; } else { - // Increase length - map_set_grass_length(x, y, mapElement, grassLength + 1); + // Increase length if not at max length + if (grassLength != GRASS_LENGTH_CLUMPS_2) + map_set_grass_length(x, y, mapElement, grassLength + 1); } } } else { @@ -3863,6 +4309,9 @@ static void map_update_grass_length(int x, int y, rct_map_element *mapElement) continue; if (z1 < mapElementAbove->base_height) continue; + + if (grassLength != GRASS_LENGTH_CLEAR_0) + map_set_grass_length(x, y, mapElement, GRASS_LENGTH_CLEAR_0); } break; } @@ -4128,6 +4577,10 @@ bool map_element_is_underground(rct_map_element *mapElement) rct_map_element *map_get_large_scenery_segment(int x, int y, int z, int direction, int sequence) { rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + if (mapElement == NULL) + { + return NULL; + } do { if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY_MULTIPLE) continue; @@ -4159,12 +4612,14 @@ rct_map_element *map_get_fence_element_at(int x, int y, int z, int direction) return NULL; } -rct_map_element *map_get_small_scenery_element_at(int x, int y, int z, int type) +rct_map_element *map_get_small_scenery_element_at(int x, int y, int z, int type, uint8 quadrant) { rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); do { if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_SCENERY) continue; + if (mapElement->type >> 6 != quadrant) + continue; if (mapElement->base_height != z) continue; if (mapElement->properties.scenery.type != type) @@ -4207,7 +4662,7 @@ bool map_large_scenery_get_origin( * * rct2: 0x006B9B05 */ -void sign_set_colour(int x, int y, int z, int direction, int sequence, uint8 mainColour, uint8 textColour) +bool sign_set_colour(int x, int y, int z, int direction, int sequence, uint8 mainColour, uint8 textColour) { rct_map_element *mapElement; rct_scenery_entry *sceneryEntry; @@ -4215,7 +4670,9 @@ void sign_set_colour(int x, int y, int z, int direction, int sequence, uint8 mai sint16 offsetX, offsetY; int x0, y0, z0; - if (!map_large_scenery_get_origin(x, y, z, direction, sequence, &x0, &y0, &z0, &mapElement)); + if (!map_large_scenery_get_origin(x, y, z, direction, sequence, &x0, &y0, &z0, &mapElement)) { + return false; + } sceneryEntry = g_largeSceneryEntries[(mapElement->properties.scenerymultiple.type) & 0x3FF]; sceneryTiles = sceneryEntry->large_scenery.tiles; @@ -4240,6 +4697,8 @@ void sign_set_colour(int x, int y, int z, int direction, int sequence, uint8 mai map_invalidate_tile(x, y, mapElement->base_height * 8 , mapElement->clearance_height * 8); } } + + return true; } /** @@ -4388,7 +4847,10 @@ int map_get_tile_quadrant(int mapX, int mapY) (subMapY < 16 ? 2 : 3); } -/* rct2: 0x00693BFF */ +/** + * + * rct2: 0x00693BFF + */ bool map_surface_is_blocked(sint16 x, sint16 y){ rct_map_element *mapElement; if (x >= 8192 || y >= 8192) @@ -4438,6 +4900,10 @@ void map_clear_all_elements() } money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direction) { + if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode) { + return MONEY32_UNDEFINED; + } + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LAND_PURCHASE * 4; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, sint16) = x; @@ -4450,7 +4916,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc } if (x <= 32 || y <= 32 || x >= (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16) - 32) || y >= (RCT2_GLOBAL(RCT2_ADDRESS_MAP_SIZE_UNITS, sint16) - 32)) { - RCT2_GLOBAL(0x00141E9AC, rct_string_id) = 3215; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = 3215; return MONEY32_UNDEFINED; } @@ -4463,7 +4929,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc } if (entranceNum == -1) { - RCT2_GLOBAL(0x00141E9AC, rct_string_id) = 3227; + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, rct_string_id) = 3227; return MONEY32_UNDEFINED; } @@ -4476,8 +4942,10 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc sint8 zLow = (z & 0xFF) * 2; sint8 zHigh = zLow + 12; - if (!map_can_construct_at(x, y, zLow, zHigh, 0xF)) { - return MONEY32_UNDEFINED; + if (!gCheatsDisableClearanceChecks) { + if (!map_can_construct_at(x, y, zLow, zHigh, 0xF)) { + return MONEY32_UNDEFINED; + } } if (flags & GAME_COMMAND_FLAG_APPLY) { @@ -4488,6 +4956,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc } rct_map_element* newElement = map_element_insert(x / 32, y / 32, zLow, 0xF); + assert(newElement != NULL); newElement->clearance_height = zHigh; if (flags & GAME_COMMAND_FLAG_GHOST) { @@ -4518,8 +4987,10 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc x += TileDirectionDelta[(direction - 1) & 0x3].x; y += TileDirectionDelta[(direction - 1) & 0x3].y; - if (!map_can_construct_at(x, y, zLow, zHigh, 0xF)) { - return MONEY32_UNDEFINED; + if (!gCheatsDisableClearanceChecks) { + if (!map_can_construct_at(x, y, zLow, zHigh, 0xF)) { + return MONEY32_UNDEFINED; + } } if (flags & GAME_COMMAND_FLAG_APPLY) { @@ -4530,6 +5001,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc } rct_map_element* newElement = map_element_insert(x / 32, y / 32, zLow, 0xF); + assert(newElement != NULL); newElement->clearance_height = zHigh; if (flags & GAME_COMMAND_FLAG_GHOST) { @@ -4553,8 +5025,10 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc x += TileDirectionDelta[(direction + 1) & 0x3].x * 2; y += TileDirectionDelta[(direction + 1) & 0x3].y * 2; - if (!map_can_construct_at(x, y, zLow, zHigh, 0xF)) { - return MONEY32_UNDEFINED; + if (!gCheatsDisableClearanceChecks) { + if (!map_can_construct_at(x, y, zLow, zHigh, 0xF)) { + return MONEY32_UNDEFINED; + } } if (flags & GAME_COMMAND_FLAG_APPLY) { @@ -4565,6 +5039,7 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc } rct_map_element* newElement = map_element_insert(x / 32, y / 32, zLow, 0xF); + assert(newElement != NULL); newElement->clearance_height = zHigh; if (flags & GAME_COMMAND_FLAG_GHOST) { @@ -4588,7 +5063,10 @@ money32 place_park_entrance(int flags, sint16 x, sint16 y, sint16 z, uint8 direc return 0; } -/* rct2: 0x006666E7 */ +/** + * + * rct2: 0x006666E7 + */ void game_command_place_park_entrance(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { *ebx = place_park_entrance( *ebx & 0xFF, @@ -4601,6 +5079,12 @@ void game_command_place_park_entrance(int* eax, int* ebx, int* ecx, int* edx, in void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { static char newName[128]; + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + log_warning("Invalid game command for setting banner name, banner id = %d", *ecx); + *ebx = MONEY32_UNDEFINED; + return; + } rct_banner* banner = &gBanners[*ecx]; int nameChunkIndex = *eax & 0xFFFF; @@ -4610,6 +5094,7 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e 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; @@ -4619,7 +5104,12 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e return; } - utf8 *buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, uint8); + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { + *ebx = 0; + return; + } + + utf8 *buffer = RCT2_ADDRESS(RCT2_ADDRESS_COMMON_STRING_FORMAT_BUFFER, utf8); utf8 *dst = buffer; dst = utf8_write_codepoint(dst, FORMAT_COLOUR_CODE_START + banner->text_colour); strncpy(dst, newName, 32); @@ -4645,6 +5135,12 @@ void game_command_set_banner_name(int* eax, int* ebx, int* ecx, int* edx, int* e void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { static char newName[128]; + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + log_warning("Invalid game command for setting sign name, banner id = %d", *ecx); + *ebx = MONEY32_UNDEFINED; + return; + } rct_banner* banner = &gBanners[*ecx]; int x = banner->x << 5; int y = banner->y << 5; @@ -4656,6 +5152,7 @@ void game_command_set_sign_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; @@ -4665,6 +5162,11 @@ void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi return; } + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { + *ebx = 0; + return; + } + if (newName[0] != 0) { rct_string_id string_id = user_string_allocate(128, newName); if (string_id != 0) { @@ -4700,6 +5202,18 @@ void game_command_set_sign_name(int* eax, int* ebx, int* ecx, int* edx, int* esi } void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { + if ((*ecx >= MAX_BANNERS) || (*ecx < 0)) + { + RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_INVALID_SELECTION_OF_OBJECTS; + *ebx = MONEY32_UNDEFINED; + return; + } + + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { + *ebx = 0; + return; + } + rct_banner* banner = &gBanners[*ecx]; banner->colour = (uint8)*edx; @@ -4728,7 +5242,7 @@ void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* *ebx = MONEY32_UNDEFINED; return; } - + map_element->properties.banner.flags = 0xFF; if (banner->flags & BANNER_FLAG_NO_ENTRY){ map_element->properties.banner.flags &= ~(1 << map_element->properties.banner.position); @@ -4736,7 +5250,7 @@ void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* int colourCodepoint = FORMAT_COLOUR_CODE_START + banner->text_colour; - uint8 buffer[256]; + utf8 buffer[256]; format_string(buffer, banner->string_idx, 0); int firstCodepoint = utf8_get_next(buffer, NULL); if (firstCodepoint >= FORMAT_COLOUR_CODE_START && firstCodepoint <= FORMAT_COLOUR_CODE_END) { @@ -4763,7 +5277,7 @@ void game_command_set_banner_style(int* eax, int* ebx, int* ecx, int* edx, int* *ebx = 0; } -void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { +void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { uint8 bannerId = *ecx & 0xFF; rct_banner *banner = &gBanners[bannerId]; int x = banner->x << 5; @@ -4771,9 +5285,9 @@ void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* es uint8 mainColour = (uint8)*edx; uint8 textColour = (uint8)*edi; - + if (*ebp == 0) { // small sign - + rct_map_element* map_element = map_get_first_element_at(x / 32, y / 32); bool fence_found = false; do{ @@ -4793,6 +5307,12 @@ void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* es *ebx = MONEY32_UNDEFINED; return; } + + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { + *ebx = 0; + return; + } + map_element->flags &= 0x9F; map_element->properties.fence.item[1] = mainColour | @@ -4808,7 +5328,12 @@ void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* es return; } - sign_set_colour( + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { + *ebx = 0; + return; + } + + if (!sign_set_colour( banner->x * 32, banner->y * 32, mapElement->base_height, @@ -4816,7 +5341,10 @@ void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* es mapElement->properties.scenerymultiple.type >> 10, mainColour, textColour - ); + )) { + *ebx = MONEY32_UNDEFINED; + return; + } } rct_window* w = window_bring_to_front_by_number(WC_BANNER, *ecx); @@ -4828,7 +5356,7 @@ void game_command_set_sign_style(int* eax, int* ebx, int* ecx, int* edx, int* es } /** - * Gets the map element at x, y, z. + * Gets the track element at x, y, z. * @param x x units, not tiles. * @param y y units, not tiles. * @param z Base height. @@ -4847,10 +5375,11 @@ rct_map_element *map_get_track_element_at(int x, int y, int z) } /** - * Gets the map element at x, y, z. + * Gets the track element at x, y, z that is the given track type. * @param x x units, not tiles. * @param y y units, not tiles. * @param z Base height. + * @param trackType */ rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int trackType) { @@ -4865,3 +5394,91 @@ rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int track return NULL; } + +/** + * Gets the track element at x, y, z that is the given track type and sequence. + * @param x x units, not tiles. + * @param y y units, not tiles. + * @param z Base height. + * @param trackType + * @param sequence + */ +rct_map_element *map_get_track_element_at_of_type_seq(int x, int y, int z, int trackType, int sequence) +{ + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (mapElement->base_height != z) continue; + if (mapElement->properties.track.type != trackType) continue; + if ((mapElement->properties.track.sequence & 0x0F) != sequence) continue; + + return mapElement; + } while (!map_element_is_last_for_tile(mapElement++)); + + return NULL; +} + +/** + * Gets the track element at x, y, z that is the given track type and sequence. + * @param x x units, not tiles. + * @param y y units, not tiles. + * @param z Base height. + * @param trackType + * @param ride index + */ +rct_map_element *map_get_track_element_at_of_type_from_ride(int x, int y, int z, int trackType, int rideIndex) { + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (mapElement->base_height != z) continue; + if (mapElement->properties.track.ride_index != rideIndex) continue; + if (mapElement->properties.track.type != trackType) continue; + + return mapElement; + } while (!map_element_is_last_for_tile(mapElement++)); + + return NULL; +}; + +/** + * Gets the track element at x, y, z that is the given track type and sequence. + * @param x x units, not tiles. + * @param y y units, not tiles. + * @param z Base height. + * @param ride index + */ +rct_map_element *map_get_track_element_at_from_ride(int x, int y, int z, int rideIndex) { + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (mapElement->base_height != z) continue; + if (mapElement->properties.track.ride_index != rideIndex) continue; + + return mapElement; + } while (!map_element_is_last_for_tile(mapElement++)); + + return NULL; +}; + +/** + * Gets the track element at x, y, z that is the given track type and sequence. + * @param x x units, not tiles. + * @param y y units, not tiles. + * @param z Base height. + * @param direction The direction (0 - 3). + * @param ride index + */ +rct_map_element *map_get_track_element_at_with_direction_from_ride(int x, int y, int z, int direction, int rideIndex) +{ + rct_map_element *mapElement = map_get_first_element_at(x >> 5, y >> 5); + do { + if (map_element_get_type(mapElement) != MAP_ELEMENT_TYPE_TRACK) continue; + if (mapElement->base_height != z) continue; + if (mapElement->properties.track.ride_index != rideIndex) continue; + if (map_element_get_direction(mapElement) != direction) continue; + + return mapElement; + } while (!map_element_is_last_for_tile(mapElement++)); + + return NULL; +}; diff --git a/src/world/map.h b/src/world/map.h index d2db49fefa..32cb69f6a4 100644 --- a/src/world/map.h +++ b/src/world/map.h @@ -31,7 +31,7 @@ typedef struct { } rct_map_element_surface_properties; typedef struct { - uint8 type; //4 + uint8 type; //4 0xF0 Path type, 0x08 Unknown/Unused, 0x04 Set when path is diagonal, 0x03 Rotation uint8 additions; //5 uint8 edges; //6 union { @@ -121,7 +121,10 @@ enum { MAP_ELEMENT_TYPE_ENTRANCE = (4 << 2), MAP_ELEMENT_TYPE_FENCE = (5 << 2), MAP_ELEMENT_TYPE_SCENERY_MULTIPLE = (6 << 2), - MAP_ELEMENT_TYPE_BANNER = (7 << 2) + MAP_ELEMENT_TYPE_BANNER = (7 << 2), + // The corrupt element type is used for skipping drawing other following + // elements on a given tile. + MAP_ELEMENT_TYPE_CORRUPT = (8 << 2), }; enum { @@ -138,6 +141,7 @@ enum { enum { MAP_ELEMENT_FLAG_GHOST = (1 << 4), MAP_ELEMENT_FLAG_BROKEN = (1 << 5), + MAP_ELEMENT_FLAG_BLOCK_BREAK_CLOSED = (1 << 5), MAP_ELEMENT_FLAG_LAST_TILE = (1 << 7) }; @@ -204,7 +208,8 @@ enum { }; enum { - ELEMENT_IS_UNDERWATER = 4, + ELEMENT_IS_UNDERGROUND = 1 << 1, + ELEMENT_IS_UNDERWATER = 1 << 2, }; #define MAP_ELEMENT_QUADRANT_MASK 0xC0 @@ -228,7 +233,12 @@ enum { #define TILE_UNDEFINED_MAP_ELEMENT (rct_map_element*)-1 typedef struct { - uint8 x, y; + union { + struct { + uint8 x, y; + }; + uint16 xy; + }; } rct_xy8; typedef struct{ @@ -277,11 +287,11 @@ void map_init(int size); void map_update_tile_pointers(); rct_map_element *map_get_first_element_at(int x, int y); void map_set_tile_elements(int x, int y, rct_map_element *elements); -int map_element_is_last_for_tile(rct_map_element *element); -int map_element_get_type(rct_map_element *element); -int map_element_get_direction(rct_map_element *element); -int map_element_get_terrain(rct_map_element *element); -int map_element_get_terrain_edge(rct_map_element *element); +int map_element_is_last_for_tile(const rct_map_element *element); +int map_element_get_type(const rct_map_element *element); +int map_element_get_direction(const rct_map_element *element); +int map_element_get_terrain(const rct_map_element *element); +int map_element_get_terrain_edge(const rct_map_element *element); void map_element_set_terrain(rct_map_element *element, int terrain); void map_element_set_terrain_edge(rct_map_element *element, int terrain); int map_height_from_slope(int x, int y, int slope); @@ -289,7 +299,7 @@ rct_map_element* map_get_banner_element_at(int x, int y, int z, uint8 direction) rct_map_element *map_get_surface_element_at(int x, int y); rct_map_element* map_get_path_element_at(int x, int y, int z); rct_map_element *map_get_fence_element_at(int x, int y, int z, int direction); -rct_map_element *map_get_small_scenery_element_at(int x, int y, int z, int type); +rct_map_element *map_get_small_scenery_element_at(int x, int y, int z, int type, uint8 quadrant); int map_element_height(int x, int y); void sub_68B089(); int map_coord_is_connected(int x, int y, int z, uint8 faceDirection); @@ -306,7 +316,10 @@ void map_invalidate_selection_rect(); void map_reorganise_elements(); int sub_68B044(); rct_map_element *map_element_insert(int x, int y, int z, int flags); -int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, void *clearFunc, uint8 bl); + +typedef int (CLEAR_FUNC)(rct_map_element** map_element, int x, int y, uint8 flags, money32* price); +int map_place_non_scenery_clear_func(rct_map_element** map_element, int x, int y, uint8 flags, money32* price); +int map_can_construct_with_clear_at(int x, int y, int zLow, int zHigh, CLEAR_FUNC *clearFunc, uint8 bl, uint8 flags, money32 *price); int map_can_construct_at(int x, int y, int zLow, int zHigh, uint8 bl); void rotate_map_coordinates(sint16 *x, sint16 *y, int rotation); rct_xy16 coordinate_3d_to_2d(const rct_xyz16* coordinate_3d, int rotation); @@ -369,7 +382,7 @@ bool map_element_is_underground(rct_map_element *mapElement); void map_remove_out_of_range_elements(); void map_extend_boundary_surface(); -void sign_set_colour(int x, int y, int z, int direction, int sequence, uint8 mainColour, uint8 textColour); +bool sign_set_colour(int x, int y, int z, int direction, int sequence, uint8 mainColour, uint8 textColour); void map_remove_walls_at(int x, int y, int z0, int z1); void map_remove_walls_at_z(int x, int y, int z); @@ -392,5 +405,9 @@ bool map_large_scenery_get_origin( rct_map_element *map_get_track_element_at(int x, int y, int z); rct_map_element *map_get_track_element_at_of_type(int x, int y, int z, int trackType); +rct_map_element *map_get_track_element_at_of_type_seq(int x, int y, int z, int trackType, int sequence); +rct_map_element *map_get_track_element_at_of_type_from_ride(int x, int y, int z, int trackType, int rideIndex); +rct_map_element *map_get_track_element_at_from_ride(int x, int y, int z, int rideIndex); +rct_map_element *map_get_track_element_at_with_direction_from_ride(int x, int y, int z, int direction, int rideIndex); #endif diff --git a/src/world/map_animation.c b/src/world/map_animation.c index ab45491527..f930c0cd26 100644 --- a/src/world/map_animation.c +++ b/src/world/map_animation.c @@ -125,7 +125,7 @@ static bool map_animation_invalidate_ride_entrance(int x, int y, int baseZ) if (mapElement->properties.entrance.type != ENTRANCE_TYPE_RIDE_ENTRANCE) continue; - ride = GET_RIDE(mapElement->properties.entrance.ride_index); + ride = get_ride(mapElement->properties.entrance.ride_index); entranceDefinition = &RideEntranceDefinitions[ride->entrance_style]; int height = (mapElement->base_height * 8) + entranceDefinition->height + 8; @@ -536,7 +536,10 @@ static bool map_animation_invalidate_wall(int x, int y, int baseZ) return !wasInvalidated; } -/** rct2: 0x009819DC */ +/** + * + * rct2: 0x009819DC + */ static const map_animation_invalidate_event_handler _animatedObjectEventHandlers[MAP_ANIMATION_TYPE_COUNT] = { map_animation_invalidate_ride_entrance, map_animation_invalidate_queue_banner, diff --git a/src/world/map_animation.h b/src/world/map_animation.h index 2bf35cd1c5..4c9ecdd9f6 100644 --- a/src/world/map_animation.h +++ b/src/world/map_animation.h @@ -57,4 +57,4 @@ extern rct_map_animation *gAnimatedObjects; void map_animation_create(int type, int x, int y, int z); void map_animation_invalidate_all(); -#endif \ No newline at end of file +#endif diff --git a/src/world/map_helpers.c b/src/world/map_helpers.c index 773def8cb9..25b88c1793 100644 --- a/src/world/map_helpers.c +++ b/src/world/map_helpers.c @@ -322,4 +322,4 @@ int map_smooth_wavy(int l, int t, int r, int b) } return raisedLand; -} \ No newline at end of file +} diff --git a/src/world/map_helpers.h b/src/world/map_helpers.h index 3a2dffa630..4c8f0e01b0 100644 --- a/src/world/map_helpers.h +++ b/src/world/map_helpers.h @@ -23,4 +23,4 @@ int map_smooth(int l, int t, int r, int b); -#endif \ No newline at end of file +#endif diff --git a/src/world/mapgen.c b/src/world/mapgen.c index 4650b4307e..8c80801779 100644 --- a/src/world/mapgen.c +++ b/src/world/mapgen.c @@ -234,6 +234,7 @@ static void mapgen_place_tree(int type, int x, int y) surfaceZ = map_element_height(x * 32 + 16, y * 32 + 16) / 8; mapElement = map_element_insert(x, y, surfaceZ, (1 | 2 | 4 | 8)); + assert(mapElement != NULL); mapElement->clearance_height = surfaceZ + (sceneryEntry->small_scenery.height >> 3); mapElement->type = MAP_ELEMENT_TYPE_SCENERY | (util_rand() % 3); diff --git a/src/world/mapgen.h b/src/world/mapgen.h index fd83f9e3e8..0f81968e90 100644 --- a/src/world/mapgen.h +++ b/src/world/mapgen.h @@ -43,4 +43,4 @@ void mapgen_generate_blank(mapgen_settings *settings); void mapgen_generate(mapgen_settings *settings); void mapgen_generate_custom_simplex(mapgen_settings *settings); -#endif \ No newline at end of file +#endif diff --git a/src/world/money_effect.c b/src/world/money_effect.c index b33565531f..33a6000990 100644 --- a/src/world/money_effect.c +++ b/src/world/money_effect.c @@ -12,7 +12,7 @@ static const rct_xy16 _moneyEffectMoveOffset[] = { /** * - * rct: 0x0067351F + * rct2: 0x0067351F */ void money_effect_create_at(money32 value, int x, int y, int z) { @@ -47,7 +47,7 @@ void money_effect_create_at(money32 value, int x, int y, int z) /** * - * rct: 0x0069C5D0 + * rct2: 0x0069C5D0 */ void money_effect_create(money32 value) { @@ -82,7 +82,7 @@ void money_effect_create(money32 value) /** * - * rct: 0x00673232 + * rct2: 0x00673232 */ void money_effect_update(rct_money_effect *moneyEffect) { diff --git a/src/world/park.c b/src/world/park.c index 1111b8a4bd..0369a0021c 100644 --- a/src/world/park.c +++ b/src/world/park.c @@ -30,11 +30,13 @@ #include "../management/research.h" #include "../peep/peep.h" #include "../ride/ride.h" +#include "../ride/ride_data.h" #include "../scenario.h" #include "../world/map.h" #include "park.h" #include "sprite.h" #include "../config.h" +#include "../cheats.h" uint8 *gParkRatingHistory = RCT2_ADDRESS(RCT2_ADDRESS_PARK_RATING_HISTORY, uint8); uint8 *gGuestsInParkHistory = RCT2_ADDRESS(RCT2_ADDRESS_GUESTS_IN_PARK_HISTORY, uint8); @@ -192,7 +194,7 @@ int calculate_park_rating() continue; if (peep->happiness > 128) num_happy_peeps++; - if ((peep->flags & PEEP_FLAGS_LEAVING_PARK) && (peep->peep_is_lost_countdown < 90)) + if ((peep->peep_flags & PEEP_FLAGS_LEAVING_PARK) && (peep->peep_is_lost_countdown < 90)) num_lost_guests++; } @@ -285,12 +287,7 @@ money32 calculate_ride_value(rct_ride *ride) return 0; // Fair value * (...) - return (ride->value * 10) * ( - ride->var_124 + ride->var_126 + ride->var_128 + ride->var_12A + - ride->var_12C + ride->var_12E + ride->age + ride->running_cost + - ride->var_134 + ride->var_136 + - *((uint8*)(0x0097D21E + (ride->type * 8))) * 4 - ); + return (ride->value * 10) * (ride_customers_in_last_5_minutes(ride) + rideBonusValue[ride->type] * 4); } /** @@ -306,7 +303,7 @@ money32 calculate_park_value() // Sum ride values result = 0; for (i = 0; i < 255; i++) { - ride = &g_ride_list[i]; + ride = get_ride(i); result += calculate_ride_value(ride); } @@ -371,7 +368,7 @@ static int park_calculate_guest_generation_probability() continue; // Add guest score for ride type - suggestedMaxGuests += RCT2_GLOBAL(0x0097D21E + (ride->type * 8), uint8); + suggestedMaxGuests += rideBonusValue[ride->type]; // Add ride value if (ride->value != RIDE_VALUE_UNDEFINED) { @@ -402,7 +399,7 @@ static int park_calculate_guest_generation_probability() continue; // Bonus guests for good ride - suggestedMaxGuests += RCT2_GLOBAL(0x0097D21E + (ride->type * 8), uint8) * 2; + suggestedMaxGuests += rideBonusValue[ride->type] * 2; } } @@ -662,7 +659,7 @@ void park_set_open(int open) */ void game_command_set_park_open(int* eax, int* ebx, int* ecx, int* edx, int* esi, int* edi, int* ebp) { - if (*ebx & GAME_COMMAND_FLAG_APPLY) { + if (!(*ebx & GAME_COMMAND_FLAG_APPLY)) { *ebx = 0; return; } @@ -809,6 +806,11 @@ void game_command_remove_park_entrance(int *eax, int *ebx, int *ecx, int *edx, i y = *ecx & 0xFFFF; z = *edx * 16; + if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode) { + *ebx = MONEY32_UNDEFINED; + return; + } + RCT2_GLOBAL(RCT2_ADDRESS_NEXT_EXPENDITURE_TYPE, uint8) = RCT_EXPENDITURE_TYPE_LAND_PURCHASE * 4; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_X, uint16) = x; RCT2_GLOBAL(RCT2_ADDRESS_COMMAND_MAP_Y, uint16) = y; @@ -875,6 +877,7 @@ void game_command_set_park_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; @@ -989,6 +992,10 @@ money32 map_buy_land_rights_for_tile(int x, int y, int setting, int flags) { } return 0; default: + if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_EDITOR) && !gCheatsSandboxMode) { + return MONEY32_UNDEFINED; + } + if (x <= 32 || y <= 32) { RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = 3215; return MONEY32_UNDEFINED; @@ -1059,7 +1066,7 @@ int map_buy_land_rights(int x0, int y0, int x1, int y1, int setting, int flags) // Game command modified to accept selection size totalCost = 0; RCT2_GLOBAL(RCT2_ADDRESS_GAME_COMMAND_ERROR_TEXT, uint16) = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gConfigCheat.build_in_pause_mode) { + if ((RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) == 0 || gCheatsBuildInPauseMode) { for (y = y0; y <= y1; y += 32) { for (x = x0; x <= x1; x += 32) { cost = map_buy_land_rights_for_tile(x, y, setting, flags); diff --git a/src/world/park.h b/src/world/park.h index 5f24a295e4..be78949208 100644 --- a/src/world/park.h +++ b/src/world/park.h @@ -35,7 +35,7 @@ enum { PARK_FLAGS_FORBID_HIGH_CONSTRUCTION = (1 << 5), // below tree height PARK_FLAGS_PREF_LESS_INTENSE_RIDES = (1 << 6), PARK_FLAGS_FORBID_MARKETING_CAMPAIGN = (1 << 7), - PARK_FLAGS_8 = (1 << 8), + PARK_FLAGS_ANTI_CHEAT_DEPRECATED = (1 << 8), // Not used anymore, used for cheat detection PARK_FLAGS_PREF_MORE_INTENSE_RIDES = (1 << 9), PARK_FLAGS_NO_MONEY = (1 << 11), PARK_FLAGS_DIFFICULT_GUEST_GENERATION = (1 << 12), @@ -44,13 +44,15 @@ enum { PARK_FLAGS_LOCK_REAL_NAMES_OPTION = (1 << 15), PARK_FLAGS_NO_MONEY_SCENARIO = (1 << 17), // equivalent to PARK_FLAGS_NO_MONEY, but used in scenario editor PARK_FLAGS_18 = (1 << 18), - PARK_FLAGS_SIX_FLAGS_DEPRECATED = (1 << 19) + PARK_FLAGS_SIX_FLAGS_DEPRECATED = (1 << 19) // Not used anymore }; extern uint8 *gParkRatingHistory; extern uint8 *gGuestsInParkHistory; +extern int _guestGenerationProbability; +extern int _suggestedGuestMaximum; -void set_forced_park_rating(); +void set_forced_park_rating(int rating); int get_forced_park_rating(); int park_is_open(); diff --git a/src/world/particle.c b/src/world/particle.c index ecec4ff98d..60e8ecdfeb 100644 --- a/src/world/particle.c +++ b/src/world/particle.c @@ -16,14 +16,14 @@ void crashed_vehicle_particle_create(rct_vehicle_colour colours, int x, int y, i sprite->sprite_height_negative = 8; sprite->sprite_height_positive = 8; sprite->sprite_identifier = SPRITE_IDENTIFIER_MISC; - sprite_move(x, y, z + 4, (rct_sprite*)sprite); + sprite_move(x, y, z, (rct_sprite*)sprite); sprite->misc_identifier = SPRITE_MISC_CRASHED_VEHICLE_PARTICLE; sprite->var_26 = (util_rand() & 0xFF) * 12; sprite->var_24 = (util_rand() & 0x7F) + 140; sprite->var_2E = ((util_rand() & 0xFF) * 5) >> 8; - sprite->acceleration_x = (util_rand() & 0xFFFF) * 4; - sprite->acceleration_y = (util_rand() & 0xFFFF) * 4; + sprite->acceleration_x = ((sint16)(util_rand() & 0xFFFF)) * 4; + sprite->acceleration_y = ((sint16)(util_rand() & 0xFFFF)) * 4; sprite->acceleration_z = (util_rand() & 0xFFFF) * 4 + 0x10000; sprite->velocity_x = 0; sprite->velocity_y = 0; @@ -33,7 +33,7 @@ void crashed_vehicle_particle_create(rct_vehicle_colour colours, int x, int y, i /** * - * rct: 0x00673298 + * rct2: 0x00673298 */ void crashed_vehicle_particle_update(rct_crashed_vehicle_particle *particle) { @@ -112,7 +112,7 @@ void crash_splash_create(int x, int y, int z) /** * - * rct: 0x0067339D + * rct2: 0x0067339D */ void crash_splash_update(rct_crash_splash *splash) { diff --git a/src/world/scenery.c b/src/world/scenery.c index 9974593d96..21c19b2dde 100644 --- a/src/world/scenery.c +++ b/src/world/scenery.c @@ -28,6 +28,7 @@ #include "map.h" #include "park.h" #include "scenery.h" +#include "footpath.h" void scenery_increase_age(int x, int y, rct_map_element *mapElement); @@ -40,10 +41,9 @@ void scenery_update_tile(int x, int y) if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_SCENERY) { scenery_update_age(x, y, mapElement); } else if (map_element_get_type(mapElement) == MAP_ELEMENT_TYPE_PATH) { - int additions = mapElement->properties.path.additions & 0x0F; - if (additions != 0 && !(mapElement->properties.path.additions & 0x80)) { + if (footpath_element_has_path_scenery(mapElement) && !footpath_element_path_scenery_is_ghost(mapElement)) { rct_scenery_entry *sceneryEntry; - sceneryEntry = g_pathBitSceneryEntries[additions - 1]; + sceneryEntry = g_pathBitSceneryEntries[footpath_element_get_path_scenery_index(mapElement)]; if (sceneryEntry->path_bit.var_06 & PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER) { jumping_fountain_begin(JUMPING_FOUNTAIN_TYPE_WATER, x, y, mapElement); } else if (sceneryEntry->path_bit.var_06 & PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW) { @@ -111,7 +111,7 @@ void scenery_increase_age(int x, int y, rct_map_element *mapElement) } } -/* +/** * * rct2: 0x006E2712 */ @@ -192,4 +192,4 @@ void scenery_remove_ghost_tool_placement(){ 0, 0); } -} \ No newline at end of file +} diff --git a/src/world/scenery.h b/src/world/scenery.h index 7f68bae88b..332d11c8da 100644 --- a/src/world/scenery.h +++ b/src/world/scenery.h @@ -99,7 +99,7 @@ typedef enum { WALL_SCENERY_FLAG1 = (1 << 0), // 0x1 WALL_SCENERY_FLAG2 = (1 << 1), // 0x2 WALL_SCENERY_FLAG3 = (1 << 2), // 0x4 - WALL_SCENERY_FLAG4 = (1 << 3), // 0x8 + WALL_SCENERY_FLAG4 = (1 << 3), // 0x8 // Probably indicates translucency WALL_SCENERY_FLAG5 = (1 << 4), // 0x10 WALL_SCENERY_FLAG6 = (1 << 5), // 0x20 WALL_SCENERY_HAS_SECONDARY_COLOUR = (1 << 6), // 0x40 @@ -163,6 +163,7 @@ enum { #define g_largeSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_LARGE_SCENERY].chunks) #define g_wallSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_WALLS].chunks) #define g_bannerSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_BANNERS].chunks) +#define g_pathSceneryEntries ((rct_scenery_entry**)object_entry_groups[OBJECT_TYPE_PATHS].chunks) // Often 0x009ADA50 is used for pathBits this is 1 entry before g_pathBitSceneryEntries and is used // because 0 represents no path bits on a path. So remember to remove 1 when using it for 0x009ADA50 @@ -187,4 +188,4 @@ void scenery_set_default_placement_configuration(); void scenery_remove_ghost_tool_placement(); void scenery_set_default_placement_configuration(); -#endif \ No newline at end of file +#endif diff --git a/src/world/sprite.c b/src/world/sprite.c index 3be296848e..5f6ba1e77e 100644 --- a/src/world/sprite.c +++ b/src/world/sprite.c @@ -29,7 +29,9 @@ rct_sprite* g_sprite_list = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_LIST, rct_sprite); -static uint16 sprite_get_first_in_quadrant(int x, int y) +rct_sprite_entry* g_sprite_entries = RCT2_ADDRESS(RCT2_ADDRESS_SPRITE_ENTRIES, rct_sprite_entry); + +uint16 sprite_get_first_in_quadrant(int x, int y) { int offset = ((x & 0x1FE0) << 3) | (y >> 5); return RCT2_ADDRESS(0x00F1EF60, uint16)[offset]; @@ -72,20 +74,22 @@ void invalidate_sprite_1(rct_sprite *sprite) } /** -* Invalidate sprite if not at furthest zoom. -* rct2: 0x006EC473 -*/ + * Invalidate sprite if not at furthest zoom. + * rct2: 0x006EC473 + * + * @param sprite (esi) + */ void invalidate_sprite_2(rct_sprite *sprite) { invalidate_sprite_max_zoom(sprite, 2); } -/* +/** * - * rct2: 0x0069EB13 + * rct2: 0x0069EB13 */ void reset_sprite_list(){ - RCT2_GLOBAL(0x1388698, uint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_SAVED_AGE, uint16) = 0; memset(g_sprite_list, 0, sizeof(rct_sprite) * MAX_SPRITES); for (int i = 0; i < 6; ++i){ @@ -120,7 +124,8 @@ void reset_sprite_list(){ } /** - * rct2: 0x0069EBE4 + * + * rct2: 0x0069EBE4 * This function looks as though it sets some sort of order for sprites. * Sprites can share thier position if this is the case. */ @@ -150,7 +155,7 @@ void reset_0x69EBE4(){ /** * Clears all the unused sprite memory to zero. Probably so that it can be compressed better when saving. - * rct2: 0x0069EBA4 + * rct2: 0x0069EBA4 */ void sprite_clear_all_unused() { @@ -183,7 +188,7 @@ rct_sprite *create_sprite(uint8 bl) if ((bl & 2) != 0) { // 69EC96; - uint16 cx = 0x12C - RCT2_GLOBAL(0x13573CE, uint16); + sint16 cx = 0x12C - RCT2_GLOBAL(RCT2_ADDRESS_SPRITES_COUNT_MISC, uint16); if (cx >= RCT2_GLOBAL(0x13573C8, uint16)) { return NULL; @@ -207,7 +212,7 @@ rct_sprite *create_sprite(uint8 bl) sprite->sprite_width = 0x10; sprite->sprite_height_negative = 0x14; sprite->sprite_height_positive = 0x8; - sprite->var_0C = 0; + sprite->flags = 0; sprite->sprite_left = SPRITE_LOCATION_NULL; sprite->next_in_quadrant = RCT2_ADDRESS(0xF1EF60, uint16)[0x10000]; @@ -270,20 +275,25 @@ void move_sprite_to_list(rct_sprite *sprite, uint8 cl) /** * - * rct: 0x00673200 + * rct2: 0x00673200 */ -static void sprite_misc_0_update(rct_sprite *sprite) +static void sprite_steam_particle_update(rct_steam_particle *steam) { - invalidate_sprite_2(sprite); + invalidate_sprite_2((rct_sprite*)steam); - int original_var24 = sprite->unknown.var_24; - sprite->unknown.var_24 += 0x5555; - if (sprite->unknown.var_24 < 0x5555) { - sprite_move(sprite->unknown.x, sprite->unknown.y, sprite->unknown.z + 1, sprite); + int original_var24 = steam->var_24; + steam->var_24 += 0x5555; + if (steam->var_24 < 0x5555) { + sprite_move( + steam->x, + steam->y, + steam->z + 1, + (rct_sprite*)steam + ); } - sprite->unknown.var_26 += 64; - if (sprite->unknown.var_26 >= (56 * 64)) { - sprite_remove(sprite); + steam->var_26 += 64; + if (steam->var_26 >= (56 * 64)) { + sprite_remove((rct_sprite*)steam); } } @@ -307,7 +317,7 @@ void sprite_misc_3_create(int x, int y, int z) /** * - * rct: 0x00673385 + * rct2: 0x00673385 */ static void sprite_misc_3_update(rct_sprite *sprite) { @@ -338,7 +348,7 @@ void sprite_misc_5_create(int x, int y, int z) /** * - * rct: 0x006733B4 + * rct2: 0x006733B4 */ static void sprite_misc_5_update(rct_sprite *sprite) { @@ -351,13 +361,13 @@ static void sprite_misc_5_update(rct_sprite *sprite) /** * - * rct: 0x006731CD + * rct2: 0x006731CD */ void sprite_misc_update(rct_sprite *sprite) { switch (sprite->unknown.misc_identifier) { - case SPRITE_MISC_0: - sprite_misc_0_update(sprite); + case SPRITE_MISC_STEAM_PARTICLE: + sprite_steam_particle_update((rct_steam_particle*)sprite); break; case SPRITE_MISC_MONEY_EFFECT: money_effect_update(&sprite->money_effect); @@ -389,7 +399,7 @@ void sprite_misc_update(rct_sprite *sprite) /** * - * rct: 0x00672AA4 + * rct2: 0x00672AA4 */ void sprite_misc_update_all() { @@ -405,11 +415,13 @@ void sprite_misc_update_all() } /** + * Moves a sprite to a new location. * rct2: 0x0069E9D3 - * Moves a sprite to a new location. - * ax: x - * cx: y - * dx: z + * + * @param x (ax) + * @param y (cx) + * @param z (dx) + * @param sprite (esi) */ void sprite_move(sint16 x, sint16 y, sint16 z, rct_sprite* sprite){ if (x < 0 || y < 0 || x > 0x1FFF || y > 0x1FFF) diff --git a/src/world/sprite.h b/src/world/sprite.h index 89fdb512d2..c2f0f65dbe 100644 --- a/src/world/sprite.h +++ b/src/world/sprite.h @@ -56,7 +56,7 @@ typedef struct { // Height from center of sprite to bottom uint8 sprite_height_negative; // 0x09 uint16 sprite_index; // 0x0A - uint16 var_0C; + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -88,7 +88,7 @@ typedef struct { uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... uint8 sprite_height_negative; // 0x09 uint16 sprite_index; // 0x0A - uint16 pad_0C; + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -108,8 +108,8 @@ typedef struct { uint16 previous; // 0x06 uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... uint8 var_09; // 0x09 - uint16 var_0A; - uint8 pad_0C[0x2]; + uint16 sprite_index; // 0x0A + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -137,8 +137,8 @@ typedef struct { uint16 previous; // 0x06 uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... uint8 var_09; // 0x09 - uint16 var_0A; - uint8 pad_0C[0x2]; + uint16 sprite_index; // 0x0A + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -163,7 +163,8 @@ typedef struct { uint16 previous; // 0x06 uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... uint8 var_09; - uint8 pad_0A[0x4]; + uint16 sprite_index; // 0x0A + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -181,7 +182,7 @@ typedef struct { }; uint8 pad_28[0x6]; uint8 var_2E; - uint8 flags; + uint8 fountain_flags; // 0x2F sint16 target_x; // 0x30 sint16 target_y; // 0x32 uint8 pad_34[0x12]; @@ -196,7 +197,8 @@ typedef struct { uint16 previous; // 0x06 uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... uint8 var_09; - uint8 pad_0A[0x4]; + uint16 sprite_index; // 0x0A + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -221,7 +223,7 @@ typedef struct { // Height from center of sprite to bottom uint8 sprite_height_negative; // 0x09 uint16 sprite_index; // 0x0A - uint16 var_0C; + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -263,7 +265,7 @@ typedef struct { // Height from center of sprite to bottom uint8 sprite_height_negative; // 0x09 uint16 sprite_index; // 0x0A - uint16 var_0C; + uint16 flags; // 0x0C sint16 x; // 0x0E sint16 y; // 0x10 sint16 z; // 0x12 @@ -282,6 +284,35 @@ typedef struct { uint16 var_26; } rct_crash_splash; +typedef struct { + uint8 sprite_identifier; // 0x00 + uint8 misc_identifier; // 0x01 + uint16 next_in_quadrant; // 0x02 + uint16 next; // 0x04 + uint16 previous; // 0x06 + uint8 linked_list_type_offset; // 0x08 Valid values are SPRITE_LINKEDLIST_OFFSET_... + // Height from center of sprite to bottom + uint8 sprite_height_negative; // 0x09 + uint16 sprite_index; // 0x0A + uint16 flags; // 0x0C + sint16 x; // 0x0E + sint16 y; // 0x10 + sint16 z; // 0x12 + // Width from center of sprite to edge + uint8 sprite_width; // 0x14 + // Height from center of sprite to top + uint8 sprite_height_positive; // 0x15 + sint16 sprite_left; // 0x16 + sint16 sprite_top; // 0x18 + sint16 sprite_right; // 0x1A + sint16 sprite_bottom; // 0x1C + uint8 sprite_direction; // 0x1E + uint8 pad_1F[3]; // 0x1F + uint16 name_string_idx; // 0x22 + uint16 var_24; + uint16 var_26; +} rct_steam_particle; + /** * Sprite structure. * size: 0x0100 @@ -298,10 +329,28 @@ typedef union { rct_money_effect money_effect; rct_crashed_vehicle_particle crashed_vehicle_particle; rct_crash_splash crash_splash; + rct_steam_particle steam_particle; } rct_sprite; +typedef struct { + uint8 sprite_width; // 0x00 + uint8 sprite_height_negative; // 0x01 + uint8 sprite_height_positive; // 0x02 + uint8 unused; // 0x03 +} rct_sprite_bounds; + +typedef struct { + uint32 base_image; // 0x00 + uint8* unkn_04; // 0x04 +} rct_sprite_image; + +typedef struct { + rct_sprite_image *sprite_image; // 0x00 + rct_sprite_bounds *sprite_bounds; // 0x04 +} rct_sprite_entry; + enum { - SPRITE_MISC_0, + SPRITE_MISC_STEAM_PARTICLE, SPRITE_MISC_MONEY_EFFECT, SPRITE_MISC_CRASHED_VEHICLE_PARTICLE, SPRITE_MISC_3, // (related to vehicle crash, probably crash particles) @@ -313,9 +362,19 @@ enum { SPRITE_MISC_JUMPING_FOUNTAIN_SNOW }; +enum { + SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE = 1 << 7, + SPRITE_FLAGS_PEEP_VISIBLE = 1 << 8, // Peep is eligible to show in summarized guest list window (is inside park?) + SPRITE_FLAGS_PEEP_FLASHING = 1 << 9, // Peep belongs to highlighted group (flashes red on map) +}; + // rct2: 0x010E63BC extern rct_sprite* g_sprite_list; +// rct2: 0x00982708 +extern rct_sprite_entry* g_sprite_entries; + + rct_sprite *create_sprite(uint8 bl); void reset_sprite_list(); void reset_0x69EBE4(); @@ -331,6 +390,7 @@ void litter_create(int x, int y, int z, int direction, int type); void litter_remove_at(int x, int y, int z); void sprite_misc_3_create(int x, int y, int z); void sprite_misc_5_create(int x, int y, int z); +uint16 sprite_get_first_in_quadrant(int x, int y); /////////////////////////////////////////////////////////////// // Balloon diff --git a/src/world/water.h b/src/world/water.h index 72018c7ddc..4fd9838fe4 100644 --- a/src/world/water.h +++ b/src/world/water.h @@ -31,4 +31,4 @@ typedef struct { uint16 var_0E; } rct_water_type; -#endif \ No newline at end of file +#endif diff --git a/test.bat b/test.bat deleted file mode 100644 index 59c0adf8e0..0000000000 --- a/test.bat +++ /dev/null @@ -1,2 +0,0 @@ -msbuild .\projects\openrct2.sln "/p:Configuration=Release with Tests" /p:Platform=Win32 -.\build\Release\openrct2.exe test \ No newline at end of file diff --git a/test/management/finance_test.c b/test/management/finance_test.c deleted file mode 100644 index 0772dfb0ff..0000000000 --- a/test/management/finance_test.c +++ /dev/null @@ -1,60 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2015 Marco Costa -* 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 . -*****************************************************************************/ - -#include "../../src/addresses.h" -#include "../../src/management/finance.h" -#include "../../src/openrct2.h" -#include "../../src/scenario.h" - -#include "finance_test.h" - -void test_finance_setup(CuTest* tc) { - test_load_scenario(tc, "Build your own Six Flags Park.SC6"); -} - -void test_finance_loan_increase(CuTest* tc) { - money32 initialCash = finance_get_current_cash(); - money32 initialLoan = finance_get_current_loan(); - - money32 newLoan = finance_get_maximum_loan(); - finance_set_loan(newLoan); - - money32 actual = finance_get_current_loan(); - CuAssertIntEquals(tc, newLoan, actual); - - money32 actualCash = finance_get_current_cash(); - CuAssertIntEquals(tc, initialCash + newLoan - initialLoan, actualCash); -} - -void test_finance_loan_pay_back(CuTest* tc) { - money32 initialCash = finance_get_current_cash(); - money32 initialLoan = finance_get_current_loan(); - - money32 newLoan = MONEY(0, 00); - finance_set_loan(newLoan); - - money32 actual = finance_get_current_loan(); - CuAssertIntEquals(tc, newLoan, actual); - - money32 actualCash = finance_get_current_cash(); - CuAssertIntEquals(tc, MONEY(0, 00), actualCash); -} - - diff --git a/test/management/finance_test.h b/test/management/finance_test.h deleted file mode 100644 index 700a79ebc9..0000000000 --- a/test/management/finance_test.h +++ /dev/null @@ -1,30 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2015 Marco Costa -* 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 . -*****************************************************************************/ - -#ifndef _FINANCE_TEST_H_ -#define _FINANCE_TEST_H_ - -#include "../tests.h" - -void test_finance_setup(CuTest* tc); -void test_finance_loan_increase(CuTest* tc); -void test_finance_loan_pay_back(CuTest* tc); - -#endif \ No newline at end of file diff --git a/test/ride/ride_ratings_test.c b/test/ride/ride_ratings_test.c deleted file mode 100644 index 929396f6ca..0000000000 --- a/test/ride/ride_ratings_test.c +++ /dev/null @@ -1,38 +0,0 @@ -#include "../../src/ride/ride_ratings.h" -#include "../../src/localisation/localisation.h" - -#include "ride_ratings_test.h" - -void test_ride_ratings_setup(CuTest* tc) { - test_load_scenario(tc, "Six Flags Magic Mountain.SC6"); -} - -void test_ride_ratings(CuTest* tc) { - int i; - rct_ride *ride; - rating_tuple *rideRatings = malloc(256 * sizeof(rating_tuple)); - char rideName[256]; - char buffer[256]; - - // Store original ride ratings - FOR_ALL_RIDES(i, ride) - rideRatings[i] = ride->ratings; - - // Update all the ride ratings - // TODO use a better function that can just be called once for each ride - for (int i = 0; i < MAX_RIDES * 10; i++) - ride_ratings_update_all(); - - FOR_ALL_RIDES(i, ride) { - format_string(rideName, ride->name, &ride->name_arguments); - - sprintf(buffer, "[%s.excitement]", rideName); - CuAssertIntEquals_Msg(tc, buffer, rideRatings[i].excitement, ride->excitement); - sprintf(buffer, "[%s.intensity]", rideName); - CuAssertIntEquals_Msg(tc, buffer, rideRatings[i].intensity, ride->intensity); - sprintf(buffer, "[%s.nausea]", rideName); - CuAssertIntEquals_Msg(tc, buffer, rideRatings[i].nausea, ride->nausea); - } - - free(rideRatings); -} \ No newline at end of file diff --git a/test/ride/ride_ratings_test.h b/test/ride/ride_ratings_test.h deleted file mode 100644 index 43526ef500..0000000000 --- a/test/ride/ride_ratings_test.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _RIDE_RATINGS_TEST_H_ -#define _RIDE_RATINGS_TEST_H_ - -#include "../tests.h" - -void test_ride_ratings_setup(CuTest* tc); -void test_ride_ratings(CuTest* tc); - -#endif \ No newline at end of file diff --git a/test/tests.c b/test/tests.c deleted file mode 100644 index 6963f14517..0000000000 --- a/test/tests.c +++ /dev/null @@ -1,76 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2015 Marco Costa -* 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 . -*****************************************************************************/ - -#include "../src/openrct2.h" -#include "management/finance_test.h" -#include "ride/ride_ratings_test.h" - -int cmdline_for_test(const char **argv, int argc) -{ - // NOTE Currently all tests are running in a OpenRCT2 setup frame. Tests for the initialisation and disposing should be - // separate and independent. - - int numFailedTests; - - gOpenRCT2Headless = true; - if (openrct2_initialise()) { - numFailedTests = run_all_tests(); - - openrct2_dispose(); - } - return numFailedTests > 0 ? -1 : 1; -} - -CuSuite* new_suite(void) -{ - CuSuite* suite = CuSuiteNew(); - - // Test Finance - SUITE_ADD_TEST(suite, test_finance_setup); - SUITE_ADD_TEST(suite, test_finance_loan_increase); - SUITE_ADD_TEST(suite, test_finance_loan_pay_back); - - // Test Ride - SUITE_ADD_TEST(suite, test_ride_ratings_setup); - SUITE_ADD_TEST(suite, test_ride_ratings); - - // Future Tests: - // Test X - // SUITE_ADD_TEST(suite, test_X_setup); - // SUITE_ADD_TEST(suite, test_X_Y); - // SUITE_ADD_TEST(suite, test_X_Z); - - return suite; -} - -int run_all_tests(void) -{ - CuString *output = CuStringNew(); - CuSuite* suite = CuSuiteNew(); - - CuSuiteAddSuite(suite, new_suite()); - - CuSuiteRun(suite); - CuSuiteSummary(suite, output); - CuSuiteDetails(suite, output); - printf("Test results:\n%s\n", output->buffer); - - return suite->failCount; -} diff --git a/test/tests.h b/test/tests.h deleted file mode 100644 index 10f94b39ed..0000000000 --- a/test/tests.h +++ /dev/null @@ -1,43 +0,0 @@ -/***************************************************************************** -* Copyright (c) 2015 Marco Costa -* 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 . -*****************************************************************************/ - -#ifndef _TESTS_H_ -#define _TESTS_H_ - -#include -#include -#include "../src/common.h" - -int cmdline_for_test(const char **argv, int argc); -int run_all_tests(); - -// Test utilities - -#include "../src/scenario.h" - -static void test_load_scenario(CuTest* tc, const char* file_name) { - const rct_scenario_basic* scenario = get_scenario_by_filename(file_name); - if (scenario == NULL) { - CuFail(tc, "Could not load scenario"); - } - scenario_load_and_play(scenario); -} - -#endif \ No newline at end of file