diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..b312c8a4 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,104 @@ +name: Build + +on: [push, pull_request] + +jobs: + build: + runs-on: ${{ matrix.host_os }} + container: ${{ matrix.container }} + strategy: + matrix: + target_os: [linux] + host_os: [ubuntu-18.04, ubuntu-20.04] + container: [''] + include: + - target_os: windows + host_os: ubuntu-latest + container: krzysh/colobot-build:latest + fail-fast: false + steps: + - name: Install Colobot dependencies + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet + if: matrix.container == '' + - uses: actions/checkout@v2 + - name: Create build directory + run: cmake -E make_directory build + - name: Run CMake (for Windows using MXE) + working-directory: build + # FIXME: without -lsetupapi linking sdl2 fails + run: /opt/mxe/usr/bin/i686-w64-mingw32.static-cmake -DCMAKE_CXX_STANDARD_LIBRARIES="-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -lsetupapi" -DCMAKE_INSTALL_PREFIX=/install -DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=0 -DMXE_USE_CCACHE=0 .. + if: matrix.target_os == 'windows' + - name: Run CMake (for Linux) + working-directory: build + run: cmake -DCMAKE_INSTALL_PREFIX=/install -DCMAKE_SKIP_INSTALL_RPATH=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=1 -DDESKTOP=1 .. + if: matrix.target_os == 'linux' + - name: Build + working-directory: build + run: make -j `nproc` + - name: Install + working-directory: build + run: DESTDIR=. make install + - name: Patch library path + working-directory: build + run: patchelf --set-rpath '.' install/colobot + if: matrix.target_os == 'linux' + - name: Upload build + uses: actions/upload-artifact@v2 + with: + name: ${{matrix.target_os}}-debug + path: build/install + if: matrix.target_os == 'windows' || matrix.host_os == 'ubuntu-18.04' + - name: Create AppImage + working-directory: build + run: | + # Download app image tool + wget -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage + chmod +x linuxdeploy-x86_64.AppImage + ./linuxdeploy-x86_64.AppImage --appimage-extract + + # Create AppImage + NO_STRIP=1 ./squashfs-root/AppRun -e colobot --output appimage --appdir colobot.AppDir -d desktop/colobot.desktop -i ../desktop/colobot.svg + chmod +x Colobot-*-x86_64.AppImage + + # Prepare folder for zip + mkdir -p appimage + cp -rp install/data appimage/data + cp -rp install/lang appimage/lang + cp -p Colobot-*-x86_64.AppImage appimage/colobot + if: matrix.target_os == 'linux' + - name: Upload AppImage + uses: actions/upload-artifact@v2 + with: + name: ${{matrix.target_os}}-debug-AppImage + path: build/appimage + if: matrix.target_os == 'linux' && matrix.host_os == 'ubuntu-18.04' + - name: Run tests + # TODO: Maybe run Windows tests using wine as well? + working-directory: build + run: ./colobot_ut --gtest_output=xml:gtestresults.xml + if: matrix.target_os == 'linux' + - name: Upload test results + uses: actions/upload-artifact@v2 + with: + name: Test results (${{ matrix.target_os }}, ${{ matrix.host_os }}) + path: build/gtestresults.xml + if: matrix.target_os == 'linux' + doc: + runs-on: ubuntu-latest + steps: + - name: Install Colobot dependencies + run: sudo apt-get update && sudo apt-get install -y --no-install-recommends build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools librsvg2-bin xmlstarlet doxygen graphviz + - uses: actions/checkout@v2 + - name: Create build directory + run: cmake -E make_directory build + - name: Run CMake + working-directory: build + run: cmake .. + - name: Build docs + working-directory: build + run: make doc + - name: Upload docs + uses: actions/upload-artifact@v2 + with: + name: doc + path: build/doc diff --git a/.github/workflows/verify-pr-target.yml b/.github/workflows/verify-pr-target.yml new file mode 100644 index 00000000..c5f388d7 --- /dev/null +++ b/.github/workflows/verify-pr-target.yml @@ -0,0 +1,21 @@ +name: Verify pull request target + +on: [pull_request_target] + +jobs: + check_pr_target: + runs-on: ubuntu-latest + steps: + - name: Send comment if wrong pull request target + if: github.base_ref == 'master' + uses: peter-evans/create-or-update-comment@v1 + with: + issue-number: ${{ github.event.number }} + body: | + Hey! This pull request targets the `master` branch. You should probably target `dev` instead. Make sure to read the [contributing guidelines](https://github.com/colobot/colobot/blob/master/CONTRIBUTING.md#submitting-pull-requests) and [edit the target branch if necessary](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/changing-the-base-branch-of-a-pull-request). + - name: Wrong pull request target + if: github.base_ref == 'master' + run: echo "This pull request targets the master branch. Please edit the pull request to target dev." && exit 1 + - name: Correct pull request target + if: github.base_ref != 'master' + run: echo "This pull request targets the correct branch." && exit 0 diff --git a/.gitignore b/.gitignore index f3461be1..e195dc2b 100644 --- a/.gitignore +++ b/.gitignore @@ -23,7 +23,7 @@ Makefile /saves # Standard build directory -/build +/build* # Ignore KDevelop files .kdev4 @@ -39,6 +39,10 @@ CMakeLists.txt.user.* # Ignore Visual Studio Code files /.vscode +# Ignore CLion files +/.idea + # Ignore Visual Studio files /CMakeSettings.json /.vs +/out diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c40e085..90843488 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,9 +16,9 @@ set(COLOBOT_VERSION_MINOR 1) set(COLOBOT_VERSION_REVISION 12) # Used on official releases -set(COLOBOT_VERSION_RELEASE_CODENAME "-alpha") +#set(COLOBOT_VERSION_RELEASE_CODENAME "-alpha") # Used on unreleased, development builds -#set(COLOBOT_VERSION_UNRELEASED "+alpha") +set(COLOBOT_VERSION_UNRELEASED "+alpha") # Append git characteristics to version if(DEFINED COLOBOT_VERSION_UNRELEASED) @@ -60,6 +60,7 @@ if("${CMAKE_SYSTEM_NAME}" MATCHES "Windows") set(PLATFORM_GNU 0) set(PLATFORM_LINUX 0) set(PLATFORM_MACOSX 0) + set(PLATFORM_FREEBSD 0) set(PLATFORM_OTHER 0) # Platform-dependent implementation of system.h @@ -71,6 +72,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Linux") set(PLATFORM_LINUX 1) set(PLATFORM_GNU 1) set(PLATFORM_MACOSX 0) + set(PLATFORM_FREEBSD 0) set(PLATFORM_OTHER 0) # Platform-dependent implementation of system.h @@ -82,6 +84,7 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "kFreeBSD" OR "${CMAKE_SYSTEM_NAME}" STREQ set(PLATFORM_LINUX 0) set(PLATFORM_GNU 1) set(PLATFORM_MACOSX 0) + set(PLATFORM_FREEBSD 0) set(PLATFORM_OTHER 0) # Platform-dependent implementation of system.h @@ -94,18 +97,35 @@ elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin") set(PLATFORM_GNU 0) set(PLATFORM_MACOSX 1) set(PLATFORM_OTHER 0) + set(PLATFORM_FREEBSD 0) # Platform-dependent implementation of system.h set(SYSTEM_CPP_MODULE "system_macosx.cpp") set(SYSTEM_H_MODULE "system_macosx.h") # To avoid CMake warning set(CMAKE_MACOSX_RPATH 1) +elseif("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD") + message(STATUS "Build for FreeBSD system") + set(PLATFORM_WINDOWS 0) + set(PLATFORM_LINUX 0) + set(PLATFORM_GNU 0) + set(PLATFORM_MACOSX 0) + set(PLATFORM_FREEBSD 1) + set(PLATFORM_OTHER 0) + + # Platform-dependent implementation of system.h + # On FreeBSD we can use *_other + set(SYSTEM_CPP_MODULE "system_other.cpp") + set(SYSTEM_H_MODULE "system_other.h") + # To avoid CMake warning + set(CMAKE_MACOSX_RPATH 1) else() message(STATUS "Build for other system") set(PLATFORM_WINDOWS 0) set(PLATFORM_LINUX 0) set(PLATFORM_GNU 0) set(PLATFORM_MACOSX 0) + set(PLATFORM_FREEBSD 0) set(PLATFORM_OTHER 1) # Platform-dependent implementation of system.h @@ -153,6 +173,10 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") message(STATUS "Detected Clang version 3.1+") + if (${PLATFORM_FREEBSD}) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=bfd") + endif() + set(NORMAL_CXX_FLAGS "-std=c++11 -Wall -Werror -Wold-style-cast -pedantic-errors -Wmissing-prototypes") set(NORMAL_CXX_FLAGS "${NORMAL_CXX_FLAGS} -Wno-error=deprecated-declarations") # updated version of physfs is not available on some platforms so we keep using deprecated functions, see #958 set(RELEASE_CXX_FLAGS "-O2") @@ -165,16 +189,16 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(NORMAL_CXX_FLAGS "/wd\"4244\" /wd\"4309\" /wd\"4800\" /wd\"4996\" /wd\"4351\" /EHsc") # disable some useless warnings if(MSVC_STATIC) set(RELEASE_CXX_FLAGS "/MT /Ox") - set(DEBUG_CXX_FLAGS "/MTd /ZI") + set(DEBUG_CXX_FLAGS "/MTd /Od /ZI") else(MSVC_STATIC) set(RELEASE_CXX_FLAGS "/MD /Ox") - set(DEBUG_CXX_FLAGS "/MDd /ZI") + set(DEBUG_CXX_FLAGS "/MDd /Od /ZI") endif() - set(TEST_CXX_FLAGS "") + set(TEST_CXX_FLAGS "${DEBUG_CXX_FLAGS}") add_definitions(-DNOEXCEPT= -DHAS_MSVC_EXCEPTION_BUG) # Needed for Debug information (it's set to "No" by default for some reason) - set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS} /DEBUG") + set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /NODEFAULTLIB:MSVCRTD /NODEFAULTLIB:LIBCMT") set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS} /DEBUG") else() message(FATAL_ERROR "Your C++ compiler doesn't seem to be supported.") @@ -206,7 +230,10 @@ option(DEV_BUILD "Enable development build (enables some debugging tools, local # PLEASE DO NOT USE ON UNOFFICIAL BUILDS. Thanks. option(OFFICIAL_COLOBOT_BUILD "Official build (changes crash screen text)" OFF) -# Portable build - load all data from current directory +# Hardcode relative paths instead of absolute paths +option(USE_RELATIVE_PATHS "Generate relative paths from absolute paths" OFF) + +# Portable build - load all data from the base directory option(PORTABLE "Portable build" OFF) # Portable saves - suitable for e.g. putting the whole game on external storage and moving your saves with it @@ -367,12 +394,12 @@ endif() # Installation paths defined before compiling sources if(PORTABLE OR (PLATFORM_WINDOWS AND MXE)) - # We need to use STRING because PATH doesn't accept relative paths - set(COLOBOT_INSTALL_BIN_DIR ./ CACHE STRING "Colobot binary directory") - set(COLOBOT_INSTALL_LIB_DIR ./ CACHE STRING "Colobot libraries directory") - set(COLOBOT_INSTALL_DATA_DIR ./data CACHE STRING "Colobot shared data directory") - set(COLOBOT_INSTALL_I18N_DIR ./lang CACHE STRING "Colobot translations directory") - set(COLOBOT_INSTALL_DOC_DIR ./doc CACHE STRING "Colobot documentation directory") + set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory") + set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory") + set(COLOBOT_INSTALL_DATA_DIR ${CMAKE_INSTALL_PREFIX}/data CACHE PATH "Colobot shared data directory") + set(COLOBOT_INSTALL_I18N_DIR ${CMAKE_INSTALL_PREFIX}/lang CACHE PATH "Colobot translations directory") + set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/doc CACHE PATH "Colobot documentation directory") + set(USE_RELATIVE_PATHS ON) elseif(PLATFORM_WINDOWS) set(COLOBOT_INSTALL_BIN_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot binary directory") set(COLOBOT_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/ CACHE PATH "Colobot libraries directory") @@ -393,6 +420,18 @@ else() set(COLOBOT_INSTALL_DOC_DIR ${CMAKE_INSTALL_PREFIX}/share/doc/colobot CACHE PATH "Colobot documentation directory") endif() +# Generate relative paths from absolute paths +if(USE_RELATIVE_PATHS) + message(STATUS "Generating relative paths") + file(RELATIVE_PATH COLOBOT_DATA_DIR ${COLOBOT_INSTALL_BIN_DIR} ${COLOBOT_INSTALL_DATA_DIR}) + file(RELATIVE_PATH COLOBOT_I18N_DIR ${COLOBOT_INSTALL_BIN_DIR} ${COLOBOT_INSTALL_I18N_DIR}) + + add_definitions(-DUSE_RELATIVE_PATHS) +else() + set(COLOBOT_DATA_DIR ${COLOBOT_INSTALL_DATA_DIR}) + set(COLOBOT_I18N_DIR ${COLOBOT_INSTALL_I18N_DIR}) +endif() + # Subdirectory with sources add_subdirectory(src) diff --git a/INSTALL-MSYS2.md b/INSTALL-MSYS2.md index f35634f3..bc5f90d1 100644 --- a/INSTALL-MSYS2.md +++ b/INSTALL-MSYS2.md @@ -110,7 +110,7 @@ Easy, isn't it? If you are lazy, you can just use this one-line command, although there is no guarantee it will work or install everything (might be out of date): ```sh -pacman -S mingw-w64-i686-boost mingw-w64-i686-glew mingw-w64-i686-libpng gettext mingw-w64-i686-gettext mingw-w64-i686-libpng mingw-w64-i686-libsndfile mingw-w64-i686-libvorbis mingw-w64-i686-libogg mingw-w64-i686-openal mingw-w64-i686-SDL2 mingw-w64-i686-SDL2_image mingw-w64-i686-SDL2_ttf +pacman -S mingw-w64-i686-boost mingw-w64-i686-glew mingw-w64-i686-libpng gettext mingw-w64-i686-gettext mingw-w64-i686-libpng mingw-w64-i686-libsndfile mingw-w64-i686-libvorbis mingw-w64-i686-libogg mingw-w64-i686-openal mingw-w64_i686-physfs mingw-w64-i686-SDL2 mingw-w64-i686-SDL2_image mingw-w64-i686-SDL2_ttf ``` You should now have everything set up and working. You can close all instances of MSYS2 and autorebase to ensure everything installed properly. diff --git a/INSTALL.md b/INSTALL.md index 423166dc..fc69342c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -71,7 +71,7 @@ You will need: On Ubuntu (and probably any other Debian-based system), you can use the following command to install all required packages: ``` - $ apt-get install build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng12-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools + $ apt-get install build-essential cmake libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsndfile1-dev libvorbis-dev libogg-dev libpng-dev libglew-dev libopenal-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-regex-dev libphysfs-dev gettext git po4a vorbis-tools ``` Make sure you install the packages along with header files (often distributed in separate *-dev packages). If you miss any requirements, diff --git a/Jenkinsfile b/Jenkinsfile index 95b567a8..7b52c57b 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -27,10 +27,11 @@ pipeline { dir('build/windows') { sh ''' # FIXME: without -lsetupapi linking sdl2 fails + rm -rf * /opt/mxe/usr/bin/i686-w64-mingw32.static-cmake \ -DCMAKE_CXX_STANDARD_LIBRARIES="-lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 -lsetupapi" \ -DCMAKE_INSTALL_PREFIX=/install \ - -DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=0 ../.. + -DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=0 -DMXE_USE_CCACHE=0 ../.. make rm -rf install DESTDIR=. make install @@ -53,6 +54,7 @@ pipeline { sh 'mkdir -p build/linux' dir('build/linux') { sh ''' + rm -rf * cmake \ -DCMAKE_INSTALL_PREFIX=/install -DCMAKE_SKIP_INSTALL_RPATH=ON \ -DCMAKE_BUILD_TYPE=RelWithDebInfo -DDEV_BUILD=1 -DPORTABLE=1 -DTOOLS=1 -DTESTS=1 -DDESKTOP=1 ../.. @@ -81,6 +83,8 @@ pipeline { # Create AppImage NO_STRIP=1 ./squashfs-root/AppRun -e colobot --output appimage --appdir colobot.AppDir -d desktop/colobot.desktop -i ../../desktop/colobot.svg + #rename AppImage file to avoid "No such file or directory" errors + find . -maxdepth 1 -type f -name '*AppImage' -name 'Colobot*' -exec sh -c 'x="{}"; mv "$x" "Colobot-x86_64.AppImage"' \\; chmod +x Colobot-x86_64.AppImage # Prepare folder for zip diff --git a/LICENSE-HEADER.txt b/LICENSE-HEADER.txt index 1ac94d9f..1a4a3071 100644 --- a/LICENSE-HEADER.txt +++ b/LICENSE-HEADER.txt @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/README.md b/README.md index c7d4a9a5..4bb5e62a 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ On some Linux distributions there are also distribution packages available: * Debian Sid (unstable): http://packages.debian.org/sid/colobot * Arch Linux (AUR): https://aur.archlinux.org/packages/colobot-gold * openSUSE: http://software.opensuse.org/download.html?project=games&package=colobot + * Fedora: https://src.fedoraproject.org/rpms/colobot + * Guix https://guix.gnu.org/en/packages/colobot-0.1.12-alpha/ ## Compiling and running the game @@ -42,9 +44,4 @@ If you want to contribute to the project, see [CONTRIBUTING.md](CONTRIBUTING.md) ## Contact -If you want to help in the project, please contact us on our IRC channels or [our forum](http://colobot.info/forum/). - -### IRC channels - -* [#colobot on Freenode](irc://freenode.net#colobot) - main development channel (English); -* [#colobot on pirc.pl](irc://pirc.pl#colobot) - Polish community channel; +If you want to help in the project, please contact us on our [Discord server](https://discord.gg/56Fm9kb). diff --git a/data b/data index c467bd99..74c762b4 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit c467bd994e60fb54cf977fbe8583f92957330695 +Subproject commit 74c762b47fcac7c073a0afb5c82cf046e7ea42f3 diff --git a/desktop/CMakeLists.txt b/desktop/CMakeLists.txt index af704932..2ee308cc 100644 --- a/desktop/CMakeLists.txt +++ b/desktop/CMakeLists.txt @@ -82,20 +82,6 @@ if(PLATFORM_GNU) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps/ ) - # Translate translatable material - find_program(PO4A po4a) - if(NOT PO4A) - message(WARNING "po4a not found; desktop and manpage files will not be translated") - endif() - - if(PO4A) - add_custom_target(desktop_po4a - COMMAND ${PO4A} po4a.cfg - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - ) - add_dependencies(desktopfile desktop_po4a) - endif() - # Create manpage from pod-formatted file find_program(POD2MAN pod2man) if(NOT POD2MAN) @@ -133,11 +119,30 @@ if(PLATFORM_GNU) # Create the english manpage podman(PODFILE colobot.pod) + # Translate translatable material + find_program(PO4A po4a) + if(NOT PO4A) + message(WARNING "po4a not found; desktop and manpage files will not be translated") + endif() + if(PO4A) # Translate the manpage to other languages - add_dependencies(man desktop_po4a) file(GLOB LINGUAS_PO RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/po/ ${CMAKE_CURRENT_SOURCE_DIR}/po/*.po) string(REGEX REPLACE ".po$" "" LINGUAS ${LINGUAS_PO}) + + set(PO4A_OUTPUTS) + foreach(LOCALE ${LINGUAS}) + list(APPEND PO4A_OUTPUTS ${CMAKE_CURRENT_SOURCE_DIR}/lang/${LOCALE}/colobot.pod) + endforeach() + add_custom_command( + OUTPUT ${PO4A_OUTPUTS} + COMMAND ${PO4A} po4a.cfg + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + add_custom_target(desktop_po4a DEPENDS ${PO4A_OUTPUTS}) + add_dependencies(man desktop_po4a) + add_dependencies(desktopfile desktop_po4a) + foreach(LOCALE ${LINGUAS}) podman(PODFILE lang/${LOCALE}/colobot.pod LOCALE ${LOCALE}) add_dependencies(man${PM_LOCALE} desktop_po4a) diff --git a/desktop/colobot.ini b/desktop/colobot.ini index 0cba2158..3a78019a 100644 --- a/desktop/colobot.ini +++ b/desktop/colobot.ini @@ -1,4 +1,4 @@ Name="Colobot" GenericName="Game to learn programming" Comment="Colonize with bots" -Keywords="robots;3d;space;astronaut;java;c++" +Keywords="robots;3d;space;astronaut;java;c++;" diff --git a/desktop/po/colobot-desktop.pot b/desktop/po/colobot-desktop.pot index 52e6e1a8..c33ab83d 100644 --- a/desktop/po/colobot-desktop.pot +++ b/desktop/po/colobot-desktop.pot @@ -37,7 +37,7 @@ msgstr "" #. type: Keywords= #: colobot.ini:4 #, no-wrap -msgid "robots;3d;space;astronaut;java;c++" +msgid "robots;3d;space;astronaut;java;c++;" msgstr "" #. type: =head1 diff --git a/desktop/po/fr.po b/desktop/po/fr.po index 5032271f..784113ba 100644 --- a/desktop/po/fr.po +++ b/desktop/po/fr.po @@ -3,18 +3,20 @@ # This file is distributed under the same license as the Colobot package. # # Didier Raboud , 2012, 2016. +# B-CE <.>, 2019. msgid "" msgstr "" -"Project-Id-Version: colobot 0.1.7\n" +"Project-Id-Version: colobot 0.1.12\n" "POT-Creation-Date: 2016-03-30 13:45+0200\n" -"PO-Revision-Date: 2016-03-30 13:49+0100\n" -"Last-Translator: Didier Raboud \n" +"PO-Revision-Date: 2019-06-01 09:43+0200\n" +"Last-Translator: BCE <.>\n" +"Language-Team: French \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Lokalize 2.0\n" +"X-Generator: Lokalize 18.12.3\n" #. type: Name= #: colobot.ini:1 @@ -32,13 +34,13 @@ msgstr "Apprentissage de la programmation par le jeu" #: colobot.ini:3 #, no-wrap msgid "Colonize with bots" -msgstr "Colonise avec des roBots" +msgstr "COlonise avec des roBOTs" #. type: Keywords= #: colobot.ini:4 #, no-wrap -msgid "robots;3d;space;astronaut;java;c++" -msgstr "robots;3d;espace;astronaute;cosmonaute;java;c++" +msgid "robots;3d;space;astronaut;java;c++;" +msgstr "robots;3d;espace;astronaute;cosmonaute;java;c++;programmation;jeux" #. type: =head1 #: colobot.pod:3 @@ -74,12 +76,12 @@ msgid "" "real-time graphics and a C++ and Java-like, object-oriented language, CBOT, " "which can be used to program the robots available in the game." msgstr "" -"Colobot (Colonise avec des roBots) est un jeu éducatif visant à " -"l'enseignement de la programmation par le jeu. Vous jouez un astronaute en " +"Colobot (Colonise avec des roBots) est un jeu éducatif visant " +"à l'enseignement de la programmation par le jeu. Vous jouez un astronaute en " "voyage avec des robots à la recherche d'une planète à coloniser. Son " -"interface est en trois-dimensions et en temps réel; le language utilisé " -"(CBOT) ressemble au C++ et à Java et peut être utilisé pour programmer les " -"robots disponibles dans le jeu." +"interface est en trois-dimensions et en temps réel. Le langage utilisé " +"(CBOT), orienté objet , ressemble au C++ et à Java. Il peut être utilisé " +"pour programmer les robots disponibles dans le jeu." #. type: =head1 #: colobot.pod:19 @@ -208,9 +210,9 @@ msgid "" "Enable debug mode (more info printed in logs). Possible values are as " "follows, as well as any comma-separated combination" msgstr "" -"Active le mode de I (plus d'informations dans les logs). Les valeurs" -" possibles sont les suivantes, ainsi que toute combinaison séparée par des" -" virgules" +"Active le mode de I (plus d'informations dans les logs). " +"Les valeurs possibles sont les suivantes, " +"ainsi que toute combinaison séparée par des virgules" #. type: =item #: colobot.pod:81 @@ -260,7 +262,7 @@ msgstr "models" #. type: textblock #: colobot.pod:99 msgid "Models-related debugging" -msgstr "Debug pour les modèles" +msgstr "Débug pour les modèles" #. type: =item #: colobot.pod:101 @@ -270,7 +272,7 @@ msgstr "all" #. type: textblock #: colobot.pod:103 msgid "All above debugging statements" -msgstr "Tout les messages de debug ci-dessus" +msgstr "Tous les messages de debug ci-dessus" #. type: =item #: colobot.pod:107 @@ -280,9 +282,7 @@ msgstr "B<-headless>" #. type: textblock #: colobot.pod:109 msgid "Run in headless mode - disables graphics, sound and user interaction" -msgstr "" -"Lance en mode I - désactive les graphiques, sons et interactions" -" utilisateurs" +msgstr "Lance en mode I - désactive les graphiques, sons et interactions utilisateurs" #. type: =item #: colobot.pod:111 @@ -292,7 +292,7 @@ msgstr "B<-runscene> I" #. type: textblock #: colobot.pod:113 msgid "Run given scene on start (skip menus)" -msgstr "Lance une scène donnée au lancement (saute les menus)" +msgstr "Démarre directement une scène (saute les menus)" #. type: =item #: colobot.pod:115 @@ -317,7 +317,7 @@ msgstr "LC_MESSAGES" #. type: textblock #: colobot.pod:127 msgid "Used to determine the runtime language." -msgstr "Utilisé pour déterminer la langue au lancement" +msgstr "Utilisé pour déterminer la langue au lancement." #. type: =head1 #: colobot.pod:131 diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt index 6a5d7073..28229f32 100644 --- a/po/CMakeLists.txt +++ b/po/CMakeLists.txt @@ -12,7 +12,7 @@ add_custom_command(OUTPUT ${_potFile} COMMAND ${XGETTEXT_CMD} ${colobot_SOURCE_DIR}/src/app/app.cpp --output=${_potFile} --no-wrap COMMAND ${XGETTEXT_CMD} ${colobot_SOURCE_DIR}/src/common/restext.cpp --output=${_potFile} --no-wrap --join-existing --no-location --keyword=TR COMMAND ${XGETTEXT_CMD} ${colobot_SOURCE_DIR}/src/script/script.cpp --output=${_potFile} --no-wrap --join-existing --no-location - COMMAND sed -i -e "s|^\\(\"POT-Creation-Date:\\).*$|\\1 DATE\\\\n\"|" ${_potFile} + COMMAND sed -bi -e "s/^\\(\"POT-Creation-Date:\\).*$/\\1 DATE\\\\n\"/" ${_potFile} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Extract translatable messages to ${_potFile}" diff --git a/po/colobot.pot b/po/colobot.pot index b91aba04..442eafd6 100644 --- a/po/colobot.pot +++ b/po/colobot.pot @@ -84,6 +84,12 @@ msgstr "" msgid "Load a saved mission" msgstr "" +msgid "Missions+" +msgstr "" + +msgid "Mods" +msgstr "" + msgid "Chapters:" msgstr "" @@ -166,6 +172,23 @@ msgstr "" msgid "This menu is for userlevels from mods, but you didn't install any" msgstr "" +msgid "Could not open the file explorer!" +msgstr "" + +#, c-format +msgid "The path %s could not be opened in a file explorer." +msgstr "" + +msgid "Could not open the web browser!" +msgstr "" + +#, c-format +msgid "The address %s could not be opened in a web browser." +msgstr "" + +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "Keyword help(\\key cbot;)" msgstr "" @@ -206,6 +229,12 @@ msgstr "" msgid "Public\\Common folder" msgstr "" +msgid "Overwrite existing file?" +msgstr "" + +msgid "Select Folder" +msgstr "" + msgid "Original game developed by:" msgstr "" @@ -274,6 +303,42 @@ msgstr "" msgid "%s: %d pts" msgstr "" +msgid "Mods:" +msgstr "" + +msgid "Information:" +msgstr "" + +msgid "Description:" +msgstr "" + +msgid "Enable\\Enable the selected mod" +msgstr "" + +msgid "Disable\\Disable the selected mod" +msgstr "" + +msgid "Unknown author" +msgstr "" + +msgid "by" +msgstr "" + +msgid "Version" +msgstr "" + +msgid "Website" +msgstr "" + +msgid "Changes" +msgstr "" + +msgid "No description." +msgstr "" + +msgid "No changes." +msgstr "" + msgid "Code battle" msgstr "" @@ -286,6 +351,9 @@ msgstr "" msgid "Previous" msgstr "" +msgid "New Folder" +msgstr "" + msgid "Exercises\\Programming exercises" msgstr "" @@ -307,6 +375,9 @@ msgstr "" msgid "SatCom" msgstr "" +msgid "Mods\\Mod manager" +msgstr "" + msgid "Change player\\Change player" msgstr "" @@ -331,9 +402,30 @@ msgstr "" msgid "<< Back \\Back to the previous screen" msgstr "" +msgid "+\\Missions with bonus content and optional challenges" +msgstr "" + msgid "Play\\Start mission!" msgstr "" +msgid "Workshop\\Open the workshop to search for mods" +msgstr "" + +msgid "Open Directory\\Open the mods directory" +msgstr "" + +msgid "Apply\\Apply the current mod configuration" +msgstr "" + +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Device\\Driver and resolution settings" msgstr "" @@ -406,6 +498,9 @@ msgstr "" msgid "Pause in background\\Pause the game when the window is unfocused" msgstr "" +msgid "Mute sounds in background\\Mute all game sounds when the window is unfocused" +msgstr "" + msgid "Automatic indent\\When program editing" msgstr "" @@ -571,6 +666,15 @@ msgstr "" msgid "Invert\\Invert values on this axis" msgstr "" +msgid "Space Programmer\\Disables radio-control" +msgstr "" + +msgid "Space Researcher\\Disables using all previously researched technologies" +msgstr "" + +msgid "Space Explorer\\Disables astronaut abilities" +msgstr "" + msgid "\\New player name" msgstr "" @@ -742,7 +846,7 @@ msgstr "" msgid "Build a exchange post" msgstr "" -msgid "Build a destroyer" +msgid "Build a vault" msgstr "" msgid "Show if the ground is flat" @@ -817,6 +921,18 @@ msgstr "" msgid "Build a legged sniffer" msgstr "" +msgid "Build a winged builder" +msgstr "" + +msgid "Build a tracked builder" +msgstr "" + +msgid "Build a wheeled builder" +msgstr "" + +msgid "Build a legged builder" +msgstr "" + msgid "Build a thumper" msgstr "" @@ -832,6 +948,9 @@ msgstr "" msgid "Build a subber" msgstr "" +msgid "Build a target bot" +msgstr "" + msgid "Run research program for tracked bots" msgstr "" @@ -862,6 +981,12 @@ msgstr "" msgid "Run research program for orga shooter" msgstr "" +msgid "Run research program for builder" +msgstr "" + +msgid "Run research program for target bot" +msgstr "" + msgid "Return to start" msgstr "" @@ -877,6 +1002,9 @@ msgstr "" msgid "Explode (\\key action;)" msgstr "" +msgid "Build (\\key action;)" +msgstr "" + msgid "Recycle (\\key action;)" msgstr "" @@ -1255,6 +1383,18 @@ msgstr "" msgid "Legged grabber" msgstr "" +msgid "Winged builder" +msgstr "" + +msgid "Tracked builder" +msgstr "" + +msgid "Wheeled builder" +msgstr "" + +msgid "Legged builder" +msgstr "" + msgid "Winged shooter" msgstr "" @@ -1471,7 +1611,7 @@ msgstr "" msgid "Nothing to analyze" msgstr "" -msgid "Analyzes only organic matter" +msgid "Inappropriate sample" msgstr "" msgid "Analysis already performed" @@ -1570,6 +1710,9 @@ msgstr "" msgid "Plans for nuclear power plant available" msgstr "" +msgid "Plans for builder available" +msgstr "" + msgid "New bot available" msgstr "" @@ -1795,6 +1938,12 @@ msgstr "" msgid "Invalid universal character name" msgstr "" +msgid "Empty character constant" +msgstr "" + +msgid "Duplicate label in switch" +msgstr "" + msgid "Dividing by zero" msgstr "" diff --git a/po/cs.po b/po/cs.po index b5c41e3a..453ded95 100644 --- a/po/cs.po +++ b/po/cs.po @@ -32,6 +32,9 @@ msgstr "Chybí \"]\"" msgid "%s: %d pts" msgstr "%s: %d bodů" +msgid "+\\Missions with bonus content and optional challenges" +msgstr "" + msgid "..behind" msgstr "...za sebou" @@ -110,9 +113,6 @@ msgstr "Analýza již byla dokončena" msgid "Analysis performed" msgstr "Analýza dokončena" -msgid "Analyzes only organic matter" -msgstr "Analyzuje pouze organickou hmotu" - msgid "Anisotropy level\\Anisotropy level" msgstr "Úroveň anizotropie\\Úroveň anizotropie" @@ -128,6 +128,9 @@ msgstr "Vzhled\\Upravte svůj vzhled" msgid "Apply changes\\Activates the changed settings" msgstr "Uložit změny\\Aktivovat změny nastavení" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Chybí vhodný konstruktor" @@ -185,6 +188,9 @@ msgstr "Robot zničen" msgid "Bot factory" msgstr "Továrna na roboty" +msgid "Build (\\key action;)" +msgstr "" + msgid "Build a bot factory" msgstr "Postavit továrnu na roboty" @@ -197,12 +203,12 @@ msgstr "Postavit obrannou věž" msgid "Build a derrick" msgstr "Postavit vrtnou věž" -msgid "Build a destroyer" -msgstr "Postavit drtič" - msgid "Build a exchange post" msgstr "Postavit komunikační stanici" +msgid "Build a legged builder" +msgstr "" + msgid "Build a legged grabber" msgstr "Vyrobit chodící rameno" @@ -248,9 +254,15 @@ msgstr "Vyrobit mobilní štít" msgid "Build a subber" msgstr "Vyrobit ponorku" +msgid "Build a target bot" +msgstr "" + msgid "Build a thumper" msgstr "Vyrobit buchar" +msgid "Build a tracked builder" +msgstr "" + msgid "Build a tracked grabber" msgstr "Vyrobit pásové rameno" @@ -263,6 +275,12 @@ msgstr "Vyrobit pásový kanón" msgid "Build a tracked sniffer" msgstr "Vyrobit pásový detektor" +msgid "Build a vault" +msgstr "" + +msgid "Build a wheeled builder" +msgstr "" + msgid "Build a wheeled grabber" msgstr "Vyrobit pojízdné rameno" @@ -275,6 +293,9 @@ msgstr "Vyrobit pojízdný kanón" msgid "Build a wheeled sniffer" msgstr "Vyrobit pojízdný detektor" +msgid "Build a winged builder" +msgstr "" + msgid "Build a winged grabber" msgstr "Vyrobit létající rameno" @@ -356,6 +377,9 @@ msgstr "Změnit kameru\\Přepíná mezi kamerou na robotu a za robotem" msgid "Change player\\Change player" msgstr "Změnit hráče\\Změnit hráče" +msgid "Changes" +msgstr "" + msgid "Chapters:" msgstr "Kapitoly:" @@ -425,6 +449,12 @@ msgstr "Kopírovat" msgid "Copy (Ctrl+C)" msgstr "Kopírovat (Ctrl+C)" +msgid "Could not open the file explorer!" +msgstr "" + +msgid "Could not open the web browser!" +msgstr "" + msgid "Current mission saved" msgstr "Současná mise uložena" @@ -458,6 +488,9 @@ msgstr "Vrtná věž" msgid "Descend\\Reduces the power of the jet" msgstr "Klesat\\Snížit tah tryskového motoru" +msgid "Description:" +msgstr "" + msgid "Destroy" msgstr "Zbourat" @@ -470,6 +503,9 @@ msgstr "Drtič" msgid "Device\\Driver and resolution settings" msgstr "Obrazovka\\Nastavení grafické karty a rozlišení" +msgid "Disable\\Disable the selected mod" +msgstr "" + msgid "Dividing by zero" msgstr "Dělení nulou" @@ -486,9 +522,15 @@ msgstr "Dveře blokuje robot nebo jiný objekt" msgid "Down (\\key gdown;)" msgstr "Dolů (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Tužkobot" +msgid "Duplicate label in switch" +msgstr "" + msgid "Dust\\Dust and dirt on bots and buildings" msgstr "Prach\\Prach a špína na robotech a budovách" @@ -507,6 +549,12 @@ msgstr "Upravit vybraný program" msgid "Egg" msgstr "Vejce" +msgid "Empty character constant" +msgstr "" + +msgid "Enable\\Enable the selected mod" +msgstr "" + msgid "End of block missing" msgstr "Chybí konec bloku" @@ -721,6 +769,9 @@ msgstr "Nevhodný typ baterie" msgid "Inappropriate object" msgstr "Nevhodný objekt" +msgid "Inappropriate sample" +msgstr "" + msgid "Incorrect index type" msgstr "Špatný datový typ indexu" @@ -730,6 +781,9 @@ msgstr "Infikováno virem; dočasně mimo provoz" msgid "Information exchange post" msgstr "Komunikační stanice" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Příkaz \"break\" mimo cyklus" @@ -790,6 +844,9 @@ msgstr "Nápověda ke klíčovému slovu (\\key cbot;)" msgid "LOADING" msgstr "NAČÍTÁNÍ" +msgid "Legged builder" +msgstr "" + msgid "Legged grabber" msgstr "Chodící rameno" @@ -874,9 +931,21 @@ msgstr "Mise" msgid "Missions on this planet:" msgstr "Mise na této planetě:" +msgid "Missions+" +msgstr "Mise+" + msgid "Missions\\Select mission" msgstr "Mise\\Vyberte misi" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Vodorovné převrácení posunu\\Při vodorovném posunu kamery myší pousouvat opačným směrem" @@ -889,6 +958,9 @@ msgstr "Posunout vybraný program níže" msgid "Move selected program up" msgstr "Posunout vybraný program výše" +msgid "Mute sounds in background\\Mute all game sounds when the window is unfocused" +msgstr "" + msgid "Mute\\No sound" msgstr "Ticho\\Bez zvuku" @@ -907,6 +979,9 @@ msgstr "Nový" msgid "New ..." msgstr "Nový..." +msgid "New Folder" +msgstr "" + msgid "New bot available" msgstr "Robot vyroben" @@ -919,6 +994,12 @@ msgstr "Další objekt\\Vybere následující objekt" msgid "No" msgstr "Ne" +msgid "No changes." +msgstr "" + +msgid "No description." +msgstr "" + msgid "No energy in the subsoil" msgstr "Pod povrchem není zdroj energie" @@ -1039,6 +1120,9 @@ msgstr "Otevřít" msgid "Open (Ctrl+O)" msgstr "Otevřít (Ctrl+O)" +msgid "Open Directory\\Open the mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Chybí levá složená závorka" @@ -1063,6 +1147,9 @@ msgstr "Zdroj poslední zprávy\\Zobrazí objekt, který poslal poslední zpráv msgid "Original game developed by:" msgstr "Vývojáři původní hry:" +msgid "Overwrite existing file?" +msgstr "" + msgid "Parameters missing" msgstr "Některé parametry nejsou vyplněné" @@ -1096,6 +1183,9 @@ msgstr "Místo je obsazeno" msgid "Planets:" msgstr "Planety:" +msgid "Plans for builder available" +msgstr "" + msgid "Plans for defense tower available" msgstr "Plány pro obrannou věž jsou k dispozici" @@ -1243,6 +1333,9 @@ msgstr "Červená vlajka" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Odlesky na tlačítkách\\Blyštivá tlačítka" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Pozůstatky mise Apollo" @@ -1300,6 +1393,9 @@ msgstr "Robbie" msgid "Ruin" msgstr "Trosky" +msgid "Run research program for builder" +msgstr "" + msgid "Run research program for defense tower" msgstr "Spustit výzkum obranných věží" @@ -1321,6 +1417,9 @@ msgstr "Spustit výzkum mobilního štítu" msgid "Run research program for shooter" msgstr "Spustit výzkum kanónů" +msgid "Run research program for target bot" +msgstr "" + msgid "Run research program for thumper" msgstr "Spustit výzkum bucharu" @@ -1351,6 +1450,9 @@ msgstr "Uložit\\Uložit současnou misi" msgid "Save\\Saves the current mission" msgstr "Uložit\\Uloží současnou misi" +msgid "Select Folder" +msgstr "" + msgid "Select the astronaut\\Selects the astronaut" msgstr "Vybrat kosmonauta\\Vybere kosmonauta" @@ -1417,6 +1519,15 @@ msgstr "Zvukové efekty:\\Hlasitost motorů, hlasů, střelby, atd." msgid "Sound\\Music and game sound volume" msgstr "Zvuk\\Hlasitost hudby a zvukových efektů" +msgid "Space Explorer\\Disables astronaut abilities" +msgstr "" + +msgid "Space Programmer\\Disables radio-control" +msgstr "" + +msgid "Space Researcher\\Disables using all previously researched technologies" +msgstr "" + msgid "Spaceship" msgstr "Raketa" @@ -1495,6 +1606,10 @@ msgstr "Filtrování textur\\Filtrování textur" msgid "Textures" msgstr "Textury" +#, c-format +msgid "The address %s could not be opened in a web browser." +msgstr "" + msgid "The battle has ended" msgstr "Souboj skončil" @@ -1507,9 +1622,16 @@ msgstr "Funkce nevrátila žádnou hodnotu" msgid "The mission is not accomplished yet (press \\key help; for more details)" msgstr "Mise ještě nebyla splněna (pro podrobnosti stiskněte \\key help;)" +#, c-format +msgid "The path %s could not be opened in a file explorer." +msgstr "" + msgid "The types of the two operands are incompatible" msgstr "Operaci nelze provést s operandy těchto dvou typů" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Tato třída již existuje" @@ -1583,6 +1705,9 @@ msgstr "Příliš mnoho vlajek této barvy (maximálně 5)" msgid "Too many parameters" msgstr "Příliš mnoho parametrů" +msgid "Tracked builder" +msgstr "" + msgid "Tracked grabber" msgstr "Pásové rameno" @@ -1631,6 +1756,9 @@ msgstr "Jednotka" msgid "Unknown Object" msgstr "Neznámý objekt" +msgid "Unknown author" +msgstr "" + msgid "Unknown command" msgstr "Neznámý příkaz" @@ -1643,6 +1771,9 @@ msgstr "Neznámá funkce" msgid "Up (\\key gup;)" msgstr "Vzhůru (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Uranové ložisko (místo pro vrtnou věž)" @@ -1664,6 +1795,9 @@ msgstr "Proměnná nebyla nastavena" msgid "Vault" msgstr "Trezor" +msgid "Version" +msgstr "" + msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency" msgstr "" @@ -1682,6 +1816,12 @@ msgstr "Vosa byla smrtelně raněna" msgid "Waste" msgstr "Odpad" +msgid "Website" +msgstr "" + +msgid "Wheeled builder" +msgstr "" + msgid "Wheeled grabber" msgstr "Pojízdné rameno" @@ -1694,6 +1834,9 @@ msgstr "Pojízdný kanón" msgid "Wheeled sniffer" msgstr "Pojízdný detektor" +msgid "Winged builder" +msgstr "" + msgid "Winged grabber" msgstr "Létající rameno" @@ -1709,6 +1852,9 @@ msgstr "Létající detektor" msgid "Withdraw shield (\\key action;)" msgstr "Vypnout štít (\\key action;)" +msgid "Workshop\\Open the workshop to search for mods" +msgstr "" + msgid "Worm" msgstr "Červ" @@ -1859,8 +2005,14 @@ msgstr "\\Fialové vlajky" msgid "\\Yellow flags" msgstr "\\Žluté vlajky" +msgid "by" +msgstr "" + msgid "colobot.info" msgstr "colobot.info" msgid "epsitec.com" msgstr "epsitec.com" + +#~ msgid "Build a destroyer" +#~ msgstr "Postavit drtič" diff --git a/po/de.po b/po/de.po index 66d9918a..7bcffe5b 100644 --- a/po/de.po +++ b/po/de.po @@ -33,6 +33,9 @@ msgstr "Es fehlt eine geschlossene eckige Klammer \" ] \"" msgid "%s: %d pts" msgstr "" +msgid "+\\Missions with bonus content and optional challenges" +msgstr "" + msgid "..behind" msgstr "..hinten" @@ -111,9 +114,6 @@ msgstr "Analyse schon durchgeführt" msgid "Analysis performed" msgstr "Analyse vollendet" -msgid "Analyzes only organic matter" -msgstr "Analysiert nur Orgastoff" - msgid "Anisotropy level\\Anisotropy level" msgstr "Anisotropie-Level\\Anisotropie-Level" @@ -129,6 +129,9 @@ msgstr "Aussehen\\Erscheinungsbild des Astronauten einstellen" msgid "Apply changes\\Activates the changed settings" msgstr "Änderungen anwenden\\Getätigte Einstellungen anwenden" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Es gibt keinen geeigneten Konstruktor" @@ -186,6 +189,9 @@ msgstr "Roboter zerstört" msgid "Bot factory" msgstr "Roboterfabrik" +msgid "Build (\\key action;)" +msgstr "" + msgid "Build a bot factory" msgstr "Baut eine Roboterfabrik" @@ -198,12 +204,12 @@ msgstr "Baut einen Geschützturm" msgid "Build a derrick" msgstr "Baut einen Bohrturm" -msgid "Build a destroyer" -msgstr "Baue einen Zerstörer" - msgid "Build a exchange post" msgstr "Baut einen Infoserver" +msgid "Build a legged builder" +msgstr "" + msgid "Build a legged grabber" msgstr "Baut einen Krabbeltransporter" @@ -249,9 +255,15 @@ msgstr "Baut einen Schutzschild" msgid "Build a subber" msgstr "Baut einen Kettentaucher" +msgid "Build a target bot" +msgstr "" + msgid "Build a thumper" msgstr "Baut einen Stampfer" +msgid "Build a tracked builder" +msgstr "" + msgid "Build a tracked grabber" msgstr "Baut einen Kettentransporter" @@ -264,6 +276,12 @@ msgstr "Baut einen Kettenshooter" msgid "Build a tracked sniffer" msgstr "Baut einen Kettenschnüffler" +msgid "Build a vault" +msgstr "" + +msgid "Build a wheeled builder" +msgstr "" + msgid "Build a wheeled grabber" msgstr "Baut einen Radtransporter" @@ -276,6 +294,9 @@ msgstr "Baut einen Radshooter" msgid "Build a wheeled sniffer" msgstr "Baut einen Radschnüffler" +msgid "Build a winged builder" +msgstr "" + msgid "Build a winged grabber" msgstr "Baut einen Jettransporter" @@ -357,6 +378,9 @@ msgstr "Andere Kamera\\Sichtpunkt einstellen" msgid "Change player\\Change player" msgstr "Anderer Spieler\\Spielername ändern" +msgid "Changes" +msgstr "" + msgid "Chapters:" msgstr "Liste der Kapitel:" @@ -426,6 +450,12 @@ msgstr "Kopieren" msgid "Copy (Ctrl+C)" msgstr "Kopieren (Ctrl+C)" +msgid "Could not open the file explorer!" +msgstr "" + +msgid "Could not open the web browser!" +msgstr "" + msgid "Current mission saved" msgstr "Mission gespeichert" @@ -459,6 +489,9 @@ msgstr "Bohrturm" msgid "Descend\\Reduces the power of the jet" msgstr "Sinken\\Leistung des Triebwerks drosseln" +msgid "Description:" +msgstr "" + msgid "Destroy" msgstr "Zerstören" @@ -471,6 +504,9 @@ msgstr "Einstampfer" msgid "Device\\Driver and resolution settings" msgstr "Bildschirm\\Driver und Bildschirmauflösung" +msgid "Disable\\Disable the selected mod" +msgstr "" + msgid "Dividing by zero" msgstr "Division durch Null" @@ -487,9 +523,15 @@ msgstr "Die Türen werden von einem Gegenstand blockiert" msgid "Down (\\key gdown;)" msgstr "Sinkt (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Zeichner" +msgid "Duplicate label in switch" +msgstr "" + msgid "Dust\\Dust and dirt on bots and buildings" msgstr "Schmutz\\Schmutz auf Robotern und Bauten" @@ -508,6 +550,12 @@ msgstr "Gewähltes Programm bearbeiten" msgid "Egg" msgstr "Ei" +msgid "Empty character constant" +msgstr "" + +msgid "Enable\\Enable the selected mod" +msgstr "" + msgid "End of block missing" msgstr "Es fehlt eine geschlossene geschweifte Klammer \"}\" (Ende des Blocks)" @@ -723,6 +771,9 @@ msgstr "Falscher Batterietyp" msgid "Inappropriate object" msgstr "Objekt ungeeignet" +msgid "Inappropriate sample" +msgstr "" + msgid "Incorrect index type" msgstr "Falscher Typ für einen Index" @@ -732,6 +783,9 @@ msgstr "Von Virus infiziert, zeitweise außer Betrieb" msgid "Information exchange post" msgstr "Infoserver" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Anweisung \"break\" außerhalb einer Schleife" @@ -792,6 +846,9 @@ msgstr "Hilfe über den Begriff (\\key cbot;)" msgid "LOADING" msgstr "LADEN" +msgid "Legged builder" +msgstr "" + msgid "Legged grabber" msgstr "Transporter" @@ -890,9 +947,21 @@ msgstr "Missionen" msgid "Missions on this planet:" msgstr "Liste der Missionen des Planeten:" +msgid "Missions+" +msgstr "Missionen+" + msgid "Missions\\Select mission" msgstr "Missionen\\Aufbruch ins Weltall" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Umkehr X\\Umkehr der Kameradrehung X-Achse" @@ -905,6 +974,9 @@ msgstr "Gewähltes Programm nach unten" msgid "Move selected program up" msgstr "Gewähltes Programm nach oben" +msgid "Mute sounds in background\\Mute all game sounds when the window is unfocused" +msgstr "" + msgid "Mute\\No sound" msgstr "Kein Ton\\Keine Geräusche und Geräuschkulisse" @@ -923,6 +995,9 @@ msgstr "Neu" msgid "New ..." msgstr "Neu ..." +msgid "New Folder" +msgstr "" + msgid "New bot available" msgstr "Neuer Roboter verfügbar" @@ -935,6 +1010,12 @@ msgstr "Nächstes auswählen\\Nächstes Objekt auswählen" msgid "No" msgstr "Nein" +msgid "No changes." +msgstr "" + +msgid "No description." +msgstr "" + msgid "No energy in the subsoil" msgstr "Kein unterirdisches Energievorkommen" @@ -1055,6 +1136,9 @@ msgstr "Öffnen" msgid "Open (Ctrl+O)" msgstr "Öffnen (Ctrl+O)" +msgid "Open Directory\\Open the mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Es fehlt eine offene geschweifte Klammer\"{\"" @@ -1079,6 +1163,9 @@ msgstr "Ort der Meldung\\Zeigt den Ort, von dem die letzte Meldung stammt" msgid "Original game developed by:" msgstr "Ursprünglichen Spiel entwickelt von:" +msgid "Overwrite existing file?" +msgstr "" + msgid "Parameters missing" msgstr "Nicht genug Parameter" @@ -1112,6 +1199,9 @@ msgstr "Stelle schon besetzt" msgid "Planets:" msgstr "Liste der Planeten:" +msgid "Plans for builder available" +msgstr "" + msgid "Plans for defense tower available" msgstr "Errichtung eines Geschützturms möglich" @@ -1260,6 +1350,9 @@ msgstr "Rote Fahne" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Glänzende Tasten\\Glänzende Tasten in den Menüs" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Überreste einer Apollo-Mission" @@ -1317,6 +1410,9 @@ msgstr "Robby" msgid "Ruin" msgstr "Gebäuderuine" +msgid "Run research program for builder" +msgstr "" + msgid "Run research program for defense tower" msgstr "Forschungsprogramm Geschützturm" @@ -1338,6 +1434,9 @@ msgstr "Forschungsprogramm Schutzschild" msgid "Run research program for shooter" msgstr "Forschungsprogramm Shooterkanone" +msgid "Run research program for target bot" +msgstr "" + msgid "Run research program for thumper" msgstr "Forschungsprogramm Stampfer" @@ -1368,6 +1467,9 @@ msgstr "Speichern\\Aktuelle Mission speichern" msgid "Save\\Saves the current mission" msgstr "Speichern\\Speichert die Mission" +msgid "Select Folder" +msgstr "" + msgid "Select the astronaut\\Selects the astronaut" msgstr "Astronauten auswählen\\Astronauten auswählen" @@ -1434,6 +1536,15 @@ msgstr "Geräusche:\\Lautstärke Motoren, Stimmen, usw." msgid "Sound\\Music and game sound volume" msgstr "Geräusche\\Lautstärke Geräusche und Musik" +msgid "Space Explorer\\Disables astronaut abilities" +msgstr "" + +msgid "Space Programmer\\Disables radio-control" +msgstr "" + +msgid "Space Researcher\\Disables using all previously researched technologies" +msgstr "" + msgid "Spaceship" msgstr "Raumschiff" @@ -1512,6 +1623,10 @@ msgstr "Texturfilterung\\Texturfilterung" msgid "Textures" msgstr "Texturen" +#, c-format +msgid "The address %s could not be opened in a web browser." +msgstr "" + msgid "The battle has ended" msgstr "" @@ -1524,9 +1639,16 @@ msgstr "Die Funktion hat kein Ergebnis zurückgegeben" msgid "The mission is not accomplished yet (press \\key help; for more details)" msgstr "Mission noch nicht beendet (Drücken Sie auf \\key help; für weitere Informationen)" +#, c-format +msgid "The path %s could not be opened in a file explorer." +msgstr "" + msgid "The types of the two operands are incompatible" msgstr "Die zwei Operanden sind nicht kompatibel" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Diese Klasse gibt es schon" @@ -1600,6 +1722,9 @@ msgstr "Zu viele Fahnen dieser Farbe (Maximum 5)" msgid "Too many parameters" msgstr "Zu viele Parameter" +msgid "Tracked builder" +msgstr "" + msgid "Tracked grabber" msgstr "Transporter" @@ -1648,6 +1773,9 @@ msgstr "Einheit" msgid "Unknown Object" msgstr "Das Objekt existiert nicht" +msgid "Unknown author" +msgstr "" + msgid "Unknown command" msgstr "Befehl unbekannt" @@ -1660,6 +1788,9 @@ msgstr "Unbekannte Funktion" msgid "Up (\\key gup;)" msgstr "Steigt (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Markierung für unterirdisches Platinvorkommen" @@ -1681,6 +1812,9 @@ msgstr "Der Wert dieser Variable wurde nicht definiert" msgid "Vault" msgstr "Bunker" +msgid "Version" +msgstr "" + msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency" msgstr "" @@ -1699,6 +1833,12 @@ msgstr "Wespe tödlich verwundet" msgid "Waste" msgstr "Abfall" +msgid "Website" +msgstr "" + +msgid "Wheeled builder" +msgstr "" + msgid "Wheeled grabber" msgstr "Transporter" @@ -1711,6 +1851,9 @@ msgstr "Shooter" msgid "Wheeled sniffer" msgstr "Schnüffler" +msgid "Winged builder" +msgstr "" + msgid "Winged grabber" msgstr "Transporter" @@ -1726,6 +1869,9 @@ msgstr "Schnüffler" msgid "Withdraw shield (\\key action;)" msgstr "Schutzschild einholen (\\key action;)" +msgid "Workshop\\Open the workshop to search for mods" +msgstr "" + msgid "Worm" msgstr "Wurm" @@ -1874,6 +2020,9 @@ msgstr "\\Violette Fahne" msgid "\\Yellow flags" msgstr "\\Gelbe Fahne" +msgid "by" +msgstr "" + msgid "colobot.info" msgstr "colobot.info" @@ -1895,6 +2044,9 @@ msgstr "epsitec.com" #~ msgid "3D sound\\3D positioning of the sound" #~ msgstr "3D-Geräusche\\Orten der Geräusche im Raum" +#~ msgid "Build a destroyer" +#~ msgstr "Baue einen Zerstörer" + #~ msgid "Building too close" #~ msgstr "Gebäude zu nahe" diff --git a/po/fr.po b/po/fr.po index c8d48217..a6375ce7 100644 --- a/po/fr.po +++ b/po/fr.po @@ -1,21 +1,21 @@ # Didier Raboud , 2012, 2015, 2016. -# Martin Quinson , 2016 -# B-CE, 2018 -# Pascal Audoux , 2018 +# Martin Quinson , 2016. +# B-CE <.>, 2018, 2019. +# Pascal Audoux , 2018. msgid "" msgstr "" -"Project-Id-Version: Colobot 0.1.11\n" +"Project-Id-Version: Colobot 0.1.12\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: DATE\n" -"PO-Revision-Date: 2019-01-09 23:07+0100\n" -"Last-Translator: B-CE\n" -"Language-Team: \n" +"PO-Revision-Date: 2019-06-13 01:31+0200\n" +"Last-Translator: BCE <.>\n" +"Language-Team: French <>\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 2.0.6\n" +"X-Generator: Lokalize 18.12.3\n" "X-Language: fr_FR\n" "X-Source-Language: en_US\n" @@ -32,6 +32,9 @@ msgstr "\" ] \" manquant" msgid "%s: %d pts" msgstr "%s: %d points" +msgid "+\\Missions with bonus content and optional challenges" +msgstr "" + msgid "..behind" msgstr "..derrière" @@ -39,7 +42,7 @@ msgid "..in front" msgstr "..devant" msgid "..power cell" -msgstr "..pile" +msgstr "..batterie" msgid "1) First click on the key you want to redefine." msgstr "1) Cliquez d'abord sur la touche à redéfinir." @@ -110,9 +113,6 @@ msgstr "Analyse déjà effectuée" msgid "Analysis performed" msgstr "Analyse terminée" -msgid "Analyzes only organic matter" -msgstr "N'analyse que la matière organique" - msgid "Anisotropy level\\Anisotropy level" msgstr "Niveau d'anisotropie\\Niveau d'anisotropie" @@ -128,6 +128,9 @@ msgstr "Aspect\\Choisir votre aspect" msgid "Apply changes\\Activates the changed settings" msgstr "Appliquer les changements\\Active les changements effectués" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Constructeur approprié manquant" @@ -141,10 +144,10 @@ msgid "Automatic indent\\When program editing" msgstr "Indentation automatique\\Pendant l'édition d'un programme" msgid "Autosave interval\\How often your game will autosave" -msgstr "Interval d'auto-sauvegarde\\À quels intervals les parties vont-t-elles êtres sauvegardées automatiquement" +msgstr "Interval auto-sauvegarde\\À quels intervals les parties vont-t-elles êtres sauvegardées automatiquement" msgid "Autosave slots\\How many autosave slots you'll have" -msgstr "Nombre d'auto-sauvegardes\\Combien d'auto-sauvegarde seront conservées" +msgstr "Nb auto-sauvegardes\\Combien d'auto-sauvegarde seront conservées" msgid "Autosave\\Enables autosave" msgstr "Auto-sauvegarde\\Activer l'auto-sauvegarde" @@ -186,13 +189,16 @@ msgid "Bot destroyed" msgstr "Robot détruit" msgid "Bot factory" -msgstr "Fabrique de robots" +msgstr "Usine de robots" + +msgid "Build (\\key action;)" +msgstr "" msgid "Build a bot factory" -msgstr "Construire une fabrique de robots" +msgstr "Construire une usine de robots" msgid "Build a converter" -msgstr "Construire un convertisseur" +msgstr "Construire une raffinerie" msgid "Build a defense tower" msgstr "Construire une tour" @@ -200,14 +206,14 @@ msgstr "Construire une tour" msgid "Build a derrick" msgstr "Construire un derrick" -msgid "Build a destroyer" -msgstr "Construire un destructeur" - msgid "Build a exchange post" -msgstr "Construire une borne d'information" +msgstr "Construire une station relais" + +msgid "Build a legged builder" +msgstr "" msgid "Build a legged grabber" -msgstr "Fabriquer un déménageur à pattes" +msgstr "Fabriquer un préhenseur à pattes" msgid "Build a legged orga shooter" msgstr "Fabriquer un tireur organique à pattes" @@ -225,10 +231,10 @@ msgid "Build a nuclear power plant" msgstr "Construire une centrale nucléaire" msgid "Build a phazer shooter" -msgstr "Fabriquer un robot canon à phases" +msgstr "Fabriquer un robot canon hachoir" msgid "Build a power cell factory" -msgstr "Construire une fabrique de piles" +msgstr "Construire une fabrique de batteries" msgid "Build a power station" msgstr "Construire une station de recharge" @@ -251,11 +257,17 @@ msgstr "Fabriquer un robot bouclier" msgid "Build a subber" msgstr "Fabriquer un robot sous-marin" +msgid "Build a target bot" +msgstr "" + msgid "Build a thumper" msgstr "Fabriquer un robot secoueur" +msgid "Build a tracked builder" +msgstr "" + msgid "Build a tracked grabber" -msgstr "Fabriquer un déménageur à chenilles" +msgstr "Fabriquer un préhenseur à chenilles" msgid "Build a tracked orga shooter" msgstr "Fabriquer un tireur organique à chenilles" @@ -266,8 +278,14 @@ msgstr "Fabriquer un tireur à chenilles" msgid "Build a tracked sniffer" msgstr "Fabriquer un renifleur à chenilles" +msgid "Build a vault" +msgstr "" + +msgid "Build a wheeled builder" +msgstr "" + msgid "Build a wheeled grabber" -msgstr "Fabriquer un déménageur à roues" +msgstr "Fabriquer un préhenseur à roues" msgid "Build a wheeled orga shooter" msgstr "Fabriquer un tireur organique à roues" @@ -278,8 +296,11 @@ msgstr "Fabriquer un tireur à roues" msgid "Build a wheeled sniffer" msgstr "Fabriquer un renifleur à roues" +msgid "Build a winged builder" +msgstr "" + msgid "Build a winged grabber" -msgstr "Fabriquer un déménageur volant" +msgstr "Fabriquer un préhenseur volant" msgid "Build a winged orga shooter" msgstr "Fabriquer un tireur organique volant" @@ -315,19 +336,19 @@ msgid "Camera border scrolling\\Scrolling when the mouse touches right or left b msgstr "Défilement dans les bords\\Défilement lorsque la souris touche les bords gauche ou droite" msgid "Camera closer\\Moves the camera forward" -msgstr "Caméra plus proche\\Avance la caméra" +msgstr "Plus proche\\Avance la caméra" msgid "Camera down\\Turns the camera down" -msgstr "Baisser caméra\\Baisse la caméra" +msgstr "Plus bas\\Tourne la caméra vers le bas" msgid "Camera left\\Turns the camera left" -msgstr "Caméra à gauche\\Tourne la caméra vers la gauche" +msgstr "À gauche\\Tourne la caméra vers la gauche" msgid "Camera right\\Turns the camera right" -msgstr "Caméra à droite\\Tourne la caméra vers la droite" +msgstr "À droite\\Tourne la caméra vers la droite" msgid "Camera up\\Turns the camera up" -msgstr "Lever caméra\\Monte la caméra" +msgstr "Plus haut\\Tourne la caméra vers le haut" msgid "Can not produce not researched object" msgstr "Impossible de créer un objet n'ayant pas été recherché" @@ -359,6 +380,9 @@ msgstr "Changement de caméra\\Autre de point de vue" msgid "Change player\\Change player" msgstr "Autre joueur\\Choix du nom du joueur" +msgid "Changes" +msgstr "" + msgid "Chapters:" msgstr "Liste des chapitres :" @@ -366,7 +390,7 @@ msgid "Cheat console\\Show cheat console" msgstr "Console de triche\\Montre la console de triche" msgid "Checkpoint" -msgstr "Indicateur" +msgstr "Point de passage" msgid "Class name expected" msgstr "Nom de classe attendu" @@ -420,7 +444,7 @@ msgid "Controls\\Keyboard, joystick and mouse settings" msgstr "Commandes\\Touches du clavier" msgid "Converts ore to titanium" -msgstr "Conversion de minerai en titane" +msgstr "Raffinage de minerai en titane" msgid "Copy" msgstr "Copier" @@ -428,6 +452,12 @@ msgstr "Copier" msgid "Copy (Ctrl+C)" msgstr "Copier (Ctrl+C)" +msgid "Could not open the file explorer!" +msgstr "" + +msgid "Could not open the web browser!" +msgstr "" + msgid "Current mission saved" msgstr "Enregistrement effectué" @@ -461,6 +491,9 @@ msgstr "Derrick" msgid "Descend\\Reduces the power of the jet" msgstr "Descendre\\Diminuer la puissance du réacteur" +msgid "Description:" +msgstr "" + msgid "Destroy" msgstr "Détruire" @@ -473,6 +506,9 @@ msgstr "Destructeur" msgid "Device\\Driver and resolution settings" msgstr "Affichage\\Pilote et résolution d'affichage" +msgid "Disable\\Disable the selected mod" +msgstr "" + msgid "Dividing by zero" msgstr "Division par zéro" @@ -489,9 +525,15 @@ msgstr "Portes bloquées par un robot ou un objet" msgid "Down (\\key gdown;)" msgstr "Descend (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Robot dessinateur" +msgid "Duplicate label in switch" +msgstr "" + msgid "Dust\\Dust and dirt on bots and buildings" msgstr "Salissures\\Salissures des robots et bâtiments" @@ -510,11 +552,17 @@ msgstr "Éditer le programme sélectionné" msgid "Egg" msgstr "Oeuf" +msgid "Empty character constant" +msgstr "" + +msgid "Enable\\Enable the selected mod" +msgstr "" + msgid "End of block missing" msgstr "Il manque la fin du bloc" msgid "Energy deposit (site for power station)" -msgstr "Emplacement pour une station de recharge ou une fabrique de pile" +msgstr "Sous sol énergétique (Emplacement pour une station de recharge ou une fabrique de batteries)" msgid "Energy level" msgstr "Niveau d'énergie" @@ -569,7 +617,7 @@ msgstr "But/Objectif" # OBJECT_END : GoalArea msgid "Fixed mine" -msgstr "Mine fixe" +msgstr "Mine anti-personnel" msgid "Flat ground not large enough" msgstr "Sol plat pas assez grand" @@ -600,7 +648,7 @@ msgid "Found a site for a derrick" msgstr "Emplacement pour un derrick trouvé" msgid "Found a site for power station" -msgstr "Emplacement pour station de recharge ou fabrique de pile trouvé" +msgstr "Emplacement pour station de recharge ou fabrique de batteries trouvé" msgid "Found key A (site for derrick)" msgstr "Emplacement pour un derrick (clé A)" @@ -720,11 +768,14 @@ msgid "Inappropriate bot" msgstr "Robot inadapté" msgid "Inappropriate cell type" -msgstr "Pas le bon type de pile" +msgstr "Source d'énergie non adapté" msgid "Inappropriate object" msgstr "Pas le bon objet" +msgid "Inappropriate sample" +msgstr "" + msgid "Incorrect index type" msgstr "Mauvais type d'index" @@ -732,7 +783,10 @@ msgid "Infected by a virus; temporarily out of order" msgstr "Infecté par un virus; ne fonctionne plus temporairement" msgid "Information exchange post" -msgstr "Borne d'information" +msgstr "Station relais" + +msgid "Information:" +msgstr "" msgid "Instruction \"break\" outside a loop" msgstr "Instruction \"break\" en dehors d'une boucle" @@ -794,8 +848,11 @@ msgstr "Aide sur le mot-clé (\\key cbot;)" msgid "LOADING" msgstr "CHARGEMENT" +msgid "Legged builder" +msgstr "" + msgid "Legged grabber" -msgstr "Robot déménageur à pattes" +msgstr "Robot préhenseur à pattes" msgid "Legged orga shooter" msgstr "Robot tireur organique à pattes" @@ -866,7 +923,7 @@ msgid "Lunar Roving Vehicle" msgstr "Véhicule d'exploration lunaire" msgid "MSAA\\Multisample anti-aliasing" -msgstr "ACME\\Anticrénelage multiéchantillon" +msgstr "ACME\\Anticrénelage multiéchantillon (MSAA: Multisample anti-aliasing)" msgid "Maximize" msgstr "Taille maximale" @@ -892,9 +949,21 @@ msgstr "Missions" msgid "Missions on this planet:" msgstr "Liste des missions du chapitre :" +msgid "Missions+" +msgstr "Missions+" + msgid "Missions\\Select mission" msgstr "Missions\\La grande aventure" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Inversion souris X\\Inversion de la rotation lorsque la souris touche un bord" @@ -907,6 +976,9 @@ msgstr "Déplace le programme sélectionné vers le bas" msgid "Move selected program up" msgstr "Déplace le programme sélectionné vers le haut" +msgid "Mute sounds in background\\Mute all game sounds when the window is unfocused" +msgstr "" + msgid "Mute\\No sound" msgstr "Silencieux\\Totalement silencieux" @@ -925,6 +997,9 @@ msgstr "Nouveau" msgid "New ..." msgstr "Nouveau ..." +msgid "New Folder" +msgstr "" + msgid "New bot available" msgstr "Nouveau robot disponible" @@ -937,6 +1012,12 @@ msgstr "Sélectionner l'objet suivant\\Sélectionner l'objet suivant" msgid "No" msgstr "Non" +msgid "No changes." +msgstr "" + +msgid "No description." +msgstr "" + msgid "No energy in the subsoil" msgstr "Pas d'énergie en sous-sol" @@ -953,7 +1034,7 @@ msgid "No function with this name accepts this number of parameters" msgstr "Aucune fonction de ce nom n'accepte ce nombre de paramètres" msgid "No information exchange post within range" -msgstr "Pas de borne d'information accessible" +msgstr "Pas de station relais accessible" msgid "No more energy" msgstr "Plus d'énergie" @@ -962,7 +1043,7 @@ msgid "No ore in the subsoil" msgstr "Pas de minerai en sous-sol" msgid "No power cell" -msgstr "Pas de pile" +msgstr "Pas de source d'énergie" msgid "No titanium" msgstr "Pas de titane" @@ -971,7 +1052,7 @@ msgid "No titanium around" msgstr "Pas de titane accessible" msgid "No titanium ore to convert" -msgstr "Pas de minerai de titane à convertir" +msgstr "Pas de minerai de titane à raffiner" msgid "No titanium to transform" msgstr "Pas de titane à transformer" @@ -1016,10 +1097,10 @@ msgid "Nothing to recycle" msgstr "Rien à recycler" msgid "Nuclear power cell" -msgstr "Pile nucléaire" +msgstr "Pile atomique" msgid "Nuclear power cell available" -msgstr "Pile nucléaire disponible" +msgstr "Pile atomique disponible" msgid "Nuclear power station" msgstr "Centrale nucléaire" @@ -1040,7 +1121,7 @@ msgid "OK\\Choose the selected player" msgstr "D'accord\\Choisir le joueur" msgid "OK\\Close program editor and return to game" -msgstr "D'accord\\Compiler le programme" +msgstr "D'accord\\Compiler le programme et fermer la fenêtre d'édition" msgid "Object too close" msgstr "Objet trop proche" @@ -1057,6 +1138,9 @@ msgstr "Ouvrir" msgid "Open (Ctrl+O)" msgstr "Ouvrir (Ctrl+O)" +msgid "Open Directory\\Open the mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Début d'un bloc attendu" @@ -1081,6 +1165,9 @@ msgstr "Montrer le lieu d'un message\\Montrer le lieu du dernier message" msgid "Original game developed by:" msgstr "Jeu original développé par :" +msgid "Overwrite existing file?" +msgstr "" + msgid "Parameters missing" msgstr "Pas assez de paramètres" @@ -1103,7 +1190,7 @@ msgid "Pause\\Pause the game without opening menu" msgstr "Pause\\Mettre le jeu en pause sans ouvrir le menu" msgid "Phazer shooter" -msgstr "Robot canon à phases" +msgstr "Robot canon hachoir" msgid "Photography" msgstr "Vue de la mission" @@ -1114,6 +1201,9 @@ msgstr "Emplacement occupé" msgid "Planets:" msgstr "Liste des planètes :" +msgid "Plans for builder available" +msgstr "" + msgid "Plans for defense tower available" msgstr "Construction d'une tour de défense possible" @@ -1121,7 +1211,7 @@ msgid "Plans for nuclear power plant available" msgstr "Construction d'une centrale nucléaire possible" msgid "Plans for phazer shooter available" -msgstr "Fabrication des robots canon à phases possible" +msgstr "Fabrication des robots canon hachoir possible" msgid "Plans for shielder available" msgstr "Fabrication d'un robot bouclier possible" @@ -1151,13 +1241,13 @@ msgid "Player's name" msgstr "Nom du joueur" msgid "Power cell" -msgstr "Pile normale" +msgstr "Batterie standard" msgid "Power cell available" -msgstr "Pile disponible" +msgstr "Batterie disponible" msgid "Power cell factory" -msgstr "Fabrique de piles" +msgstr "Fabrique de batteries" msgid "Power station" msgstr "Station de recharge" @@ -1235,7 +1325,7 @@ msgid "Quit\\Quit Colobot: Gold Edition" msgstr "Quitter\\Quitter Colobot : Édition Gold" msgid "Quit\\Quit the current mission or exercise" -msgstr "Quitter la mission en cours\\Terminer un exercice ou une mssion" +msgstr "Quitter la mission en cours\\Terminer un exercice ou une mission" msgid "Radar station" msgstr "Radar" @@ -1262,6 +1352,9 @@ msgstr "Drapeau rouge" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Reflets sur les boutons\\Boutons brillants" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Vestige d'une mission Apollo" @@ -1319,35 +1412,41 @@ msgstr "Robbie" msgid "Ruin" msgstr "Bâtiment en ruine" +msgid "Run research program for builder" +msgstr "" + msgid "Run research program for defense tower" -msgstr "Recherche la tour de défense" +msgstr "Lancer la recherche de la tour de défense" msgid "Run research program for legged bots" -msgstr "Recherche du fonctionnement des pattes" +msgstr "Lancer la recherche du fonctionnement des pattes" msgid "Run research program for nuclear power" -msgstr "Recherche du programme nucléaire" +msgstr "Lancer la recherche du programme nucléaire" msgid "Run research program for orga shooter" -msgstr "Recherche le canon organique" +msgstr "Lancer la recherche du canon organique" msgid "Run research program for phazer shooter" -msgstr "Recherche le canon à phases" +msgstr "Lancer la recherche du canon hachoir" msgid "Run research program for shielder" -msgstr "Recherche le bouclier" +msgstr "Lancer la recherche du bouclier" msgid "Run research program for shooter" -msgstr "Recherche le canon de tir" +msgstr "Lancer la recherche du canon de tir" + +msgid "Run research program for target bot" +msgstr "" msgid "Run research program for thumper" -msgstr "Recherche le secoueur" +msgstr "Lancer la recherche du secoueur" msgid "Run research program for tracked bots" -msgstr "Recherche du fonctionnement des chenilles" +msgstr "Lancer la recherche du fonctionnement des chenilles" msgid "Run research program for winged bots" -msgstr "Recherche du fonctionnement du jet" +msgstr "Lancer la recherche du fonctionnement du jet" msgid "SatCom" msgstr "SatCom" @@ -1370,6 +1469,9 @@ msgstr "Enregistrer\\Enregistrer la mission en cours" msgid "Save\\Saves the current mission" msgstr "Enregistrer\\Enregistrer la mission en cours" +msgid "Select Folder" +msgstr "" + msgid "Select the astronaut\\Selects the astronaut" msgstr "Sélectionner le cosmonaute\\Sélectionner le cosmonaute" @@ -1436,11 +1538,20 @@ msgstr "Sons :\\Volume des moteurs, voix, etc." msgid "Sound\\Music and game sound volume" msgstr "Son\\Volumes des sons & musiques" +msgid "Space Explorer\\Disables astronaut abilities" +msgstr "" + +msgid "Space Programmer\\Disables radio-control" +msgstr "" + +msgid "Space Researcher\\Disables using all previously researched technologies" +msgstr "" + msgid "Spaceship" msgstr "Vaisseau spatial" msgid "Spaceship ruin" -msgstr "Epave de vaisseau spatial" +msgstr "Épave de vaisseau spatial" msgid "Spider" msgstr "Araignée" @@ -1497,7 +1608,7 @@ msgid "Switch bots <-> buildings" msgstr "Permute robots <-> bâtiments" msgid "Take off to finish the mission" -msgstr "Décolle pour terminer la mission" +msgstr "Décollage pour terminer la mission" msgid "Target" msgstr "Cible" @@ -1514,6 +1625,10 @@ msgstr "Filtrage de textures\\Filtrage de textures" msgid "Textures" msgstr "Textures" +#, c-format +msgid "The address %s could not be opened in a web browser." +msgstr "" + msgid "The battle has ended" msgstr "La bataille est terminée" @@ -1526,9 +1641,16 @@ msgstr "La fonction n'a pas retourné de résultat" msgid "The mission is not accomplished yet (press \\key help; for more details)" msgstr "La mission n'est pas terminée (appuyez sur \\key help; pour plus de détails)" +#, c-format +msgid "The path %s could not be opened in a file explorer." +msgstr "" + msgid "The types of the two operands are incompatible" msgstr "Les deux opérandes ne sont pas de types compatibles" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Cette classe existe déjà" @@ -1560,7 +1682,7 @@ msgid "This program is read-only, clone it to edit" msgstr "Ce programme est en lecture-seule, le dupliquer pour pouvoir le modifier" msgid "Thump (\\key action;)" -msgstr "Secoue (\\key action;)" +msgstr "Secouer (\\key action;)" msgid "Thumper" msgstr "Robot secoueur" @@ -1602,8 +1724,11 @@ msgstr "Trop de drapeaux de cette couleur (maximum 5)" msgid "Too many parameters" msgstr "Trop de paramètres" +msgid "Tracked builder" +msgstr "" + msgid "Tracked grabber" -msgstr "Robot déménageur à chenilles" +msgstr "Robot préhenseur à chenilles" msgid "Tracked orga shooter" msgstr "Robot tireur organique à chenilles" @@ -1650,6 +1775,9 @@ msgstr "Unité" msgid "Unknown Object" msgstr "Objet inconnu" +msgid "Unknown author" +msgstr "" + msgid "Unknown command" msgstr "Commande inconnue" @@ -1662,6 +1790,9 @@ msgstr "Routine inconnue" msgid "Up (\\key gup;)" msgstr "Monte (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Emplacement pour un derrick (minerai d'uranium)" @@ -1683,9 +1814,12 @@ msgstr "Variable non initialisée" msgid "Vault" msgstr "Coffre-fort" -msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency" +msgid "Version" msgstr "" +msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency" +msgstr "Synchronisation verticale :\\Réduit la fréquence d'images par seconde à afficher." + msgid "Violet flag" msgstr "Drapeau violet" @@ -1701,8 +1835,14 @@ msgstr "Guêpe mortellement touchée" msgid "Waste" msgstr "Déchet" +msgid "Website" +msgstr "" + +msgid "Wheeled builder" +msgstr "" + msgid "Wheeled grabber" -msgstr "Robot déménageur à roues" +msgstr "Robot préhenseur à roues" msgid "Wheeled orga shooter" msgstr "Robot tireur organique à roues" @@ -1713,8 +1853,11 @@ msgstr "Robot tireur à roues" msgid "Wheeled sniffer" msgstr "Robot renifleur à roues" +msgid "Winged builder" +msgstr "" + msgid "Winged grabber" -msgstr "Robot déménageur volant" +msgstr "Robot préhenseur volant" msgid "Winged orga shooter" msgstr "Robot tireur organique volant" @@ -1728,6 +1871,9 @@ msgstr "Robot renifleur volant" msgid "Withdraw shield (\\key action;)" msgstr "Refermer le bouclier (\\key action;)" +msgid "Workshop\\Open the workshop to search for mods" +msgstr "" + msgid "Worm" msgstr "Ver" @@ -1735,7 +1881,7 @@ msgid "Worm fatally wounded" msgstr "Ver mortellement touché" msgid "Wreckage" -msgstr "Epave de robot" +msgstr "Épave de robot" msgid "Write error" msgstr "Erreur lors de l'écriture" @@ -1820,7 +1966,7 @@ msgid "\\New player name" msgstr "\\Nom du joueur à créer" msgid "\\No eyeglasses" -msgstr "\\Pas de lunettes" +msgstr "\\Pas de lunette" msgid "\\Raise the pencil" msgstr "\\Relève le crayon" @@ -1876,15 +2022,15 @@ msgstr "\\Drapeaux violets" msgid "\\Yellow flags" msgstr "\\Drapeaux jaunes" +msgid "by" +msgstr "" + msgid "colobot.info" msgstr "colobot.info" msgid "epsitec.com" msgstr "epsitec.com" -#~ msgid " " -#~ msgstr " " - #~ msgid " Drivers:" #~ msgstr " Pilotes :" @@ -1897,6 +2043,9 @@ msgstr "epsitec.com" #~ msgid "3D sound\\3D positioning of the sound" #~ msgstr "Bruitages 3D\\Positionnement sonore dans l'espace" +#~ msgid "Build a destroyer" +#~ msgstr "Construire un destructeur" + #~ msgid "Building too close" #~ msgstr "Bâtiment trop proche" diff --git a/po/pl.po b/po/pl.po index 073c7b58..90e9f65f 100644 --- a/po/pl.po +++ b/po/pl.po @@ -31,6 +31,9 @@ msgstr "Brak \" ] \"" msgid "%s: %d pts" msgstr "%s: %d pkt" +msgid "+\\Missions with bonus content and optional challenges" +msgstr "+\\Misje z dodatkową zawartością i opcjonalnymi wyzwaniami" + msgid "..behind" msgstr "..za" @@ -109,9 +112,6 @@ msgstr "Analiza została już wykonana" msgid "Analysis performed" msgstr "Analiza wykonana" -msgid "Analyzes only organic matter" -msgstr "Analizuje jedynie materię organiczną" - msgid "Anisotropy level\\Anisotropy level" msgstr "Filtrowanie anizotropowe\\Poziom filtrowania anizotropowego" @@ -127,6 +127,9 @@ msgstr "Wygląd\\Wybierz swoją postać" msgid "Apply changes\\Activates the changed settings" msgstr "Zastosuj zmiany\\Aktywuje zmienione ustawienia" +msgid "Apply\\Apply the current mod configuration" +msgstr "Zastosuj\\Zastosuj obecną konfigurację modów" + msgid "Appropriate constructor missing" msgstr "Brak odpowiedniego konstruktora" @@ -184,6 +187,9 @@ msgstr "Robot zniszczony" msgid "Bot factory" msgstr "Fabryka robotów" +msgid "Build (\\key action;)" +msgstr "Buduj (\\key action;)" + msgid "Build a bot factory" msgstr "Zbuduj fabrykę robotów" @@ -196,12 +202,12 @@ msgstr "Zbuduj wieżę obronną" msgid "Build a derrick" msgstr "Zbuduj kopalnię" -msgid "Build a destroyer" -msgstr "Zbuduj niszczarkę" - msgid "Build a exchange post" msgstr "Zbuduj stację przekaźnikową" +msgid "Build a legged builder" +msgstr "Zbuduj budowniczego na nogach" + msgid "Build a legged grabber" msgstr "Zbuduj transporter na nogach" @@ -247,9 +253,15 @@ msgstr "Zbuduj robota osłaniacza" msgid "Build a subber" msgstr "Zbuduj robota nurka" +msgid "Build a target bot" +msgstr "Zbuduj robota-cel" + msgid "Build a thumper" msgstr "Zbuduj robota uderzacza" +msgid "Build a tracked builder" +msgstr "Zbuduj budowniczego na gąsienicach" + msgid "Build a tracked grabber" msgstr "Zbuduj transporter na gąsienicach" @@ -262,6 +274,12 @@ msgstr "Zbuduj działo na gąsienicach" msgid "Build a tracked sniffer" msgstr "Zbuduj szperacz na gąsienicach" +msgid "Build a vault" +msgstr "Zbuduj skrytkę" + +msgid "Build a wheeled builder" +msgstr "Zbuduj budowniczego na kołach" + msgid "Build a wheeled grabber" msgstr "Zbuduj transporter na kołach" @@ -274,6 +292,9 @@ msgstr "Zbuduj działo na kołach" msgid "Build a wheeled sniffer" msgstr "Zbuduj szperacz na kołach" +msgid "Build a winged builder" +msgstr "Zbuduj latającego budowniczego" + msgid "Build a winged grabber" msgstr "Zbuduj transporter latający" @@ -355,6 +376,9 @@ msgstr "Zmień kamerę\\Przełącza pomiędzy kamerą pokładową i śledzącą" msgid "Change player\\Change player" msgstr "Zmień gracza\\Zmień gracza" +msgid "Changes" +msgstr "Zmiany" + msgid "Chapters:" msgstr "Rozdziały:" @@ -365,7 +389,7 @@ msgid "Checkpoint" msgstr "Punkt kontrolny" msgid "Class name expected" -msgstr "" +msgstr "Oczekiwano nazwy klasy" msgid "Climb\\Increases the power of the jet" msgstr "W górę\\Zwiększa moc silnika" @@ -424,6 +448,12 @@ msgstr "Kopiuj" msgid "Copy (Ctrl+C)" msgstr "Kopiuj (Ctrl+C)" +msgid "Could not open the file explorer!" +msgstr "Nie udało się otworzyć przeglądarki plików!" + +msgid "Could not open the web browser!" +msgstr "Nie udało się otworzyć przeglądarki internetowej!" + msgid "Current mission saved" msgstr "Bieżąca misja zapisana" @@ -457,6 +487,9 @@ msgstr "Kopalnia" msgid "Descend\\Reduces the power of the jet" msgstr "W dół\\Zmniejsza moc silnika" +msgid "Description:" +msgstr "Opis:" + msgid "Destroy" msgstr "Zniszcz" @@ -469,6 +502,9 @@ msgstr "Destroyer" msgid "Device\\Driver and resolution settings" msgstr "Urządzenie\\Ustawienia sterownika i rozdzielczości" +msgid "Disable\\Disable the selected mod" +msgstr "Wyłącz\\Wyłącza zaznaczonego moda" + msgid "Dividing by zero" msgstr "Dzielenie przez zero" @@ -485,9 +521,15 @@ msgstr "Drzwi zablokowane przez robota lub inny obiekt" msgid "Down (\\key gdown;)" msgstr "Dół (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "W dół\\Przenieś zaznaczonego moda w dół, aby był załadowany później (mody mogą nadpisywać pliki modów wyżej)" + msgid "Drawer bot" msgstr "Robot rysownik" +msgid "Duplicate label in switch" +msgstr "Zduplikowana wartość w instrukcji switch" + msgid "Dust\\Dust and dirt on bots and buildings" msgstr "Kurz\\Kurz i bród na robotach i budynkach" @@ -506,6 +548,12 @@ msgstr "Edytuj zaznaczony program" msgid "Egg" msgstr "Jajo" +msgid "Empty character constant" +msgstr "Stała będąca pustym znakiem" + +msgid "Enable\\Enable the selected mod" +msgstr "Włącz\\Włącza zaznaczonego moda" + msgid "End of block missing" msgstr "Brak końca bloku" @@ -628,7 +676,7 @@ msgid "Function name missing" msgstr "Brakująca nazwa funkcji" msgid "Function needs return type \"void\"" -msgstr "" +msgstr "Funkcja potrzebuje typu zwracanego \"void\"" msgid "Game speed" msgstr "Prędkość gry" @@ -679,7 +727,7 @@ msgid "Help balloons\\Explain the function of the buttons" msgstr "Dymki pomocy\\Wyjaśnia funkcje przycisków" msgid "Hex value out of range" -msgstr "" +msgstr "Wartość heksadecymalna poza zakresem" msgid "Higher speed\\Doubles speed" msgstr "Zwiększ prędkość\\Podwaja prędkość" @@ -720,6 +768,9 @@ msgstr "Nieodpowiedni rodzaj ogniw" msgid "Inappropriate object" msgstr "Nieodpowiedni obiekt" +msgid "Inappropriate sample" +msgstr "Nieprawidłowa próbka" + msgid "Incorrect index type" msgstr "Nieprawidłowy typ indeksu" @@ -729,6 +780,9 @@ msgstr "Zainfekowane wirusem, chwilowo niesprawne" msgid "Information exchange post" msgstr "Stacja przekaźnikowa informacji" +msgid "Information:" +msgstr "Informacje:" + msgid "Instruction \"break\" outside a loop" msgstr "Polecenie \"break\" na zewnątrz pętli" @@ -760,7 +814,7 @@ msgid "Internal error - tell the developers" msgstr "Błąd wewnętrzny - powiadom twórców gry" msgid "Invalid universal character name" -msgstr "" +msgstr "Nieprawidłowy znak Unicode" msgid "Invert\\Invert values on this axis" msgstr "Odwróć\\Odwróć wartości na tej osi" @@ -789,6 +843,9 @@ msgstr "Skróty klawiszowe (\\key cbot;)" msgid "LOADING" msgstr "WCZYTYWANIE" +msgid "Legged builder" +msgstr "Budowniczy na nogach" + msgid "Legged grabber" msgstr "Transporter na nogach" @@ -859,10 +916,10 @@ msgid "Mipmap level\\Mipmap level" msgstr "Poziom mipmap\\Poziom mipmap" msgid "Missing end quote" -msgstr "" +msgstr "Brak cudzysłowu zamykającego" msgid "Missing hex digits after escape sequence" -msgstr "" +msgstr "Brak cyfr heksadecymalnych po znaku ucieczki" msgid "Mission name" msgstr "Nazwa misji" @@ -873,9 +930,21 @@ msgstr "Misje" msgid "Missions on this planet:" msgstr "Misje na tej planecie:" +msgid "Missions+" +msgstr "Misje+" + msgid "Missions\\Select mission" msgstr "Misje\\Wybierz misję" +msgid "Mods" +msgstr "Mody" + +msgid "Mods:" +msgstr "Mody:" + +msgid "Mods\\Mod manager" +msgstr "Mody\\Zarządzanie modami" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Odwrócenie myszy X\\Odwrócenie kierunków przewijania w poziomie" @@ -888,6 +957,9 @@ msgstr "Przenieś zaznaczony program w dół" msgid "Move selected program up" msgstr "Przenieś zaznaczony program w górę" +msgid "Mute sounds in background\\Mute all game sounds when the window is unfocused" +msgstr "Cisza, gdy okno jest w tle\\Wycisza wszystkie dźwięki, gdy okno gry stanie się nieaktywne" + msgid "Mute\\No sound" msgstr "Cisza\\Brak dźwięków" @@ -906,6 +978,9 @@ msgstr "Nowy" msgid "New ..." msgstr "Nowy ..." +msgid "New Folder" +msgstr "Nowy folder" + msgid "New bot available" msgstr "Dostępny nowy robot" @@ -918,6 +993,12 @@ msgstr "Następny obiekt\\Zaznacza następny obiekt" msgid "No" msgstr "Nie" +msgid "No changes." +msgstr "Brak zmian." + +msgid "No description." +msgstr "Brak opisu." + msgid "No energy in the subsoil" msgstr "Brak energii w ziemi" @@ -964,7 +1045,7 @@ msgid "No userlevels installed!" msgstr "Brak zainstalowanych poziomów użytkownika!" msgid "Non-void function needs \"return;\"" -msgstr "" +msgstr "Funkcja zwracająca typ inny, niż \"void\", wymaga \"return;\"" msgid "Normal size" msgstr "Normalna wielkość" @@ -1027,7 +1108,7 @@ msgid "Object too close" msgstr "Obiekt za blisko" msgid "Octal value out of range" -msgstr "" +msgstr "Wartość ósemkowa poza zakresem" msgid "One step" msgstr "Jeden krok" @@ -1038,6 +1119,9 @@ msgstr "Otwórz" msgid "Open (Ctrl+O)" msgstr "Otwórz (Ctrl+O)" +msgid "Open Directory\\Open the mods directory" +msgstr "Otwórz katalog\\Otwórz katalog z modami" + msgid "Opening brace missing" msgstr "Brak klamry otwierającej" @@ -1062,6 +1146,9 @@ msgstr "Miejsce nadania wiadomości\\Pokazuje skąd została wysłana ostatnia w msgid "Original game developed by:" msgstr "Twórcy oryginalnej gry:" +msgid "Overwrite existing file?" +msgstr "Nadpisać istniejący plik?" + msgid "Parameters missing" msgstr "Brak wymaganego parametru" @@ -1072,7 +1159,7 @@ msgid "Paste (Ctrl+V)" msgstr "Wklej (Ctrl+V)" msgid "Pause blur\\Blur the background on the pause screen" -msgstr "" +msgstr "Rozmyta pauza\\Rozmyj tło na ekranie pauzy" msgid "Pause in background\\Pause the game when the window is unfocused" msgstr "Wstrzymaj w tle\\Wstrzymaj grę gdy okno stanie się nieaktywne" @@ -1095,6 +1182,9 @@ msgstr "Miejsce zajęte" msgid "Planets:" msgstr "Planety:" +msgid "Plans for builder available" +msgstr "Dostępne plany robota budowniczego" + msgid "Plans for defense tower available" msgstr "Dostępne plany wieży obronnej" @@ -1242,6 +1332,9 @@ msgstr "Czerwona flaga" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Odbicia na przyciskach \\Świecące przyciski" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "Odśwież\\Odśwież listę obecnie zainstalowanych modów" + msgid "Remains of Apollo mission" msgstr "Pozostałości z misji Apollo" @@ -1299,6 +1392,9 @@ msgstr "Robbie" msgid "Ruin" msgstr "Ruiny" +msgid "Run research program for builder" +msgstr "Rozpocznij prace badawcze nad robotem budowniczym" + msgid "Run research program for defense tower" msgstr "Rozpocznij prace badawcze nad wieżą obronną" @@ -1320,6 +1416,9 @@ msgstr "Rozpocznij prace badawcze nad robotem osłaniaczem" msgid "Run research program for shooter" msgstr "Rozpocznij prace badawcze nad działem" +msgid "Run research program for target bot" +msgstr "Rozpocznij prace badawcze nad robotem-celem" + msgid "Run research program for thumper" msgstr "Rozpocznij prace badawcze nad robotem uderzaczem" @@ -1350,6 +1449,9 @@ msgstr "Zapisz\\Zapisuje bieżącą misję" msgid "Save\\Saves the current mission" msgstr "Zapisz\\Zapisuje bieżącą misję" +msgid "Select Folder" +msgstr "Wybierz folder" + msgid "Select the astronaut\\Selects the astronaut" msgstr "Zaznacz astronautę\\Zaznacza astronautę" @@ -1416,6 +1518,15 @@ msgstr "Efekty dźwiękowe:\\Głośność silników, głosów, strzałów, itp." msgid "Sound\\Music and game sound volume" msgstr "Dźwięk\\Głośność muzyki i dźwięków gry" +msgid "Space Explorer\\Disables astronaut abilities" +msgstr "Kosmiczny odkrywca\\Wyłącza umiejętności astronauty" + +msgid "Space Programmer\\Disables radio-control" +msgstr "Kosmiczny koder\\Wyłącza zdalną kontrolę" + +msgid "Space Researcher\\Disables using all previously researched technologies" +msgstr "Kosmiczny badacz\\Blokuje dostęp do poprzednio wynalezionych technologii" + msgid "Spaceship" msgstr "Statek kosmiczny" @@ -1494,6 +1605,10 @@ msgstr "Filtrowanie tekstur\\Filtrowanie tekstur" msgid "Textures" msgstr "Tekstury" +#, c-format +msgid "The address %s could not be opened in a web browser." +msgstr "Nie udało się otworzyć adresu %s w przeglądarce internetowej." + msgid "The battle has ended" msgstr "Bitwa zakończyła się" @@ -1506,9 +1621,16 @@ msgstr "Funkcja nie zwróciła żadnej wartości" msgid "The mission is not accomplished yet (press \\key help; for more details)" msgstr "Misja nie jest wypełniona (naciśnij \\key help; aby uzyskać szczegóły)" +#, c-format +msgid "The path %s could not be opened in a file explorer." +msgstr "Nie udało się otworzyć ścieżki %s w przeglądarce plików." + msgid "The types of the two operands are incompatible" msgstr "Niezgodne typy operatorów" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "Są niezapisane zmiany. Czy chcesz je zapisać przed wyjściem?" + msgid "This class already exists" msgstr "Taka klasa już istnieje" @@ -1534,7 +1656,7 @@ msgid "This object is not a member of a class" msgstr "Ten obiekt nie jest członkiem klasy" msgid "This parameter needs a default value" -msgstr "" +msgstr "Ten parametr wymaga podania domyślnej wartości" msgid "This program is read-only, clone it to edit" msgstr "Ten program jest tylko do odczytu, skopiuj go, aby edytować" @@ -1582,6 +1704,9 @@ msgstr "Za dużo flag w tym kolorze (maksymalnie 5)" msgid "Too many parameters" msgstr "Za dużo parametrów" +msgid "Tracked builder" +msgstr "Budowniczy na gąsienicach" + msgid "Tracked grabber" msgstr "Transporter na gąsienicach" @@ -1630,11 +1755,14 @@ msgstr "Jednostka" msgid "Unknown Object" msgstr "Obiekt nieznany" +msgid "Unknown author" +msgstr "Nieznany autor" + msgid "Unknown command" msgstr "Nieznane polecenie" msgid "Unknown escape sequence" -msgstr "" +msgstr "Nieznany znak ucieczki" msgid "Unknown function" msgstr "Funkcja nieznana" @@ -1642,6 +1770,9 @@ msgstr "Funkcja nieznana" msgid "Up (\\key gup;)" msgstr "Góra (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "W górę\\Przenieś zaznaczonego moda w górę, aby był załadowany wcześniej (mody mogą nadpisywać pliki modów wyżej)" + msgid "Uranium deposit (site for derrick)" msgstr "Złoże uranu (miejsce na kopalnię)" @@ -1663,6 +1794,9 @@ msgstr "Zmienna nie została zainicjalizowana" msgid "Vault" msgstr "Skrytka" +msgid "Version" +msgstr "Wersja" + msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency" msgstr "Synchronizacja pionowa\\Ogranicza ilość klatek na sekundę do wartości odświeżania ekranu" @@ -1681,6 +1815,12 @@ msgstr "Osa śmiertelnie raniona" msgid "Waste" msgstr "Odpady" +msgid "Website" +msgstr "Strona internetowa" + +msgid "Wheeled builder" +msgstr "Budowniczy na kołach" + msgid "Wheeled grabber" msgstr "Transporter na kołach" @@ -1693,6 +1833,9 @@ msgstr "Działo na kołach" msgid "Wheeled sniffer" msgstr "Szperacz na kołach" +msgid "Winged builder" +msgstr "Budowniczy latający" + msgid "Winged grabber" msgstr "Transporter latający" @@ -1708,6 +1851,9 @@ msgstr "Szperacz latający" msgid "Withdraw shield (\\key action;)" msgstr "Wyłącz osłonę (\\key action;)" +msgid "Workshop\\Open the workshop to search for mods" +msgstr "Warsztat\\Otwórz warsztat, aby poszukać modów" + msgid "Worm" msgstr "Robal" @@ -1858,6 +2004,9 @@ msgstr "\\Fioletowe flagi" msgid "\\Yellow flags" msgstr "\\Żółte flagi" +msgid "by" +msgstr "autorstwa" + msgid "colobot.info" msgstr "colobot.info" @@ -1873,6 +2022,9 @@ msgstr "epsitec.com" #~ msgid "3D sound\\3D positioning of the sound" #~ msgstr "Dźwięk 3D\\Przestrzenne pozycjonowanie dźwięków" +#~ msgid "Build a destroyer" +#~ msgstr "Zbuduj niszczarkę" + #~ msgid "Building too close" #~ msgstr "Budynek za blisko" diff --git a/po/pt.po b/po/pt.po index f99a9cbf..8c152823 100644 --- a/po/pt.po +++ b/po/pt.po @@ -29,6 +29,9 @@ msgstr "\" ] \" faltando" msgid "%s: %d pts" msgstr "" +msgid "+\\Missions with bonus content and optional challenges" +msgstr "" + msgid "..behind" msgstr "..atrás" @@ -107,9 +110,6 @@ msgstr "Análise já realizada" msgid "Analysis performed" msgstr "Análise realizada" -msgid "Analyzes only organic matter" -msgstr "Analisa apenas matéria orgânica" - msgid "Anisotropy level\\Anisotropy level" msgstr "Nível de anisotropia\\Nível de anisotropia" @@ -125,6 +125,9 @@ msgstr "Aparência\\Escolha sua aparência" msgid "Apply changes\\Activates the changed settings" msgstr "Aplicar mudanças\\Ativa as configurações alteradas" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Construtor apropriado faltando" @@ -182,6 +185,9 @@ msgstr "Robo destruido" msgid "Bot factory" msgstr "Fábrica de robos" +msgid "Build (\\key action;)" +msgstr "" + msgid "Build a bot factory" msgstr "Construir uma fábrica de robos" @@ -194,12 +200,12 @@ msgstr "Construir uma torre de defesa" msgid "Build a derrick" msgstr "Construir um extrator" -msgid "Build a destroyer" -msgstr "Construir um destruidor" - msgid "Build a exchange post" msgstr "Construir um posto de troca" +msgid "Build a legged builder" +msgstr "" + msgid "Build a legged grabber" msgstr "Construir um agarrador com pernas" @@ -245,9 +251,15 @@ msgstr "Construir um defensor" msgid "Build a subber" msgstr "Construir um mergulhador" +msgid "Build a target bot" +msgstr "" + msgid "Build a thumper" msgstr "Construir um batedor" +msgid "Build a tracked builder" +msgstr "" + msgid "Build a tracked grabber" msgstr "Construir um agarrador com esteiras" @@ -260,6 +272,12 @@ msgstr "Construir um atirador com esteiras" msgid "Build a tracked sniffer" msgstr "Construir um farejador com esteiras" +msgid "Build a vault" +msgstr "" + +msgid "Build a wheeled builder" +msgstr "" + msgid "Build a wheeled grabber" msgstr "Construir um agarrador com rodas" @@ -272,6 +290,9 @@ msgstr "Construir um atirador com rodas" msgid "Build a wheeled sniffer" msgstr "Construir um farejador com rodas" +msgid "Build a winged builder" +msgstr "" + msgid "Build a winged grabber" msgstr "Construir um agarrador alado" @@ -353,6 +374,9 @@ msgstr "Mudar câmera\\Alterna entre câmera incorporada e câmera seguidora" msgid "Change player\\Change player" msgstr "Mudar jogador\\Mudar jogador" +msgid "Changes" +msgstr "" + msgid "Chapters:" msgstr "Capítulos:" @@ -423,6 +447,12 @@ msgstr "Copiar" msgid "Copy (Ctrl+C)" msgstr "Copiar (Ctrl+C)" +msgid "Could not open the file explorer!" +msgstr "" + +msgid "Could not open the web browser!" +msgstr "" + msgid "Current mission saved" msgstr "Missão atual salva" @@ -456,6 +486,9 @@ msgstr "Extrator" msgid "Descend\\Reduces the power of the jet" msgstr "Descer\\Diminui o poder do jato" +msgid "Description:" +msgstr "" + msgid "Destroy" msgstr "Destruir" @@ -468,6 +501,9 @@ msgstr "Destruidor" msgid "Device\\Driver and resolution settings" msgstr "Dispositivo\\Configurações de driver e resolução" +msgid "Disable\\Disable the selected mod" +msgstr "" + msgid "Dividing by zero" msgstr "Dividindo por zero" @@ -484,9 +520,15 @@ msgstr "Portas bloqueadas por um robô ou outro objeto" msgid "Down (\\key gdown;)" msgstr "Baixo (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Robô cartoonista" +msgid "Duplicate label in switch" +msgstr "" + msgid "Dust\\Dust and dirt on bots and buildings" msgstr "Poeira\\Poeira e sujeira nos robôs e prédios" @@ -505,6 +547,12 @@ msgstr "Alterar o programa selecionado" msgid "Egg" msgstr "Ovo" +msgid "Empty character constant" +msgstr "" + +msgid "Enable\\Enable the selected mod" +msgstr "" + msgid "End of block missing" msgstr "Fim do bloco ausente" @@ -720,6 +768,9 @@ msgstr "Tipo de célula inapropriada" msgid "Inappropriate object" msgstr "Objeto inapropiado" +msgid "Inappropriate sample" +msgstr "" + msgid "Incorrect index type" msgstr "Tipo de índice inválido" @@ -729,6 +780,9 @@ msgstr "Infectado por vírus; temporariamento fora de serviço" msgid "Information exchange post" msgstr "Posto de troca de informação" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Intrução \"break\" fora de um laço" @@ -789,6 +843,9 @@ msgstr "Palavra-chave ajuda (\\key cbot;)" msgid "LOADING" msgstr "CARREGANDO" +msgid "Legged builder" +msgstr "" + msgid "Legged grabber" msgstr "Agarrador com pernas" @@ -887,9 +944,21 @@ msgstr "Missões" msgid "Missions on this planet:" msgstr "Lista de missões neste planeta:" +msgid "Missions+" +msgstr "Missões+" + msgid "Missions\\Select mission" msgstr "Missões\\Selecione uma missão" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Inversão de mouse X\\Inverte a direção da rolagem no eixo X" @@ -902,6 +971,9 @@ msgstr "Move o programa selecionado para baixo" msgid "Move selected program up" msgstr "Move o programa selecionado para cima" +msgid "Mute sounds in background\\Mute all game sounds when the window is unfocused" +msgstr "" + msgid "Mute\\No sound" msgstr "Mudo\\Sem som" @@ -920,6 +992,9 @@ msgstr "Novo" msgid "New ..." msgstr "Novo ..." +msgid "New Folder" +msgstr "" + msgid "New bot available" msgstr "Novo robô disponível" @@ -932,6 +1007,12 @@ msgstr "Próximo objeto\\Selecionar o próximo objeto" msgid "No" msgstr "Não" +msgid "No changes." +msgstr "" + +msgid "No description." +msgstr "" + msgid "No energy in the subsoil" msgstr "Nenhuma energia no subsolo" @@ -1052,6 +1133,9 @@ msgstr "Abrir" msgid "Open (Ctrl+O)" msgstr "Abrir (Ctrl+O)" +msgid "Open Directory\\Open the mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Chave de abertura ausente" @@ -1076,6 +1160,9 @@ msgstr "Origem da última mensagem\\Mostra de onde a última mensagem foi enviad msgid "Original game developed by:" msgstr "Jogo original desenvolvido por:" +msgid "Overwrite existing file?" +msgstr "" + msgid "Parameters missing" msgstr "Parâmetros ausentes" @@ -1109,6 +1196,9 @@ msgstr "Local ocupado" msgid "Planets:" msgstr "Planetas:" +msgid "Plans for builder available" +msgstr "" + msgid "Plans for defense tower available" msgstr "Planos para a torre de defesa disponíveis" @@ -1257,6 +1347,9 @@ msgstr "Bandeira vermelha" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Reflexões nos botões\\Botões brilhantes" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Restos da missão Apollo" @@ -1314,6 +1407,9 @@ msgstr "Robbie" msgid "Ruin" msgstr "Ruína" +msgid "Run research program for builder" +msgstr "" + msgid "Run research program for defense tower" msgstr "Executar programa de pesquisa para torre de defesa" @@ -1335,6 +1431,9 @@ msgstr "Executar programa de pesquisa para defensor" msgid "Run research program for shooter" msgstr "Executar programa de pesquisa para atirador" +msgid "Run research program for target bot" +msgstr "" + msgid "Run research program for thumper" msgstr "Executar programa de pesquisa para batedor" @@ -1365,6 +1464,9 @@ msgstr "Salvar\\Salve a missão atual" msgid "Save\\Saves the current mission" msgstr "Salvar\\Salva a missão atual" +msgid "Select Folder" +msgstr "" + msgid "Select the astronaut\\Selects the astronaut" msgstr "Selecione o astronauta\\Seleciona o astronauta" @@ -1431,6 +1533,15 @@ msgstr "Efeitos sonoros:\\Volume dos motores, voz, tiros, etc." msgid "Sound\\Music and game sound volume" msgstr "Som\\Volume do som das músicas e do jogo" +msgid "Space Explorer\\Disables astronaut abilities" +msgstr "" + +msgid "Space Programmer\\Disables radio-control" +msgstr "" + +msgid "Space Researcher\\Disables using all previously researched technologies" +msgstr "" + msgid "Spaceship" msgstr "Nave espacial" @@ -1509,6 +1620,10 @@ msgstr "Filtragem de textura\\Filtragem de textura" msgid "Textures" msgstr "Texturas" +#, c-format +msgid "The address %s could not be opened in a web browser." +msgstr "" + msgid "The battle has ended" msgstr "A batalha acabou" @@ -1521,9 +1636,16 @@ msgstr "A função não retornou nenhum valor" msgid "The mission is not accomplished yet (press \\key help; for more details)" msgstr "A missão não foi completada ainda (pressione \\key help; para mais detalhes)" +#, c-format +msgid "The path %s could not be opened in a file explorer." +msgstr "" + msgid "The types of the two operands are incompatible" msgstr "Os tipos dos dois operandos são incompativeis" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Esta classe já existe" @@ -1597,6 +1719,9 @@ msgstr "Muitas bandeiras dessa cor (máximo 5)" msgid "Too many parameters" msgstr "Muitos parâmetros" +msgid "Tracked builder" +msgstr "" + msgid "Tracked grabber" msgstr "Pegador com esteiras" @@ -1645,6 +1770,9 @@ msgstr "Unidade" msgid "Unknown Object" msgstr "Objeto desconhecido" +msgid "Unknown author" +msgstr "" + msgid "Unknown command" msgstr "Comando desconhecido" @@ -1657,6 +1785,9 @@ msgstr "Função desconhecida" msgid "Up (\\key gup;)" msgstr "Cima (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Depósito de urânio (local para extrator)" @@ -1678,6 +1809,9 @@ msgstr "Variável não inicializada" msgid "Vault" msgstr "Cofre" +msgid "Version" +msgstr "" + msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency" msgstr "" @@ -1696,6 +1830,12 @@ msgstr "Vespa fatalmente ferida" msgid "Waste" msgstr "Desperdício" +msgid "Website" +msgstr "" + +msgid "Wheeled builder" +msgstr "" + msgid "Wheeled grabber" msgstr "Agarrador com rodas" @@ -1708,6 +1848,9 @@ msgstr "Atirador com rodas" msgid "Wheeled sniffer" msgstr "Farejador com rodas" +msgid "Winged builder" +msgstr "" + msgid "Winged grabber" msgstr "Agarrador alado" @@ -1723,6 +1866,9 @@ msgstr "Farejador alado" msgid "Withdraw shield (\\key action;)" msgstr "Retirar escudo (\\key action;)" +msgid "Workshop\\Open the workshop to search for mods" +msgstr "" + msgid "Worm" msgstr "Verme" @@ -1871,6 +2017,9 @@ msgstr "\\Bandeiras violetas" msgid "\\Yellow flags" msgstr "\\Bandeiras amarelas" +msgid "by" +msgstr "" + msgid "colobot.info" msgstr "colobot.info" @@ -1892,6 +2041,9 @@ msgstr "epsitec.com" #~ msgid "3D sound\\3D positioning of the sound" #~ msgstr "Bruitages 3D\\Positionnement sonore dans l'espace" +#~ msgid "Build a destroyer" +#~ msgstr "Construir um destruidor" + #~ msgid "Building too close" #~ msgstr "Bâtiment trop proche" diff --git a/po/ru.po b/po/ru.po index ca44c0c5..09d3d571 100644 --- a/po/ru.po +++ b/po/ru.po @@ -31,6 +31,9 @@ msgstr "Отсутствует \"]\" " msgid "%s: %d pts" msgstr "" +msgid "+\\Missions with bonus content and optional challenges" +msgstr "" + msgid "..behind" msgstr "Сзади" @@ -109,9 +112,6 @@ msgstr "Анализ уже выполнен" msgid "Analysis performed" msgstr "Анализ выполнен" -msgid "Analyzes only organic matter" -msgstr "Анализирую только органические вещества" - msgid "Anisotropy level\\Anisotropy level" msgstr "Уровень анизотр. фильтр.\\Уровень анизотропной фильтрации" @@ -127,6 +127,9 @@ msgstr "Внешность\\Настройка внешности" msgid "Apply changes\\Activates the changed settings" msgstr "Принять\\Принять изменения настроек" +msgid "Apply\\Apply the current mod configuration" +msgstr "" + msgid "Appropriate constructor missing" msgstr "Соответствующий конструктор отсутствует" @@ -185,6 +188,9 @@ msgstr "Бот уничтожен" msgid "Bot factory" msgstr "Завод ботов" +msgid "Build (\\key action;)" +msgstr "" + msgid "Build a bot factory" msgstr "Построить завод ботов" @@ -197,12 +203,12 @@ msgstr "Построить защитную башню" msgid "Build a derrick" msgstr "Построить буровую вышку" -msgid "Build a destroyer" -msgstr "Построить уничтожитель" - msgid "Build a exchange post" msgstr "Построить пост по обмену сообщениями" +msgid "Build a legged builder" +msgstr "" + msgid "Build a legged grabber" msgstr "Собрать шагающего сборщика" @@ -248,9 +254,15 @@ msgstr "Собрать передвижной щит" msgid "Build a subber" msgstr "Собрать саббера" +msgid "Build a target bot" +msgstr "" + msgid "Build a thumper" msgstr "Собрать ударника" +msgid "Build a tracked builder" +msgstr "" + msgid "Build a tracked grabber" msgstr "Собрать гусеничного сборщика" @@ -263,6 +275,12 @@ msgstr "Собрать гусеничного стрелка" msgid "Build a tracked sniffer" msgstr "Собрать гусеничного искателя" +msgid "Build a vault" +msgstr "" + +msgid "Build a wheeled builder" +msgstr "" + msgid "Build a wheeled grabber" msgstr "Собрать колесного сборщика" @@ -275,6 +293,9 @@ msgstr "Собрать колесного стрелка" msgid "Build a wheeled sniffer" msgstr "Собрать колесного искателя" +msgid "Build a winged builder" +msgstr "" + msgid "Build a winged grabber" msgstr "Собрать летающего сборщика" @@ -360,6 +381,9 @@ msgstr "Изменить вид\\Переключение между борто msgid "Change player\\Change player" msgstr "Новый игрок\\Выберите имя для игрока" +msgid "Changes" +msgstr "" + msgid "Chapters:" msgstr "Разделы:" @@ -431,6 +455,12 @@ msgstr "Копировать" msgid "Copy (Ctrl+C)" msgstr "Копировать (Ctrl+C)" +msgid "Could not open the file explorer!" +msgstr "" + +msgid "Could not open the web browser!" +msgstr "" + msgid "Current mission saved" msgstr "Текущая миссия сохранена" @@ -465,6 +495,9 @@ msgstr "Космический корабль" msgid "Descend\\Reduces the power of the jet" msgstr "Снижение и посадка\\Понижение мощности реактивного двигателя" +msgid "Description:" +msgstr "" + msgid "Destroy" msgstr "Уничтожить" @@ -477,6 +510,9 @@ msgstr "Уничтожитель" msgid "Device\\Driver and resolution settings" msgstr "Устройство\\Драйвер и настройки разрешения" +msgid "Disable\\Disable the selected mod" +msgstr "" + msgid "Dividing by zero" msgstr "Деление на ноль (запрещено!)" @@ -493,9 +529,15 @@ msgstr "Двери заблокированы роботом или другим msgid "Down (\\key gdown;)" msgstr "Вниз (\\key gdown;)" +msgid "Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Drawer bot" msgstr "Рисовальщик" +msgid "Duplicate label in switch" +msgstr "" + msgid "Dust\\Dust and dirt on bots and buildings" msgstr "Пыль\\Пыль и грязь на ботах и зданиях" @@ -514,6 +556,12 @@ msgstr "Изменить выбранную программу" msgid "Egg" msgstr "Яйцо" +msgid "Empty character constant" +msgstr "" + +msgid "Enable\\Enable the selected mod" +msgstr "" + msgid "End of block missing" msgstr "Отсутствует конец блока" @@ -729,6 +777,9 @@ msgstr "Батарея не подходит" msgid "Inappropriate object" msgstr "Неподходящий объект" +msgid "Inappropriate sample" +msgstr "" + msgid "Incorrect index type" msgstr "Неверный тип индекса" @@ -738,6 +789,9 @@ msgstr "Заражено вирусом. Временно вышел из стр msgid "Information exchange post" msgstr "Пост обмена информацией" +msgid "Information:" +msgstr "" + msgid "Instruction \"break\" outside a loop" msgstr "Инструкция \"break\" вне цикла" @@ -798,6 +852,9 @@ msgstr "Помощь(\\key cbot;)" msgid "LOADING" msgstr "ЗАГРУЗКА" +msgid "Legged builder" +msgstr "" + msgid "Legged grabber" msgstr "Шагающий сборщик" @@ -896,9 +953,21 @@ msgstr "Миссии" msgid "Missions on this planet:" msgstr "Миссии на этой планете:" +msgid "Missions+" +msgstr "Миссии+" + msgid "Missions\\Select mission" msgstr "Миссии\\Выбор миссии" +msgid "Mods" +msgstr "" + +msgid "Mods:" +msgstr "" + +msgid "Mods\\Mod manager" +msgstr "" + msgid "Mouse inversion X\\Inversion of the scrolling direction on the X axis" msgstr "Инверсия мыши по оси X\\Инверсия прокрутки по оси Х" @@ -913,6 +982,9 @@ msgstr "Изменить выбранную программу" msgid "Move selected program up" msgstr "Изменить выбранную программу" +msgid "Mute sounds in background\\Mute all game sounds when the window is unfocused" +msgstr "" + msgid "Mute\\No sound" msgstr "Без звука\\Без звука" @@ -931,6 +1003,9 @@ msgstr "Новый" msgid "New ..." msgstr "Новый ..." +msgid "New Folder" +msgstr "" + msgid "New bot available" msgstr "Доступен новый бот" @@ -943,6 +1018,12 @@ msgstr "Следующий объект\\Выбор следующего объ msgid "No" msgstr "Нет" +msgid "No changes." +msgstr "" + +msgid "No description." +msgstr "" + msgid "No energy in the subsoil" msgstr "Под землей нет запасов энергии" @@ -1063,6 +1144,9 @@ msgstr "Открыть" msgid "Open (Ctrl+O)" msgstr "Открыть (Ctrl+O)" +msgid "Open Directory\\Open the mods directory" +msgstr "" + msgid "Opening brace missing" msgstr "Открывающая скобка отсутствует" @@ -1087,6 +1171,9 @@ msgstr "Источник сообщения\\Показывает место, о msgid "Original game developed by:" msgstr "Оригинальная игра была разработана:" +msgid "Overwrite existing file?" +msgstr "" + msgid "Parameters missing" msgstr "Отсутствуют параметры" @@ -1120,6 +1207,9 @@ msgstr "Место занято" msgid "Planets:" msgstr "Планеты:" +msgid "Plans for builder available" +msgstr "" + msgid "Plans for defense tower available" msgstr "Доступны схемы защитной башни" @@ -1269,6 +1359,9 @@ msgstr "Красный флаг" msgid "Reflections on the buttons \\Shiny buttons" msgstr "Отражения на кнопках \\Блестящие кнопки" +msgid "Refresh\\Refresh the list of currently installed mods" +msgstr "" + msgid "Remains of Apollo mission" msgstr "Остатки миссии Аполлон" @@ -1328,6 +1421,9 @@ msgstr "Робби" msgid "Ruin" msgstr "Руины" +msgid "Run research program for builder" +msgstr "" + msgid "Run research program for defense tower" msgstr "Начать исследование программы для защитной башни" @@ -1349,6 +1445,9 @@ msgstr "Начать исследование программы для пере msgid "Run research program for shooter" msgstr "Начать исследование программы для стрелка" +msgid "Run research program for target bot" +msgstr "" + msgid "Run research program for thumper" msgstr "Начать исследование программы для ударника" @@ -1379,6 +1478,9 @@ msgstr "Сохранить\\Сохранить текущую миссию" msgid "Save\\Saves the current mission" msgstr "Сохранить\\Сохранить текущую миссию" +msgid "Select Folder" +msgstr "" + msgid "Select the astronaut\\Selects the astronaut" msgstr "Выбор астронавта\\Выбор астронавта" @@ -1446,6 +1548,15 @@ msgstr "Общий звук:\\Гормкость двигателя, голос msgid "Sound\\Music and game sound volume" msgstr "Звук\\Громкость музыки и звуков" +msgid "Space Explorer\\Disables astronaut abilities" +msgstr "" + +msgid "Space Programmer\\Disables radio-control" +msgstr "" + +msgid "Space Researcher\\Disables using all previously researched technologies" +msgstr "" + msgid "Spaceship" msgstr "Космический корабль" @@ -1525,6 +1636,10 @@ msgstr "Фильтрация текстур\\Фильтрация текстур msgid "Textures" msgstr "Текстуры" +#, c-format +msgid "The address %s could not be opened in a web browser." +msgstr "" + msgid "The battle has ended" msgstr "" @@ -1537,9 +1652,16 @@ msgstr "Функция не возвратила значения" msgid "The mission is not accomplished yet (press \\key help; for more details)" msgstr "Миссия еще не выполнена (нажмите \\key help; для более подробной информации)" +#, c-format +msgid "The path %s could not be opened in a file explorer." +msgstr "" + msgid "The types of the two operands are incompatible" msgstr "Типы операндов несовместимы" +msgid "There are unsaved changes. Do you want to save them before leaving?" +msgstr "" + msgid "This class already exists" msgstr "Этот класс уже существует" @@ -1613,6 +1735,9 @@ msgstr "Слишком много флагов этого цвета (макси msgid "Too many parameters" msgstr "Слишком много параметров" +msgid "Tracked builder" +msgstr "" + msgid "Tracked grabber" msgstr "Гусеничный сборщик" @@ -1661,6 +1786,9 @@ msgstr "Юнит" msgid "Unknown Object" msgstr "Неизвестный объект" +msgid "Unknown author" +msgstr "" + msgid "Unknown command" msgstr "Неизвестная команда" @@ -1673,6 +1801,9 @@ msgstr "Неизвестная функция" msgid "Up (\\key gup;)" msgstr "Вверх (\\key gup;)" +msgid "Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)" +msgstr "" + msgid "Uranium deposit (site for derrick)" msgstr "Запасы урана (место для буровой вышки)" @@ -1694,6 +1825,9 @@ msgstr "Переменная не инициализирована" msgid "Vault" msgstr "Хранилище" +msgid "Version" +msgstr "" + msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency" msgstr "" @@ -1712,6 +1846,12 @@ msgstr "Оса смертельно ранена" msgid "Waste" msgstr "Мусор" +msgid "Website" +msgstr "" + +msgid "Wheeled builder" +msgstr "" + msgid "Wheeled grabber" msgstr "Колесный сборщик" @@ -1724,6 +1864,9 @@ msgstr "Колесный стрелок" msgid "Wheeled sniffer" msgstr "Колесный искатель" +msgid "Winged builder" +msgstr "" + msgid "Winged grabber" msgstr "Летающий сборщик" @@ -1739,6 +1882,9 @@ msgstr "Летающий искатель" msgid "Withdraw shield (\\key action;)" msgstr "Снять щит (\\key action;)" +msgid "Workshop\\Open the workshop to search for mods" +msgstr "" + msgid "Worm" msgstr "Червь" @@ -1887,6 +2033,9 @@ msgstr "\\Фиолетовый флаг" msgid "\\Yellow flags" msgstr "\\Желтый флаг" +msgid "by" +msgstr "" + msgid "colobot.info" msgstr "colobot.info" @@ -1908,6 +2057,9 @@ msgstr "epsitec.com" #~ msgid "3D sound\\3D positioning of the sound" #~ msgstr "3D-звук\\Стерео звук" +#~ msgid "Build a destroyer" +#~ msgstr "Построить уничтожитель" + #~ msgid "Building too close" #~ msgstr "Здание слишком близко" diff --git a/src/CBot/CBot.h b/src/CBot/CBot.h index b0720aa3..f64d4ae9 100644 --- a/src/CBot/CBot.h +++ b/src/CBot/CBot.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotCStack.cpp b/src/CBot/CBotCStack.cpp index 0abcb3ae..ba48ebcb 100644 --- a/src/CBot/CBotCStack.cpp +++ b/src/CBot/CBotCStack.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -20,6 +20,7 @@ #include "CBot/CBotCStack.h" +#include "CBot/CBotClass.h" #include "CBot/CBotToken.h" #include "CBot/CBotExternalCall.h" @@ -30,107 +31,100 @@ namespace CBot { -//////////////////////////////////////////////////////////////////////////////// -CBotProgram* CBotCStack::m_prog = nullptr; // init the static variable -CBotError CBotCStack::m_error = CBotNoErr; -int CBotCStack::m_end = 0; -CBotTypResult CBotCStack::m_retTyp = CBotTypResult(0); +struct CBotCStack::Data +{ + //! The program currently being compiled + CBotProgram* prog = nullptr; + //! The current error state of the compile stack + CBotError error = CBotNoErr; + int errEnd = 0; + //! The return type of the function currently being compiled + CBotTypResult retTyp = CBotTypResult(CBotTypVoid); +}; -//////////////////////////////////////////////////////////////////////////////// CBotCStack::CBotCStack(CBotCStack* ppapa) { - m_next = nullptr; m_prev = ppapa; if (ppapa == nullptr) { - m_error = CBotNoErr; - m_start = 0; - m_end = 0; + m_data = new CBotCStack::Data; + m_errStart = 0; m_bBlock = true; } else { - m_start = ppapa->m_start; + m_data = ppapa->m_data; + m_errStart = ppapa->m_errStart; m_bBlock = false; } - - m_listVar = nullptr; - m_var = nullptr; } //////////////////////////////////////////////////////////////////////////////// CBotCStack::~CBotCStack() { - if (m_next != nullptr) delete m_next; - if (m_prev != nullptr) m_prev->m_next = nullptr; // removes chain - - delete m_var; - delete m_listVar; + if (m_prev == nullptr) delete m_data; } //////////////////////////////////////////////////////////////////////////////// CBotCStack* CBotCStack::TokenStack(CBotToken* pToken, bool bBlock) { - if (m_next != nullptr) return m_next; // include on an existing stack + if (m_next) return m_next.get(); // include on an existing stack - CBotCStack* p = new CBotCStack(this); - m_next = p; // channel element - p->m_bBlock = bBlock; + m_next.reset(new CBotCStack(this)); + m_next->m_bBlock = bBlock; - if (pToken != nullptr) p->SetStartError(pToken->GetStart()); + if (pToken != nullptr) m_next->SetStartError(pToken->GetStart()); - return p; + return m_next.get(); +} + +void CBotCStack::DeleteNext() +{ + m_next.reset(); } -//////////////////////////////////////////////////////////////////////////////// CBotInstr* CBotCStack::Return(CBotInstr* inst, CBotCStack* pfils) { if ( pfils == this ) return inst; - if (m_var != nullptr) delete m_var; // value replaced? - m_var = pfils->m_var; // result transmitted - pfils->m_var = nullptr; // not to destroy the variable + m_var = std::move(pfils->m_var); // result transmitted - if (m_error) + if (m_data->error != CBotNoErr) { - m_start = pfils->m_start; // retrieves the position of the error - m_end = pfils->m_end; + m_errStart = pfils->m_errStart; // retrieves the position of the error } - delete pfils; + m_next.reset(); return inst; } //////////////////////////////////////////////////////////////////////////////// CBotFunction* CBotCStack::ReturnFunc(CBotFunction* inst, CBotCStack* pfils) { - if (m_var != nullptr) delete m_var; // value replaced? - m_var = pfils->m_var; // result transmitted - pfils->m_var = nullptr; // not to destroy the variable + m_var = std::move(pfils->m_var); // result transmitted - if (m_error) + if (m_data->error != CBotNoErr) { - m_start = pfils->m_start; // retrieves the position of the error - m_end = pfils->m_end; + m_errStart = pfils->m_errStart; // retrieves the position of the error } - delete pfils; + m_next.reset(); return inst; } //////////////////////////////////////////////////////////////////////////////// CBotError CBotCStack::GetError(int& start, int& end) { - start = m_start; - end = m_end; - return m_error; + start = m_errStart; + end = m_data->errEnd; + return m_data->error; } //////////////////////////////////////////////////////////////////////////////// CBotError CBotCStack::GetError() { - return m_error; + return m_data->error; } //////////////////////////////////////////////////////////////////////////////// @@ -170,18 +164,13 @@ void CBotCStack::SetType(CBotTypResult& type) CBotVar* CBotCStack::FindVar(CBotToken* &pToken) { CBotCStack* p = this; - std::string name = pToken->GetString(); + const auto& name = pToken->GetString(); while (p != nullptr) { - CBotVar* pp = p->m_listVar; - while ( pp != nullptr) + if (p->m_bBlock) for (auto& var : p->m_listVar) { - if (name == pp->GetName()) - { - return pp; - } - pp = pp->m_next; + if (name == var->GetName()) return var.get(); } p = p->m_prev; } @@ -210,39 +199,39 @@ CBotVar* CBotCStack::CopyVar(CBotToken& Token) //////////////////////////////////////////////////////////////////////////////// bool CBotCStack::IsOk() { - return (m_error == 0); + return (m_data->error == CBotNoErr); } //////////////////////////////////////////////////////////////////////////////// void CBotCStack::SetStartError( int pos ) { - if ( m_error != 0) return; // does not change existing error - m_start = pos; + if (m_data->error != CBotNoErr) return; // does not change existing error + m_errStart = pos; } //////////////////////////////////////////////////////////////////////////////// void CBotCStack::SetError(CBotError n, int pos) { - if ( n!= 0 && m_error != 0) return; // does not change existing error - m_error = n; - m_end = pos; + if (n != CBotNoErr && m_data->error != CBotNoErr) return; // does not change existing error + m_data->error = n; + m_data->errEnd = pos; } //////////////////////////////////////////////////////////////////////////////// void CBotCStack::SetError(CBotError n, CBotToken* p) { - if (m_error) return; // does not change existing error - m_error = n; - m_start = p->GetStart(); - m_end = p->GetEnd(); + if (m_data->error != CBotNoErr) return; // does not change existing error + m_data->error = n; + m_errStart = p->GetStart(); + m_data->errEnd = p->GetEnd(); } //////////////////////////////////////////////////////////////////////////////// void CBotCStack::ResetError(CBotError n, int start, int end) { - m_error = n; - m_start = start; - m_end = end; + m_data->error = n; + m_errStart = start; + m_data->errEnd = end; } //////////////////////////////////////////////////////////////////////////////// @@ -260,48 +249,47 @@ bool CBotCStack::NextToken(CBotToken* &p) //////////////////////////////////////////////////////////////////////////////// void CBotCStack::SetProgram(CBotProgram* p) { - m_prog = p; + m_data->prog = p; } //////////////////////////////////////////////////////////////////////////////// CBotProgram* CBotCStack::GetProgram() { - return m_prog; + return m_data->prog; } //////////////////////////////////////////////////////////////////////////////// void CBotCStack::SetRetType(CBotTypResult& type) { - m_retTyp = type; + m_data->retTyp = type; } //////////////////////////////////////////////////////////////////////////////// CBotTypResult CBotCStack::GetRetType() { - return m_retTyp; + return m_data->retTyp; } //////////////////////////////////////////////////////////////////////////////// void CBotCStack::SetVar( CBotVar* var ) { - if (m_var) delete m_var; // replacement of a variable - m_var = var; + m_var.reset(var); } //////////////////////////////////////////////////////////////////////////////// void CBotCStack::SetCopyVar( CBotVar* var ) { - if (m_var) delete m_var; // replacement of a variable + m_var.reset(); if ( var == nullptr ) return; - m_var = CBotVar::Create("", var->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC)); + m_var.reset(CBotVar::Create("", var->GetTypResult(CBotVar::GetTypeMode::CLASS_AS_INTRINSIC))); m_var->Copy( var ); } //////////////////////////////////////////////////////////////////////////////// CBotVar* CBotCStack::GetVar() { - return m_var; + return m_var.get(); } //////////////////////////////////////////////////////////////////////////////// @@ -309,34 +297,70 @@ void CBotCStack::AddVar(CBotVar* pVar) { CBotCStack* p = this; - // returns to the father element + // find the level of the current block while (p != nullptr && p->m_bBlock == 0) p = p->m_prev; - if ( p == nullptr ) return; + if (p == nullptr || pVar == nullptr) return; - CBotVar** pp = &p->m_listVar; - while ( *pp != nullptr ) pp = &(*pp)->m_next; + p->m_listVar.emplace_back(pVar); +} - *pp = pVar; // added after +//////////////////////////////////////////////////////////////////////////////// +void CBotCStack::CreateVarThis(CBotClass* pClass) +{ + if ( pClass == nullptr ) return; + + CBotVar* pThis = CBotVar::Create("this", CBotTypResult(CBotTypClass, pClass)); + + pThis->SetUniqNum(-2); // special ID for "this" + AddVar(pThis); +} + +//////////////////////////////////////////////////////////////////////////////// +void CBotCStack::CreateVarSuper(CBotClass* pClass) +{ + if ( pClass == nullptr ) return; + + CBotVar* pSuper = CBotVar::Create("super", CBotTypResult(CBotTypClass, pClass)); + + pSuper->SetUniqNum(-3); // special ID for "super" + AddVar(pSuper); +} + +//////////////////////////////////////////////////////////////////////////////// +void CBotCStack::CreateMemberVars(CBotClass* pClass, bool setDefined) +{ + while (pClass != nullptr) + { + CBotVar* pv = pClass->GetVar(); + while (pv != nullptr) + { + CBotVar* pcopy = CBotVar::Create(pv); + CBotVar::InitType initType = CBotVar::InitType::UNDEF; + if (setDefined || pv->IsStatic()) + initType = CBotVar::InitType::DEF; + pcopy->SetInit(initType); + pcopy->SetUniqNum(pv->GetUniqNum()); + pcopy->SetPrivate(pv->GetPrivate()); + AddVar(pcopy); + pv = pv->GetNext(); + } + pClass = pClass->GetParent(); + } } //////////////////////////////////////////////////////////////////////////////// bool CBotCStack::CheckVarLocal(CBotToken* &pToken) { CBotCStack* p = this; - std::string name = pToken->GetString(); + const auto& name = pToken->GetString(); - while (p != nullptr) + // find the level of the current block + while (p != nullptr && p->m_bBlock == 0) p = p->m_prev; + + if (p != nullptr) for (auto& var : p->m_listVar) { - CBotVar* pp = p->m_listVar; - while ( pp != nullptr) - { - if (name == pp->GetName()) - return true; - pp = pp->m_next; - } - if ( p->m_bBlock ) return false; - p = p->m_prev; + if (name == var->GetName()) return true; } return false; } @@ -347,10 +371,10 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId nIdent = 0; CBotTypResult val(-1); - val = m_prog->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this); + val = GetProgram()->GetExternalCalls()->CompileCall(p, nullptr, ppVars, this); if (val.GetType() < 0) { - val = CBotFunction::CompileCall(m_prog->GetFunctions(), p->GetString(), ppVars, nIdent); + val = CBotFunction::CompileCall(p->GetString(), ppVars, nIdent, GetProgram()); if ( val.GetType() < 0 ) { // pVar = nullptr; // the error is not on a particular parameter @@ -363,16 +387,19 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId } //////////////////////////////////////////////////////////////////////////////// -bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam) +bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::string& className) { - std::string name = pToken->GetString(); + const auto& name = pToken->GetString(); - if ( m_prog->GetExternalCalls()->CheckCall(name) ) return true; + if ( GetProgram()->GetExternalCalls()->CheckCall(name) ) return true; - for (CBotFunction* pp : m_prog->GetFunctions()) + for (CBotFunction* pp : GetProgram()->GetFunctions()) { - if ( pToken->GetString() == pp->GetName() ) + if ( name == pp->GetName() ) { + // ignore methods for a different class + if ( className != pp->GetClassName() ) + continue; // are parameters exactly the same? if ( pp->CheckParam( pParam ) ) return true; @@ -381,8 +408,11 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam) for (CBotFunction* pp : CBotFunction::m_publicFunctions) { - if ( pToken->GetString() == pp->GetName() ) + if ( name == pp->GetName() ) { + // ignore methods for a different class + if ( className != pp->GetClassName() ) + continue; // are parameters exactly the same? if ( pp->CheckParam( pParam ) ) return true; @@ -392,4 +422,4 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam) return false; } -} +} // namespace CBot diff --git a/src/CBot/CBotCStack.h b/src/CBot/CBotCStack.h index 40ad9424..adcbee59 100644 --- a/src/CBot/CBotCStack.h +++ b/src/CBot/CBotCStack.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -22,6 +22,9 @@ #include "CBot/CBotVar/CBotVar.h" #include "CBot/CBotProgram.h" +#include +#include + namespace CBot { @@ -100,6 +103,25 @@ public: */ void AddVar(CBotVar* p); + /*! + * \brief Create 'this' as a local variable. + * \param pClass The current class referred to by 'this' + */ + void CreateVarThis(CBotClass* pClass); + + /*! + * \brief Create 'super' as a local variable. + * \param pClass The parent class referred to by 'super' + */ + void CreateVarSuper(CBotClass* pClass); + + /*! + * \brief Create member variables of the current class as local variables. + * \param pClass The current class. + * \param setDefined Whether to mark the variables as initialized. + */ + void CreateMemberVars(CBotClass* pClass, bool setDefined); + /*! * \brief FindVar Finds a variable. Seeks a variable on the stack the token * may be a result of TokenTypVar (object of a class) or a pointer in the @@ -138,6 +160,11 @@ public: */ CBotCStack* TokenStack(CBotToken* pToken = nullptr, bool bBlock = false); + /*! + * \brief Deletes all subsequent stack frames created by TokenStack. + */ + void DeleteNext(); + /*! * \brief Return Transmits the result upper. * \param p @@ -235,11 +262,12 @@ public: /*! * \brief CheckCall Test if a procedure name is already defined somewhere. - * \param pToken - * \param pParam + * \param pToken Token representing the name of a function. + * \param pParam List of parameters. + * \param className Name of a class when checking for methods. * \return */ - bool CheckCall(CBotToken* &pToken, CBotDefParam* pParam); + bool CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::string& className); /*! * \brief NextToken @@ -249,21 +277,20 @@ public: bool NextToken(CBotToken* &p); private: - CBotCStack* m_next; + std::unique_ptr m_next; CBotCStack* m_prev; - static CBotError m_error; - static int m_end; - int m_start; + int m_errStart = 0; + + struct Data; + + CBotCStack::Data* m_data; //! Result of the operations. - CBotVar* m_var; + std::unique_ptr m_var; //! Is part of a block (variables are local to this block). bool m_bBlock; - CBotVar* m_listVar; - //! List of compiled functions. - static CBotProgram* m_prog; - static CBotTypResult m_retTyp; + std::list> m_listVar; }; } // namespace CBot diff --git a/src/CBot/CBotClass.cpp b/src/CBot/CBotClass.cpp index f1a658ad..a7993a9a 100644 --- a/src/CBot/CBotClass.cpp +++ b/src/CBot/CBotClass.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -36,7 +36,6 @@ #include "CBot/CBotCStack.h" #include "CBot/CBotDefParam.h" #include "CBot/CBotUtils.h" -#include "CBot/CBotFileUtils.h" #include @@ -316,7 +315,7 @@ CBotTypResult CBotClass::CompileMethode(CBotToken* name, // find the methods declared by user - r = CBotFunction::CompileCall(m_pMethod, name->GetString(), ppParams, nIdent); + r = CBotFunction::CompileMethodCall(name->GetString(), ppParams, nIdent, pStack, this); if ( r.Eq(CBotErrUndefCall) && m_parent != nullptr ) return m_parent->CompileMethode(name, pThis, ppParams, pStack, nIdent); return r; @@ -333,7 +332,7 @@ bool CBotClass::ExecuteMethode(long& nIdent, int ret = m_externalMethods->DoCall(pToken, pThis, ppParams, pStack, pResultType); if (ret >= 0) return ret; - ret = CBotFunction::DoCall(m_pMethod, nIdent, pToken->GetString(), pThis, ppParams, pStack, pToken, this); + ret = CBotFunction::DoCall(nIdent, pToken->GetString(), pThis, ppParams, pStack, pToken, this); if (ret >= 0) return ret; if (m_parent != nullptr) @@ -356,7 +355,7 @@ void CBotClass::RestoreMethode(long& nIdent, CBotClass* pClass = this; while (pClass != nullptr) { - bool ok = CBotFunction::RestoreCall(pClass->m_pMethod, nIdent, name->GetString(), pThis, ppParams, pStack, pClass); + bool ok = CBotFunction::RestoreCall(nIdent, name->GetString(), pThis, ppParams, pStack, pClass); if (ok) return; pClass = pClass->m_parent; } @@ -364,69 +363,70 @@ void CBotClass::RestoreMethode(long& nIdent, } //////////////////////////////////////////////////////////////////////////////// -bool CBotClass::SaveStaticState(FILE* pf) +bool CBotClass::SaveStaticState(std::ostream &ostr) { - if (!WriteWord( pf, CBOTVERSION*2)) return false; + if (!WriteLong(ostr, CBOTVERSION*2)) return false; // saves the state of static variables in classes for (CBotClass* p : m_publicClasses) { - if (!WriteWord( pf, 1 )) return false; + if (!WriteWord(ostr, 1)) return false; // save the name of the class - if (!WriteString( pf, p->GetName() )) return false; + if (!WriteString(ostr, p->GetName())) return false; CBotVar* pv = p->GetVar(); while( pv != nullptr ) { if ( pv->IsStatic() ) { - if (!WriteWord( pf, 1 )) return false; - if (!WriteString( pf, pv->GetName() )) return false; + if (!WriteWord(ostr, 1)) return false; + if (!WriteString(ostr, pv->GetName())) return false; - if ( !pv->Save0State(pf) ) return false; // common header - if ( !pv->Save1State(pf) ) return false; // saves as the child class - if ( !WriteWord( pf, 0 ) ) return false; + if (!pv->Save0State(ostr)) return false; // common header + if (!pv->Save1State(ostr)) return false; // saves as the child class + if (!WriteWord(ostr, 0)) return false; } pv = pv->GetNext(); } - if (!WriteWord( pf, 0 )) return false; + if (!WriteWord(ostr, 0)) return false; } - if (!WriteWord( pf, 0 )) return false; + if (!WriteWord(ostr, 0)) return false; return true; } //////////////////////////////////////////////////////////////////////////////// -bool CBotClass::RestoreStaticState(FILE* pf) +bool CBotClass::RestoreStaticState(std::istream &istr) { std::string ClassName, VarName; CBotClass* pClass; unsigned short w; - if (!ReadWord( pf, w )) return false; - if ( w != CBOTVERSION*2 ) return false; + long version; + if (!ReadLong(istr, version)) return false; + if (version != CBOTVERSION*2) return false; while (true) { - if (!ReadWord( pf, w )) return false; + if (!ReadWord(istr, w)) return false; if ( w == 0 ) return true; - if (!ReadString( pf, ClassName )) return false; + if (!ReadString(istr, ClassName)) return false; pClass = Find(ClassName); while (true) { - if (!ReadWord( pf, w )) return false; + if (!ReadWord(istr, w)) return false; if ( w == 0 ) break; CBotVar* pVar = nullptr; CBotVar* pv = nullptr; - if (!ReadString( pf, VarName )) return false; + if (!ReadString(istr, VarName)) return false; if ( pClass != nullptr ) pVar = pClass->GetItem(VarName); - if (!CBotVar::RestoreState(pf, pv)) return false; // the temp variable + if (!CBotVar::RestoreState(istr, pv)) return false; // the temp variable if ( pVar != nullptr ) pVar->Copy(pv); delete pv; @@ -542,6 +542,11 @@ void CBotClass::DefineClasses(std::list pClassList, CBotCStack* pSta } } +const std::list& CBotClass::GetFunctions() const +{ + return m_pMethod; +} + //////////////////////////////////////////////////////////////////////////////// bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond) { @@ -600,8 +605,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond) // return a method precompiled in pass 1 CBotCStack* pStk = pStack->TokenStack(nullptr, true); CBotDefParam* params = CBotDefParam::Compile(p, pStk ); - delete pStk; - std::list::iterator pfIter = std::find_if(m_pMethod.begin(), m_pMethod.end(), [&pp, ¶ms](CBotFunction* x) + pStack->DeleteNext(); + auto pfIter = std::find_if(m_pMethod.begin(), m_pMethod.end(), [&pp, ¶ms](CBotFunction* x) { return x->GetName() == pp && x->CheckParam( params ); }); @@ -609,45 +614,8 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond) CBotFunction* pf = *pfIter; delete params; - bool bConstructor = (pp == GetName()); CBotCStack* pile = pStack->TokenStack(nullptr, true); - // make "this" known - CBotToken TokenThis(std::string("this"), std::string()); - CBotVar* pThis = CBotVar::Create(TokenThis, CBotTypResult( CBotTypClass, this ) ); - pThis->SetUniqNum(-2); - pile->AddVar(pThis); - - if (m_parent) - { - // makes "super" known - CBotToken TokenSuper(std::string("super"), std::string()); - CBotVar* pThis = CBotVar::Create(TokenSuper, CBotTypResult(CBotTypClass, m_parent) ); - pThis->SetUniqNum(-3); - pile->AddVar(pThis); - } - -// int num = 1; - CBotClass* my = this; - while (my != nullptr) - { - // places a copy of variables of a class (this) on a stack - CBotVar* pv = my->m_pVar; - while (pv != nullptr) - { - CBotVar* pcopy = CBotVar::Create(pv); - CBotVar::InitType initType = CBotVar::InitType::UNDEF; - if (!bConstructor || pv->IsStatic()) - initType = CBotVar::InitType::DEF; - pcopy->SetInit(initType); - pcopy->SetUniqNum(pv->GetUniqNum()); - pcopy->SetPrivate(pv->GetPrivate()); - pile->AddVar(pcopy); - pv = pv->GetNext(); - } - my = my->m_parent; - } - // compiles a method p = pBase; CBotFunction* f = @@ -658,7 +626,7 @@ bool CBotClass::CompileDefItem(CBotToken* &p, CBotCStack* pStack, bool bSecond) f->m_pProg = pStack->GetProgram(); f->m_bSynchro = bSynchro; } - pStack->Return(nullptr, pile); + pStack->DeleteNext(); } return pStack->IsOk(); diff --git a/src/CBot/CBotClass.h b/src/CBot/CBotClass.h index 0f9a8ce4..507a3daf 100644 --- a/src/CBot/CBotClass.h +++ b/src/CBot/CBotClass.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -303,6 +303,12 @@ public: */ static void DefineClasses(std::list pClassList, CBotCStack* pStack); + /*! + * \brief Get the list of user-defined methods in this class. + * \return List of methods, can be empty. + */ + const std::list& GetFunctions() const; + /*! * \brief CompileDefItem * \param p @@ -331,18 +337,18 @@ public: static void ClearPublic(); /*! - * \brief SaveStaticState - * \param pf - * \return + * \brief Save all static variables from each public class + * \param ostr Output stream + * \return true on success */ - static bool SaveStaticState(FILE* pf); + static bool SaveStaticState(std::ostream &ostr); /*! - * \brief RestoreStaticState - * \param pf - * \return + * \brief Restore all static variables in each public class + * \param istr Input stream + * \return true on success */ - static bool RestoreStaticState(FILE* pf); + static bool RestoreStaticState(std::istream &istr); /** * \brief Request a lock on this class (for "synchronized" keyword) diff --git a/src/CBot/CBotDebug.cpp b/src/CBot/CBotDebug.cpp index bef509b0..1e8463dd 100644 --- a/src/CBot/CBotDebug.cpp +++ b/src/CBot/CBotDebug.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotDebug.h b/src/CBot/CBotDebug.h index 9194bc44..b5cd1065 100644 --- a/src/CBot/CBotDebug.h +++ b/src/CBot/CBotDebug.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotDefParam.cpp b/src/CBot/CBotDefParam.cpp index af4fb6ec..d25f9bda 100644 --- a/src/CBot/CBotDefParam.cpp +++ b/src/CBot/CBotDefParam.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -64,10 +64,8 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack) if (list == nullptr) list = param; else list->AddNext(param); // added to the list -// CBotClass* pClass = nullptr;//= CBotClass::Find(p); param->m_typename = p->GetString(); CBotTypResult type = param->m_type = TypeParam(p, pStack); -// if ( type == CBotTypPointer ) type = CBotTypClass; // we must create a new object if (param->m_type.GetType() > 0) { @@ -96,7 +94,7 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack) prevHasDefault = true; } else pStack->SetError(CBotErrNoExpression, p); - delete pStk; + pStack->DeleteNext(); } else if (prevHasDefault) pStack->SetError(CBotErrDefaultValue, p->GetPrev()); @@ -105,7 +103,6 @@ CBotDefParam* CBotDefParam::Compile(CBotToken* &p, CBotCStack* pStack) if ( type.Eq(CBotTypArrayPointer) ) type.SetType(CBotTypArrayBody); CBotVar* var = CBotVar::Create(pp->GetString(), type); // creates the variable -// if ( pClass ) var->SetClass(pClass); var->SetInit(CBotVar::InitType::IS_POINTER); // mark initialized param->m_nIdent = CBotVar::NextUniqNum(); var->SetUniqNum(param->m_nIdent); @@ -140,6 +137,7 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj) while ( p != nullptr ) { pile = pile->AddStack(); + if (pile->StackOver()) return pj->Return(pile); if (pile->GetState() == 1) // already done? { if (ppVars != nullptr && ppVars[i] != nullptr) ++i; @@ -151,13 +149,12 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj) if (useDefault || (ppVars == nullptr || ppVars[i] == nullptr)) { - assert(p->m_expr != nullptr); - - useDefault = true; - - if (!p->m_expr->Execute(pile)) return false; // interupt here - - pVar = pile->GetVar(); + useDefault = true; // end of arguments found + if (p->m_expr != nullptr) // has default expression ? + { + if (!p->m_expr->Execute(pile)) return false; // interupt here + pVar = pile->GetVar(); + } } else pVar = ppVars[i]; @@ -173,14 +170,34 @@ bool CBotDefParam::Execute(CBotVar** ppVars, CBotStack* &pj) { switch (p->m_type.GetType()) { + case CBotTypByte: + newvar->SetValByte(pVar->GetValByte()); + newvar->SetInit(pVar->GetInit()); // copy nan + break; + case CBotTypShort: + newvar->SetValShort(pVar->GetValShort()); + newvar->SetInit(pVar->GetInit()); // copy nan + break; + case CBotTypChar: + newvar->SetValChar(pVar->GetValChar()); + newvar->SetInit(pVar->GetInit()); // copy nan + break; case CBotTypInt: newvar->SetValInt(pVar->GetValInt()); newvar->SetInit(pVar->GetInit()); // copy nan break; + case CBotTypLong: + newvar->SetValLong(pVar->GetValLong()); + newvar->SetInit(pVar->GetInit()); // copy nan + break; case CBotTypFloat: newvar->SetValFloat(pVar->GetValFloat()); newvar->SetInit(pVar->GetInit()); // copy nan break; + case CBotTypDouble: + newvar->SetValDouble(pVar->GetValDouble()); + newvar->SetInit(pVar->GetInit()); // copy nan + break; case CBotTypString: newvar->SetValString(pVar->GetValString()); break; diff --git a/src/CBot/CBotDefParam.h b/src/CBot/CBotDefParam.h index 88a4cc20..9327c4ab 100644 --- a/src/CBot/CBotDefParam.h +++ b/src/CBot/CBotDefParam.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotDefines.h b/src/CBot/CBotDefines.h index 0d51d5d3..88d162e6 100644 --- a/src/CBot/CBotDefines.h +++ b/src/CBot/CBotDefines.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotEnums.h b/src/CBot/CBotEnums.h index 0b33bfdc..963ca261 100644 --- a/src/CBot/CBotEnums.h +++ b/src/CBot/CBotEnums.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -35,13 +35,13 @@ namespace CBot enum CBotType { CBotTypVoid = 0, //!< void - CBotTypByte = 1, //!< byte (NOT IMPLEMENTED) - CBotTypShort = 2, //!< short (NOT IMPLEMENTED) - CBotTypChar = 3, //!< char (NOT IMPLEMENTED) + CBotTypByte = 1, //!< byte + CBotTypShort = 2, //!< short + CBotTypChar = 3, //!< char CBotTypInt = 4, //!< int - CBotTypLong = 5, //!< long (NOT IMPLEMENTED) + CBotTypLong = 5, //!< long CBotTypFloat = 6, //!< float - CBotTypDouble = 7, //!< double (NOT IMPLEMENTED) + CBotTypDouble = 7, //!< double CBotTypBoolean = 8, //!< bool CBotTypString = 9, //!< string @@ -100,12 +100,18 @@ enum TokenId ID_STATIC, ID_PROTECTED, ID_PRIVATE, + ID_REPEAT, ID_INT, ID_FLOAT, ID_BOOLEAN, ID_STRING, ID_VOID, ID_BOOL, + ID_BYTE, + ID_SHORT, + ID_CHAR, + ID_LONG, + ID_DOUBLE, TokenKeyVal = 2200, //!< keywords that represent values (true, false, null, nan) ID_TRUE = 2200, @@ -177,7 +183,8 @@ enum TokenType TokenTypNum = 2, //!< number TokenTypString = 3, //!< string TokenTypVar = 4, //!< a variable name - TokenTypDef = 5 //!< value according DefineNum + TokenTypDef = 5, //!< value according DefineNum + TokenTypChar = 6, //!< character literal }; /** @@ -247,6 +254,8 @@ enum CBotError : int CBotErrHexDigits = 5052, //!< missing hex digits after escape sequence CBotErrHexRange = 5053, //!< hex value out of range CBotErrUnicodeName = 5054, //!< invalid universal character name + CBotErrCharEmpty = 5055, //!< empty character constant + CBotErrRedefCase = 5056, //!< duplicate label in switch // Runtime errors CBotErrZeroDiv = 6000, //!< division by zero diff --git a/src/CBot/CBotExternalCall.cpp b/src/CBot/CBotExternalCall.cpp index 4d840b8f..5b1b4c73 100644 --- a/src/CBot/CBotExternalCall.cpp +++ b/src/CBot/CBotExternalCall.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -82,19 +82,23 @@ int CBotExternalCallList::DoCall(CBotToken* token, CBotVar* thisVar, CBotVar** p CBotExternalCall* pt = m_list[token->GetString()].get(); - if (pStack->IsCallFinished()) return true; - CBotStack* pile = pStack->AddStackExternalCall(pt); + if (thisVar == nullptr && pStack->IsCallFinished()) return true; // only for non-method external call - // lists the parameters depending on the contents of the stack (pStackVar) - CBotVar* pVar = MakeListVars(ppVar, true); + // if this is a method call we need to use AddStack() + CBotStack* pile = (thisVar != nullptr) ? pStack->AddStack() : pStack->AddStackExternalCall(pt); - // creates a variable to the result - CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype); + if (pile->GetState() == 0) // the first time? + { + // lists the parameters depending on the contents of the stack + CBotVar* pVar = MakeListVars(ppVar, true); + pile->SetVar(pVar); - pile->SetVar(pVar); - - CBotStack* pile2 = pile->AddStack(); - pile2->SetVar(pResult); + CBotStack* pile2 = pile->AddStack(); + // creates a variable to the result + CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype); + pile2->SetVar(pResult); + pile->IncState(); // increment state to mark this step done + } pile->SetError(CBotNoErr, token); // save token for the position in case of error return pt->Run(thisVar, pStack); @@ -107,7 +111,8 @@ bool CBotExternalCallList::RestoreCall(CBotToken* token, CBotVar* thisVar, CBotV CBotExternalCall* pt = m_list[token->GetString()].get(); - CBotStack* pile = pStack->RestoreStackEOX(pt); + // if this is a method call we need to use RestoreStack() + CBotStack* pile = (thisVar != nullptr) ? pStack->RestoreStack() : pStack->RestoreStackEOX(pt); if (pile == nullptr) return true; pile->RestoreStack(); @@ -163,8 +168,7 @@ bool CBotExternalCallDefault::Run(CBotVar* thisVar, CBotStack* pStack) return false; } - if (result != nullptr) pStack->SetCopyVar(result); - + pStack->Return(pile2); // return 'result' and clear extra stack return true; } @@ -187,8 +191,8 @@ CBotTypResult CBotExternalCallClass::Compile(CBotVar* thisVar, CBotVar* args, vo bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack) { - if (pStack->IsCallFinished()) return true; - CBotStack* pile = pStack->AddStackExternalCall(this); + assert(thisVar != nullptr); + CBotStack* pile = pStack->AddStack(); CBotVar* args = pile->GetVar(); CBotStack* pile2 = pile->AddStack(); @@ -207,9 +211,8 @@ bool CBotExternalCallClass::Run(CBotVar* thisVar, CBotStack* pStack) return false; } - if (result != nullptr) pStack->SetCopyVar(result); - + pStack->Return(pile2); // return 'result' and clear extra stack return true; } -} +} // namespace CBot diff --git a/src/CBot/CBotExternalCall.h b/src/CBot/CBotExternalCall.h index 1c3424ec..26cf5ca1 100644 --- a/src/CBot/CBotExternalCall.h +++ b/src/CBot/CBotExternalCall.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotFileUtils.cpp b/src/CBot/CBotFileUtils.cpp index c473493a..7a614558 100644 --- a/src/CBot/CBotFileUtils.cpp +++ b/src/CBot/CBotFileUtils.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,129 +21,285 @@ #include "CBot/CBotClass.h" #include "CBot/CBotEnums.h" -#include "CBot/CBotUtils.h" namespace CBot { - -// file management - -// necessary because it is not possible to do the fopen in the main program -// fwrite and fread in a dll or using the FILE * returned. - -//////////////////////////////////////////////////////////////////////////////// -FILE* fOpen(const char* name, const char* mode) +template +static bool WriteBinary(std::ostream &ostr, T value, unsigned padTo = 0) { - return fopen(name, mode); -} - -//////////////////////////////////////////////////////////////////////////////// -int fClose(FILE* filehandle) -{ - return fclose(filehandle); -} - -//////////////////////////////////////////////////////////////////////////////// -std::size_t fWrite(const void *buffer, - std::size_t elemsize, - std::size_t length, - FILE* filehandle) -{ - return fwrite(buffer, elemsize, length, filehandle); -} - -//////////////////////////////////////////////////////////////////////////////// -std::size_t fRead(void *buffer, - std::size_t elemsize, - std::size_t length, - FILE* filehandle) -{ - return fread(buffer, elemsize, length, filehandle); -} - - -//////////////////////////////////////////////////////////////////////////////// -bool ReadWord(FILE* pf, unsigned short& w) -{ - size_t lg; - - lg = fread(&w, sizeof( unsigned short ), 1, pf ); - - return (lg == 1); -} - -//////////////////////////////////////////////////////////////////////////////// -bool ReadFloat(FILE* pf, float& w) -{ - size_t lg; - - lg = fread(&w, sizeof( float ), 1, pf ); - - return (lg == 1); -} - -//////////////////////////////////////////////////////////////////////////////// -bool WriteLong(FILE* pf, long w) -{ - size_t lg; - - lg = fwrite(&w, sizeof( long ), 1, pf ); - - return (lg == 1); -} - -//////////////////////////////////////////////////////////////////////////////// -bool ReadLong(FILE* pf, long& w) -{ - size_t lg; - - lg = fread(&w, sizeof( long ), 1, pf ); - - return (lg == 1); -} - -//////////////////////////////////////////////////////////////////////////////// -bool ReadString(FILE* pf, std::string& s) -{ - unsigned short w; - char buf[1000]; - size_t lg1, lg2; - - if (!ReadWord(pf, w)) return false; - lg1 = w; - lg2 = fread(buf, 1, lg1, pf ); - buf[lg2] = 0; - - s = buf; - return (lg1 == lg2); -} - -//////////////////////////////////////////////////////////////////////////////// -bool WriteType(FILE* pf, const CBotTypResult &type) -{ - int typ = type.GetType(); - if ( typ == CBotTypIntrinsic ) typ = CBotTypClass; - if ( !WriteWord(pf, typ) ) return false; - if ( typ == CBotTypClass ) + unsigned char chr; + unsigned count = 1; + while (value > 127) // unsigned LEB128 { - CBotClass* p = type.GetClass(); - if ( !WriteString(pf, p->GetName()) ) return false; + ++count; + chr = (value & 0x7F) | 0x80; + if (!ostr.write(reinterpret_cast(&chr), 1)) return false; + value >>= 7; } - if ( type.Eq( CBotTypArrayBody ) || - type.Eq( CBotTypArrayPointer ) ) + chr = value & 0x7F; + if (count < padTo) chr |= 0x80; + if (!ostr.write(reinterpret_cast(&chr), 1)) return false; + + if (count < padTo) { - if ( !WriteWord(pf, type.GetLimite()) ) return false; - if ( !WriteType(pf, type.GetTypElem()) ) return false; + while (++count < padTo) + if (!(ostr << '\x80')) return false; + if (!(ostr << '\x00')) return false; } return true; } -//////////////////////////////////////////////////////////////////////////////// -bool ReadType(FILE* pf, CBotTypResult &type) +template +static bool ReadBinary(std::istream &istr, T &value) +{ + value = 0; + unsigned char chr; + unsigned shift = 0; + while (true) // unsigned LEB128 + { + if (!istr.read(reinterpret_cast(&chr), 1)) return false; + if (shift < sizeof(T) * 8 - 1) + value |= static_cast(chr & 0x7F) << shift; + shift += 7; + if ((chr & 0x80) == 0) break; + } + return true; +} + +template +static bool WriteSignedBinary(std::ostream &ostr, T value, unsigned padTo = 0) +{ + signed char sign = value >> (8 * sizeof(T) - 1); + unsigned count = 0; + while (true) // signed LEB128 + { + ++count; + unsigned char chr = value & 0x7F; + value >>= 7; + if (!(value != sign || ((chr ^ sign) & 0x40) != 0)) + { + if (count < padTo) chr |= 0x80; + if (!ostr.write(reinterpret_cast(&chr), 1)) return false; + break; + } + chr |= 0x80; + if (!ostr.put(chr)) return false; + } + + if (count < padTo) + { + char chr = (sign < 0) ? 0x7F : 0x00; + while (++count < padTo) + if (!ostr.put(chr | 0x80)) return false; + if (!ostr.put(chr)) return false; + } + return true; +} + +template +static bool ReadSignedBinary(std::istream &istr, T &value) +{ + value = 0; + unsigned char chr; + unsigned shift = 0; + while (true) // signed LEB128 + { + if (!istr.read(reinterpret_cast(&chr), 1)) return false; + if (shift < sizeof(T) * 8 - 1) + value |= (static_cast(chr & 0x7F) << shift); + shift += 7; + if ((chr & 0x80) == 0) break; + } + + if (shift >= 8 * sizeof(T) - 1) shift = 8 * sizeof(T) - 1; + if ((chr & 0x40) != 0) + value |= static_cast(-1) << shift; + + return true; +} + +bool WriteWord(std::ostream &ostr, unsigned short w) +{ + return WriteBinary(ostr, w); +} + +bool ReadWord(std::istream &istr, unsigned short &w) +{ + return ReadBinary(istr, w); +} + +bool WriteByte(std::ostream &ostr, char c) +{ + if (!ostr.put(c)) return false; + return true; +} + +bool ReadByte(std::istream &istr, char& c) +{ + if (!istr.get(c)) return false; + return true; +} + +bool WriteShort(std::ostream &ostr, short s) +{ + return WriteSignedBinary(ostr, s); +} + +bool ReadShort(std::istream &istr, short &s) +{ + return ReadSignedBinary(istr, s); +} + +bool WriteUInt32(std::ostream &ostr, uint32_t i) +{ + return WriteBinary(ostr, i); +} + +bool ReadUInt32(std::istream &istr, uint32_t &i) +{ + return ReadBinary(istr, i); +} + +bool WriteInt(std::ostream &ostr, int i) +{ + return WriteSignedBinary(ostr, i); +} + +bool ReadInt(std::istream &istr, int &i) +{ + return ReadSignedBinary(istr, i); +} + +bool WriteLong(std::ostream &ostr, long l, unsigned padTo) +{ + return WriteSignedBinary(ostr, l, padTo); +} + +bool ReadLong(std::istream &istr, long &l) +{ + return ReadSignedBinary(istr, l); +} + +bool WriteFloat(std::ostream &ostr, float f) +{ + union TypeConverter + { + float fValue; + unsigned int iValue; + }; + + TypeConverter u; + u.fValue = 0.0f; + u.iValue = 0; + + u.fValue = f; + return WriteBinary(ostr, u.iValue); +} + +bool ReadFloat(std::istream &istr, float &f) +{ + union TypeConverter + { + float fValue; + unsigned int iValue; + }; + + TypeConverter u; + u.fValue = 0.0f; + u.iValue = 0; + + if (!ReadBinary(istr, u.iValue)) return false; + f = u.fValue; + return true; +} + +bool WriteDouble(std::ostream &ostr, double d) +{ + union TypeConverter + { + double dValue; + unsigned long iValue; + }; + + TypeConverter u; + u.dValue = 0.0; + u.iValue = 0; + + u.dValue = d; + return WriteBinary(ostr, u.iValue); +} + +bool ReadDouble(std::istream &istr, double &d) +{ + union TypeConverter + { + double dValue; + unsigned long iValue; + }; + + TypeConverter u; + u.dValue = 0.0; + u.iValue = 0; + + if (!ReadBinary(istr, u.iValue)) return false; + d = u.dValue; + return true; +} + +bool WriteString(std::ostream &ostr, const std::string &s) +{ + if (!WriteBinary(ostr, s.size())) return false; + if (!ostr.write(&(s[0]), s.size())) return false; + + return true; +} + +bool ReadString(std::istream &istr, std::string &s) +{ + size_t length = 0; + if (!ReadBinary(istr, length)) return false; + + s.resize(length); + if (length != 0) + { + if (!istr.read(&(s[0]), length)) return false; + } + return true; +} + +bool WriteType(std::ostream &ostr, const CBotTypResult &type) +{ + int typ = type.GetType(); + if ( typ == CBotTypIntrinsic ) typ = CBotTypClass; + if ( !WriteWord(ostr, typ) ) return false; + if ( typ == CBotTypClass ) + { + CBotClass* p = type.GetClass(); + if (!WriteString(ostr, p->GetName())) return false; + } + if ( type.Eq( CBotTypArrayBody ) || + type.Eq( CBotTypArrayPointer ) ) + { + if (!WriteWord(ostr, type.GetLimite())) return false; + if (!WriteType(ostr, type.GetTypElem())) return false; + } + + if ( type.Eq(CBotTypPointer) ) + { + if (type.GetClass() != nullptr) + { + if (!WriteString(ostr, type.GetClass()->GetName())) return false; + } + else if (!WriteString(ostr, "")) return false; + } + return true; +} + +bool ReadType(std::istream &istr, CBotTypResult &type) { unsigned short w, ww; - if ( !ReadWord(pf, w) ) return false; + if (!ReadWord(istr, w)) return false; type.SetType(w); if ( type.Eq( CBotTypIntrinsic ) ) @@ -154,7 +310,7 @@ bool ReadType(FILE* pf, CBotTypResult &type) if ( type.Eq( CBotTypClass ) ) { std::string s; - if ( !ReadString(pf, s) ) return false; + if (!ReadString(istr, s)) return false; type = CBotTypResult( w, s ); } @@ -162,11 +318,45 @@ bool ReadType(FILE* pf, CBotTypResult &type) type.Eq( CBotTypArrayBody ) ) { CBotTypResult r; - if ( !ReadWord(pf, ww) ) return false; - if ( !ReadType(pf, r) ) return false; + if (!ReadWord(istr, ww)) return false; + if (!ReadType(istr, r)) return false; type = CBotTypResult( w, r ); type.SetLimite(static_cast(ww)); } + + if ( type.Eq(CBotTypPointer) ) + { + std::string className; + if (!ReadString(istr, className)) return false; + type = CBotTypResult(w, className); + } + return true; +} + +bool WriteStream(std::ostream &ostr, std::istream& istr) +{ + if (!istr.seekg(0, istr.end)) return false; + auto size = istr.tellg(); + + if (size == 0) return WriteLong(ostr, 0); + if (!WriteLong(ostr, size)) return false; + + if (!istr.seekg(0, istr.beg)) return false; + if (!(ostr << istr.rdbuf())) return false; + + return true; +} + +bool ReadStream(std::istream& istr, std::ostream &ostr) +{ + long length; + if (!ReadLong(istr, length)) return false; + if (length == 0) return true; + + while (length-- > 0) + { + if (!(ostr << istr.get())) return false; + } return true; } diff --git a/src/CBot/CBotFileUtils.h b/src/CBot/CBotFileUtils.h index fec6298a..8b53c10c 100644 --- a/src/CBot/CBotFileUtils.h +++ b/src/CBot/CBotFileUtils.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ #pragma once -#include +#include #include namespace CBot @@ -28,128 +28,189 @@ namespace CBot class CBotVar; class CBotTypResult; -/////////////////////////////////////////////////////////////////////////////// -// routines for file management (* FILE) - /*! - * \brief fOpen - * \param name - * \param mode - * \return + * \brief Save a linked list if variables + * \param ostr Output stream + * \param pVar First variable in the list + * \return true on success */ -FILE* fOpen(const char* name, const char* mode); - -/*! - * \brief fClose - * \param filehandle - * \return - */ -int fClose(FILE* filehandle); - -/*! - * \brief fWrite - * \param buffer - * \param elemsize - * \param length - * \param filehandle - * \return - */ -std::size_t fWrite(const void *buffer, - std::size_t elemsize, - std::size_t length, - FILE* filehandle); - -/*! - * \brief fRead - * \param buffer - * \param elemsize - * \param length - * \param filehandle - * \return - */ -std::size_t fRead(void *buffer, - std::size_t elemsize, - std::size_t length, - FILE* filehandle); - -/*! - * \brief SaveVars - * \param pf - * \param pVar - * \return - */ -bool SaveVars(FILE* pf, CBotVar* pVar); +bool SaveVars(std::ostream &ostr, CBotVar* pVar); /*! * \brief WriteWord - * \param pf + * \param ostr Output stream * \param w - * \return + * \return true on success */ -bool WriteWord(FILE* pf, unsigned short w); +bool WriteWord(std::ostream &ostr, unsigned short w); /*! * \brief ReadWord - * \param pf - * \param w - * \return + * \param istr Input stream + * \param[out] w + * \return true on success */ -bool ReadWord(FILE* pf, unsigned short& w); +bool ReadWord(std::istream &istr, unsigned short &w); /*! - * \brief ReadLong - * \param pf - * \param w - * \return + * \brief WriteByte + * \param ostr Output stream + * \param c + * \return true on success */ -bool ReadLong(FILE* pf, long& w); +bool WriteByte(std::ostream &ostr, char c); /*! - * \brief WriteFloat - * \param pf - * \param w - * \return + * \brief ReadByte + * \param istr Input stream + * \param[out] c + * \return true on success */ -bool WriteFloat(FILE* pf, float w); +bool ReadByte(std::istream &istr, char& c); + +/*! + * \brief WriteShort + * \param ostr Output stream + * \param s + * \return true on success + */ +bool WriteShort(std::ostream &ostr, short s); + +/*! + * \brief ReadShort + * \param istr Input stream + * \param[out] s + * \return true on success + */ +bool ReadShort(std::istream &istr, short &s); + +/*! + * \brief WriteUInt32 + * \param ostr Output stream + * \param i + * \return true on success + */ +bool WriteUInt32(std::ostream &ostr, uint32_t i); + +/*! + * \brief ReadUInt32 + * \param istr Input stream + * \param[out] i + * \return true on success + */ +bool ReadUInt32(std::istream &istr, uint32_t &i); + +/*! + * \brief WriteInt + * \param ostr Output stream + * \param i + * \return true on success + */ +bool WriteInt(std::ostream &ostr, int i); + +/*! + * \brief ReadInt + * \param istr Input stream + * \param[out] i + * \return true on success + */ +bool ReadInt(std::istream &istr, int &i); /*! * \brief WriteLong - * \param pf - * \param w - * \return + * \param ostr Output stream + * \param l + * \param padTo minimum number of bytes to write + * \return true on success */ -bool WriteLong(FILE* pf, long w); +bool WriteLong(std::ostream &ostr, long l, unsigned padTo = 0); + +/*! + * \brief ReadLong + * \param istr Input stream + * \param[out] l + * \return true on success + */ +bool ReadLong(std::istream &istr, long &l); + +/*! + * \brief WriteFloat + * \param ostr Output stream + * \param f + * \return true on success + */ +bool WriteFloat(std::ostream &ostr, float f); /*! * \brief ReadFloat - * \param pf - * \param w - * \return + * \param istr Input stream + * \param[out] f + * \return true on success */ -bool ReadFloat(FILE* pf, float& w); +bool ReadFloat(std::istream &istr, float &f); + +/*! + * \brief WriteDouble + * \param ostr Output stream + * \param d + * \return true on success + */ +bool WriteDouble(std::ostream &ostr, double d); + +/*! + * \brief ReadDouble + * \param istr Input stream + * \param[out] d + * \return true on success + */ +bool ReadDouble(std::istream &istr, double &d); + +/*! + * \brief WriteString + * \param ostr Output stream + * \param s + * \return true on success + */ +bool WriteString(std::ostream &ostr, const std::string &s); /*! * \brief ReadString - * \param pf - * \param s - * \return + * \param istr Input stream + * \param[out] s + * \return true on success */ -bool ReadString(FILE* pf, std::string& s); +bool ReadString(std::istream &istr, std::string &s); /*! * \brief WriteType - * \param pf + * \param ostr Output stream * \param type - * \return + * \return true on success */ -bool WriteType(FILE* pf, const CBotTypResult &type); +bool WriteType(std::ostream &ostr, const CBotTypResult &type); /*! * \brief ReadType - * \param pf - * \param type - * \return + * \param istr Input stream + * \param[out] type + * \return true on success */ -bool ReadType(FILE* pf, CBotTypResult &type); +bool ReadType(std::istream &istr, CBotTypResult &type); + +/*! + * \brief WriteStream + * \param ostr Output stream + * \param istr Input stream + * \return true on success + */ +bool WriteStream(std::ostream &ostr, std::istream& istr); + +/*! + * \brief ReadStream + * \param istr Input stream + * \param ostr Output stream + * \return true on success + */ +bool ReadStream(std::istream& istr, std::ostream &ostr); } // namespace CBot diff --git a/src/CBot/CBotInstr/CBotBlock.cpp b/src/CBot/CBotInstr/CBotBlock.cpp index aa9be145..7bcd38cd 100644 --- a/src/CBot/CBotInstr/CBotBlock.cpp +++ b/src/CBot/CBotInstr/CBotBlock.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotBlock.h b/src/CBot/CBotInstr/CBotBlock.h index 5054b65c..c4ce2be9 100644 --- a/src/CBot/CBotInstr/CBotBlock.h +++ b/src/CBot/CBotInstr/CBotBlock.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotBoolExpr.cpp b/src/CBot/CBotInstr/CBotBoolExpr.cpp index a90a72dc..ffe93bed 100644 --- a/src/CBot/CBotInstr/CBotBoolExpr.cpp +++ b/src/CBot/CBotInstr/CBotBoolExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotBoolExpr.h b/src/CBot/CBotInstr/CBotBoolExpr.h index 828df199..7bb7f987 100644 --- a/src/CBot/CBotInstr/CBotBoolExpr.h +++ b/src/CBot/CBotInstr/CBotBoolExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotBreak.cpp b/src/CBot/CBotInstr/CBotBreak.cpp index ee0bae81..adfb0f62 100644 --- a/src/CBot/CBotInstr/CBotBreak.cpp +++ b/src/CBot/CBotInstr/CBotBreak.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotBreak.h b/src/CBot/CBotInstr/CBotBreak.h index 6f72262b..19ec1b88 100644 --- a/src/CBot/CBotInstr/CBotBreak.h +++ b/src/CBot/CBotInstr/CBotBreak.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotCase.cpp b/src/CBot/CBotInstr/CBotCase.cpp index 35e17d3d..14087e86 100644 --- a/src/CBot/CBotInstr/CBotCase.cpp +++ b/src/CBot/CBotInstr/CBotCase.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -19,7 +19,7 @@ #include "CBot/CBotInstr/CBotCase.h" -#include "CBot/CBotInstr/CBotExprLitNum.h" +#include "CBot/CBotInstr/CBotTwoOpExpr.h" #include "CBot/CBotStack.h" #include "CBot/CBotCStack.h" @@ -30,69 +30,107 @@ namespace CBot //////////////////////////////////////////////////////////////////////////////// CBotCase::CBotCase() { - m_value = nullptr; + m_instr = nullptr; } //////////////////////////////////////////////////////////////////////////////// CBotCase::~CBotCase() { - delete m_value; + delete m_instr; } -//////////////////////////////////////////////////////////////////////////////// -CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack) +CBotInstr* CBotCase::Compile(CBotToken* &p, CBotCStack* pStack, std::unordered_map& labels) { - CBotCase* inst = new CBotCase(); // creates the object CBotToken* pp = p; // preserves at the ^ token (starting position) - inst->SetToken(p); if (!IsOfType(p, ID_CASE, ID_DEFAULT)) return nullptr; // should never happen + pStack->SetStartError(pp->GetStart()); - if ( pp->GetType() == ID_CASE ) + long labelValue = 0; + + if (pp->GetType() == ID_CASE) { - pp = p; - inst->m_value = CBotExprLitNum::Compile(p, pStack); - if (inst->m_value == nullptr ) + CBotInstr* i = nullptr; + if (nullptr != (i = CBotTwoOpExpr::Compile(p, pStack, nullptr, true))) { - pStack->SetError( CBotErrBadNum, pp ); - delete inst; - return nullptr; + if (pStack->GetType() <= CBotTypLong) + { + CBotStack* pile = CBotStack::AllocateStack(); + while ( !i->Execute(pile) ); + labelValue = pile->GetVar()->GetValLong(); + pile->Delete(); + + if (labels.count(labelValue) > 0) + { + pStack->SetError(CBotErrRedefCase, p->GetStart()); + } + } + else + pStack->SetError(CBotErrBadNum, p->GetStart()); + delete i; } - } - if ( !IsOfType( p, ID_DOTS )) - { - pStack->SetError( CBotErrNoDoubleDots, p->GetStart() ); - delete inst; - return nullptr; + else + pStack->SetError(CBotErrBadNum, p->GetStart()); } - return inst; + if (pStack->IsOk() && IsOfType(p, ID_DOTS)) + { + CBotCase* newCase = new CBotCase(); + newCase->SetToken(pp); + if (pp->GetType() == ID_CASE) + labels[labelValue] = newCase; + return newCase; + } + + pStack->SetError(CBotErrNoDoubleDots, p->GetStart()); + return nullptr; } //////////////////////////////////////////////////////////////////////////////// bool CBotCase::Execute(CBotStack* &pj) { - return true; // the "case" statement does nothing! + if (m_instr == nullptr) return true; + CBotStack* pile = pj->AddStack(this, CBotStack::BlockVisibilityType::BLOCK); + + int state = pile->GetState(); + CBotInstr* p = m_instr; + while (state-- > 0) p = p->GetNext(); + + while (p != nullptr) + { + if (!p->Execute(pile)) return false; + pile->IncState(); + p = p->GetNext(); + } + + pile->Delete(); + return pj->IsOk(); } //////////////////////////////////////////////////////////////////////////////// void CBotCase::RestoreState(CBotStack* &pj, bool bMain) { -} + if (!bMain) return; -//////////////////////////////////////////////////////////////////////////////// -bool CBotCase::CompCase(CBotStack* &pile, int val) -{ - if (m_value == nullptr ) return true; // "default" case + CBotStack* pile = pj->RestoreStack(this); + if (pile == nullptr) return; - while (!m_value->Execute(pile)); // puts the value on the correspondent stack (without interruption) - return (pile->GetVal() == val); // compared with the given value + CBotInstr* p = m_instr; + + int state = pile->GetState(); + while (p != nullptr && state-- > 0) + { + p->RestoreState(pile, bMain); + p = p->GetNext(); + } + + if (p != nullptr) p->RestoreState(pile, bMain); } std::map CBotCase::GetDebugLinks() { auto links = CBotInstr::GetDebugLinks(); - links["m_value"] = m_value; + links["m_instr"] = m_instr; return links; } diff --git a/src/CBot/CBotInstr/CBotCase.h b/src/CBot/CBotInstr/CBotCase.h index e2863cde..394223c6 100644 --- a/src/CBot/CBotInstr/CBotCase.h +++ b/src/CBot/CBotInstr/CBotCase.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,8 @@ #include "CBot/CBotInstr/CBotInstr.h" +#include + namespace CBot { @@ -42,7 +44,7 @@ public: * \param pStack * \return */ - static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack); + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, std::unordered_map& labels); /*! * \brief Execute Execution of instruction "case". @@ -58,22 +60,15 @@ public: */ void RestoreState(CBotStack* &pj, bool bMain) override; - /*! - * \brief CompCase Routine to find the entry point of "case" corresponding - * to the value seen. - * \param pj - * \param val - * \return - */ - bool CompCase(CBotStack* &pj, int val) override; - protected: virtual const std::string GetDebugName() override { return "CBotCase"; } virtual std::map GetDebugLinks() override; private: - //! Value to compare. - CBotInstr* m_value; + //! List of instructions after case label + CBotInstr* m_instr; + + friend class CBotSwitch; }; } // namespace CBot diff --git a/src/CBot/CBotInstr/CBotCatch.cpp b/src/CBot/CBotInstr/CBotCatch.cpp index 5951cd97..a22f2627 100644 --- a/src/CBot/CBotInstr/CBotCatch.cpp +++ b/src/CBot/CBotInstr/CBotCatch.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotCatch.h b/src/CBot/CBotInstr/CBotCatch.h index a42f8754..21ad4684 100644 --- a/src/CBot/CBotInstr/CBotCatch.h +++ b/src/CBot/CBotInstr/CBotCatch.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotCondition.cpp b/src/CBot/CBotInstr/CBotCondition.cpp index 7c345d70..9b00ad95 100644 --- a/src/CBot/CBotInstr/CBotCondition.cpp +++ b/src/CBot/CBotInstr/CBotCondition.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotCondition.h b/src/CBot/CBotInstr/CBotCondition.h index 8c8bd1fc..205add6e 100644 --- a/src/CBot/CBotInstr/CBotCondition.h +++ b/src/CBot/CBotInstr/CBotCondition.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDefArray.cpp b/src/CBot/CBotInstr/CBotDefArray.cpp index 7d06674a..0a32b482 100644 --- a/src/CBot/CBotInstr/CBotDefArray.cpp +++ b/src/CBot/CBotInstr/CBotDefArray.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDefArray.h b/src/CBot/CBotInstr/CBotDefArray.h index 8b2fb205..850e1cf0 100644 --- a/src/CBot/CBotInstr/CBotDefArray.h +++ b/src/CBot/CBotInstr/CBotDefArray.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDefBoolean.cpp b/src/CBot/CBotInstr/CBotDefBoolean.cpp index 6a6ea499..c140ebfd 100644 --- a/src/CBot/CBotInstr/CBotDefBoolean.cpp +++ b/src/CBot/CBotInstr/CBotDefBoolean.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDefBoolean.h b/src/CBot/CBotInstr/CBotDefBoolean.h index 8d55adf2..f26669b6 100644 --- a/src/CBot/CBotInstr/CBotDefBoolean.h +++ b/src/CBot/CBotInstr/CBotDefBoolean.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDefClass.cpp b/src/CBot/CBotInstr/CBotDefClass.cpp index 174b973f..f50196ed 100644 --- a/src/CBot/CBotInstr/CBotDefClass.cpp +++ b/src/CBot/CBotInstr/CBotDefClass.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -135,12 +135,12 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p // the constructor is there? // std::string noname; CBotTypResult r = pClass->CompileMethode(&token, var, ppVars, pStk, inst->m_nMethodeIdent); - delete pStk->TokenStack(); // releases the supplement stack + pStk->DeleteNext(); // releases the supplement stack int typ = r.GetType(); if (typ == CBotErrUndefCall) { - // si le constructeur n'existe pas + // if the ctor don't exist if (inst->m_parameters != nullptr) // with parameters { pStk->SetError(CBotErrNoConstruct, vartoken); @@ -160,7 +160,7 @@ CBotInstr* CBotDefClass::Compile(CBotToken* &p, CBotCStack* pStack, CBotClass* p if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true))) { inst->m_exprRetVar->SetToken(vartoken); - delete pStk->TokenStack(); + pStk->DeleteNext(); } pStk->SetVar(nullptr); @@ -360,6 +360,7 @@ bool CBotDefClass::Execute(CBotStack* &pj) if ( p != nullptr) while ( true ) { pile2 = pile2->AddStack(); // place on the stack for the results + if (pile2->StackOver()) return pj->Return(pile2); if ( pile2->GetState() == 0 ) { if (!p->Execute(pile2)) return false; // interrupted here? diff --git a/src/CBot/CBotInstr/CBotDefClass.h b/src/CBot/CBotInstr/CBotDefClass.h index 1c501376..0b0fd9e8 100644 --- a/src/CBot/CBotInstr/CBotDefClass.h +++ b/src/CBot/CBotInstr/CBotDefClass.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDefFloat.cpp b/src/CBot/CBotInstr/CBotDefFloat.cpp index 65449b02..98e1d314 100644 --- a/src/CBot/CBotInstr/CBotDefFloat.cpp +++ b/src/CBot/CBotInstr/CBotDefFloat.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -46,13 +46,22 @@ CBotDefFloat::~CBotDefFloat() } //////////////////////////////////////////////////////////////////////////////// -CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip) +CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip, CBotTypResult vartype) { CBotToken* pp = cont ? nullptr : p; - if (!cont && !IsOfType(p, ID_FLOAT)) return nullptr; + if (!cont) + { + switch (p->GetType()) + { + case ID_FLOAT: vartype.SetType(CBotTypFloat ); break; + case ID_DOUBLE: vartype.SetType(CBotTypDouble); break; + default: return nullptr; + } + p = p->GetNext(); + } - CBotDefFloat* inst = static_cast(CompileArray(p, pStack, CBotTypFloat)); + CBotDefFloat* inst = static_cast(CompileArray(p, pStack, vartype)); if (inst != nullptr || !pStack->IsOk()) return inst; CBotCStack* pStk = pStack->TokenStack(pp); @@ -67,7 +76,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk ))) { - (static_cast(inst->m_var))->m_typevar = CBotTypFloat; + (static_cast(inst->m_var))->m_typevar = vartype; if (pStk->CheckVarLocal(vartoken)) // redefinition of a variable { pStk->SetStartError(vartoken->GetStart()); @@ -79,7 +88,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b { delete inst; p = vartoken; - inst = static_cast(CBotDefArray::Compile(p, pStk, CBotTypFloat)); + inst = static_cast(CBotDefArray::Compile(p, pStk, vartype)); goto suite; // no assignment, variable already created } @@ -103,7 +112,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b } } - var = CBotVar::Create(*vartoken, CBotTypFloat); + var = CBotVar::Create(*vartoken, vartype); var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF); var->SetUniqNum( (static_cast(inst->m_var))->m_nIdent = CBotVar::NextUniqNum()); @@ -111,7 +120,7 @@ CBotInstr* CBotDefFloat::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, b suite: if (pStk->IsOk() && IsOfType(p, ID_COMMA)) { - if (nullptr != ( inst->m_next2b = CBotDefFloat::Compile(p, pStk, true, noskip))) + if (nullptr != ( inst->m_next2b = CBotDefFloat::Compile(p, pStk, true, noskip, vartype))) { return pStack->Return(inst, pStk); } diff --git a/src/CBot/CBotInstr/CBotDefFloat.h b/src/CBot/CBotInstr/CBotDefFloat.h index a8060b41..a8e95c3f 100644 --- a/src/CBot/CBotInstr/CBotDefFloat.h +++ b/src/CBot/CBotInstr/CBotDefFloat.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -41,7 +41,7 @@ public: * \param noskip * \return */ - static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false); + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip=false, CBotTypResult vartype = CBotTypFloat); /*! * \brief Execute Executes the definition of a real variable. diff --git a/src/CBot/CBotInstr/CBotDefInt.cpp b/src/CBot/CBotInstr/CBotDefInt.cpp index 6cfb30e6..621f8471 100644 --- a/src/CBot/CBotInstr/CBotDefInt.cpp +++ b/src/CBot/CBotInstr/CBotDefInt.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -47,13 +47,25 @@ CBotDefInt::~CBotDefInt() } //////////////////////////////////////////////////////////////////////////////// -CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip) +CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, bool noskip, CBotTypResult vartype) { CBotToken* pp = cont ? nullptr : p; // no repetition of the token "int" - if (!cont && !IsOfType(p, ID_INT)) return nullptr; + if (!cont) + { + switch (p->GetType()) + { + case ID_BYTE: vartype.SetType(CBotTypByte ); break; + case ID_SHORT: vartype.SetType(CBotTypShort); break; + case ID_CHAR: vartype.SetType(CBotTypChar ); break; + case ID_INT: vartype.SetType(CBotTypInt ); break; + case ID_LONG: vartype.SetType(CBotTypLong ); break; + default: return nullptr; + } + p = p->GetNext(); + } - CBotDefInt* inst = static_cast(CompileArray(p, pStack, CBotTypInt)); + CBotDefInt* inst = static_cast(CompileArray(p, pStack, vartype)); if (inst != nullptr || !pStack->IsOk()) return inst; CBotCStack* pStk = pStack->TokenStack(pp); @@ -68,7 +80,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo // determines the expression is valid for the item on the left side if (nullptr != (inst->m_var = CBotLeftExprVar::Compile( p, pStk ))) { - (static_cast(inst->m_var))->m_typevar = CBotTypInt; + (static_cast(inst->m_var))->m_typevar = vartype; if (pStk->CheckVarLocal(vartoken)) // redefinition of the variable { pStk->SetError(CBotErrRedefVar, vartoken); @@ -82,7 +94,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo // compiles an array declaration - CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, CBotTypInt); + CBotInstr* inst2 = CBotDefArray::Compile(p, pStk, vartype); inst = static_cast(inst2); goto suite; // no assignment, variable already created @@ -108,7 +120,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo } { - CBotVar* var = CBotVar::Create(*vartoken, CBotTypInt);// create the variable (evaluated after the assignment) + CBotVar* var = CBotVar::Create(*vartoken, vartype); // create the variable (evaluated after the assignment) var->SetInit(inst->m_expr != nullptr ? CBotVar::InitType::DEF : CBotVar::InitType::UNDEF); // if initialized with assignment var->SetUniqNum( //set it with a unique number (static_cast(inst->m_var))->m_nIdent = CBotVar::NextUniqNum()); @@ -117,7 +129,7 @@ CBotInstr* CBotDefInt::Compile(CBotToken* &p, CBotCStack* pStack, bool cont, boo suite: if (pStk->IsOk() && IsOfType(p, ID_COMMA)) // chained several definitions { - if (nullptr != ( inst->m_next2b = CBotDefInt::Compile(p, pStk, true, noskip))) // compile next one + if (nullptr != ( inst->m_next2b = CBotDefInt::Compile(p, pStk, true, noskip, vartype))) // compile next one { return pStack->Return(inst, pStk); } diff --git a/src/CBot/CBotInstr/CBotDefInt.h b/src/CBot/CBotInstr/CBotDefInt.h index 2962eab3..7fc52b0f 100644 --- a/src/CBot/CBotInstr/CBotDefInt.h +++ b/src/CBot/CBotInstr/CBotDefInt.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -41,7 +41,7 @@ public: * \param noskip * \return */ - static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip = false); + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool cont = false, bool noskip = false, CBotTypResult vartype = CBotTypInt); /*! * \brief Execute Execute the definition of the integer variable. diff --git a/src/CBot/CBotInstr/CBotDefString.cpp b/src/CBot/CBotInstr/CBotDefString.cpp index 3c80e5d3..0a68a908 100644 --- a/src/CBot/CBotInstr/CBotDefString.cpp +++ b/src/CBot/CBotInstr/CBotDefString.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDefString.h b/src/CBot/CBotInstr/CBotDefString.h index d2d3fea5..72135adb 100644 --- a/src/CBot/CBotInstr/CBotDefString.h +++ b/src/CBot/CBotInstr/CBotDefString.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotDo.cpp b/src/CBot/CBotInstr/CBotDo.cpp index caf10920..800b97fa 100644 --- a/src/CBot/CBotInstr/CBotDo.cpp +++ b/src/CBot/CBotInstr/CBotDo.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -57,7 +57,7 @@ CBotInstr* CBotDo::Compile(CBotToken* &p, CBotCStack* pStack) inst->SetToken(p); if (!IsOfType(p, ID_DO)) return nullptr; // should never happen - CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp + CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz // looking for a statement block after the do diff --git a/src/CBot/CBotInstr/CBotDo.h b/src/CBot/CBotInstr/CBotDo.h index ffbef08d..0463588f 100644 --- a/src/CBot/CBotInstr/CBotDo.h +++ b/src/CBot/CBotInstr/CBotDo.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotEmpty.cpp b/src/CBot/CBotInstr/CBotEmpty.cpp index 7176973d..e6a8936b 100644 --- a/src/CBot/CBotInstr/CBotEmpty.cpp +++ b/src/CBot/CBotInstr/CBotEmpty.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotEmpty.h b/src/CBot/CBotInstr/CBotEmpty.h index ca7476a3..b1b9bc51 100644 --- a/src/CBot/CBotInstr/CBotEmpty.h +++ b/src/CBot/CBotInstr/CBotEmpty.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprLitBool.cpp b/src/CBot/CBotInstr/CBotExprLitBool.cpp index 8c0ea450..672ad723 100644 --- a/src/CBot/CBotInstr/CBotExprLitBool.cpp +++ b/src/CBot/CBotInstr/CBotExprLitBool.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprLitBool.h b/src/CBot/CBotInstr/CBotExprLitBool.h index 3344b5af..59a4c151 100644 --- a/src/CBot/CBotInstr/CBotExprLitBool.h +++ b/src/CBot/CBotInstr/CBotExprLitBool.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprLitChar.cpp b/src/CBot/CBotInstr/CBotExprLitChar.cpp new file mode 100644 index 00000000..9f206746 --- /dev/null +++ b/src/CBot/CBotInstr/CBotExprLitChar.cpp @@ -0,0 +1,151 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include "CBot/CBotInstr/CBotExprLitChar.h" + +#include "CBot/CBotStack.h" +#include "CBot/CBotCStack.h" + +#include "CBot/CBotVar/CBotVar.h" + +namespace CBot +{ + +CBotExprLitChar::CBotExprLitChar() +{ +} + +CBotExprLitChar::~CBotExprLitChar() +{ +} + +CBotInstr* CBotExprLitChar::Compile(CBotToken* &p, CBotCStack* pStack) +{ + CBotCStack* pStk = pStack->TokenStack(); + + const auto& s = p->GetString(); + + auto it = s.cbegin(); + if (++it != s.cend()) + { + if (*it != '\'') // not empty quotes ? + { + uint32_t valchar = 0; + int pos = p->GetStart() + 1; + + if (*it != '\\') valchar = *(it++); // not escape sequence ? + else if (++it != s.cend()) + { + pStk->SetStartError(pos++); + unsigned char c = *(it++); + if (c == '\"' || c == '\'' || c == '\\') valchar = c; + else if (c == 'a') valchar = '\a'; // alert bell + else if (c == 'b') valchar = '\b'; // backspace + else if (c == 'f') valchar = '\f'; // form feed + else if (c == 'n') valchar = '\n'; // new line + else if (c == 'r') valchar = '\r'; // carriage return + else if (c == 't') valchar = '\t'; // horizontal tab + else if (c == 'v') valchar = '\v'; // vertical tab + else if (c == 'u' || c == 'U') // unicode escape + { + if (it != s.cend()) + { + std::string hex = ""; + size_t maxlen = (c == 'u') ? 4 : 8; + + for (size_t i = 0; i < maxlen; i++) + { + if (!CharInList(*it, "0123456789ABCDEFabcdef")) break; + ++pos; + hex += *it; + if (++it == s.cend()) break; + } + + if (maxlen == hex.length()) // unicode character + { + try + { + valchar = std::stoi(hex, nullptr, 16); + if (0x10FFFF < valchar || (0xD7FF < valchar && valchar < 0xE000)) + pStk->SetError(CBotErrUnicodeName, pos + 1); + } + catch (const std::out_of_range& e) + { + pStk->SetError(CBotErrHexRange, pos + 1); + } + } + else + pStk->SetError(CBotErrHexDigits, pos + 1); + } + else + pStk->SetError(CBotErrHexDigits, pos + 1); + } + else + pStk->SetError(CBotErrBadEscape, pos + 1); + } + + if (it == s.cend() || *it != '\'') + pStk->SetError(CBotErrEndQuote, p); + + if (pStk->IsOk()) + { + CBotExprLitChar* inst = new CBotExprLitChar(); + inst->m_valchar = valchar; + inst->SetToken(p); + p = p->GetNext(); + + CBotVar* var = CBotVar::Create("", CBotTypChar); + pStk->SetVar(var); + + return pStack->Return(inst, pStk); + } + } + pStk->SetError(CBotErrCharEmpty, p); + } + + pStk->SetError(CBotErrEndQuote, p); + return pStack->Return(nullptr, pStk); +} + +bool CBotExprLitChar::Execute(CBotStack* &pj) +{ + CBotStack* pile = pj->AddStack(this); + + if (pile->IfStep()) return false; + + CBotVar* var = CBotVar::Create("", CBotTypChar); + + var->SetValChar(m_valchar); + + pile->SetVar(var); + + return pj->Return(pile); +} + +void CBotExprLitChar::RestoreState(CBotStack* &pj, bool bMain) +{ + if (bMain) pj->RestoreStack(this); +} + +std::string CBotExprLitChar::GetDebugData() +{ + return m_token.GetString(); +} + +} // namespace CBot diff --git a/src/CBot/CBotInstr/CBotExprLitChar.h b/src/CBot/CBotInstr/CBotExprLitChar.h new file mode 100644 index 00000000..fd9b8ad0 --- /dev/null +++ b/src/CBot/CBotInstr/CBotExprLitChar.h @@ -0,0 +1,60 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "CBot/CBotInstr/CBotInstr.h" + +namespace CBot +{ + +/** + * \brief A character literal + * \verbatim 'a', '\n', '\t', '\uFFFD', '\U0000FFFD', etc. \endverbatim + */ +class CBotExprLitChar : public CBotInstr +{ +public: + CBotExprLitChar(); + ~CBotExprLitChar(); + + /*! + * \brief Compile a character literal + */ + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack); + + /*! + * \brief Execute, returns the corresponding char. + */ + bool Execute(CBotStack* &pj) override; + + /*! + * \brief RestoreState + */ + void RestoreState(CBotStack* &pj, bool bMain) override; + +protected: + virtual const std::string GetDebugName() override { return "CBotExprLitChar"; } + virtual std::string GetDebugData() override; + +private: + uint32_t m_valchar = 0; +}; + +} // namespace CBot diff --git a/src/CBot/CBotInstr/CBotExprLitNan.cpp b/src/CBot/CBotInstr/CBotExprLitNan.cpp index 25156732..ad67f68e 100644 --- a/src/CBot/CBotInstr/CBotExprLitNan.cpp +++ b/src/CBot/CBotInstr/CBotExprLitNan.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprLitNan.h b/src/CBot/CBotInstr/CBotExprLitNan.h index 74aae18d..a8ae585b 100644 --- a/src/CBot/CBotInstr/CBotExprLitNan.h +++ b/src/CBot/CBotInstr/CBotExprLitNan.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprLitNull.cpp b/src/CBot/CBotInstr/CBotExprLitNull.cpp index 88237127..7d7bb97f 100644 --- a/src/CBot/CBotInstr/CBotExprLitNull.cpp +++ b/src/CBot/CBotInstr/CBotExprLitNull.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprLitNull.h b/src/CBot/CBotInstr/CBotExprLitNull.h index 0233cb82..71da9945 100644 --- a/src/CBot/CBotInstr/CBotExprLitNull.h +++ b/src/CBot/CBotInstr/CBotExprLitNull.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprLitNum.cpp b/src/CBot/CBotInstr/CBotExprLitNum.cpp index 9273e8ee..c03103cb 100644 --- a/src/CBot/CBotInstr/CBotExprLitNum.cpp +++ b/src/CBot/CBotInstr/CBotExprLitNum.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -25,52 +25,85 @@ #include "CBot/CBotUtils.h" +#include #include namespace CBot { -//////////////////////////////////////////////////////////////////////////////// -CBotExprLitNum::CBotExprLitNum() +template <> +CBotExprLitNum::CBotExprLitNum(int val) : m_numtype(CBotTypInt), m_value(val) { } -//////////////////////////////////////////////////////////////////////////////// -CBotExprLitNum::~CBotExprLitNum() +template <> +CBotExprLitNum::CBotExprLitNum(long val) : m_numtype(CBotTypLong), m_value(val) { } -//////////////////////////////////////////////////////////////////////////////// -CBotInstr* CBotExprLitNum::Compile(CBotToken* &p, CBotCStack* pStack) +template <> +CBotExprLitNum::CBotExprLitNum(float val) : m_numtype(CBotTypFloat), m_value(val) +{ +} + +template <> +CBotExprLitNum::CBotExprLitNum(double val) : m_numtype(CBotTypDouble), m_value(val) +{ +} + +template +CBotExprLitNum::~CBotExprLitNum() +{ +} + +CBotInstr* CompileExprLitNum(CBotToken* &p, CBotCStack* pStack) { CBotCStack* pStk = pStack->TokenStack(); - CBotExprLitNum* inst = new CBotExprLitNum(); + const auto& s = p->GetString(); - inst->SetToken(p); - std::string s = p->GetString(); + CBotInstr* inst = nullptr; + CBotType numtype = CBotTypInt; - inst->m_numtype = CBotTypInt; if (p->GetType() == TokenTypDef) { - inst->m_valint = p->GetKeywordId(); + inst = new CBotExprLitNum(static_cast(p->GetKeywordId())); } else { if (s.find('.') != std::string::npos || ( s.find('x') == std::string::npos && ( s.find_first_of("eE") != std::string::npos ) )) { - inst->m_numtype = CBotTypFloat; - inst->m_valfloat = GetNumFloat(s); + double val = GetNumFloat(s); + if (val > static_cast(std::numeric_limits::max())) + { + numtype = CBotTypDouble; + inst = new CBotExprLitNum(val); + } + else + { + numtype = CBotTypFloat; + inst = new CBotExprLitNum(static_cast(val)); + } } else { - inst->m_valint = GetNumInt(s); + long val = GetNumInt(s); + if (val > std::numeric_limits::max()) + { + numtype = CBotTypLong; + inst = new CBotExprLitNum(val); + } + else + { + inst = new CBotExprLitNum(static_cast(val)); + } } } + inst->SetToken(p); if (pStk->NextToken(p)) { - CBotVar* var = CBotVar::Create("", inst->m_numtype); + CBotVar* var = CBotVar::Create("", numtype); pStk->SetVar(var); return pStack->Return(inst, pStk); @@ -79,8 +112,48 @@ CBotInstr* CBotExprLitNum::Compile(CBotToken* &p, CBotCStack* pStack) return pStack->Return(nullptr, pStk); } -//////////////////////////////////////////////////////////////////////////////// -bool CBotExprLitNum::Execute(CBotStack* &pj) +CBotInstr* CompileSizeOf(CBotToken* &p, CBotCStack* pStack) +{ + CBotToken* pp = p; + + if (!IsOfType(p, TokenTypVar)) return nullptr; + if (pp->GetString() == "sizeof" && IsOfType(p, ID_OPENPAR)) + { + CBotCStack* pStk = pStack->TokenStack(); + + int value; + + if (IsOfType(p, ID_BYTE)) value = sizeof(signed char); + else if (IsOfType(p, ID_SHORT)) value = sizeof(short); + else if (IsOfType(p, ID_CHAR)) value = sizeof(uint32_t); + else if (IsOfType(p, ID_INT)) value = sizeof(int); + else if (IsOfType(p, ID_LONG)) value = sizeof(long); + else if (IsOfType(p, ID_FLOAT)) value = sizeof(float); + else if (IsOfType(p, ID_DOUBLE)) value = sizeof(double); + else + { + p = pp; + return pStack->Return(nullptr, pStk); + } + + if (IsOfType(p, ID_CLOSEPAR)) + { + auto inst = new CBotExprLitNum(value); + inst->SetToken(pp); + + CBotVar* var = CBotVar::Create("", CBotTypInt); + pStk->SetVar(var); + return pStack->Return(inst, pStk); + } + pStk->SetError(CBotErrClosePar, p->GetStart()); + return pStack->Return(nullptr, pStk); + } + p = pp; + return nullptr; +} + +template +bool CBotExprLitNum::Execute(CBotStack* &pj) { CBotStack* pile = pj->AddStack(this); @@ -88,39 +161,38 @@ bool CBotExprLitNum::Execute(CBotStack* &pj) CBotVar* var = CBotVar::Create("", m_numtype); - std::string nombre ; if (m_token.GetType() == TokenTypDef) { - nombre = m_token.GetString(); + var->SetValInt(m_value, m_token.GetString()); } - - switch (m_numtype) + else { - case CBotTypShort: - case CBotTypInt: - var->SetValInt(m_valint, nombre); - break; - case CBotTypFloat: - var->SetValFloat(m_valfloat); - break; - default: - assert(false); + *var = m_value; } pile->SetVar(var); // place on the stack return pj->Return(pile); // it's ok } -//////////////////////////////////////////////////////////////////////////////// -void CBotExprLitNum::RestoreState(CBotStack* &pj, bool bMain) +template +void CBotExprLitNum::RestoreState(CBotStack* &pj, bool bMain) { if (bMain) pj->RestoreStack(this); } -std::string CBotExprLitNum::GetDebugData() +template +std::string CBotExprLitNum::GetDebugData() { std::stringstream ss; - ss << "(" << (m_numtype == CBotTypFloat ? "float" : "int") << ") " << (m_numtype == CBotTypFloat ? m_valfloat : m_valint); + switch (m_numtype) + { + case CBotTypInt : ss << "(int) "; break; + case CBotTypLong : ss << "(long) "; break; + case CBotTypFloat : ss << "(float) "; break; + case CBotTypDouble: ss << "(double) "; break; + default: assert(false); + } + ss << m_value; return ss.str(); } diff --git a/src/CBot/CBotInstr/CBotExprLitNum.h b/src/CBot/CBotInstr/CBotExprLitNum.h index 414f2d8e..103b35d8 100644 --- a/src/CBot/CBotInstr/CBotExprLitNum.h +++ b/src/CBot/CBotInstr/CBotExprLitNum.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -24,25 +24,24 @@ namespace CBot { +CBotInstr* CompileExprLitNum(CBotToken* &p, CBotCStack* pStack); + +CBotInstr* CompileSizeOf(CBotToken* &p, CBotCStack* pStack); + /** * \brief A number literal - 5, 1, 2.5, 3.75, etc. or a predefined numerical constant (see CBotToken::DefineNum()) * - * Can be of type ::CBotTypInt or ::CBotTypFloat + * Can be of type ::CBotTypInt, ::CBotTypLong, ::CBotTypFloat, or ::CBotTypDouble */ +template class CBotExprLitNum : public CBotInstr { public: - CBotExprLitNum(); - ~CBotExprLitNum(); + // To keep linter happy, instead of = delete (see https://stackoverflow.com/a/37593094) + CBotExprLitNum(T val) { static_assert(sizeof(T) == 0, "Only specializations of CBotExprLitNum can be used"); }; - /*! - * \brief Compile - * \param p - * \param pStack - * \return - */ - static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack); + ~CBotExprLitNum(); /*! * \brief Execute Execute, returns the corresponding number. @@ -65,10 +64,8 @@ protected: private: //! The type of number. CBotType m_numtype; - //! Value for an int. - long m_valint; - //! Value for a float. - float m_valfloat; + //! Value + T m_value; }; diff --git a/src/CBot/CBotInstr/CBotExprLitString.cpp b/src/CBot/CBotInstr/CBotExprLitString.cpp index 72cca72b..70eea871 100644 --- a/src/CBot/CBotInstr/CBotExprLitString.cpp +++ b/src/CBot/CBotInstr/CBotExprLitString.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -24,6 +24,8 @@ #include "CBot/CBotVar/CBotVar.h" +#include + namespace CBot { @@ -42,7 +44,7 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack) { CBotCStack* pStk = pStack->TokenStack(); - std::string s = p->GetString(); + const auto& s = p->GetString(); auto it = s.cbegin(); if (++it != s.cend()) @@ -51,7 +53,7 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack) std::string valstring = ""; while (it != s.cend() && *it != '\"') { - pStk->SetStartError(++pos); + ++pos; if (*it != '\\') // not escape sequence ? { valstring += *(it++); @@ -59,6 +61,7 @@ CBotInstr* CBotExprLitString::Compile(CBotToken* &p, CBotCStack* pStack) } if (++it == s.cend()) break; + pStk->SetStartError(pos); if (CharInList(*it, "01234567")) // octal { diff --git a/src/CBot/CBotInstr/CBotExprLitString.h b/src/CBot/CBotInstr/CBotExprLitString.h index 59d3ae52..f5d423c6 100644 --- a/src/CBot/CBotInstr/CBotExprLitString.h +++ b/src/CBot/CBotInstr/CBotExprLitString.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprRetVar.cpp b/src/CBot/CBotInstr/CBotExprRetVar.cpp index 3d0305f3..1a85cdae 100644 --- a/src/CBot/CBotInstr/CBotExprRetVar.cpp +++ b/src/CBot/CBotInstr/CBotExprRetVar.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprRetVar.h b/src/CBot/CBotInstr/CBotExprRetVar.h index 31606a3c..d0e6eaf9 100644 --- a/src/CBot/CBotInstr/CBotExprRetVar.h +++ b/src/CBot/CBotInstr/CBotExprRetVar.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprUnaire.cpp b/src/CBot/CBotInstr/CBotExprUnaire.cpp index c39fd89e..8d8e7a16 100644 --- a/src/CBot/CBotInstr/CBotExprUnaire.cpp +++ b/src/CBot/CBotInstr/CBotExprUnaire.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -40,8 +40,7 @@ CBotExprUnaire::~CBotExprUnaire() delete m_expr; } -//////////////////////////////////////////////////////////////////////////////// -CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral) +CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral, bool bConstExpr) { int op = p->GetType(); CBotToken* pp = p; @@ -52,8 +51,10 @@ CBotInstr* CBotExprUnaire::Compile(CBotToken* &p, CBotCStack* pStack, bool bLite CBotExprUnaire* inst = new CBotExprUnaire(); inst->SetToken(pp); - if (!bLiteral) inst->m_expr = CBotParExpr::Compile(p, pStk); - else inst->m_expr = CBotParExpr::CompileLitExpr(p, pStk); + if (bConstExpr || !bLiteral) + inst->m_expr = CBotParExpr::Compile(p, pStk, bConstExpr); + else + inst->m_expr = CBotParExpr::CompileLitExpr(p, pStk); if (inst->m_expr != nullptr) { diff --git a/src/CBot/CBotInstr/CBotExprUnaire.h b/src/CBot/CBotInstr/CBotExprUnaire.h index 8a743a81..554b1c6a 100644 --- a/src/CBot/CBotInstr/CBotExprUnaire.h +++ b/src/CBot/CBotInstr/CBotExprUnaire.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -40,7 +40,7 @@ public: * \param bLiteral If true, compiles only literal expressions Ex: ~11, -4.0, !false, not true * \return The compiled instruction or nullptr */ - static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral = false); + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bLiteral = false, bool bConstExpr = false); /*! * \brief Execute diff --git a/src/CBot/CBotInstr/CBotExprVar.cpp b/src/CBot/CBotInstr/CBotExprVar.cpp index 2b09f59c..8c02c475 100644 --- a/src/CBot/CBotInstr/CBotExprVar.cpp +++ b/src/CBot/CBotInstr/CBotExprVar.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExprVar.h b/src/CBot/CBotInstr/CBotExprVar.h index 50a3a528..0c0c2b9b 100644 --- a/src/CBot/CBotInstr/CBotExprVar.h +++ b/src/CBot/CBotInstr/CBotExprVar.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExpression.cpp b/src/CBot/CBotInstr/CBotExpression.cpp index 165d3fbc..bcf1a09b 100644 --- a/src/CBot/CBotInstr/CBotExpression.cpp +++ b/src/CBot/CBotInstr/CBotExpression.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotExpression.h b/src/CBot/CBotInstr/CBotExpression.h index 7299843c..ce78ae66 100644 --- a/src/CBot/CBotInstr/CBotExpression.h +++ b/src/CBot/CBotInstr/CBotExpression.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotFieldExpr.cpp b/src/CBot/CBotInstr/CBotFieldExpr.cpp index 9b79272d..1abcbaf3 100644 --- a/src/CBot/CBotInstr/CBotFieldExpr.cpp +++ b/src/CBot/CBotInstr/CBotFieldExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotFieldExpr.h b/src/CBot/CBotInstr/CBotFieldExpr.h index 05270d5c..073e6dfb 100644 --- a/src/CBot/CBotInstr/CBotFieldExpr.h +++ b/src/CBot/CBotInstr/CBotFieldExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotFor.cpp b/src/CBot/CBotInstr/CBotFor.cpp index 92aafa0b..8aa2375d 100644 --- a/src/CBot/CBotInstr/CBotFor.cpp +++ b/src/CBot/CBotInstr/CBotFor.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -67,7 +67,7 @@ CBotInstr* CBotFor::Compile(CBotToken* &p, CBotCStack* pStack) return nullptr; } - CBotCStack* pStk = pStack->TokenStack(pp, true); // un petit bout de pile svp + CBotCStack* pStk = pStack->TokenStack(pp, true); // some size for a stack, plz // compiles instructions for initialization inst->m_init = CBotListExpression::Compile(p, pStk ); diff --git a/src/CBot/CBotInstr/CBotFor.h b/src/CBot/CBotInstr/CBotFor.h index 6ff431bb..4aa90553 100644 --- a/src/CBot/CBotInstr/CBotFor.h +++ b/src/CBot/CBotInstr/CBotFor.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotFunction.cpp b/src/CBot/CBotInstr/CBotFunction.cpp index b4473cd8..e4a62e95 100644 --- a/src/CBot/CBotInstr/CBotFunction.cpp +++ b/src/CBot/CBotInstr/CBotFunction.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -76,6 +76,18 @@ bool CBotFunction::IsPublic() return m_bPublic; } +//////////////////////////////////////////////////////////////////////////////// +bool CBotFunction::IsProtected() const +{ + return m_bProtect; +} + +//////////////////////////////////////////////////////////////////////////////// +bool CBotFunction::IsPrivate() const +{ + return m_bPrivate; +} + //////////////////////////////////////////////////////////////////////////////// bool CBotFunction::IsExtern() { @@ -129,21 +141,17 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct { CBotToken* pp; CBotFunction* func = finput; - if ( func == nullptr ) func = new CBotFunction(); + assert(func != nullptr); // a pre-compiled function is required CBotCStack* pStk = pStack->TokenStack(p, bLocal); -// func->m_nFuncIdent = CBotVar::NextUniqNum(); - while (true) { - if ( IsOfType(p, ID_PUBLIC) ) - { - func->m_bPublic = true; - continue; - } + if (IsOfType(p, ID_PRIVATE)) break; + if (IsOfType(p, ID_PROTECTED)) break; + if (IsOfType(p, ID_PUBLIC)) continue; pp = p; - if ( IsOfType(p, ID_EXTERN) ) + if (IsOfType(p, ID_EXTERN)) { func->m_extern = *pp; // for the position of the word "extern" func->m_bExtern = true; @@ -169,7 +177,7 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct func->m_token = d; } - // un nom de fonction est-il là ? + // is there a function name here ? if (IsOfType(p, TokenTypVar)) { if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class @@ -183,10 +191,23 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct goto bad; } -// pp = p; + pp = p; func->m_token = *p; if (!IsOfType(p, TokenTypVar)) goto bad; - + // check if the class has a method like this + if (pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) + { + pStk->SetStartError(func->m_classToken.GetStart()); + pStk->SetError(CBotErrRedefFunc, pp->GetEnd()); + goto bad; + } + // check if a constructor has return type void + if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid)) + { + pp = &(func->m_retToken); + pStk->SetError(CBotErrFuncNotVoid, pp); + goto bad; + } } func->m_openpar = *p; delete func->m_param; @@ -198,28 +219,13 @@ CBotFunction* CBotFunction::Compile(CBotToken* &p, CBotCStack* pStack, CBotFunct if (!func->m_MasterClass.empty()) { - // return "this" known - CBotVar* pThis = CBotVar::Create("this", CBotTypResult( CBotTypClass, func->m_MasterClass )); - pThis->SetInit(CBotVar::InitType::IS_POINTER); -// pThis->SetUniqNum(func->m_nThisIdent = -2); //CBotVar::NextUniqNum() will not - pThis->SetUniqNum(-2); - pStk->AddVar(pThis); + CBotClass* pClass = CBotClass::Find(func->m_MasterClass); - // initialize variables acording to This - // only saves the pointer to the first, - // the rest is chained - CBotVar* pv = pThis->GetItemList(); -// int num = 1; - while (pv != nullptr) - { - CBotVar* pcopy = CBotVar::Create(pv); -// pcopy->SetInit(2); - pcopy->Copy(pv); - pcopy->SetPrivate(pv->GetPrivate()); -// pcopy->SetUniqNum(pv->GetUniqNum()); //num++); - pStk->AddVar(pcopy); - pv = pv->GetNext(); - } + pStk->CreateVarThis(pClass); + pStk->CreateVarSuper(pClass->GetParent()); + + bool bConstructor = (func->GetName() == func->m_MasterClass); + pStk->CreateMemberVars(pClass, !bConstructor); } // and compiles the following instruction block @@ -242,7 +248,6 @@ bad: pStk->SetError(CBotErrNoFunc, p); } pStk->SetError(CBotErrNoType, p); - if ( finput == nullptr ) delete func; return pStack->ReturnFunc(nullptr, pStk); } @@ -254,14 +259,30 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas CBotCStack* pStk = pStack->TokenStack(p, true); + CBotToken* pPriv = p; + while (true) { - if ( IsOfType(p, ID_PUBLIC) ) + if (!func->m_bPublic) // don't repeat 'public' { - // func->m_bPublic = true; // will be done in two passes - continue; + pPriv = p; + if (IsOfType(p, ID_PRIVATE)) + { + func->m_bPrivate = true; + break; + } + if (IsOfType(p, ID_PROTECTED)) + { + func->m_bProtect = true; + break; + } + if (IsOfType(p, ID_PUBLIC)) + { + func->m_bPublic = true; + continue; + } } - if ( IsOfType(p, ID_EXTERN) ) + if (!func->m_bExtern && IsOfType(p, ID_EXTERN)) { func->m_bExtern = true; continue; @@ -284,7 +305,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas func->m_token = d; } - // un nom de fonction est-il là ? + // is there a function name here ? if (IsOfType(p, TokenTypVar)) { if ( IsOfType( p, ID_DBLDOTS ) ) // method for a class @@ -297,12 +318,21 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas if (!IsOfType(p, TokenTypVar)) goto bad; } + else if (pClass == nullptr) // not method in a class ? + { + if (func->m_bPrivate || func->m_bProtect) // not allowed for regular functions + { + pStk->SetError(CBotErrNoType, pPriv); + goto bad; + } + } CBotToken* openPar = p; func->m_param = CBotDefParam::Compile(p, pStk); // compile parameters if (pStk->IsOk() && pClass != nullptr) // method in a class { + func->m_MasterClass = pClass->GetName(); // check if a constructor has return type void if (func->GetName() == pClass->GetName() && !func->m_retTyp.Eq(CBotTypVoid)) { @@ -331,7 +361,7 @@ CBotFunction* CBotFunction::Compile1(CBotToken* &p, CBotCStack* pStack, CBotClas { // looks if the function exists elsewhere pp = &(func->m_token); - if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param)) && + if (( pClass != nullptr || !pStack->CheckCall(pp, func->m_param, func->m_MasterClass)) && ( pClass == nullptr || !pClass->CheckCall(pStack->GetProgram(), func->m_param, pp)) ) { if (IsOfType(p, ID_OPBLK)) @@ -415,7 +445,7 @@ bool CBotFunction::Execute(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInstance) pile->IncState(); } - if ( !m_block->Execute(pile) ) + if (!pile->GetRetVar(m_block->Execute(pile))) { if ( pile->GetError() < 0 ) pile->SetError( CBotNoErr ); @@ -472,10 +502,10 @@ void CBotFunction::RestoreState(CBotVar** ppVars, CBotStack* &pj, CBotVar* pInst } //////////////////////////////////////////////////////////////////////////////// -CBotTypResult CBotFunction::CompileCall(const std::list& localFunctionList, const std::string &name, CBotVar** ppVars, long &nIdent) +CBotTypResult CBotFunction::CompileCall(const std::string &name, CBotVar** ppVars, long &nIdent, CBotProgram* program) { CBotTypResult type; - if (!FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type)) + if (!FindLocalOrPublic(program->GetFunctions(), nIdent, name, ppVars, type, program)) { // Reset the identifier to "not found" value nIdent = 0; @@ -485,7 +515,7 @@ CBotTypResult CBotFunction::CompileCall(const std::list& localFun //////////////////////////////////////////////////////////////////////////////// CBotFunction* CBotFunction::FindLocalOrPublic(const std::list& localFunctionList, long &nIdent, const std::string &name, - CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic) + CBotVar** ppVars, CBotTypResult &TypeOrError, CBotProgram* baseProg) { TypeOrError.SetType(CBotErrUndefCall); // no routine of the name @@ -515,10 +545,39 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list& lo std::map funcMap; - for (CBotFunction* pt : localFunctionList) + CBotFunction::SearchList(localFunctionList, name, ppVars, TypeOrError, funcMap); + + CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap); + + if (baseProg != nullptr && baseProg->m_thisVar != nullptr) + { + // find object:: functions + CBotClass* pClass = baseProg->m_thisVar->GetClass(); + CBotFunction::SearchList(localFunctionList, name, ppVars, TypeOrError, funcMap, pClass); + CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap, pClass); + } + + return CBotFunction::BestFunction(funcMap, nIdent, TypeOrError); +} + +//////////////////////////////////////////////////////////////////////////////// +void CBotFunction::SearchList(const std::list& functionList, + const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError, + std::map& funcMap, CBotClass* pClass) +{ + for (CBotFunction* pt : functionList) { if ( pt->m_token.GetString() == name ) { + if (pClass != nullptr) // looking for a method ? + { + if (pt->m_MasterClass != pClass->GetName()) continue; + } + else // looking for a function + { + if (!pt->m_MasterClass.empty()) continue; + } + int i = 0; int alpha = 0; // signature of parameters // parameters are compatible? @@ -575,16 +634,29 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list& lo funcMap.insert( std::pair(pt, alpha) ); } } +} - if ( bPublic ) +//////////////////////////////////////////////////////////////////////////////// +void CBotFunction::SearchPublic(const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError, + std::map& funcMap, CBotClass* pClass) +{ { for (CBotFunction* pt : m_publicFunctions) { if ( pt->m_token.GetString() == name ) { + if (pClass != nullptr) // looking for a method ? + { + if (pt->m_MasterClass != pClass->GetName()) continue; + } + else // looking for a function + { + if (!pt->m_MasterClass.empty()) continue; + } + int i = 0; int alpha = 0; // signature of parameters - // parameters sont-ils compatibles ? + // are parameters compatible ? CBotDefParam* pv = pt->m_param; // list of expected parameters CBotVar* pw = ppVars[i++]; // list of provided parameters while ( pv != nullptr && (pw != nullptr || pv->HasDefault()) ) @@ -639,7 +711,12 @@ CBotFunction* CBotFunction::FindLocalOrPublic(const std::list& lo } } } +} +//////////////////////////////////////////////////////////////////////////////// +CBotFunction* CBotFunction::BestFunction(std::map& funcMap, + long& nIdent, CBotTypResult& TypeOrError) +{ if ( !funcMap.empty() ) { auto it = funcMap.begin(); @@ -675,7 +752,7 @@ int CBotFunction::DoCall(CBotProgram* program, const std::list& l CBotFunction* pt = nullptr; CBotProgram* baseProg = pStack->GetProgram(true); - pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type); + pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, baseProg); if ( pt != nullptr ) { @@ -766,7 +843,7 @@ void CBotFunction::RestoreCall(const std::list& localFunctionList CBotStack* pStk3; CBotProgram* baseProg = pStack->GetProgram(true); - pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type); + pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, baseProg); if ( pt != nullptr ) { @@ -824,13 +901,121 @@ void CBotFunction::RestoreCall(const std::list& localFunctionList } //////////////////////////////////////////////////////////////////////////////// -int CBotFunction::DoCall(const std::list& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, +CBotTypResult CBotFunction::CompileMethodCall(const std::string& name, CBotVar** ppVars, + long& nIdent, CBotCStack* pStack, CBotClass* pClass) +{ + nIdent = 0; + CBotTypResult type; + + CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pStack->GetProgram()); + + if (pt != nullptr) + { + CBotToken token("this"); + CBotVar* pThis = pStack->FindVar(token); // for 'this' context + + if (pThis == nullptr || pThis->GetType() != CBotTypPointer) // called from inside a function + { + if (pt->IsPrivate() || pt->IsProtected()) + type.SetType(CBotErrPrivate); + } + else // called from inside a method + { + CBotClass* thisClass = pThis->GetClass(); // current class + CBotClass* funcClass = CBotClass::Find(pt->m_MasterClass); // class of the method + + if (pt->IsPrivate() && thisClass != funcClass) + type.SetType(CBotErrPrivate); + + if (pt->IsProtected() && !thisClass->IsChildOf(funcClass)) + type.SetType(CBotErrPrivate); + } + } + + return type; +} + +//////////////////////////////////////////////////////////////////////////////// +CBotFunction* CBotFunction::FindMethod(long& nIdent, const std::string& name, + CBotVar** ppVars, CBotTypResult& TypeOrError, + CBotClass* pClass, CBotProgram* program) +{ + TypeOrError.SetType(CBotErrUndefCall); // no routine of the name + + auto methods = pClass->GetFunctions(); + + if ( nIdent ) + { + // search methods in the class + for (CBotFunction* pt : methods) + { + if ( pt->m_nFuncIdent == nIdent ) + { + TypeOrError = pt->m_retTyp; + return pt; + } + } + + bool skipPublic = false; + if (program != nullptr) + { + // search the current program + for (CBotFunction* pt : program->GetFunctions()) + { + if ( pt->m_nFuncIdent == nIdent ) + { + // check if the method is inherited + if ( pt->GetClassName() != pClass->GetName() ) + { + skipPublic = true; + break; // break in case there is an override + } + TypeOrError = pt->m_retTyp; + return pt; + } + } + } + + // search the list of public functions + if (!skipPublic) + { + for (CBotFunction* pt : m_publicFunctions) + { + if (pt->m_nFuncIdent == nIdent) + { + // check if the method is inherited, break in case there is an override + if ( pt->GetClassName() != pClass->GetName() ) break; + TypeOrError = pt->m_retTyp; + return pt; + } + } + } + } + + if ( name.empty() ) return nullptr; + + std::map funcMap; + + // search methods in the class + CBotFunction::SearchList(methods, name, ppVars, TypeOrError, funcMap, pClass); + + // search the current program for methods + if (program != nullptr) + CBotFunction::SearchList(program->GetFunctions(), name, ppVars, TypeOrError, funcMap, pClass); + + CBotFunction::SearchPublic(name, ppVars, TypeOrError, funcMap, pClass); + + return CBotFunction::BestFunction(funcMap, nIdent, TypeOrError); +} + +//////////////////////////////////////////////////////////////////////////////// +int CBotFunction::DoCall(long &nIdent, const std::string &name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass) { CBotTypResult type; CBotProgram* pProgCurrent = pStack->GetProgram(); - CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type, false); + CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pProgCurrent); if ( pt != nullptr ) { @@ -925,11 +1110,11 @@ int CBotFunction::DoCall(const std::list& localFunctionList, long } //////////////////////////////////////////////////////////////////////////////// -bool CBotFunction::RestoreCall(const std::list& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, +bool CBotFunction::RestoreCall(long &nIdent, const std::string &name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass) { CBotTypResult type; - CBotFunction* pt = FindLocalOrPublic(localFunctionList, nIdent, name, ppVars, type); + CBotFunction* pt = FindMethod(nIdent, name, ppVars, type, pClass, pStack->GetProgram()); if ( pt != nullptr ) { @@ -1020,6 +1205,12 @@ std::string CBotFunction::GetParams() return params; } +//////////////////////////////////////////////////////////////////////////////// +const std::string& CBotFunction::GetClassName() const +{ + return m_MasterClass; +} + //////////////////////////////////////////////////////////////////////////////// void CBotFunction::AddPublic(CBotFunction* func) { diff --git a/src/CBot/CBotInstr/CBotFunction.h b/src/CBot/CBotInstr/CBotFunction.h index b16780cd..dad5e90d 100644 --- a/src/CBot/CBotInstr/CBotFunction.h +++ b/src/CBot/CBotInstr/CBotFunction.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -105,21 +105,19 @@ public: * * See FindLocalOrPublic for more detailed explanation * - * \param localFunctionList Linked list of local functions to search in, can be null * \param name Name of the function * \param ppVars List of function arguments * \param nIdent[in, out] Unique identifier of the function + * \param program The current program, to search for functions. * \return Type returned by the function or error code * \see FindLocalOrPublic */ - static CBotTypResult CompileCall(const std::list& localFunctionList, - const std::string &name, CBotVar** ppVars, long &nIdent); + static CBotTypResult CompileCall(const std::string &name, CBotVar** ppVars, + long &nIdent, CBotProgram* program); /*! * \brief Finds a local or public function * - *

Finds a local or (if bPublic is true) public function to call - * *

First, it looks for a function according to its unique identifier.
* If the identifier is not found, looks by name and parameters. * @@ -128,11 +126,46 @@ public: * \param name Name of the function * \param ppVars List of function arguments * \param TypeOrError Type returned by the function or error code - * \param bPublic Whether to look in public functions or not + * \param baseProg Initial program, for context of the object/bot * \return Pointer to found CBotFunction instance, or nullptr in case of no match or ambiguity (see TypeOrError for error code) */ static CBotFunction* FindLocalOrPublic(const std::list& localFunctionList, long &nIdent, const std::string &name, - CBotVar** ppVars, CBotTypResult &TypeOrError, bool bPublic = true); + CBotVar** ppVars, CBotTypResult &TypeOrError, CBotProgram* baseProg); + + /*! + * \brief Find all functions that match the name and arguments. + * \param functionList List of functions to search, can be empty. + * \param name Name of the function to find. + * \param ppVars Arguments to compare with parameters. + * \param TypeOrError Contains a CBotError when no useable function has been found. + * \param funcMap Container for suitable functions and their signature values. + * \param pClass Pointer to class when searching for methods. + */ + static void SearchList(const std::list& functionList, + const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError, + std::map& funcMap, CBotClass* pClass = nullptr); + + /*! + * \brief Find all public functions that match the name and arguments. + * \param name Name of the function to find. + * \param ppVars Arguments to compare with parameters. + * \param TypeOrError Contains a CBotError when no useable function has been found. + * \param funcMap Container for suitable functions and their signature values. + * \param pClass Pointer to class when searching for methods. + */ + static void SearchPublic(const std::string& name, CBotVar** ppVars, CBotTypResult& TypeOrError, + std::map& funcMap, CBotClass* pClass = nullptr); + + /*! + * \brief Find the function with the lowest signature value. If there is more + * than one of the same signature value, TypeOrError is set to CBotErrAmbiguousCall. + * \param funcMap List of functions and their signature values, can be empty. + * \param[out] nIdent Unique identifier of the function. + * \param TypeOrError Type returned by the function or error code. + * \return Pointer to the function with the lowest signature or nullptr. + */ + static CBotFunction* BestFunction(std::map& funcMap, + long& nIdent, CBotTypResult& TypeOrError); /*! * \brief DoCall Fait un appel à une fonction. @@ -160,10 +193,34 @@ public: static void RestoreCall(const std::list& localFunctionList, long &nIdent, const std::string &name, CBotVar** ppVars, CBotStack* pStack); + /*! + * \brief Find a method matching the name and arguments. + * \param name Name of the method to find. + * \param ppVars Arguments to compare with parameters. + * \param[out] nIdent Unique identifier of the method. + * \param pStack Current compilation stack frame. + * \param pClass Pointer to the class. + * \return The return type for the method or a CBotError. + */ + static CBotTypResult CompileMethodCall(const std::string& name, CBotVar** ppVars, + long& nIdent, CBotCStack* pStack, CBotClass* pClass); + + /*! + * \brief Find a method by its unique identifier or by name and parameters. + * \param[in,out] nIdent Unique identifier of the method. + * \param name Name of the method to find. + * \param ppVars Arguments to compare with parameters. + * \param TypeOrError The return type for the method or a CBotError. + * \param pClass Pointer to the class. + * \param program The current program, to search for out-of-class methods. + * \return Pointer to the method that best matches the given arguments or nullptr. + */ + static CBotFunction* FindMethod(long& nIdent, const std::string& name, + CBotVar** ppVars, CBotTypResult& TypeOrError, + CBotClass* pClass, CBotProgram* program); + /*! * \brief DoCall Makes call of a method - * note: this is already on the stack, the pointer pThis is just to simplify. - * \param localFunctionList * \param nIdent * \param name * \param pThis @@ -173,12 +230,11 @@ public: * \param pClass * \return */ - static int DoCall(const std::list& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, + static int DoCall(long &nIdent, const std::string &name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotToken* pToken, CBotClass* pClass); /*! * \brief RestoreCall - * \param localFunctionList * \param nIdent * \param name * \param pThis @@ -187,7 +243,7 @@ public: * \param pClass * \return Returns true if the method call was restored. */ - static bool RestoreCall(const std::list& localFunctionList, long &nIdent, const std::string &name, CBotVar* pThis, + static bool RestoreCall(long &nIdent, const std::string &name, CBotVar* pThis, CBotVar** ppVars, CBotStack* pStack, CBotClass* pClass); /*! @@ -215,12 +271,30 @@ public: */ std::string GetParams(); + /*! + * \brief Get the name of the class for a method. + * \return The name of a class or empty string if it's not a method. + */ + const std::string& GetClassName() const; + /*! * \brief IsPublic * \return */ bool IsPublic(); + /*! + * \brief Check if a method is protected. + * \return true if a method was compiled with "protected" keyword. + */ + bool IsProtected() const; + + /*! + * \brief Check if a method is private. + * \return true if a method was compiled with "private" keyword. + */ + bool IsPrivate() const; + /*! * \brief IsExtern * \return @@ -266,6 +340,10 @@ private: CBotTypResult m_retTyp; //! Public function. bool m_bPublic; + //! Protected method. + bool m_bProtect = false; + //! Private method. + bool m_bPrivate = false; //! Extern function. bool m_bExtern; //! Name of the class we are part of diff --git a/src/CBot/CBotInstr/CBotIf.cpp b/src/CBot/CBotInstr/CBotIf.cpp index 5d8e309a..e5031378 100644 --- a/src/CBot/CBotInstr/CBotIf.cpp +++ b/src/CBot/CBotInstr/CBotIf.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotIf.h b/src/CBot/CBotInstr/CBotIf.h index e558fc63..98b5f039 100644 --- a/src/CBot/CBotInstr/CBotIf.h +++ b/src/CBot/CBotInstr/CBotIf.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotIndexExpr.cpp b/src/CBot/CBotInstr/CBotIndexExpr.cpp index bad92fc1..7bc01639 100644 --- a/src/CBot/CBotInstr/CBotIndexExpr.cpp +++ b/src/CBot/CBotInstr/CBotIndexExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotIndexExpr.h b/src/CBot/CBotInstr/CBotIndexExpr.h index 8844604b..52d72ba1 100644 --- a/src/CBot/CBotInstr/CBotIndexExpr.h +++ b/src/CBot/CBotInstr/CBotIndexExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotInstr.cpp b/src/CBot/CBotInstr/CBotInstr.cpp index f69785f6..0115ba28 100644 --- a/src/CBot/CBotInstr/CBotInstr.cpp +++ b/src/CBot/CBotInstr/CBotInstr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -30,6 +30,7 @@ #include "CBot/CBotInstr/CBotExpression.h" #include "CBot/CBotInstr/CBotFor.h" #include "CBot/CBotInstr/CBotIf.h" +#include "CBot/CBotInstr/CBotRepeat.h" #include "CBot/CBotInstr/CBotReturn.h" #include "CBot/CBotInstr/CBotSwitch.h" #include "CBot/CBotInstr/CBotThrow.h" @@ -176,7 +177,7 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack) { type = pp->GetType(); // Allow only instructions that accept a label - if (!IsOfTypeList(pp, ID_WHILE, ID_FOR, ID_DO, 0)) + if (!IsOfTypeList(pp, ID_WHILE, ID_FOR, ID_DO, ID_REPEAT, 0)) { pStack->SetError(CBotErrLabel, pp->GetStart()); return nullptr; @@ -195,6 +196,9 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack) case ID_DO: return CBotDo::Compile(p, pStack); + case ID_REPEAT: + return CBotRepeat::Compile(p, pStack); + case ID_BREAK: case ID_CONTINUE: return CBotBreak::Compile(p, pStack); @@ -208,10 +212,15 @@ CBotInstr* CBotInstr::Compile(CBotToken* &p, CBotCStack* pStack) case ID_THROW: return CBotThrow::Compile(p, pStack); + case ID_BYTE: + case ID_SHORT: + case ID_CHAR: case ID_INT: + case ID_LONG: return CBotDefInt::Compile(p, pStack); case ID_FLOAT: + case ID_DOUBLE: return CBotDefFloat::Compile(p, pStack); case ID_STRING: @@ -312,13 +321,6 @@ void CBotInstr::RestoreStateVar(CBotStack* &pile, bool bMain) assert(0); // dad do not know, see the girls } -//////////////////////////////////////////////////////////////////////////////// -bool CBotInstr::CompCase(CBotStack* &pj, int val) -{ - return false; -} - -//////////////////////////////////////////////////////////////////////////////// CBotInstr* CBotInstr::CompileArray(CBotToken* &p, CBotCStack* pStack, CBotTypResult type, bool first) { if (IsOfType(p, ID_OPBRK)) diff --git a/src/CBot/CBotInstr/CBotInstr.h b/src/CBot/CBotInstr/CBotInstr.h index 712b379d..235055f4 100644 --- a/src/CBot/CBotInstr/CBotInstr.h +++ b/src/CBot/CBotInstr/CBotInstr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -191,17 +191,6 @@ public: virtual void RestoreStateVar(CBotStack* &pile, bool bMain); - /** - * \brief CompCase This routine is defined only for the subclass CBotCase - * this allows to make the call on all instructions CompCase to see if it's - * a case to the desired value.. - * \param pj - * \param val - * \return - */ - virtual bool CompCase(CBotStack* &pj, - int val); - /** * \brief SetToken Set the token corresponding to the instruction. * \param p diff --git a/src/CBot/CBotInstr/CBotInstrCall.cpp b/src/CBot/CBotInstr/CBotInstrCall.cpp index 58203e80..2274f3ac 100644 --- a/src/CBot/CBotInstr/CBotInstrCall.cpp +++ b/src/CBot/CBotInstr/CBotInstrCall.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -78,12 +78,12 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack) { // if (pVar2!=nullptr) pp = pVar2->RetToken(); pStack->SetError( static_cast(inst->m_typRes.GetType()), pp ); - delete pStack->TokenStack(); + pStack->DeleteNext(); delete inst; return nullptr; } - delete pStack->TokenStack(); + pStack->DeleteNext(); if ( inst->m_typRes.GetType() > 0 ) { CBotVar* pRes = CBotVar::Create("", inst->m_typRes); @@ -94,7 +94,7 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack) if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack))) { inst->m_exprRetVar->SetToken(&inst->m_token); - delete pStack->TokenStack(); + pStack->DeleteNext(); } if ( !pStack->IsOk() ) { @@ -105,7 +105,7 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack) return inst; } p = pp; - delete pStack->TokenStack(); + pStack->DeleteNext(); return nullptr; } @@ -138,6 +138,7 @@ bool CBotInstrCall::Execute(CBotStack* &pj) if ( p != nullptr) while ( true ) { pile = pile->AddStack(); // place on the stack for the results + if (pile->StackOver()) return pj->Return(pile); if ( pile->GetState() == 0 ) { if (!p->Execute(pile)) return false; // interrupted here? diff --git a/src/CBot/CBotInstr/CBotInstrCall.h b/src/CBot/CBotInstr/CBotInstrCall.h index 88c82759..e4e13545 100644 --- a/src/CBot/CBotInstr/CBotInstrCall.h +++ b/src/CBot/CBotInstr/CBotInstrCall.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotInstrMethode.cpp b/src/CBot/CBotInstr/CBotInstrMethode.cpp index 386e8f3a..6b7045e3 100644 --- a/src/CBot/CBotInstr/CBotInstrMethode.cpp +++ b/src/CBot/CBotInstr/CBotInstrMethode.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -70,7 +70,7 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* CBotClass* pClass = var->GetClass(); // pointer to the class inst->m_className = pClass->GetName(); // name of the class CBotTypResult r = pClass->CompileMethode(pp, var, ppVars, pStack, inst->m_MethodeIdent); - delete pStack->TokenStack(); // release parameters on the stack + pStack->DeleteNext(); // release parameters on the stack inst->m_typRes = r; if (inst->m_typRes.GetType() > 20) @@ -95,7 +95,7 @@ CBotInstr* CBotInstrMethode::Compile(CBotToken* &p, CBotCStack* pStack, CBotVar* if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStack, bMethodChain))) { inst->m_exprRetVar->SetToken(pp); - delete pStack->TokenStack(); + pStack->DeleteNext(); } if ( pStack->IsOk() ) @@ -164,6 +164,7 @@ bool CBotInstrMethode::ExecuteVar(CBotVar* &pVar, CBotStack* &pj, CBotToken* pre } ppVars[i++] = pile2->GetVar(); // construct the list of pointers pile2 = pile2->AddStack(); // space on the stack for the result + if (pile2->StackOver()) return pj->Return(pile2); p = p->GetNext(); if ( p == nullptr) break; } diff --git a/src/CBot/CBotInstr/CBotInstrMethode.h b/src/CBot/CBotInstr/CBotInstrMethode.h index c14815ca..2d0b33ef 100644 --- a/src/CBot/CBotInstr/CBotInstrMethode.h +++ b/src/CBot/CBotInstr/CBotInstrMethode.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotInstrUtils.cpp b/src/CBot/CBotInstr/CBotInstrUtils.cpp index 04c42211..c4638d60 100644 --- a/src/CBot/CBotInstr/CBotInstrUtils.cpp +++ b/src/CBot/CBotInstr/CBotInstrUtils.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -65,7 +65,7 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars) { if (pile->GetTypResult().Eq(99)) { - delete pStack->TokenStack(); + pStack->DeleteNext(); pStack->SetError(CBotErrVoid, p->GetStart()); return nullptr; } @@ -78,7 +78,7 @@ CBotInstr* CompileParams(CBotToken* &p, CBotCStack* pStack, CBotVar** ppVars) } pStack->SetError(CBotErrClosePar, p->GetStart()); - delete pStack->TokenStack(); + pStack->DeleteNext(); return nullptr; } } @@ -129,6 +129,13 @@ bool TypeCompatible(CBotTypResult& type1, CBotTypResult& type2, int op) return true; } + if (op == ID_ASR || op == ID_SR || op == ID_SL || + op == ID_ASSOR || op == ID_ASSSL || op == ID_ASSSR || + op == ID_ASSAND || op == ID_ASSXOR || op == ID_ASSASR) + { + if (max > CBotTypLong) return false; + } + type1.SetType(max); type2.SetType(max); return true; diff --git a/src/CBot/CBotInstr/CBotInstrUtils.h b/src/CBot/CBotInstr/CBotInstrUtils.h index 88d2a96e..21b98a7e 100644 --- a/src/CBot/CBotInstr/CBotInstrUtils.h +++ b/src/CBot/CBotInstr/CBotInstrUtils.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotLeftExpr.cpp b/src/CBot/CBotInstr/CBotLeftExpr.cpp index 25f147a5..74e20006 100644 --- a/src/CBot/CBotInstr/CBotLeftExpr.cpp +++ b/src/CBot/CBotInstr/CBotLeftExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotLeftExpr.h b/src/CBot/CBotInstr/CBotLeftExpr.h index e19ef01e..13f46210 100644 --- a/src/CBot/CBotInstr/CBotLeftExpr.h +++ b/src/CBot/CBotInstr/CBotLeftExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotLeftExprVar.cpp b/src/CBot/CBotInstr/CBotLeftExprVar.cpp index bac68394..563cbc7f 100644 --- a/src/CBot/CBotInstr/CBotLeftExprVar.cpp +++ b/src/CBot/CBotInstr/CBotLeftExprVar.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotLeftExprVar.h b/src/CBot/CBotInstr/CBotLeftExprVar.h index 37582a4b..1690636e 100644 --- a/src/CBot/CBotInstr/CBotLeftExprVar.h +++ b/src/CBot/CBotInstr/CBotLeftExprVar.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotListArray.cpp b/src/CBot/CBotInstr/CBotListArray.cpp index b6658aa6..d758652d 100644 --- a/src/CBot/CBotInstr/CBotListArray.cpp +++ b/src/CBot/CBotInstr/CBotListArray.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotListArray.h b/src/CBot/CBotInstr/CBotListArray.h index 927db579..80c94abc 100644 --- a/src/CBot/CBotInstr/CBotListArray.h +++ b/src/CBot/CBotInstr/CBotListArray.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotListExpression.cpp b/src/CBot/CBotInstr/CBotListExpression.cpp index d428383e..1f0765ea 100644 --- a/src/CBot/CBotInstr/CBotListExpression.cpp +++ b/src/CBot/CBotInstr/CBotListExpression.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotListExpression.h b/src/CBot/CBotInstr/CBotListExpression.h index b793fc60..0ce717b3 100644 --- a/src/CBot/CBotInstr/CBotListExpression.h +++ b/src/CBot/CBotInstr/CBotListExpression.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotListInstr.cpp b/src/CBot/CBotInstr/CBotListInstr.cpp index 1010b3ee..251f6304 100644 --- a/src/CBot/CBotInstr/CBotListInstr.cpp +++ b/src/CBot/CBotInstr/CBotListInstr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotListInstr.h b/src/CBot/CBotInstr/CBotListInstr.h index cddbe40f..0fab3ac0 100644 --- a/src/CBot/CBotInstr/CBotListInstr.h +++ b/src/CBot/CBotInstr/CBotListInstr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotLogicExpr.cpp b/src/CBot/CBotInstr/CBotLogicExpr.cpp index cf1df5dd..08a36671 100644 --- a/src/CBot/CBotInstr/CBotLogicExpr.cpp +++ b/src/CBot/CBotInstr/CBotLogicExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotLogicExpr.h b/src/CBot/CBotInstr/CBotLogicExpr.h index bd296a89..b8d30930 100644 --- a/src/CBot/CBotInstr/CBotLogicExpr.h +++ b/src/CBot/CBotInstr/CBotLogicExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotNew.cpp b/src/CBot/CBotInstr/CBotNew.cpp index b9438511..dd8d04ac 100644 --- a/src/CBot/CBotInstr/CBotNew.cpp +++ b/src/CBot/CBotInstr/CBotNew.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -87,7 +87,7 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack) // constructor exist? CBotTypResult r = pClass->CompileMethode(&inst->m_vartoken, pVar, ppVars, pStk, inst->m_nMethodeIdent); - delete pStk->TokenStack(); // release extra stack + pStk->DeleteNext(); // release extra stack int typ = r.GetType(); // if there is no constructor, and no parameters either, it's ok @@ -115,7 +115,7 @@ CBotInstr* CBotNew::Compile(CBotToken* &p, CBotCStack* pStack) if (nullptr != (inst->m_exprRetVar = CBotExprRetVar::Compile(p, pStk, true))) { inst->m_exprRetVar->SetToken(pp); - delete pStk->TokenStack(); + pStk->DeleteNext(); } if (pStack->IsOk()) @@ -189,6 +189,7 @@ bool CBotNew::Execute(CBotStack* &pj) if (p != nullptr) while ( true) { pile2 = pile2->AddStack(); // space on the stack for the result + if (pile2->StackOver()) return pj->Return(pile2); if (pile2->GetState() == 0) { if (!p->Execute(pile2)) return false; // interrupted here? diff --git a/src/CBot/CBotInstr/CBotNew.h b/src/CBot/CBotInstr/CBotNew.h index c1b2aa57..ad0c5cd3 100644 --- a/src/CBot/CBotInstr/CBotNew.h +++ b/src/CBot/CBotInstr/CBotNew.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotParExpr.cpp b/src/CBot/CBotInstr/CBotParExpr.cpp index b879ebec..c6c50f32 100644 --- a/src/CBot/CBotInstr/CBotParExpr.cpp +++ b/src/CBot/CBotInstr/CBotParExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include "CBot/CBotInstr/CBotExpression.h" #include "CBot/CBotInstr/CBotExprLitBool.h" +#include "CBot/CBotInstr/CBotExprLitChar.h" #include "CBot/CBotInstr/CBotExprLitNan.h" #include "CBot/CBotInstr/CBotExprLitNull.h" #include "CBot/CBotInstr/CBotExprLitNum.h" @@ -31,6 +32,7 @@ #include "CBot/CBotInstr/CBotNew.h" #include "CBot/CBotInstr/CBotPostIncExpr.h" #include "CBot/CBotInstr/CBotPreIncExpr.h" +#include "CBot/CBotInstr/CBotTwoOpExpr.h" #include "CBot/CBotVar/CBotVar.h" @@ -39,13 +41,15 @@ namespace CBot { -//////////////////////////////////////////////////////////////////////////////// -CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack) +CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack, bool bConstExpr) { CBotCStack* pStk = pStack->TokenStack(); pStk->SetStartError(p->GetStart()); + if (bConstExpr) + return CBotParExpr::CompileConstExpr(p, pStack); + // is it an expression in parentheses? if (IsOfType(p, ID_OPENPAR)) { @@ -68,6 +72,13 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack) if (inst != nullptr || !pStk->IsOk()) return pStack->Return(inst, pStk); + // is it sizeof operator ? + inst = CBot::CompileSizeOf(p, pStk); + if (inst != nullptr || !pStk->IsOk()) + { + return pStack->Return(inst, pStk); + } + // is it a variable name? if (p->GetType() == TokenTypVar) { @@ -83,7 +94,7 @@ CBotInstr* CBotParExpr::Compile(CBotToken* &p, CBotCStack* pStack) CBotToken* pvar = p; - // no, it an "ordinaty" variable + // no, it's an "ordinaty" variable inst = CBotExprVar::Compile(p, pStk); CBotToken* pp = p; @@ -151,7 +162,21 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack) if (p->GetType() == TokenTypNum || p->GetType() == TokenTypDef ) { - CBotInstr* inst = CBotExprLitNum::Compile(p, pStk); + CBotInstr* inst = CBot::CompileExprLitNum(p, pStk); + return pStack->Return(inst, pStk); + } + + // is it sizeof operator ? + inst = CBot::CompileSizeOf(p, pStk); + if (inst != nullptr || !pStk->IsOk()) + { + return pStack->Return(inst, pStk); + } + + // is this a character? + if (p->GetType() == TokenTypChar) + { + CBotInstr* inst = CBotExprLitChar::Compile(p, pStk); return pStack->Return(inst, pStk); } @@ -202,4 +227,55 @@ CBotInstr* CBotParExpr::CompileLitExpr(CBotToken* &p, CBotCStack* pStack) return pStack->Return(nullptr, pStk); } +CBotInstr* CBotParExpr::CompileConstExpr(CBotToken* &p, CBotCStack* pStack) +{ + CBotCStack* pStk = pStack->TokenStack(); + + // is it an expression in parentheses? + if (IsOfType(p, ID_OPENPAR)) + { + CBotInstr* inst = CBotTwoOpExpr::Compile(p, pStk, nullptr, true); + + if (nullptr != inst) + { + if (IsOfType(p, ID_CLOSEPAR)) + { + return pStack->Return(inst, pStk); + } + pStk->SetError(CBotErrClosePar, p->GetStart()); + } + delete inst; + return pStack->Return(nullptr, pStk); + } + + // is this a unary operation? + CBotInstr* inst = CBotExprUnaire::Compile(p, pStk, true, true); + if (inst != nullptr || !pStk->IsOk()) + return pStack->Return(inst, pStk); + + // is it a number or DefineNum? + if (p->GetType() == TokenTypNum || + p->GetType() == TokenTypDef ) + { + CBotInstr* inst = CBot::CompileExprLitNum(p, pStk); + return pStack->Return(inst, pStk); + } + + // is this a character? + if (p->GetType() == TokenTypChar) + { + CBotInstr* inst = CBotExprLitChar::Compile(p, pStk); + return pStack->Return(inst, pStk); + } + + // is it sizeof operator ? + inst = CBot::CompileSizeOf(p, pStk); + if (inst != nullptr || !pStk->IsOk()) + { + return pStack->Return(inst, pStk); + } + + return pStack->Return(nullptr, pStk); +} + } // namespace CBot diff --git a/src/CBot/CBotInstr/CBotParExpr.h b/src/CBot/CBotInstr/CBotParExpr.h index 235dab11..a6bcc3c3 100644 --- a/src/CBot/CBotInstr/CBotParExpr.h +++ b/src/CBot/CBotInstr/CBotParExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -52,7 +52,7 @@ public: * \param pStack * \return */ - static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack); + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, bool bConstExpr = false); /*! * \brief Compile a literal expression ("string", number, true, false, null, nan, new) @@ -62,6 +62,8 @@ public: */ static CBotInstr* CompileLitExpr(CBotToken* &p, CBotCStack* pStack); + static CBotInstr* CompileConstExpr(CBotToken* &p, CBotCStack* pStack); + private: CBotParExpr() = delete; CBotParExpr(const CBotParExpr&) = delete; diff --git a/src/CBot/CBotInstr/CBotPostIncExpr.cpp b/src/CBot/CBotInstr/CBotPostIncExpr.cpp index b4f67a77..76193e27 100644 --- a/src/CBot/CBotInstr/CBotPostIncExpr.cpp +++ b/src/CBot/CBotInstr/CBotPostIncExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotPostIncExpr.h b/src/CBot/CBotInstr/CBotPostIncExpr.h index eae16151..49d3ce8f 100644 --- a/src/CBot/CBotInstr/CBotPostIncExpr.h +++ b/src/CBot/CBotInstr/CBotPostIncExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotPreIncExpr.cpp b/src/CBot/CBotInstr/CBotPreIncExpr.cpp index a1bb4a6a..c51d0287 100644 --- a/src/CBot/CBotInstr/CBotPreIncExpr.cpp +++ b/src/CBot/CBotInstr/CBotPreIncExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotPreIncExpr.h b/src/CBot/CBotInstr/CBotPreIncExpr.h index 61e05dcc..2eb02475 100644 --- a/src/CBot/CBotInstr/CBotPreIncExpr.h +++ b/src/CBot/CBotInstr/CBotPreIncExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotRepeat.cpp b/src/CBot/CBotInstr/CBotRepeat.cpp new file mode 100644 index 00000000..8d8e0553 --- /dev/null +++ b/src/CBot/CBotInstr/CBotRepeat.cpp @@ -0,0 +1,165 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include "CBot/CBotInstr/CBotRepeat.h" + +#include "CBot/CBotInstr/CBotBlock.h" +#include "CBot/CBotInstr/CBotExpression.h" + +#include "CBot/CBotCStack.h" +#include "CBot/CBotStack.h" + +namespace CBot +{ + +CBotRepeat::CBotRepeat() +{ + m_expr = nullptr; + m_block = nullptr; +} + +CBotRepeat::~CBotRepeat() +{ + delete m_expr; + delete m_block; +} + +CBotInstr* CBotRepeat::Compile(CBotToken* &p, CBotCStack* pStack) +{ + CBotRepeat* inst = new CBotRepeat(); // creates the object + CBotToken* pp = p; // preserves at the ^ token (starting position) + + if ( IsOfType( p, TokenTypVar ) && IsOfType( p, ID_DOTS ) ) + inst->m_label = pp->GetString(); // register the name of label + + inst->SetToken(p); + if (!IsOfType(p, ID_REPEAT)) return nullptr; // should never happen + + CBotCStack* pStk = pStack->TokenStack(pp); + + if ( IsOfType(p, ID_OPENPAR ) ) + { + CBotToken* ppp = p; // preserves the ^ token (starting position) + if ( nullptr != (inst->m_expr = CBotExpression::Compile( p, pStk )) ) + { + if ( pStk->GetType() < CBotTypLong ) + { + if ( IsOfType(p, ID_CLOSEPAR ) ) + { + IncLvl(inst->m_label); + inst->m_block = CBotBlock::CompileBlkOrInst( p, pStk, true ); + DecLvl(); + + if ( pStk->IsOk() ) // the statement block is ok (it may be empty!) + return pStack->Return(inst, pStk); + } + pStack->SetError(CBotErrClosePar, p->GetStart()); + } + pStk->SetStartError(ppp->GetStart()); + pStk->SetError(CBotErrBadType1, p->GetStart()); + } + pStack->SetError(CBotErrBadNum, p); + } + pStack->SetError(CBotErrOpenPar, p->GetStart()); + + delete inst; + return pStack->Return(nullptr, pStk); +} + +// execution of intruction "repeat" + +bool CBotRepeat::Execute(CBotStack* &pj) +{ + CBotStack* pile = pj->AddStack(this); // adds an item to the stack + // or find in case of recovery + if ( pile->IfStep() ) return false; + + while( true ) switch( pile->GetState() ) // executes the loop + { // there are two possible states (depending on recovery) + case 0: + // evaluates the number of iterations + if ( !m_expr->Execute(pile) ) return false; // interrupted here ? + + // the result of the condition is on the stack + + // terminates if an error or if the condition is false + int n; + if ( !pile->IsOk() || ( n = pile->GetVal() ) < 1 ) + return pj->Return(pile); // releases the stack + + // puts the number of iterations +1 to the "state" + + if (!pile->SetState(n+1)) return false; // ready for further + continue; // continue as a result + + case 1: + // normal end of the loop + return pj->Return(pile); // releases the stack + + default: + // evaluates the associated statement block + if ( m_block != nullptr && !m_block->Execute(pile) ) + { + if (pile->IfContinue(pile->GetState()-1, m_label)) continue; // if continued, will return to test + return pj->BreakReturn(pile, m_label); // releases the stack + } + + // terminates if there is an error + if (!pile->IsOk()) return pj->Return(pile); // releases the stack + + // returns to the test again + if (!pile->SetState(pile->GetState()-1, 0)) return false; + continue; + } +} + +void CBotRepeat::RestoreState(CBotStack* &pj, bool bMain) +{ + if ( !bMain ) return; + CBotStack* pile = pj->RestoreStack(this); // adds an item to the stack + if ( pile == nullptr ) return; + + switch( pile->GetState() ) + { // there are two possible states (depending on recovery) + case 0: + // evaluates the condition + m_expr->RestoreState(pile, bMain); + return; + + case 1: + // evaluates the associated statement block + if ( m_block != nullptr ) m_block->RestoreState(pile, bMain); + return; + } +} + +std::string CBotRepeat::GetDebugData() +{ + return !m_label.empty() ? "m_label = " + m_label : ""; +} + +std::map CBotRepeat::GetDebugLinks() +{ + auto links = CBotInstr::GetDebugLinks(); + links["m_expr"] = m_expr; + links["m_block"] = m_block; + return links; +} + +} // namespace CBot diff --git a/src/CBot/CBotInstr/CBotRepeat.h b/src/CBot/CBotInstr/CBotRepeat.h new file mode 100644 index 00000000..d60f4a09 --- /dev/null +++ b/src/CBot/CBotInstr/CBotRepeat.h @@ -0,0 +1,62 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "CBot/CBotInstr/CBotInstr.h" + +namespace CBot +{ + +/** + * \brief The "repeat" loop - repeat (times) { ... } + */ +class CBotRepeat : public CBotInstr +{ +public: + CBotRepeat(); + ~CBotRepeat(); + + /// Static method used for compilation + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack); + + /// Execute + bool Execute(CBotStack* &pj) override; + + /// Restore state + void RestoreState(CBotStack* &pj, bool bMain) override; + +protected: + virtual const std::string GetDebugName() override { return "CBotRepeat"; } + virtual std::string GetDebugData() override; + virtual std::map GetDebugLinks() override; + +private: + /// Number of iterations + CBotInstr* m_expr; + + /// Instructions + CBotInstr* m_block; + + /// Label + std::string m_label; // a label if there is + +}; + +} // namespace CBot diff --git a/src/CBot/CBotInstr/CBotReturn.cpp b/src/CBot/CBotInstr/CBotReturn.cpp index ca5871cb..b10d6ae3 100644 --- a/src/CBot/CBotInstr/CBotReturn.cpp +++ b/src/CBot/CBotInstr/CBotReturn.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotReturn.h b/src/CBot/CBotInstr/CBotReturn.h index a5ccf542..6925a2ca 100644 --- a/src/CBot/CBotInstr/CBotReturn.h +++ b/src/CBot/CBotInstr/CBotReturn.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotSwitch.cpp b/src/CBot/CBotInstr/CBotSwitch.cpp index e8d1b24d..c75e9aa1 100644 --- a/src/CBot/CBotInstr/CBotSwitch.cpp +++ b/src/CBot/CBotInstr/CBotSwitch.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -51,13 +51,13 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack) inst->SetToken(p); if (!IsOfType(p, ID_SWITCH)) return nullptr; // should never happen - CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp + CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz if ( IsOfType(p, ID_OPENPAR ) ) { if ( nullptr != (inst->m_value = CBotExpression::Compile(p, pStk )) ) { - if ( pStk->GetType() < CBotTypLong ) + if ( pStk->GetType() <= CBotTypLong ) { if ( IsOfType(p, ID_CLOSEPAR ) ) { @@ -65,21 +65,35 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack) { IncLvl(); + CBotCase* caseInst = nullptr; + CBotCStack* pStk2 = nullptr; while( !IsOfType( p, ID_CLBLK ) ) { if ( p->GetType() == ID_CASE || p->GetType() == ID_DEFAULT) { - CBotCStack* pStk2 = pStk->TokenStack(p); // un petit bout de pile svp + pStk->DeleteNext(); + pStk2 = pStk->TokenStack(p, true); // some space for a stack, plz - CBotInstr* i = CBotCase::Compile( p, pStk2 ); - if (i == nullptr) + caseInst = static_cast(CBotCase::Compile(p, pStk2, inst->m_labels)); + if (caseInst == nullptr) { delete inst; return pStack->Return(nullptr, pStk2); } - delete pStk2; - if (inst->m_block == nullptr ) inst->m_block = i; - else inst->m_block->AddNext(i); + + if (inst->m_block == nullptr ) inst->m_block = caseInst; + else inst->m_block->AddNext(caseInst); + + if (ID_DEFAULT == caseInst->GetTokenType()) + { + if (inst->m_default != nullptr) + { + pStk->SetError(CBotErrRedefCase, caseInst->GetToken()); + delete inst; + return pStack->Return(nullptr, pStk); + } + inst->m_default = caseInst; + } continue; } @@ -90,13 +104,14 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack) return pStack->Return(nullptr, pStk); } - CBotInstr* i = CBotBlock::CompileBlkOrInst( p, pStk, true ); - if ( !pStk->IsOk() ) + CBotInstr* i = CBotBlock::CompileBlkOrInst(p, pStk2); + if ( !pStk2->IsOk() ) { delete inst; - return pStack->Return(nullptr, pStk); + return pStack->Return(nullptr, pStk2); } - inst->m_block->AddNext(i); + if (caseInst->m_instr == nullptr ) caseInst->m_instr = i; + else caseInst->m_instr->AddNext(i); if ( p == nullptr ) { @@ -133,40 +148,21 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack) bool CBotSwitch :: Execute(CBotStack* &pj) { CBotStack* pile1 = pj->AddStack(this); // adds an item to the stack -// if ( pile1 == EOX ) return true; - - CBotInstr* p = m_block; // first expression int state = pile1->GetState(); if (state == 0) { if ( !m_value->Execute(pile1) ) return false; - pile1->SetState(state = -1); + pile1->SetState(state = 1); } if ( pile1->IfStep() ) return false; - if ( state == -1 ) - { - state = 0; - int val = pile1->GetVal(); // result of the value + auto it = m_labels.find(pile1->GetVar()->GetValLong()); - CBotStack* pile2 = pile1->AddStack(); - while ( p != nullptr ) // search for the corresponding case in a list - { - state++; - if ( p->CompCase( pile2, val ) ) break; // found the case - p = p->GetNext(); - } - pile2->Delete(); + CBotInstr* p = (it != m_labels.end()) ? it->second : m_default; - if ( p == nullptr ) return pj->Return(pile1); // completed if nothing - - if ( !pile1->SetState(state) ) return false; - } - - p = m_block; // returns to the beginning - while (state-->0) p = p->GetNext(); // advance in the list + while (--state > 0) p = p->GetNext(); while( p != nullptr ) { @@ -185,8 +181,6 @@ void CBotSwitch :: RestoreState(CBotStack* &pj, bool bMain) CBotStack* pile1 = pj->RestoreStack(this); // adds an item to the stack if ( pile1 == nullptr ) return; - CBotInstr* p = m_block; // first expression - int state = pile1->GetState(); if (state == 0) { @@ -194,13 +188,11 @@ void CBotSwitch :: RestoreState(CBotStack* &pj, bool bMain) return; } - if ( state == -1 ) - { - return; - } + auto it = m_labels.find(pile1->GetVar()->GetValLong()); -// p = m_block; // returns to the beginning - while ( p != nullptr && state-- > 0 ) + CBotInstr* p = (it != m_labels.end()) ? it->second : m_default; + + while (p != nullptr && --state > 0) { p->RestoreState(pile1, false); p = p->GetNext(); // advance in the list diff --git a/src/CBot/CBotInstr/CBotSwitch.h b/src/CBot/CBotInstr/CBotSwitch.h index ca6b2b20..6d94dbc3 100644 --- a/src/CBot/CBotInstr/CBotSwitch.h +++ b/src/CBot/CBotInstr/CBotSwitch.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,8 @@ #include "CBot/CBotInstr/CBotInstr.h" +#include + namespace CBot { @@ -64,8 +66,12 @@ protected: private: //! Value to seek CBotInstr* m_value; - //! Instructions - CBotInstr* m_block; + //! List of case instructions + CBotInstr* m_block = nullptr; + //! Pointer to default label + CBotInstr* m_default = nullptr; + //! Map of case labels + std::unordered_map m_labels; }; } // namespace CBot diff --git a/src/CBot/CBotInstr/CBotThrow.cpp b/src/CBot/CBotInstr/CBotThrow.cpp index 07b7dbcd..1d93e995 100644 --- a/src/CBot/CBotInstr/CBotThrow.cpp +++ b/src/CBot/CBotInstr/CBotThrow.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotThrow.h b/src/CBot/CBotInstr/CBotThrow.h index 4181c72f..f3cb4b07 100644 --- a/src/CBot/CBotInstr/CBotThrow.h +++ b/src/CBot/CBotInstr/CBotThrow.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotTry.cpp b/src/CBot/CBotInstr/CBotTry.cpp index 1a881c99..182476ff 100644 --- a/src/CBot/CBotInstr/CBotTry.cpp +++ b/src/CBot/CBotInstr/CBotTry.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -52,7 +52,7 @@ CBotInstr* CBotTry::Compile(CBotToken* &p, CBotCStack* pStack) inst->SetToken(p); if (!IsOfType(p, ID_TRY)) return nullptr; // should never happen - CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp + CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz inst->m_block = CBotBlock::CompileBlkOrInst(p, pStk ); CBotCatch** pn = &inst->m_catchList; @@ -102,11 +102,11 @@ bool CBotTry::Execute(CBotStack* &pj) val = pile1->GetError(); if ( val == CBotNoErr && pile1->GetTimer() == 0 ) // mode step? - return false; // does not make the catch + return false; // don't jump to the catch pile1->IncState(); pile2->SetState(val); // stores the error number - pile1->SetError(CBotNoErr); // for now there is are more errors! + pile1->SetError(CBotNoErr); // for now there are more errors! if ( val == CBotNoErr && pile1->GetTimer() < 0 ) // mode step? return false; // does not make the catch @@ -124,8 +124,7 @@ bool CBotTry::Execute(CBotStack* &pj) { if ( --state <= 0 ) { - // request to the catch block if they feel concerned - // demande au bloc catch s'il se sent concerné + // ask to the catch block if it feels concerned if ( !pc->TestCatch(pile2, val) ) return false; // suspend ! pile1->IncState(); } @@ -200,8 +199,7 @@ void CBotTry::RestoreState(CBotStack* &pj, bool bMain) { if ( --state <= 0 ) { - // request to the catch block if they feel concerned - // demande au bloc catch s'il se sent concerné + // ask to the catch block if it feels concerned pc->RestoreCondState(pile2, bMain); // suspend ! return; } diff --git a/src/CBot/CBotInstr/CBotTry.h b/src/CBot/CBotInstr/CBotTry.h index a9e790d1..0aa89ed6 100644 --- a/src/CBot/CBotInstr/CBotTry.h +++ b/src/CBot/CBotInstr/CBotTry.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotInstr/CBotTwoOpExpr.cpp b/src/CBot/CBotInstr/CBotTwoOpExpr.cpp index 3d5fc6a4..f57633d5 100644 --- a/src/CBot/CBotInstr/CBotTwoOpExpr.cpp +++ b/src/CBot/CBotInstr/CBotTwoOpExpr.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -133,8 +133,7 @@ static bool TypeOk(int type, int test) } } -//////////////////////////////////////////////////////////////////////////////// -CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations) +CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations, bool bConstExpr) { int typeMask; @@ -146,8 +145,8 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera // search the intructions that may be suitable to the left of the operation CBotInstr* left = (*pOp == 0) ? - CBotParExpr::Compile( p, pStk ) : // expression (...) left - CBotTwoOpExpr::Compile( p, pStk, pOp ); // expression A * B left + CBotParExpr::Compile(p, pStk, bConstExpr) : // expression (...) left + CBotTwoOpExpr::Compile(p, pStk, pOp, bConstExpr); // expression A * B left if (left == nullptr) return pStack->Return(nullptr, pStk); // if error, transmit @@ -158,7 +157,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera CBotTypResult type1, type2; type1 = pStk->GetTypResult(); // what kind of the first operand? - if (typeOp == ID_LOGIC) // special case provided for: ? op1: op2; + if (!bConstExpr && typeOp == ID_LOGIC) // special case provided for: ? op1: op2; { if ( !type1.Eq(CBotTypBoolean) ) { @@ -207,7 +206,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera // looking statements that may be suitable for right - if ( nullptr != (inst->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp )) ) + if ( nullptr != (inst->m_rightop = CBotTwoOpExpr::Compile(p, pStk, pOp, bConstExpr)) ) // expression (...) right { // there is an second operand acceptable @@ -264,7 +263,7 @@ CBotInstr* CBotTwoOpExpr::Compile(CBotToken* &p, CBotCStack* pStack, int* pOpera type1 = TypeRes; p = p->GetNext(); // advance after - i->m_rightop = CBotTwoOpExpr::Compile( p, pStk, pOp ); + i->m_rightop = CBotTwoOpExpr::Compile(p, pStk, pOp, bConstExpr); type2 = pStk->GetTypResult(); if ( !TypeCompatible (type1, type2, typeOp) ) // the results are compatible @@ -358,8 +357,9 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack) CBotStack* pStk2 = pStk1->AddStack(); // adds an item to the stack // or return in case of recovery + if (pStk2->StackOver()) return pStack->Return(pStk2); - // 2e état, évalue l'opérande de droite + // 2nd state, evalute right operand if ( pStk2->GetState() == 0 ) { if ( !m_rightop->Execute(pStk2) ) return false; // interrupted here? @@ -399,7 +399,10 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack) TypeRes = CBotTypBoolean; break; case ID_DIV: - TypeRes = std::max(TypeRes, static_cast(CBotTypFloat)); + if (TypeRes == CBotTypFloat) + { + if (type1.Eq(CBotTypLong) || type2.Eq(CBotTypLong)) TypeRes = CBotTypDouble; + } } // creates a variable for the result @@ -512,7 +515,6 @@ bool CBotTwoOpExpr::Execute(CBotStack* &pStack) pStk2->SetVar(result); // puts the result on the stack if ( err ) pStk2->SetError(err, &m_token); // and the possible error (division by zero) -// pStk1->Return(pStk2); // releases the stack return pStack->Return(pStk2); // transmits the result } diff --git a/src/CBot/CBotInstr/CBotTwoOpExpr.h b/src/CBot/CBotInstr/CBotTwoOpExpr.h index c1110e13..0144a274 100644 --- a/src/CBot/CBotInstr/CBotTwoOpExpr.h +++ b/src/CBot/CBotInstr/CBotTwoOpExpr.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -65,7 +65,7 @@ public: * \param pOperations * \return */ - static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations = nullptr); + static CBotInstr* Compile(CBotToken* &p, CBotCStack* pStack, int* pOperations = nullptr, bool bConstExpr = false); /*! * \brief Execute Performes the operation on two operands. diff --git a/src/CBot/CBotInstr/CBotWhile.cpp b/src/CBot/CBotInstr/CBotWhile.cpp index 9254ad02..da0a48cc 100644 --- a/src/CBot/CBotInstr/CBotWhile.cpp +++ b/src/CBot/CBotInstr/CBotWhile.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -56,8 +56,7 @@ CBotInstr* CBotWhile::Compile(CBotToken* &p, CBotCStack* pStack) inst->SetToken(p); if (!IsOfType(p, ID_WHILE)) return nullptr; // should never happen - CBotCStack* pStk = pStack->TokenStack(pp); // un petit bout de pile svp - // a bit of battery please (??) + CBotCStack* pStk = pStack->TokenStack(pp); // some space for a stack, plz if ( nullptr != (inst->m_condition = CBotCondition::Compile(p, pStk )) ) { diff --git a/src/CBot/CBotInstr/CBotWhile.h b/src/CBot/CBotInstr/CBotWhile.h index 582d5cf1..a691481e 100644 --- a/src/CBot/CBotInstr/CBotWhile.h +++ b/src/CBot/CBotInstr/CBotWhile.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotProgram.cpp b/src/CBot/CBotProgram.cpp index e8065f47..4a09eef2 100644 --- a/src/CBot/CBotProgram.cpp +++ b/src/CBot/CBotProgram.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -24,7 +24,6 @@ #include "CBot/CBotCStack.h" #include "CBot/CBotClass.h" #include "CBot/CBotUtils.h" -#include "CBot/CBotFileUtils.h" #include "CBot/CBotInstr/CBotFunction.h" @@ -35,7 +34,7 @@ namespace CBot { -CBotExternalCallList* CBotProgram::m_externalCalls = new CBotExternalCallList(); +std::unique_ptr CBotProgram::m_externalCalls; CBotProgram::CBotProgram() { @@ -244,13 +243,6 @@ CBotVar* CBotProgram::GetStackVars(std::string& functionName, int level) return m_stack->GetStackVars(functionName, level); } -//////////////////////////////////////////////////////////////////////////////// -void CBotProgram::SetTimer(int n) -{ - CBotStack::SetTimer( n ); -} - -//////////////////////////////////////////////////////////////////////////////// CBotError CBotProgram::GetError() { return m_error; @@ -332,51 +324,56 @@ bool CBotProgram::DefineNum(const std::string& name, long val) } //////////////////////////////////////////////////////////////////////////////// -bool CBotProgram::SaveState(FILE* pf) +bool CBotProgram::SaveState(std::ostream &ostr) { - if (!WriteWord( pf, CBOTVERSION)) return false; + if (!WriteLong(ostr, CBOTVERSION)) return false; if (m_stack != nullptr ) { - if (!WriteWord( pf, 1)) return false; - if (!WriteString( pf, m_entryPoint->GetName() )) return false; - if (!m_stack->SaveState(pf)) return false; + if (!WriteWord(ostr, 1)) return false; + if (!WriteString(ostr, m_entryPoint->GetName())) return false; + if (!m_stack->SaveState(ostr)) return false; } else { - if (!WriteWord( pf, 0)) return false; + if (!WriteWord(ostr, 0)) return false; } return true; } -bool CBotProgram::RestoreState(FILE* pf) +bool CBotProgram::RestoreState(std::istream &istr) { unsigned short w; std::string s; Stop(); - if (!ReadWord( pf, w )) return false; - if ( w != CBOTVERSION ) return false; + long version; + if (!ReadLong(istr, version)) return false; + if ( version != CBOTVERSION ) return false; - if (!ReadWord( pf, w )) return false; + if (!ReadWord(istr, w)) return false; if ( w == 0 ) return true; - if (!ReadString( pf, s )) return false; - Start(s); // point de reprise + // don't restore if compile error exists + if (m_error != CBotNoErr) return false; - if (m_stack != nullptr) + if (!ReadString(istr, s)) return false; + if (!Start(s)) return false; // point de reprise + // Start() already created the new stack + // and called m_stack->SetProgram(this); + + // retrieves the stack from the memory + if (!m_stack->RestoreState(istr, m_stack)) { m_stack->Delete(); m_stack = nullptr; + m_stack = CBotStack::AllocateStack(); // start from the top + m_stack->SetProgram(this); + return false; // signal error } - // retrieves the stack from the memory - m_stack = CBotStack::AllocateStack(); - if (!m_stack->RestoreState(pf, m_stack)) return false; - m_stack->SetProgram(this); // bases for routines - // restored some states in the stack according to the structure m_entryPoint->RestoreState(nullptr, m_stack, m_thisVar); return true; @@ -391,6 +388,8 @@ int CBotProgram::GetVersion() void CBotProgram::Init() { + m_externalCalls.reset(new CBotExternalCallList); + CBotProgram::DefineNum("CBotErrZeroDiv", CBotErrZeroDiv); // division by zero CBotProgram::DefineNum("CBotErrNotInit", CBotErrNotInit); // uninitialized variable CBotProgram::DefineNum("CBotErrBadThrow", CBotErrBadThrow); // throw a negative value @@ -416,9 +415,10 @@ void CBotProgram::Free() CBotToken::ClearDefineNum(); m_externalCalls->Clear(); CBotClass::ClearPublic(); + m_externalCalls.reset(); } -CBotExternalCallList* CBotProgram::GetExternalCalls() +const std::unique_ptr& CBotProgram::GetExternalCalls() { return m_externalCalls; } diff --git a/src/CBot/CBotProgram.h b/src/CBot/CBotProgram.h index e258fff0..41ef6b8b 100644 --- a/src/CBot/CBotProgram.h +++ b/src/CBot/CBotProgram.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -19,11 +19,12 @@ #pragma once -#include "CBot/CBotTypResult.h" #include "CBot/CBotEnums.h" -#include #include +#include +#include +#include namespace CBot { @@ -31,6 +32,7 @@ namespace CBot class CBotFunction; class CBotClass; class CBotStack; +class CBotTypResult; class CBotVar; class CBotExternalCallList; @@ -200,14 +202,6 @@ public: */ void Stop(); - /** - * \brief Sets the number of steps (parts of instructions) to execute in Run() before suspending the program execution - * \param n new timer value - * - * FIXME: Seems to be currently kind of broken (see issue #410) - */ - static void SetTimer(int n); - /** * \brief Add a function that can be called from CBot * @@ -282,27 +276,20 @@ public: /** * \brief Save the current execution status into a file - * \param pf - * \parblock - * file handle - * - * This file handle must have been opened by this library! Otherwise crashes on Windows - * - * TODO: Verify this - * \endparblock + * \param ostr Output stream * \return true on success, false on write error */ - bool SaveState(FILE* pf); + bool SaveState(std::ostream &ostr); /** * \brief Restore the execution state from a file * * The previous program code must already have been recompiled with Compile() before calling this function * - * \param pf file handle + * \param istr Input stream * \return true on success, false on read error */ - bool RestoreState(FILE* pf); + bool RestoreState(std::istream &istr); /** * \brief GetPosition Gives the position of a routine in the original text @@ -342,11 +329,11 @@ public: /** * \brief Returns static list of all registered external calls */ - static CBotExternalCallList* GetExternalCalls(); + static const std::unique_ptr& GetExternalCalls(); private: //! All external calls - static CBotExternalCallList* m_externalCalls; + static std::unique_ptr m_externalCalls; //! All user-defined functions std::list m_functions{}; //! The entry point function diff --git a/src/CBot/CBotStack.cpp b/src/CBot/CBotStack.cpp index 9f9db2d6..7de0670b 100644 --- a/src/CBot/CBotStack.cpp +++ b/src/CBot/CBotStack.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -26,7 +26,6 @@ #include "CBot/CBotVar/CBotVarPointer.h" #include "CBot/CBotVar/CBotVarClass.h" -#include "CBot/CBotFileUtils.h" #include "CBot/CBotUtils.h" #include "CBot/CBotExternalCall.h" @@ -40,16 +39,24 @@ namespace CBot const int DEFAULT_TIMER = 100; -int CBotStack::m_initimer = DEFAULT_TIMER; -int CBotStack::m_timer = 0; -CBotVar* CBotStack::m_retvar = nullptr; -CBotError CBotStack::m_error = CBotNoErr; -int CBotStack::m_start = 0; -int CBotStack::m_end = 0; -std::string CBotStack::m_labelBreak=""; -void* CBotStack::m_pUser = nullptr; +struct CBotStack::Data +{ + int initimer = DEFAULT_TIMER; + int timer = 0; + + CBotError error = CBotNoErr; + int errStart = 0; + int errEnd = 0; + + std::string labelBreak = ""; + + CBotProgram* baseProg = nullptr; + CBotStack* topStack = nullptr; + void* pUser = nullptr; + + std::unique_ptr retvar; +}; -//////////////////////////////////////////////////////////////////////////////// CBotStack* CBotStack::AllocateStack() { CBotStack* p; @@ -64,7 +71,6 @@ CBotStack* CBotStack::AllocateStack() memset(p, 0, size); p->m_block = BlockVisibilityType::BLOCK; - m_timer = m_initimer; // sets the timer at the beginning CBotStack* pp = p; pp += MAXSTACK; @@ -75,7 +81,8 @@ CBotStack* CBotStack::AllocateStack() pp ++; } - m_error = CBotNoErr; // avoids deadlocks because m_error is static + p->m_data = new CBotStack::Data; + p->m_data->topStack = p; return p; } @@ -99,6 +106,7 @@ void CBotStack::Delete() CBotStack* p = m_prev; bool bOver = m_bOver; + if ( m_prev == nullptr ) delete m_data; // clears the freed block memset(this, 0, sizeof(CBotStack)); @@ -125,6 +133,7 @@ CBotStack* CBotStack::AddStack(CBotInstr* instr, BlockVisibilityType bBlock) while ( p->m_prev != nullptr ); m_next = p; // chain an element + p->m_data = m_data; p->m_block = bBlock; p->m_instr = instr; p->m_prog = m_prog; @@ -168,6 +177,7 @@ CBotStack* CBotStack::AddStack2(BlockVisibilityType bBlock) while ( p->m_prev != nullptr ); m_next2 = p; // chain an element + p->m_data = m_data; p->m_prev = this; p->m_block = bBlock; p->m_prog = m_prog; @@ -222,18 +232,32 @@ bool CBotStack::ReturnKeep(CBotStack* pfils) bool CBotStack::StackOver() { if (!m_bOver) return false; - m_error = CBotErrStackOver; + m_data->error = CBotErrStackOver; return true; } -//////////////////////////////////////////////////////////////////////////////// +CBotError CBotStack::GetError(int& start, int& end) +{ + start = m_data->errStart; + end = m_data->errEnd; + return m_data->error; +} + +CBotError CBotStack::GetError() +{ + return m_data->error; +} + +bool CBotStack::IsOk() +{ + return m_data->error == CBotNoErr; +} + void CBotStack::Reset() { - m_timer = m_initimer; // resets the timer - m_error = CBotNoErr; -// m_start = 0; -// m_end = 0; - m_labelBreak.clear(); + m_data->timer = m_data->initimer; // resets the timer + m_data->error = CBotNoErr; + m_data->labelBreak.clear(); } //////////////////////////////////////////////////////////////////////////////// @@ -260,35 +284,35 @@ CBotStack* CBotStack::RestoreStackEOX(CBotExternalCall* instr) // routine for execution step by step bool CBotStack::IfStep() { - if ( m_initimer > 0 || m_step++ > 0 ) return false; + if (m_data->initimer > 0 || m_step++ > 0) return false; return true; } //////////////////////////////////////////////////////////////////////////////// bool CBotStack::BreakReturn(CBotStack* pfils, const std::string& name) { - if ( m_error>=0 ) return false; // normal output - if ( m_error==CBotError(-3) ) return false; // normal output (return current) + if (m_data->error >= CBotNoErr) return false; // normal output + if (m_data->error == CBotError(-3)) return false; // normal output (return current) - if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name)) + if (!m_data->labelBreak.empty() && (name.empty() || m_data->labelBreak != name)) return false; // it's not for me - m_error = CBotNoErr; - m_labelBreak.clear(); + m_data->error = CBotNoErr; + m_data->labelBreak.clear(); return Return(pfils); } //////////////////////////////////////////////////////////////////////////////// bool CBotStack::IfContinue(int state, const std::string& name) { - if ( m_error != CBotError(-2) ) return false; + if (m_data->error != CBotError(-2)) return false; - if (!m_labelBreak.empty() && (name.empty() || m_labelBreak != name)) + if (!m_data->labelBreak.empty() && (name.empty() || m_data->labelBreak != name)) return false; // it's not for me m_state = state; // where again? - m_error = CBotNoErr; - m_labelBreak.clear(); + m_data->error = CBotNoErr; + m_data->labelBreak.clear(); if (m_next != nullptr) m_next->Delete(); // purge above stack return true; } @@ -296,11 +320,11 @@ bool CBotStack::IfContinue(int state, const std::string& name) //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetBreak(int val, const std::string& name) { - m_error = static_cast(-val); // reacts as an Exception - m_labelBreak = name; + m_data->error = static_cast(-val); // reacts as an Exception + m_data->labelBreak = name; if (val == 3) // for a return { - m_retvar = m_var; + m_data->retvar.reset(m_var); m_var = nullptr; } } @@ -309,12 +333,11 @@ void CBotStack::SetBreak(int val, const std::string& name) //////////////////////////////////////////////////////////////////////////////// bool CBotStack::GetRetVar(bool bRet) { - if (m_error == CBotError(-3)) + if (m_data->error == CBotError(-3)) { if ( m_var ) delete m_var; - m_var = m_retvar; - m_retvar = nullptr; - m_error = CBotNoErr; + m_var = m_data->retvar.release(); + m_data->error = CBotNoErr; return true; } return bRet; // interrupted by something other than return @@ -324,7 +347,7 @@ bool CBotStack::GetRetVar(bool bRet) CBotVar* CBotStack::FindVar(CBotToken*& pToken, bool bUpdate) { CBotStack* p = this; - std::string name = pToken->GetString(); + const auto& name = pToken->GetString(); while (p != nullptr) { @@ -334,7 +357,7 @@ CBotVar* CBotStack::FindVar(CBotToken*& pToken, bool bUpdate) if (pp->GetName() == name) { if ( bUpdate ) - pp->Update(m_pUser); + pp->Update(m_data->pUser); return pp; } @@ -377,7 +400,7 @@ CBotVar* CBotStack::FindVar(long ident, bool bUpdate) if (pp->GetUniqNum() == ident) { if ( bUpdate ) - pp->Update(m_pUser); + pp->Update(m_data->pUser); return pp; } @@ -412,8 +435,8 @@ bool CBotStack::SetState(int n, int limite) { m_state = n; - m_timer--; // decrement the timer - return ( m_timer > limite ); // interrupted if timer pass + m_data->timer--; // decrement the timer + return (m_data->timer > limite); // interrupted if timer pass } //////////////////////////////////////////////////////////////////////////////// @@ -421,46 +444,46 @@ bool CBotStack::IncState(int limite) { m_state++; - m_timer--; // decrement the timer - return ( m_timer > limite ); // interrupted if timer pass + m_data->timer--; // decrement the timer + return (m_data->timer > limite); // interrupted if timer pass } //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetError(CBotError n, CBotToken* token) { - if (n != CBotNoErr && m_error != CBotNoErr) return; // does not change existing error - m_error = n; + if (n != CBotNoErr && m_data->error != CBotNoErr) return; // does not change existing error + m_data->error = n; if (token != nullptr) { - m_start = token->GetStart(); - m_end = token->GetEnd(); + m_data->errStart = token->GetStart(); + m_data->errEnd = token->GetEnd(); } } //////////////////////////////////////////////////////////////////////////////// void CBotStack::ResetError(CBotError n, int start, int end) { - m_error = n; - m_start = start; - m_end = end; + m_data->error = n; + m_data->errStart = start; + m_data->errEnd = end; } //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetPosError(CBotToken* token) { - m_start = token->GetStart(); - m_end = token->GetEnd(); + m_data->errStart = token->GetStart(); + m_data->errEnd = token->GetEnd(); } //////////////////////////////////////////////////////////////////////////////// void CBotStack::SetTimer(int n) { - m_initimer = n; + m_data->initimer = n; } int CBotStack::GetTimer() { - return m_initimer; + return m_data->initimer; } //////////////////////////////////////////////////////////////////////////////// @@ -544,26 +567,25 @@ void CBotStack::SetProgram(CBotProgram* p) { m_prog = p; m_func = IsFunction::YES; + if (this == m_data->topStack) m_data->baseProg = p; } //////////////////////////////////////////////////////////////////////////////// CBotProgram* CBotStack::GetProgram(bool bFirst) { if ( ! bFirst ) return m_prog; - CBotStack* p = this; - while ( p->m_prev != nullptr ) p = p->m_prev; - return p->m_prog; + return m_data->baseProg; } //////////////////////////////////////////////////////////////////////////////// void* CBotStack::GetUserPtr() { - return m_pUser; + return m_data->pUser; } void CBotStack::SetUserPtr(void* user) { - m_pUser = user; + m_data->pUser = user; } //////////////////////////////////////////////////////////////////////////////// @@ -687,108 +709,106 @@ CBotVar* CBotStack::GetStackVars(std::string& functionName, int level) } //////////////////////////////////////////////////////////////////////////////// -bool CBotStack::SaveState(FILE* pf) +bool CBotStack::SaveState(std::ostream &ostr) { if (m_next2 != nullptr) { - if (!WriteWord(pf, 2)) return false; // a marker of type (m_next2) - if (!m_next2->SaveState(pf)) return false; // saves the next element + if (!WriteWord(ostr, 2)) return false; // a marker of type (m_next2) + if (!m_next2->SaveState(ostr)) return false; // saves the next element } else { - if (!WriteWord(pf, 1)) return false; // a marker of type (m_next) + if (!WriteWord(ostr, 1)) return false; // a marker of type (m_next) } - if (!WriteWord(pf, static_cast(m_block))) return false; - if (!WriteWord(pf, m_state)) return false; - if (!WriteWord(pf, 0)) return false; // for backwards combatibility (m_bDontDelete) - if (!WriteWord(pf, m_step)) return false; + if (!WriteWord(ostr, static_cast(m_block))) return false; + if (!WriteInt(ostr, m_state)) return false; + if (!WriteWord(ostr, 0)) return false; // for backwards combatibility (m_bDontDelete) + if (!WriteInt(ostr, m_step)) return false; - - if (!SaveVars(pf, m_var)) return false; // current result - if (!SaveVars(pf, m_listVar)) return false; // local variables + if (!SaveVars(ostr, m_var)) return false; // current result + if (!SaveVars(ostr, m_listVar)) return false; // local variables if (m_next != nullptr) { - if (!m_next->SaveState(pf)) return false; // saves the next element + if (!m_next->SaveState(ostr)) return false; // saves the next element } else { - if (!WriteWord(pf, 0)) return false; // terminator + if (!WriteWord(ostr, 0)) return false; // 0 - CBotStack::SaveState terminator } return true; } -bool SaveVars(FILE* pf, CBotVar* pVar) +bool SaveVars(std::ostream &ostr, CBotVar* pVar) { while (pVar != nullptr) { - if (!pVar->Save0State(pf)) return false; // common header - if (!pVar->Save1State(pf)) return false; // saves the data + if (!pVar->Save0State(ostr)) return false; // common header + if (!pVar->Save1State(ostr)) return false; // saves the data pVar = pVar->GetNext(); } - return WriteWord(pf, 0); // terminator + return WriteWord(ostr, 0); // 0 - CBot::SaveVars terminator } //////////////////////////////////////////////////////////////////////////////// -bool CBotStack::RestoreState(FILE* pf, CBotStack* &pStack) +bool CBotStack::RestoreState(std::istream &istr, CBotStack* &pStack) { unsigned short w; if (pStack != this) pStack = nullptr; - if (!ReadWord(pf, w)) return false; - if ( w == 0 ) return true; // 0 - terminator + if (!ReadWord(istr, w)) return false; + if ( w == 0 ) return true; // 0 - CBotStack::SaveState terminator if (pStack == nullptr) pStack = AddStack(); if ( w == 2 ) // 2 - m_next2 { - if (!pStack->RestoreState(pf, pStack->m_next2)) return false; + if (!pStack->RestoreState(istr, pStack->m_next2)) return false; } - if (!ReadWord(pf, w)) return false; + if (!ReadWord(istr, w)) return false; pStack->m_block = static_cast(w); - if (!ReadWord(pf, w)) return false; - pStack->SetState(static_cast(w)); + int state; + if (!ReadInt(istr, state)) return false; + pStack->SetState(state); - if (!ReadWord(pf, w)) return false; // backwards compatibility (m_bDontDelete) + if (!ReadWord(istr, w)) return false; // backwards compatibility (m_bDontDelete) - if (!ReadWord(pf, w)) return false; - pStack->m_step = w; + if (!ReadInt(istr, state)) return false; + pStack->m_step = state; - if (!CBotVar::RestoreState(pf, pStack->m_var)) return false; // temp variable - if (!CBotVar::RestoreState(pf, pStack->m_listVar)) return false;// local variables + if (!CBotVar::RestoreState(istr, pStack->m_var)) return false; // temp variable + if (!CBotVar::RestoreState(istr, pStack->m_listVar)) return false; // local variables - return pStack->RestoreState(pf, pStack->m_next); + return pStack->RestoreState(istr, pStack->m_next); } //////////////////////////////////////////////////////////////////////////////// -bool CBotVar::Save0State(FILE* pf) +bool CBotVar::Save0State(std::ostream &ostr) { - if (!WriteWord(pf, 100+static_cast(m_mPrivate)))return false; // private variable? - if (!WriteWord(pf, m_bStatic))return false; // static variable? - if (!WriteWord(pf, m_type.GetType()))return false; // saves the type (always non-zero) + if (!WriteWord(ostr, 100+static_cast(m_mPrivate)))return false; // private variable? + if (!WriteWord(ostr, m_bStatic))return false; // static variable? + if (!WriteWord(ostr, m_type.GetType()))return false; // saves the type (always non-zero) if (m_type.Eq(CBotTypPointer) && GetPointer() != nullptr) { if (GetPointer()->m_bConstructor) // constructor was called? { - if (!WriteWord(pf, (2000 + static_cast(m_binit)) )) return false; - return WriteString(pf, m_token->GetString()); // and variable name + if (!WriteWord(ostr, (2000 + static_cast(m_binit)) )) return false; + return WriteString(ostr, m_token->GetString()); // and variable name } } - if (!WriteWord(pf, static_cast(m_binit))) return false; // variable defined? - return WriteString(pf, m_token->GetString()); // and variable name + if (!WriteWord(ostr, static_cast(m_binit))) return false; // variable defined? + return WriteString(ostr, m_token->GetString()); // and variable name } //////////////////////////////////////////////////////////////////////////////// -bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar) +bool CBotVar::RestoreState(std::istream &istr, CBotVar* &pVar) { unsigned short w, wi, prv, st; - float ww; - std::string name, s; delete pVar; @@ -798,27 +818,27 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar) while ( true ) // retrieves a list { - if (!ReadWord(pf, w)) return false; // private or type? - if ( w == 0 ) return true; + if (!ReadWord(istr, w)) return false; // private or type? + if ( w == 0 ) return true; // 0 - CBot::SaveVars terminator std::string defnum; if ( w == 200 ) { - if (!ReadString(pf, defnum)) return false; // number with identifier - if (!ReadWord(pf, w)) return false; // type + if (!ReadString(istr, defnum)) return false; // number with identifier + if (!ReadWord(istr, w)) return false; // type } prv = 100; st = 0; if ( w >= 100 ) { prv = w; - if (!ReadWord(pf, st)) return false; // static - if (!ReadWord(pf, w)) return false; // type + if (!ReadWord(istr, st)) return false; // static + if (!ReadWord(istr, w)) return false; // type } if ( w == CBotTypClass ) w = CBotTypIntrinsic; // necessarily intrinsic - if (!ReadWord(pf, wi)) return false; // init ? + if (!ReadWord(istr, wi)) return false; // init ? bool bConstructor = false; if (w == CBotTypPointer && wi >= 2000) { @@ -827,31 +847,70 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar) } CBotVar::InitType initType = static_cast(wi); - if (!ReadString(pf, name)) return false; // variable name - - CBotToken token(name, std::string()); + std::string varname; + if (!ReadString(istr, varname)) return false; // variable name + CBotToken token(varname, std::string()); bool isClass = false; switch (w) { - case CBotTypInt: case CBotTypBoolean: + char valBool; + if (!ReadByte(istr, valBool)) return false; pNew = CBotVar::Create(token, w); // creates a variable - if (!ReadWord(pf, w)) return false; - pNew->SetValInt(static_cast(w), defnum); + pNew->SetValInt(valBool); + break; + case CBotTypByte: + char valByte; + if (!ReadByte(istr, valByte)) return false; + pNew = CBotVar::Create(token, w); // creates a variable + pNew->SetValByte(valByte); + break; + case CBotTypShort: + short valShort; + if (!ReadShort(istr, valShort)) return false; + pNew = CBotVar::Create(token, w); // creates a variable + pNew->SetValShort(valShort); + break; + case CBotTypChar: + uint32_t valChar; + if (!ReadUInt32(istr, valChar)) return false; + pNew = CBotVar::Create(token, w); // creates a variable + pNew->SetValChar(valChar); + break; + case CBotTypInt: + int valInt; + if (!ReadInt(istr, valInt)) return false; + pNew = CBotVar::Create(token, w); // creates a variable + pNew->SetValInt(valInt, defnum); + break; + case CBotTypLong: + long valLong; + if (!ReadLong(istr, valLong)) return false; + pNew = CBotVar::Create(token, w); // creates a variable + pNew->SetValInt(valLong); break; case CBotTypFloat: + float valFloat; + if (!ReadFloat(istr, valFloat)) return false; pNew = CBotVar::Create(token, w); // creates a variable - if (!ReadFloat(pf, ww)) return false; - pNew->SetValFloat(ww); + pNew->SetValFloat(valFloat); + break; + case CBotTypDouble: + double valDouble; + if (!ReadDouble(istr, valDouble)) return false; + pNew = CBotVar::Create(token, w); // creates a variable + pNew->SetValDouble(valDouble); break; case CBotTypString: - pNew = CBotVar::Create(token, w); // creates a variable - if (!ReadString(pf, s)) return false; - pNew->SetValString(s); - break; - + { + std::string valString; + if (!ReadString(istr, valString)) return false; + pNew = CBotVar::Create(token, w); // creates a variable + pNew->SetValString(valString); + break; + } // returns an intrinsic object or element of an array case CBotTypIntrinsic: isClass = true; @@ -859,28 +918,32 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar) { CBotTypResult r; long id; - if (!ReadType(pf, r)) return false; // complete type - if (!ReadLong(pf, id) ) return false; + if (!ReadType(istr, r)) return false; // complete type + if (!ReadLong(istr, id)) return false; -// if (!ReadString(pf, s)) return false; { CBotVar* p = nullptr; if ( id ) p = CBotVarClass::Find(id) ; pNew = new CBotVarClass(token, r); // directly creates an instance // attention cptuse = 0 - if ( !RestoreState(pf, (static_cast(pNew))->m_pVar)) return false; + if (!RestoreState(istr, (static_cast(pNew))->m_pVar)) return false; pNew->SetIdent(id); if (isClass && p == nullptr) // set id for each item in this instance { - CBotVar* pVars = pNew->GetItemList(); - CBotVar* pv = pNew->GetClass()->GetVar(); - while (pVars != nullptr && pv != nullptr) + CBotClass* pClass = pNew->GetClass(); + CBotVar* pVars = (static_cast(pNew))->m_pVar; + while (pClass != nullptr && pVars != nullptr) { - pVars->m_ident = pv->m_ident; - pv = pv->GetNext(); - pVars = pVars->GetNext(); + CBotVar* pv = pClass->GetVar(); + while (pVars != nullptr && pv != nullptr) + { + pVars->m_ident = pv->m_ident; + pVars = pVars->m_next; + pv = pv->m_next; + } + pClass = pClass->GetParent(); } } @@ -895,18 +958,20 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar) case CBotTypPointer: case CBotTypNullPointer: - if (!ReadString(pf, s)) return false; // name of the class + { + std::string className; + if (!ReadString(istr, className)) return false; // name of the class { - CBotTypResult ptrType(w, s); - pNew = CBotVar::Create(token, ptrType);// creates a variable // CBotVarClass* p = nullptr; long id; - ReadLong(pf, id); + if (!ReadLong(istr, id)) return false; // if ( id ) p = CBotVarClass::Find(id); // found the instance (made by RestoreInstance) + CBotTypResult ptrType(w, className); + pNew = CBotVar::Create(token, ptrType); // creates a variable // returns a copy of the original instance CBotVar* pInstance = nullptr; - if ( !CBotVar::RestoreState( pf, pInstance ) ) return false; + if (!CBotVar::RestoreState(istr, pInstance)) return false; (static_cast(pNew))->SetPointer( pInstance ); // and point over if (bConstructor) pNew->ConstructorSet(); // constructor was called @@ -916,22 +981,22 @@ bool CBotVar::RestoreState(FILE* pf, CBotVar* &pVar) } break; - + } case CBotTypArrayPointer: { CBotTypResult r; - if (!ReadType(pf, r)) return false; + if (!ReadType(istr, r)) return false; pNew = CBotVar::Create(token, r); // creates a variable // returns a copy of the original instance CBotVar* pInstance = nullptr; - if ( !CBotVar::RestoreState( pf, pInstance ) ) return false; + if (!CBotVar::RestoreState(istr, pInstance)) return false; (static_cast(pNew))->SetPointer( pInstance ); // and point over } break; default: - assert(0); + return false; // signal error } if ( pPrev != nullptr ) pPrev->m_next = pNew; diff --git a/src/CBot/CBotStack.h b/src/CBot/CBotStack.h index a72b3e4a..64a81124 100644 --- a/src/CBot/CBotStack.h +++ b/src/CBot/CBotStack.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -82,9 +82,6 @@ public: //////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /** \name Error management - * - * BE CAREFUL - errors are stored in static variables! - * \todo Refactor that */ //@{ @@ -94,24 +91,21 @@ public: * \param[out] end Ending position in code of the error * \return Error number */ - CBotError GetError(int& start, int& end) { start = m_start; end = m_end; return m_error; } + CBotError GetError(int& start, int& end); /** * \brief Get last error * \return Error number * \see GetError(int&, int&) for error position in code */ - CBotError GetError() { return m_error; } + CBotError GetError(); /** * \brief Check if there was an error * \return false if an error occurred * \see GetError() */ - bool IsOk() - { - return m_error == CBotNoErr; - } + bool IsOk(); /** * \brief Set execution error unless it's already set unless you are trying to reset it @@ -357,7 +351,7 @@ public: /** * \todo Document * - * Copies the result value from static m_retvar (m_var at a moment of SetBreak(3)) to this stack result + * Copies the result value from m_data->retvar (m_var at a moment of SetBreak(3)) to this stack result */ bool GetRetVar(bool bRet); @@ -434,8 +428,8 @@ public: //! \name Write to file //@{ - bool SaveState(FILE* pf); - bool RestoreState(FILE* pf, CBotStack* &pStack); + bool SaveState(std::ostream &ostr); + bool RestoreState(std::istream &istr, CBotStack* &pStack); //@} @@ -446,11 +440,11 @@ public: * * \todo Full documentation of the timer */ - static void SetTimer(int n); + void SetTimer(int n); /** * \brief Get the current configured maximum number of "timer ticks" (parts of instructions) to execute */ - static int GetTimer(); + int GetTimer(); /** * \brief Get current position in the program @@ -476,10 +470,10 @@ private: int m_state; int m_step; - static CBotError m_error; - static int m_start; - static int m_end; - static CBotVar* m_retvar; // result of a return + + struct Data; + + CBotStack::Data* m_data; CBotVar* m_var; // result of the operations CBotVar* m_listVar; // variables declared at this level @@ -489,11 +483,6 @@ private: //! CBotProgram instance the execution is in in this stack level CBotProgram* m_prog; - static int m_initimer; - static int m_timer; - static std::string m_labelBreak; - static void* m_pUser; - //! The corresponding instruction CBotInstr* m_instr; //! If this stack level holds a function call diff --git a/src/CBot/CBotToken.cpp b/src/CBot/CBotToken.cpp index ea31fad9..38402d94 100644 --- a/src/CBot/CBotToken.cpp +++ b/src/CBot/CBotToken.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -65,12 +65,18 @@ static const boost::bimap KEYWORDS = makeBimap KEYWORDS = makeBimap>>="}, {ID_ASSASR, ">>="}, {ID_SL, "<<"}, - {ID_SR, ">>"}, + {ID_SR, ">>>"}, {ID_ASR, ">>"}, {ID_INC, "++"}, {ID_DEC, "--"}, @@ -299,12 +305,53 @@ CBotToken* CBotToken::NextToken(const char*& program, bool first) stop = true; } + // special case for characters + if (token[0] == '\'') + { + if (c == '\\') // escape sequence + { + token += c; + c = *(program++); + + if (c == 'u' || c == 'U') // unicode escape + { + int maxlen = (c == 'u') ? 4 : 8; + token += c; + c = *(program++); + for (int i = 0; i < maxlen; i++) + { + if (c == 0 || !CharInList(c, hexnum)) break; + token += c; + c = *(program++); + } + } + else if (c != 0 && !CharInList(c, nch)) // other escape char + { + token += c; + c = *(program++); + } + } + else if (c != 0 && c != '\'' && !CharInList(c, nch)) // single character + { + token += c; + c = *(program++); + } + + if (c == '\'') // close quote + { + token += c; + c = *(program++); + } + stop = true; + } + // special case for numbers if ( CharInList(token[0], num )) { bool bdot = false; // found a point? bool bexp = false; // found an exponent? + char bin[] = "01"; char* liste = num; if (token[0] == '0' && c == 'x') // hexadecimal value? { @@ -312,6 +359,12 @@ CBotToken* CBotToken::NextToken(const char*& program, bool first) c = *(program++); // next character liste = hexnum; } + else if (token[0] == '0' && c == 'b') // binary literal + { + liste = bin; + token += c; + c = *(program++); + } cw: while (c != 0 && CharInList(c, liste)) { @@ -394,6 +447,7 @@ bis: if (CharInList(token[0], num )) t->m_type = TokenTypNum; if (token[0] == '\"') t->m_type = TokenTypString; + if (token[0] == '\'') t->m_type = TokenTypChar; if (first) t->m_type = TokenTypNone; t->m_keywordId = GetKeyWord(token); diff --git a/src/CBot/CBotToken.h b/src/CBot/CBotToken.h index 4dc7450a..508304f9 100644 --- a/src/CBot/CBotToken.h +++ b/src/CBot/CBotToken.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotTypResult.cpp b/src/CBot/CBotTypResult.cpp index 61e96530..64e590cd 100644 --- a/src/CBot/CBotTypResult.cpp +++ b/src/CBot/CBotTypResult.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -185,8 +185,13 @@ std::string CBotTypResult::ToString() switch (m_type) { case CBotTypVoid: return "void"; + case CBotTypByte: return "byte"; + case CBotTypShort: return "short"; + case CBotTypChar: return "char"; case CBotTypInt: return "int"; + case CBotTypLong: return "long"; case CBotTypFloat: return "float"; + case CBotTypDouble: return "double"; case CBotTypBoolean: return "bool"; case CBotTypString: return "string"; case CBotTypArrayPointer: return m_next->ToString() + "[]"; diff --git a/src/CBot/CBotTypResult.h b/src/CBot/CBotTypResult.h index 42c438a1..fbeab4ef 100644 --- a/src/CBot/CBotTypResult.h +++ b/src/CBot/CBotTypResult.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/CBotUtils.cpp b/src/CBot/CBotUtils.cpp index a6c6ef9c..cf2cd9e0 100644 --- a/src/CBot/CBotUtils.cpp +++ b/src/CBot/CBotUtils.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -62,12 +62,27 @@ CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile) switch (p->GetType()) { + case ID_BYTE: + p = p->GetNext(); + return ArrayType(p, pile, CBotTypResult( CBotTypByte )); + case ID_SHORT: + p = p->GetNext(); + return ArrayType(p, pile, CBotTypResult( CBotTypShort )); + case ID_CHAR: + p = p->GetNext(); + return ArrayType(p, pile, CBotTypResult( CBotTypChar )); case ID_INT: p = p->GetNext(); return ArrayType(p, pile, CBotTypResult( CBotTypInt )); + case ID_LONG: + p = p->GetNext(); + return ArrayType(p, pile, CBotTypResult( CBotTypLong )); case ID_FLOAT: p = p->GetNext(); return ArrayType(p, pile, CBotTypResult( CBotTypFloat )); + case ID_DOUBLE: + p = p->GetNext(); + return ArrayType(p, pile, CBotTypResult( CBotTypDouble )); case ID_BOOLEAN: case ID_BOOL: p = p->GetNext(); @@ -108,38 +123,6 @@ CBotTypResult ArrayType(CBotToken* &p, CBotCStack* pile, CBotTypResult type) return type; } -//////////////////////////////////////////////////////////////////////////////// -bool WriteWord(FILE* pf, unsigned short w) -{ - size_t lg; - - lg = fwrite(&w, sizeof( unsigned short ), 1, pf ); - - return (lg == 1); -} - -//////////////////////////////////////////////////////////////////////////////// -bool WriteString(FILE* pf, std::string s) -{ - size_t lg1, lg2; - - lg1 = s.size(); - if (!WriteWord(pf, lg1)) return false; - - lg2 = fwrite(s.c_str(), 1, lg1, pf ); - return (lg1 == lg2); -} - -//////////////////////////////////////////////////////////////////////////////// -bool WriteFloat(FILE* pf, float w) -{ - size_t lg; - - lg = fwrite(&w, sizeof( float ), 1, pf ); - - return (lg == 1); -} - //////////////////////////////////////////////////////////////////////////////// long GetNumInt(const std::string& str) { @@ -172,11 +155,23 @@ long GetNumInt(const std::string& str) break; } } + else if (*p == 'b') + { + while (*++p != 0) + { + if (*p == '0' || *p == '1') + { + num = (num << 1) + *p - '0'; + continue; + } + break; + } + } return num; } //////////////////////////////////////////////////////////////////////////////// -float GetNumFloat(const std::string& str) +double GetNumFloat(const std::string& str) { const char* p = str.c_str(); double num = 0; @@ -233,7 +228,7 @@ float GetNumFloat(const std::string& str) } if (bNeg) num = -num; - return static_cast(num); + return num; } bool CharInList(const char c, const char* list) diff --git a/src/CBot/CBotUtils.h b/src/CBot/CBotUtils.h index 9042b0f8..91697055 100644 --- a/src/CBot/CBotUtils.h +++ b/src/CBot/CBotUtils.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -19,9 +19,8 @@ #pragma once -#include "CBot/CBotTypResult.h" +#include "CBot/CBotFileUtils.h" -#include #include #include @@ -31,6 +30,8 @@ namespace CBot class CBotVar; class CBotToken; class CBotCStack; +class CBotTypResult; + /*! * \brief MakeListVars Transforms the array of pointers to variables in a @@ -58,30 +59,6 @@ CBotTypResult TypeParam(CBotToken* &p, CBotCStack* pile); */ CBotTypResult ArrayType(CBotToken* &p, CBotCStack* pile, CBotTypResult type); -/*! - * \brief WriteWord - * \param pf - * \param w - * \return - */ -bool WriteWord(FILE* pf, unsigned short w); - -/*! - * \brief WriteString - * \param pf - * \param s - * \return - */ -bool WriteString(FILE* pf, std::string s); - -/*! - * \brief WriteFloat - * \param pf - * \param w - * \return - */ -bool WriteFloat(FILE* pf, float w); - /*! * \brief GetNumInt Converts a string into integer may be of the form 0xabc123. * \param str @@ -94,7 +71,7 @@ long GetNumInt(const std::string& str); * \param str * \return */ -float GetNumFloat(const std::string& str); +double GetNumFloat(const std::string& str); /*! * \brief Search a null-terminated string for a char value. diff --git a/src/CBot/CBotVar/CBotVar.cpp b/src/CBot/CBotVar/CBotVar.cpp index 62ba41f4..da31340b 100644 --- a/src/CBot/CBotVar/CBotVar.cpp +++ b/src/CBot/CBotVar/CBotVar.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -24,12 +24,17 @@ #include "CBot/CBotInstr/CBotInstr.h" #include "CBot/CBotVar/CBotVarArray.h" -#include "CBot/CBotVar/CBotVarPointer.h" -#include "CBot/CBotVar/CBotVarClass.h" #include "CBot/CBotVar/CBotVarBoolean.h" -#include "CBot/CBotVar/CBotVarString.h" +#include "CBot/CBotVar/CBotVarByte.h" +#include "CBot/CBotVar/CBotVarChar.h" +#include "CBot/CBotVar/CBotVarClass.h" +#include "CBot/CBotVar/CBotVarDouble.h" #include "CBot/CBotVar/CBotVarFloat.h" #include "CBot/CBotVar/CBotVarInt.h" +#include "CBot/CBotVar/CBotVarLong.h" +#include "CBot/CBotVar/CBotVarPointer.h" +#include "CBot/CBotVar/CBotVarShort.h" +#include "CBot/CBotVar/CBotVarString.h" #include "CBot/CBotClass.h" #include "CBot/CBotToken.h" @@ -134,7 +139,7 @@ void* CBotVar::GetUserPtr() } //////////////////////////////////////////////////////////////////////////////// -bool CBotVar::Save1State(FILE* pf) +bool CBotVar::Save1State(std::ostream &ostr) { // this routine "virtual" must never be called, // there must be a routine for each of the subclasses (CBotVarInt, CBotVarFloat, etc) @@ -160,11 +165,20 @@ CBotVar* CBotVar::Create(const CBotToken& name, CBotTypResult type) { switch (type.GetType()) { + case CBotTypByte: + return new CBotVarByte(name); case CBotTypShort: + return new CBotVarShort(name); + case CBotTypChar: + return new CBotVarChar(name); case CBotTypInt: return new CBotVarInt(name); + case CBotTypLong: + return new CBotVarLong(name); case CBotTypFloat: return new CBotVarFloat(name); + case CBotTypDouble: + return new CBotVarDouble(name); case CBotTypBoolean: return new CBotVarBoolean(name); case CBotTypString: @@ -223,11 +237,20 @@ CBotVar* CBotVar::Create(const std::string& n, CBotTypResult type) switch (type.GetType()) { + case CBotTypByte: + return new CBotVarByte(name); case CBotTypShort: + return new CBotVarShort(name); + case CBotTypChar: + return new CBotVarChar(name); case CBotTypInt: return new CBotVarInt(name); + case CBotTypLong: + return new CBotVarLong(name); case CBotTypFloat: return new CBotVarFloat(name); + case CBotTypDouble: + return new CBotVarDouble(name); case CBotTypBoolean: return new CBotVarBoolean(name); case CBotTypString: @@ -359,7 +382,7 @@ CBotVar::InitType CBotVar::GetInit() const void CBotVar::SetInit(CBotVar::InitType initType) { m_binit = initType; - if (initType == CBotVar::InitType::IS_POINTER ) m_binit = CBotVar::InitType::DEF; // cas spécial + if (initType == CBotVar::InitType::IS_POINTER ) m_binit = CBotVar::InitType::DEF; // special case if ( m_type.Eq(CBotTypPointer) && initType == CBotVar::InitType::IS_POINTER ) { @@ -472,12 +495,27 @@ void CBotVar::SetVal(CBotVar* var) case CBotTypBoolean: SetValInt(var->GetValInt()); break; + case CBotTypByte: + SetValByte(var->GetValByte()); + break; + case CBotTypShort: + SetValShort(var->GetValShort()); + break; + case CBotTypChar: + SetValChar(var->GetValChar()); + break; case CBotTypInt: SetValInt(var->GetValInt(), (static_cast(var))->m_defnum); break; + case CBotTypLong: + SetValLong(var->GetValLong()); + break; case CBotTypFloat: SetValFloat(var->GetValFloat()); break; + case CBotTypDouble: + SetValDouble(var->GetValDouble()); + break; case CBotTypString: SetValString(var->GetValString()); break; @@ -497,7 +535,7 @@ void CBotVar::SetVal(CBotVar* var) assert(0); } - m_binit = var->m_binit; // copie l'état nan s'il y a + m_binit = var->m_binit; // copy the nan status if it has } //////////////////////////////////////////////////////////////////////////////// @@ -545,33 +583,84 @@ CBotVarClass* CBotVar::GetPointer() // All these functions must be defined in the subclasses // derived from class CBotVar -//////////////////////////////////////////////////////////////////////////////// + +signed char CBotVar::GetValByte() +{ + assert(0); + return 0; +} + +short CBotVar::GetValShort() +{ + assert(0); + return 0; +} + +uint32_t CBotVar::GetValChar() +{ + assert(0); + return 0; +} + int CBotVar::GetValInt() { assert(0); return 0; } -//////////////////////////////////////////////////////////////////////////////// +long CBotVar::GetValLong() +{ + assert(0); + return 0; +} + float CBotVar::GetValFloat() { assert(0); return 0; } -//////////////////////////////////////////////////////////////////////////////// +double CBotVar::GetValDouble() +{ + assert(0); + return 0; +} + +void CBotVar::SetValByte(signed char val) +{ + assert(false); +} + +void CBotVar::SetValShort(short val) +{ + assert(false); +} + +void CBotVar::SetValChar(uint32_t val) +{ + assert(false); +} + void CBotVar::SetValInt(int c, const std::string& s) { assert(0); } -//////////////////////////////////////////////////////////////////////////////// +void CBotVar::SetValLong(long val) +{ + assert(false); +} + void CBotVar::SetValFloat(float c) { assert(0); } -//////////////////////////////////////////////////////////////////////////////// +void CBotVar::SetValDouble(double val) +{ + assert(false); +} + void CBotVar::Mul(CBotVar* left, CBotVar* right) { assert(0); @@ -752,16 +841,46 @@ CBotClass* CBotVar::GetClass() return nullptr; } +CBotVar::operator bool() +{ + return static_cast(GetValInt()); +} + +CBotVar::operator signed char() +{ + return GetValByte(); +} + +CBotVar::operator short() +{ + return GetValShort(); +} + +CBotVar::operator uint32_t() +{ + return GetValChar(); +} + CBotVar::operator int() { return GetValInt(); } +CBotVar::operator long() +{ + return GetValLong(); +} + CBotVar::operator float() { return GetValFloat(); } +CBotVar::operator double() +{ + return GetValDouble(); +} + CBotVar::operator std::string() { return GetValString(); @@ -772,16 +891,41 @@ void CBotVar::operator=(const CBotVar &var) SetVal(const_cast(&var)); } +void CBotVar::operator=(signed char x) +{ + SetValByte(x); +} + +void CBotVar::operator=(short x) +{ + SetValShort(x); +} + +void CBotVar::operator=(uint32_t x) +{ + SetValChar(x); +} + void CBotVar::operator=(int x) { SetValInt(x); } +void CBotVar::operator=(long x) +{ + SetValLong(x); +} + void CBotVar::operator=(float x) { SetValFloat(x); } +void CBotVar::operator=(double x) +{ + SetValDouble(x); +} + void CBotVar::operator=(const std::string &x) { SetValString(x); diff --git a/src/CBot/CBotVar/CBotVar.h b/src/CBot/CBotVar/CBotVar.h index d2805ddf..a94274fd 100644 --- a/src/CBot/CBotVar/CBotVar.h +++ b/src/CBot/CBotVar/CBotVar.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -444,12 +444,23 @@ public: */ //@{ + operator bool(); + operator signed char(); + operator short(); + operator uint32_t(); operator int(); + operator long(); operator float(); + operator double(); operator std::string(); void operator=(const CBotVar& var); + void operator=(signed char x); + void operator=(short x); + void operator=(uint32_t x); void operator=(int x); + void operator=(long x); void operator=(float x); + void operator=(double x); void operator=(const std::string &x); /** @@ -465,6 +476,12 @@ public: */ virtual void Copy(CBotVar* pSrc, bool bName = true); + virtual void SetValByte(signed char val); + + virtual void SetValShort(short val); + + virtual void SetValChar(uint32_t val); + /** * \brief Set value as an integer * @@ -475,30 +492,44 @@ public: */ virtual void SetValInt(int val, const std::string& name = ""); + virtual void SetValLong(long val); + /** * \brief Set value as float * \param val New value */ virtual void SetValFloat(float val); + virtual void SetValDouble(double val); + /** * \brief Set value as string * \param val New value */ virtual void SetValString(const std::string& val); + virtual signed char GetValByte(); + + virtual short GetValShort(); + + virtual uint32_t GetValChar(); + /** * \brief Get value as integer * \return Current value */ virtual int GetValInt(); + virtual long GetValLong(); + /** * \brief Get value as float * \return Current value */ virtual float GetValFloat(); + virtual double GetValDouble(); + /** * \brief Get value as string * @@ -623,28 +654,28 @@ public: /** * \brief Save common variable header (name, type, etc.) - * \param pf file pointer + * \param ostr Output stream * \return false on write error */ - virtual bool Save0State(FILE* pf); + virtual bool Save0State(std::ostream &ostr); /** * \brief Save variable data * * Overriden in child classes * - * \param pf file pointer + * \param ostr Output stream * \return false on write error */ - virtual bool Save1State(FILE* pf); + virtual bool Save1State(std::ostream &ostr); /** * \brief Restore variable - * \param pf file pointer + * \param istr Input stream * \param[out] pVar Pointer to recieve the variable * \return false on read error */ - static bool RestoreState(FILE* pf, CBotVar* &pVar); + static bool RestoreState(std::istream &istr, CBotVar* &pVar); //@} diff --git a/src/CBot/CBotVar/CBotVarArray.cpp b/src/CBot/CBotVar/CBotVarArray.cpp index 6462d119..16a1476a 100644 --- a/src/CBot/CBotVar/CBotVarArray.cpp +++ b/src/CBot/CBotVar/CBotVarArray.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -20,7 +20,6 @@ #include "CBot/CBotVar/CBotVarArray.h" #include "CBot/CBotVar/CBotVarClass.h" #include "CBot/CBotToken.h" -#include "CBot/CBotFileUtils.h" #include "CBot/CBotEnums.h" @@ -94,7 +93,7 @@ void CBotVarArray::SetPointer(CBotVar* pVarClass) !pVarClass->m_type.Eq(CBotTypArrayBody)) assert(0); - (static_cast(pVarClass))->IncrementUse(); // incement the reference + (static_cast(pVarClass))->IncrementUse(); // increment the reference } if ( m_pInstance != nullptr ) m_pInstance->DecrementUse(); @@ -137,10 +136,10 @@ std::string CBotVarArray::GetValString() } //////////////////////////////////////////////////////////////////////////////// -bool CBotVarArray::Save1State(FILE* pf) +bool CBotVarArray::Save1State(std::ostream &ostr) { - if ( !WriteType(pf, m_type) ) return false; - return SaveVars(pf, m_pInstance); // saves the instance that manages the table + if (!WriteType(ostr, m_type)) return false; + return SaveVars(ostr, m_pInstance); // saves the instance that manages the table } } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarArray.h b/src/CBot/CBotVar/CBotVarArray.h index 68b00b28..d25cdc67 100644 --- a/src/CBot/CBotVar/CBotVarArray.h +++ b/src/CBot/CBotVar/CBotVarArray.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -51,7 +51,7 @@ public: std::string GetValString() override; - bool Save1State(FILE* pf) override; + bool Save1State(std::ostream &ostr) override; private: //! Array data diff --git a/src/CBot/CBotVar/CBotVarBoolean.cpp b/src/CBot/CBotVar/CBotVarBoolean.cpp index d36de078..28eaeac6 100644 --- a/src/CBot/CBotVar/CBotVarBoolean.cpp +++ b/src/CBot/CBotVar/CBotVarBoolean.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -40,9 +40,9 @@ void CBotVarBoolean::Not() SetValInt(!GetValInt()); } -bool CBotVarBoolean::Save1State(FILE* pf) +bool CBotVarBoolean::Save1State(std::ostream &ostr) { - return WriteWord(pf, m_val); // the value of the variable + return WriteByte(ostr, m_val); // the value of the variable } } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarBoolean.h b/src/CBot/CBotVar/CBotVarBoolean.h index 44774a9f..a9967de2 100644 --- a/src/CBot/CBotVar/CBotVarBoolean.h +++ b/src/CBot/CBotVar/CBotVarBoolean.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -37,7 +37,7 @@ public: void XOr(CBotVar* left, CBotVar* right) override; void Not() override; - bool Save1State(FILE* pf) override; + bool Save1State(std::ostream &ostr) override; }; } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarByte.h b/src/CBot/CBotVar/CBotVarByte.h new file mode 100644 index 00000000..65c1a5f1 --- /dev/null +++ b/src/CBot/CBotVar/CBotVarByte.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "CBot/CBotVar/CBotVarValue.h" + +namespace CBot +{ + +/** + * \brief CBotVar subclass for managing 1-byte integer values (::CBotTypByte) + */ +class CBotVarByte : public CBotVarInteger +{ +public: + CBotVarByte(const CBotToken &name) : CBotVarInteger(name) {} + + void SR(CBotVar* left, CBotVar* right) override + { + SetValByte(static_cast(left->GetValByte()) >> right->GetValInt()); + } + + bool Save1State(std::ostream &ostr) override + { + return WriteByte(ostr, m_val); + } +}; + +} // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarChar.h b/src/CBot/CBotVar/CBotVarChar.h new file mode 100644 index 00000000..af93a698 --- /dev/null +++ b/src/CBot/CBotVar/CBotVarChar.h @@ -0,0 +1,59 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "CBot/CBotVar/CBotVarValue.h" + +namespace CBot +{ + +/** + * \brief CBotVar subclass for managing 32-bit Unicode values (::CBotTypChar) + */ +class CBotVarChar : public CBotVarInteger +{ +public: + CBotVarChar(const CBotToken &name) : CBotVarInteger(name) {} + + std::string GetValString() override + { + if (m_binit == CBotVar::InitType::UNDEF) + return LoadString(TX_UNDEF); + if (m_binit == CBotVar::InitType::IS_NAN) + return LoadString(TX_NAN); + + if (0x10FFFF < m_val || (0xD7FF < m_val && m_val < 0xE000)) + return "\xEF\xBF\xBD"; // replacement character U+FFFD + + return CodePointToUTF8(m_val); + } + + void SR(CBotVar* left, CBotVar* right) override + { + SetValChar(left->GetValChar() >> right->GetValInt()); + } + + bool Save1State(std::ostream &ostr) override + { + return WriteUInt32(ostr, m_val); + } +}; + +} // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarClass.cpp b/src/CBot/CBotVar/CBotVarClass.cpp index 36952d18..3ee19874 100644 --- a/src/CBot/CBotVar/CBotVarClass.cpp +++ b/src/CBot/CBotVar/CBotVarClass.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -23,8 +23,6 @@ #include "CBot/CBotStack.h" #include "CBot/CBotDefines.h" -#include "CBot/CBotFileUtils.h" - #include "CBot/CBotInstr/CBotInstr.h" #include @@ -53,10 +51,9 @@ CBotVarClass::CBotVarClass(const CBotToken& name, const CBotTypResult& type) : C m_type = type; if ( type.Eq(CBotTypArrayPointer) ) m_type.SetType( CBotTypArrayBody ); else if ( !type.Eq(CBotTypArrayBody) ) m_type.SetType( CBotTypClass ); - // officel type for this object + // official type for this object m_pClass = nullptr; - m_pParent = nullptr; m_binit = InitType::UNDEF; m_bStatic = false; m_mPrivate = ProtectionLevel::Public; @@ -65,14 +62,9 @@ CBotVarClass::CBotVarClass(const CBotToken& name, const CBotTypResult& type) : C m_ItemIdent = type.Eq(CBotTypIntrinsic) ? 0 : CBotVar::NextUniqNum(); // add to the list - m_instances.insert(this); + if (m_ItemIdent != 0) m_instances.insert(this); CBotClass* pClass = type.GetClass(); - if ( pClass != nullptr && pClass->GetParent() != nullptr ) - { - // also creates an instance of the parent class - m_pParent = new CBotVarClass(name, CBotTypResult(type.GetType(), pClass->GetParent()) ); //, nIdent); - } SetClass( pClass ); @@ -84,11 +76,8 @@ CBotVarClass::~CBotVarClass( ) if ( m_CptUse != 0 ) assert(0); - if ( m_pParent ) delete m_pParent; - m_pParent = nullptr; - // removes the class list - m_instances.erase(this); + if (m_ItemIdent != 0) m_instances.erase(this); delete m_pVar; } @@ -115,10 +104,6 @@ void CBotVarClass::Copy(CBotVar* pSrc, bool bName) m_binit = p->m_binit; //- m_bStatic = p->m_bStatic; m_pClass = p->m_pClass; - if ( p->m_pParent ) - { - assert(0); // "que faire du pParent"; - } // m_next = nullptr; m_pUserPtr = p->m_pUserPtr; @@ -164,9 +149,11 @@ void CBotVarClass::SetClass(CBotClass* pClass)//, int &nIdent) if (pClass == nullptr) return; - CBotVar* pv = pClass->GetVar(); // first on a list - while ( pv != nullptr ) + CBotVar* pv = nullptr; + while (pClass != nullptr) { + if ( pv == nullptr ) pv = pClass->GetVar(); + if ( pv == nullptr ) { pClass = pClass->GetParent(); continue; } // seeks the maximum dimensions of the table CBotInstr* p = pv->m_LimExpr; // the different formulas if ( p != nullptr ) @@ -216,6 +203,7 @@ void CBotVarClass::SetClass(CBotClass* pClass)//, int &nIdent) if ( m_pVar == nullptr) m_pVar = pn; else m_pVar->AddNext( pn ); pv = pv->GetNext(); + if ( pv == nullptr ) pClass = pClass->GetParent(); } } @@ -248,7 +236,6 @@ CBotVar* CBotVarClass::GetItem(const std::string& name) p = p->GetNext(); } - if ( m_pParent != nullptr ) return m_pParent->GetItem(name); return nullptr; } @@ -263,7 +250,6 @@ CBotVar* CBotVarClass::GetItemRef(int nIdent) p = p->GetNext(); } - if ( m_pParent != nullptr ) return m_pParent->GetItemRef(nIdent); return nullptr; } @@ -313,32 +299,46 @@ std::string CBotVarClass::GetValString() { res = m_pClass->GetName() + std::string("( "); - CBotVarClass* my = this; - while ( my != nullptr ) + CBotClass* pClass = m_pClass; + long prevID = 0; { - CBotVar* pv = my->m_pVar; - while ( pv != nullptr ) + CBotVar* pv = m_pVar; + if (pv != nullptr) while (true) { + if (pv->GetUniqNum() < prevID) + { + pClass = pClass->GetParent(); + if (pClass == nullptr) break; + res += " ) extends "; + res += pClass->GetName(); + res += "( "; + if (pClass->GetVar() == nullptr) continue; + } + + prevID = pv->GetUniqNum(); + res += pv->GetName() + std::string("="); if ( pv->IsStatic() ) { - CBotVar* pvv = my->m_pClass->GetItem(pv->GetName()); - res += pvv->GetValString(); + res += pClass->GetItemRef(prevID)->GetValString(); } else { res += pv->GetValString(); } pv = pv->GetNext(); - if ( pv != nullptr ) res += ", "; + if ( pv == nullptr ) break; + if ( pv->GetUniqNum() > prevID ) res += ", "; } - my = my->m_pParent; - if ( my != nullptr ) + + if (pClass != nullptr) while (true) { - res += ") extends "; - res += my->m_pClass->GetName(); - res += " ("; + pClass = pClass->GetParent(); + if (pClass == nullptr) break; + res += " ) extends "; + res += pClass->GetName(); + res += "( "; } } @@ -380,14 +380,7 @@ void CBotVarClass::DecrementUse() { m_CptUse++; // does not return to the destructor - // m_error is static in the stack - // saves the value for return - CBotError err; - int start, end; - CBotStack* pile = nullptr; - err = pile->GetError(start,end); // stack == nullptr it does not bother! - - pile = CBotStack::AllocateStack(); // clears the error + CBotStack* pile = CBotStack::AllocateStack(); CBotVar* ppVars[1]; ppVars[0] = nullptr; @@ -401,8 +394,6 @@ void CBotVarClass::DecrementUse() while ( pile->IsOk() && !m_pClass->ExecuteMethode(ident, pThis, ppVars, CBotTypResult(CBotTypVoid), pile, &token)) ; // waits for the end - pile->ResetError(err, start,end); - pile->Delete(); delete pThis; m_CptUse--; @@ -464,12 +455,12 @@ bool CBotVarClass::Ne(CBotVar* left, CBotVar* right) } //////////////////////////////////////////////////////////////////////////////// -bool CBotVarClass::Save1State(FILE* pf) +bool CBotVarClass::Save1State(std::ostream &ostr) { - if ( !WriteType(pf, m_type) ) return false; - if ( !WriteLong(pf, m_ItemIdent) ) return false; + if (!WriteType(ostr, m_type)) return false; + if (!WriteLong(ostr, m_ItemIdent)) return false; - return SaveVars(pf, m_pVar); // content of the object + return SaveVars(ostr, m_pVar); // content of the object } } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarClass.h b/src/CBot/CBotVar/CBotVarClass.h index 55bdd891..ac462d99 100644 --- a/src/CBot/CBotVar/CBotVarClass.h +++ b/src/CBot/CBotVar/CBotVarClass.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -54,7 +54,7 @@ public: CBotVar* GetItemList() override; std::string GetValString() override; - bool Save1State(FILE* pf) override; + bool Save1State(std::ostream &ostr) override; void Update(void* pUser) override; @@ -99,8 +99,6 @@ private: static std::set m_instances; //! Class definition CBotClass* m_pClass; - //! Parent class instance - CBotVarClass* m_pParent; //! Class members CBotVar* m_pVar; //! Reference counter diff --git a/src/CBot/CBotVar/CBotVarDouble.h b/src/CBot/CBotVar/CBotVarDouble.h new file mode 100644 index 00000000..be349159 --- /dev/null +++ b/src/CBot/CBotVar/CBotVarDouble.h @@ -0,0 +1,41 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "CBot/CBotVar/CBotVarValue.h" + +namespace CBot +{ + +/** + * \brief CBotVar subclass for managing double values (::CBotTypDouble) + */ +class CBotVarDouble : public CBotVarNumber +{ +public: + CBotVarDouble(const CBotToken &name) : CBotVarNumber(name) {} + + bool Save1State(std::ostream &ostr) override + { + return WriteDouble(ostr, m_val); + } +}; + +} // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarFloat.cpp b/src/CBot/CBotVar/CBotVarFloat.cpp index a1c4217f..02f2a394 100644 --- a/src/CBot/CBotVar/CBotVarFloat.cpp +++ b/src/CBot/CBotVar/CBotVarFloat.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -22,9 +22,9 @@ namespace CBot { -bool CBotVarFloat::Save1State(FILE* pf) +bool CBotVarFloat::Save1State(std::ostream &ostr) { - return WriteFloat(pf, m_val); // the value of the variable + return WriteFloat(ostr, m_val); // the value of the variable } } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarFloat.h b/src/CBot/CBotVar/CBotVarFloat.h index 81cbcde0..f9a5d2b7 100644 --- a/src/CBot/CBotVar/CBotVarFloat.h +++ b/src/CBot/CBotVar/CBotVarFloat.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -32,7 +32,7 @@ class CBotVarFloat : public CBotVarNumber public: CBotVarFloat(const CBotToken &name) : CBotVarNumber(name) {} - bool Save1State(FILE* pf) override; + bool Save1State(std::ostream &ostr) override; }; } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarInt.cpp b/src/CBot/CBotVar/CBotVarInt.cpp index 477629ae..69aed5e2 100644 --- a/src/CBot/CBotVar/CBotVarInt.cpp +++ b/src/CBot/CBotVar/CBotVarInt.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -45,67 +45,44 @@ std::string CBotVarInt::GetValString() void CBotVarInt::Neg() { CBotVarNumber::Neg(); - m_defnum.empty(); + m_defnum.clear(); } void CBotVarInt::Inc() { CBotVarNumber::Inc(); - m_defnum.empty(); + m_defnum.clear(); } void CBotVarInt::Dec() { CBotVarNumber::Dec(); - m_defnum.empty(); + m_defnum.clear(); } -void CBotVarInt::XOr(CBotVar* left, CBotVar* right) -{ - SetValInt(left->GetValInt() ^ right->GetValInt()); -} -void CBotVarInt::And(CBotVar* left, CBotVar* right) -{ - SetValInt(left->GetValInt() & right->GetValInt()); -} -void CBotVarInt::Or(CBotVar* left, CBotVar* right) -{ - SetValInt(left->GetValInt() | right->GetValInt()); -} - -void CBotVarInt::SL(CBotVar* left, CBotVar* right) -{ - SetValInt(left->GetValInt() << right->GetValInt()); -} -void CBotVarInt::ASR(CBotVar* left, CBotVar* right) -{ - SetValInt(left->GetValInt() >> right->GetValInt()); -} void CBotVarInt::SR(CBotVar* left, CBotVar* right) { - int source = left->GetValInt(); - int shift = right->GetValInt(); - if (shift >= 1) source &= 0x7fffffff; - SetValInt(source >> shift); + SetValInt(static_cast(left->GetValInt()) >> right->GetValInt()); } void CBotVarInt::Not() { m_val = ~m_val; + m_defnum.clear(); } -bool CBotVarInt::Save0State(FILE* pf) +bool CBotVarInt::Save0State(std::ostream &ostr) { if (!m_defnum.empty()) { - if(!WriteWord(pf, 200)) return false; // special marker - if(!WriteString(pf, m_defnum)) return false; + if(!WriteWord(ostr, 200)) return false; // special marker + if(!WriteString(ostr, m_defnum)) return false; } - return CBotVar::Save0State(pf); + return CBotVar::Save0State(ostr); } -bool CBotVarInt::Save1State(FILE* pf) +bool CBotVarInt::Save1State(std::ostream &ostr) { - return WriteWord(pf, m_val); + return WriteInt(ostr, m_val); } } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarInt.h b/src/CBot/CBotVar/CBotVarInt.h index 906a402d..b2436742 100644 --- a/src/CBot/CBotVar/CBotVarInt.h +++ b/src/CBot/CBotVar/CBotVarInt.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -27,10 +27,10 @@ namespace CBot /** * \brief CBotVar subclass for managing integer values (::CBotTypInt) */ -class CBotVarInt : public CBotVarNumber +class CBotVarInt : public CBotVarInteger { public: - CBotVarInt(const CBotToken &name) : CBotVarNumber(name) {} + CBotVarInt(const CBotToken &name) : CBotVarInteger(name) {} void SetValInt(int val, const std::string& s = "") override; std::string GetValString() override; @@ -40,18 +40,20 @@ public: void Neg() override; void Inc() override; void Dec() override; - - void XOr(CBotVar* left, CBotVar* right) override; - void Or(CBotVar* left, CBotVar* right) override; - void And(CBotVar* left, CBotVar* right) override; void Not() override; - void SL(CBotVar* left, CBotVar* right) override; void SR(CBotVar* left, CBotVar* right) override; - void ASR(CBotVar* left, CBotVar* right) override; - bool Save0State(FILE* pf) override; - bool Save1State(FILE* pf) override; + bool Save0State(std::ostream &ostr) override; + bool Save1State(std::ostream &ostr) override; + +protected: + + void SetValue(int val) override + { + CBotVarNumberBase::SetValue(val); + m_defnum.clear(); + } protected: //! The name if given by DefineNum. diff --git a/src/CBot/CBotVar/CBotVarLong.h b/src/CBot/CBotVar/CBotVarLong.h new file mode 100644 index 00000000..afd0af00 --- /dev/null +++ b/src/CBot/CBotVar/CBotVarLong.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "CBot/CBotVar/CBotVarValue.h" + +namespace CBot +{ + +/** + * \brief CBotVar subclass for managing long integer values (::CBotTypLong) + */ +class CBotVarLong : public CBotVarInteger +{ +public: + CBotVarLong(const CBotToken &name) : CBotVarInteger(name) {} + + void SR(CBotVar* left, CBotVar* right) override + { + SetValLong(static_cast(left->GetValLong()) >> right->GetValInt()); + } + + bool Save1State(std::ostream &ostr) override + { + return WriteLong(ostr, m_val); + } +}; + +} // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarPointer.cpp b/src/CBot/CBotVar/CBotVarPointer.cpp index 2f78c90a..a4f1ce7b 100644 --- a/src/CBot/CBotVar/CBotVarPointer.cpp +++ b/src/CBot/CBotVar/CBotVarPointer.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -24,7 +24,6 @@ #include "CBot/CBotEnums.h" #include "CBot/CBotUtils.h" -#include "CBot/CBotFileUtils.h" #include @@ -171,21 +170,21 @@ CBotClass* CBotVarPointer::GetClass() } //////////////////////////////////////////////////////////////////////////////// -bool CBotVarPointer::Save1State(FILE* pf) +bool CBotVarPointer::Save1State(std::ostream &ostr) { if ( m_type.GetClass() != nullptr ) { - if (!WriteString(pf, m_type.GetClass()->GetName())) return false; // name of the class + if (!WriteString(ostr, m_type.GetClass()->GetName())) return false; // name of the class } else { - if (!WriteString(pf, "")) return false; + if (!WriteString(ostr, "")) return false; } - if (!WriteLong(pf, GetIdent())) return false; // the unique reference + if (!WriteLong(ostr, GetIdent())) return false; // the unique reference // also saves the proceedings copies - return SaveVars(pf, GetPointer()); + return SaveVars(ostr, GetPointer()); } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/CBot/CBotVar/CBotVarPointer.h b/src/CBot/CBotVar/CBotVarPointer.h index 75c9bc98..8b10d844 100644 --- a/src/CBot/CBotVar/CBotVarPointer.h +++ b/src/CBot/CBotVar/CBotVarPointer.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -61,7 +61,7 @@ public: void ConstructorSet() override; - bool Save1State(FILE* pf) override; + bool Save1State(std::ostream &ostr) override; void Update(void* pUser) override; diff --git a/src/CBot/CBotVar/CBotVarShort.h b/src/CBot/CBotVar/CBotVarShort.h new file mode 100644 index 00000000..92d328eb --- /dev/null +++ b/src/CBot/CBotVar/CBotVarShort.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "CBot/CBotVar/CBotVarValue.h" + +namespace CBot +{ + +/** + * \brief CBotVar subclass for managing short integer values (::CBotTypShort) + */ +class CBotVarShort : public CBotVarInteger +{ +public: + CBotVarShort(const CBotToken &name) : CBotVarInteger(name) {} + + void SR(CBotVar* left, CBotVar* right) override + { + SetValShort(static_cast(left->GetValShort()) >> right->GetValInt()); + } + + bool Save1State(std::ostream &ostr) override + { + return WriteShort(ostr, m_val); + } +}; + +} // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarString.cpp b/src/CBot/CBotVar/CBotVarString.cpp index 91a0e618..cd8ba864 100644 --- a/src/CBot/CBotVar/CBotVarString.cpp +++ b/src/CBot/CBotVar/CBotVarString.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -37,9 +37,9 @@ bool CBotVarString::Ne(CBotVar* left, CBotVar* right) return left->GetValString() != right->GetValString(); } -bool CBotVarString::Save1State(FILE* pf) +bool CBotVarString::Save1State(std::ostream &ostr) { - return WriteString(pf, m_val); + return WriteString(ostr, m_val); } } // namespace CBot diff --git a/src/CBot/CBotVar/CBotVarString.h b/src/CBot/CBotVar/CBotVarString.h index d01a80f6..fb304674 100644 --- a/src/CBot/CBotVar/CBotVarString.h +++ b/src/CBot/CBotVar/CBotVarString.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -63,7 +63,7 @@ public: bool Eq(CBotVar* left, CBotVar* right) override; bool Ne(CBotVar* left, CBotVar* right) override; - bool Save1State(FILE* pf) override; + bool Save1State(std::ostream &ostr) override; private: template diff --git a/src/CBot/CBotVar/CBotVarValue.h b/src/CBot/CBotVar/CBotVarValue.h index 76e820e8..175d6b47 100644 --- a/src/CBot/CBotVar/CBotVarValue.h +++ b/src/CBot/CBotVar/CBotVarValue.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -74,6 +74,13 @@ public: return s.str(); } +protected: + virtual void SetValue(T val) + { + this->m_val = val; + this->m_binit = CBotVar::InitType::DEF; + } + protected: //! The value T m_val; @@ -86,18 +93,59 @@ template class CBotVarNumberBase : public CBotVarValue { public: - CBotVarNumberBase(const CBotToken &name) : CBotVarValue(name) {} + CBotVarNumberBase(const CBotToken &name) : CBotVarValue(name) + { + this->m_val = static_cast(0); + } + + void SetValByte(signed char val) override + { + this->SetValue(static_cast(val)); + } + + void SetValShort(short val) override + { + this->SetValue(static_cast(val)); + } + + void SetValChar(uint32_t val) override + { + this->SetValue(static_cast(val)); + } void SetValInt(int val, const std::string &s = "") override { - this->m_val = static_cast(val); - this->m_binit = CBotVar::InitType::DEF; + this->SetValue(static_cast(val)); + } + + void SetValLong(long val) override + { + this->SetValue(static_cast(val)); } void SetValFloat(float val) override { - this->m_val = static_cast(val); - this->m_binit = CBotVar::InitType::DEF; + this->SetValue(static_cast(val)); + } + + void SetValDouble(double val) override + { + this->SetValue(static_cast(val)); + } + + signed char GetValByte() override + { + return static_cast(this->m_val); + } + + short GetValShort() override + { + return static_cast(this->m_val); + } + + uint32_t GetValChar() override + { + return static_cast(this->m_val); } int GetValInt() override @@ -105,19 +153,28 @@ public: return static_cast(this->m_val); } + long GetValLong() override + { + return static_cast(this->m_val); + } + float GetValFloat() override { return static_cast(this->m_val); } + double GetValDouble() override + { + return static_cast(this->m_val); + } bool Eq(CBotVar* left, CBotVar* right) override { - return left->GetValFloat() == right->GetValFloat(); + return static_cast(*left) == static_cast(*right); } bool Ne(CBotVar* left, CBotVar* right) override { - return left->GetValFloat() != right->GetValFloat(); + return static_cast(*left) != static_cast(*right); } }; @@ -132,33 +189,33 @@ public: void Mul(CBotVar* left, CBotVar* right) override { - this->SetValFloat(left->GetValFloat() * right->GetValFloat()); + this->SetValue(static_cast(*left) * static_cast(*right)); } void Power(CBotVar* left, CBotVar* right) override { - this->SetValFloat(pow(left->GetValFloat(), right->GetValFloat())); + this->SetValue(pow(static_cast(*left), static_cast(*right))); } CBotError Div(CBotVar* left, CBotVar* right) override { - float r = right->GetValFloat(); - if (r == 0) return CBotErrZeroDiv; - this->SetValFloat(left->GetValFloat() / r); + T r = static_cast(*right); + if ( r == static_cast(0) ) return CBotErrZeroDiv; + this->SetValue(static_cast(*left) / r); return CBotNoErr; } CBotError Modulo(CBotVar* left, CBotVar* right) override { - float r = right->GetValFloat(); - if (r == 0) return CBotErrZeroDiv; - this->SetValFloat(fmod(left->GetValFloat(), r)); + T r = static_cast(*right); + if ( r == static_cast(0) ) return CBotErrZeroDiv; + this->SetValue(fmod(static_cast(*left), r)); return CBotNoErr; } void Add(CBotVar* left, CBotVar* right) override { - this->SetValFloat(left->GetValFloat() + right->GetValFloat()); + this->SetValue(static_cast(*left) + static_cast(*right)); } void Sub(CBotVar* left, CBotVar* right) override { - this->SetValFloat(left->GetValFloat() - right->GetValFloat()); + this->SetValue(static_cast(*left) - static_cast(*right)); } void Neg() override @@ -176,21 +233,65 @@ public: bool Lo(CBotVar* left, CBotVar* right) override { - return left->GetValFloat() < right->GetValFloat(); + return static_cast(*left) < static_cast(*right); } bool Hi(CBotVar* left, CBotVar* right) override { - return left->GetValFloat() > right->GetValFloat(); + return static_cast(*left) > static_cast(*right); } bool Ls(CBotVar* left, CBotVar* right) override { - return left->GetValFloat() <= right->GetValFloat(); + return static_cast(*left) <= static_cast(*right); } bool Hs(CBotVar* left, CBotVar* right) override { - return left->GetValFloat() >= right->GetValFloat(); + return static_cast(*left) >= static_cast(*right); } }; -} +/** + * \brief An integer variable (byte, short, char, int, long) + */ +template +class CBotVarInteger : public CBotVarNumber +{ +public: + CBotVarInteger(const CBotToken &name) : CBotVarNumber(name) {} + CBotError Modulo(CBotVar* left, CBotVar* right) override + { + T r = static_cast(*right); + if ( r == static_cast(0) ) return CBotErrZeroDiv; + this->SetValue(static_cast(*left) % r); + return CBotNoErr; + } + + void XOr(CBotVar* left, CBotVar* right) override + { + this->SetValue(static_cast(*left) ^ static_cast(*right)); + } + void And(CBotVar* left, CBotVar* right) override + { + this->SetValue(static_cast(*left) & static_cast(*right)); + } + void Or(CBotVar* left, CBotVar* right) override + { + this->SetValue(static_cast(*left) | static_cast(*right)); + } + + void SL(CBotVar* left, CBotVar* right) override + { + this->SetValue(static_cast(*left) << right->GetValInt()); + } + void ASR(CBotVar* left, CBotVar* right) override + { + this->SetValue(static_cast(*left) >> right->GetValInt()); + } + + void Not() override + { + this->m_val = ~(this->m_val); + } +}; + +} // namespace CBot diff --git a/src/CBot/CMakeLists.txt b/src/CBot/CMakeLists.txt index a9a83e2e..184ed0e4 100644 --- a/src/CBot/CMakeLists.txt +++ b/src/CBot/CMakeLists.txt @@ -44,6 +44,8 @@ set(SOURCES CBotInstr/CBotEmpty.h CBotInstr/CBotExprLitBool.cpp CBotInstr/CBotExprLitBool.h + CBotInstr/CBotExprLitChar.cpp + CBotInstr/CBotExprLitChar.h CBotInstr/CBotExprLitNan.cpp CBotInstr/CBotExprLitNan.h CBotInstr/CBotExprLitNull.cpp @@ -98,6 +100,8 @@ set(SOURCES CBotInstr/CBotPostIncExpr.h CBotInstr/CBotPreIncExpr.cpp CBotInstr/CBotPreIncExpr.h + CBotInstr/CBotRepeat.cpp + CBotInstr/CBotRepeat.h CBotInstr/CBotReturn.cpp CBotInstr/CBotReturn.h CBotInstr/CBotSwitch.cpp @@ -127,14 +131,19 @@ set(SOURCES CBotVar/CBotVarArray.h CBotVar/CBotVarBoolean.cpp CBotVar/CBotVarBoolean.h + CBotVar/CBotVarByte.h + CBotVar/CBotVarChar.h CBotVar/CBotVarClass.cpp CBotVar/CBotVarClass.h + CBotVar/CBotVarDouble.h CBotVar/CBotVarFloat.cpp CBotVar/CBotVarFloat.h CBotVar/CBotVarInt.cpp CBotVar/CBotVarInt.h + CBotVar/CBotVarLong.h CBotVar/CBotVarPointer.cpp CBotVar/CBotVarPointer.h + CBotVar/CBotVarShort.h CBotVar/CBotVarString.cpp CBotVar/CBotVarString.h stdlib/Compilation.cpp diff --git a/src/CBot/stdlib/Compilation.cpp b/src/CBot/stdlib/Compilation.cpp index 2ff4403a..e33fec8e 100644 --- a/src/CBot/stdlib/Compilation.cpp +++ b/src/CBot/stdlib/Compilation.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/stdlib/Compilation.h b/src/CBot/stdlib/Compilation.h index 23dcfd1a..b74ac219 100644 --- a/src/CBot/stdlib/Compilation.h +++ b/src/CBot/stdlib/Compilation.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/stdlib/FileFunctions.cpp b/src/CBot/stdlib/FileFunctions.cpp index b185ac13..979e6ec9 100644 --- a/src/CBot/stdlib/FileFunctions.cpp +++ b/src/CBot/stdlib/FileFunctions.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -181,7 +181,7 @@ CBotTypResult cfopen (CBotVar* pThis, CBotVar* &pVar) // process FILE :: close -// execeution +// execution bool rfclose (CBotVar* pThis, CBotVar* pVar, CBotVar* pResult, int& Exception, void* user) { // it shouldn't be any parameters diff --git a/src/CBot/stdlib/MathFunctions.cpp b/src/CBot/stdlib/MathFunctions.cpp index 665caffc..f6e5b484 100644 --- a/src/CBot/stdlib/MathFunctions.cpp +++ b/src/CBot/stdlib/MathFunctions.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -144,13 +144,36 @@ bool rRand(CBotVar* var, CBotVar* result, int& exception, void* user) bool rAbs(CBotVar* var, CBotVar* result, int& exception, void* user) { - float value; + switch (result->GetType()) + { + case CBotTypDouble: + *result = fabs(var->GetValDouble()); + break; + case CBotTypFloat: + *result = fabs(var->GetValFloat()); + break; + case CBotTypLong: + *result = labs(var->GetValLong()); + break; + default: + *result = abs(var->GetValInt()); + break; + } - value = var->GetValFloat(); - result->SetValFloat(fabs(value)); return true; } +CBotTypResult cAbs(CBotVar* &var, void* user) +{ + if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); + if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + + CBotTypResult returnType(var->GetType()); + var = var->GetNext(); + if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); + return returnType; +} + // Instruction "floor()" bool rFloor(CBotVar* var, CBotVar* result, int& exception, void* user) @@ -209,7 +232,7 @@ void InitMathFunctions() CBotProgram::AddFunction("sqrt", rSqrt, cOneFloat); CBotProgram::AddFunction("pow", rPow, cTwoFloat); CBotProgram::AddFunction("rand", rRand, cNull); - CBotProgram::AddFunction("abs", rAbs, cOneFloat); + CBotProgram::AddFunction("abs", rAbs, cAbs); CBotProgram::AddFunction("floor", rFloor, cOneFloat); CBotProgram::AddFunction("ceil", rCeil, cOneFloat); CBotProgram::AddFunction("round", rRound, cOneFloat); diff --git a/src/CBot/stdlib/StringFunctions.cpp b/src/CBot/stdlib/StringFunctions.cpp index a4baa5b7..0fcb693d 100644 --- a/src/CBot/stdlib/StringFunctions.cpp +++ b/src/CBot/stdlib/StringFunctions.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/stdlib/stdlib.h b/src/CBot/stdlib/stdlib.h index fbc5d3fa..b0e393f1 100644 --- a/src/CBot/stdlib/stdlib.h +++ b/src/CBot/stdlib/stdlib.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CBot/stdlib/stdlib_public.h b/src/CBot/stdlib/stdlib_public.h index b7d5ef67..d3da1c7d 100644 --- a/src/CBot/stdlib/stdlib_public.h +++ b/src/CBot/stdlib/stdlib_public.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c58172bd..3c5f4063 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -48,33 +48,43 @@ elseif(PLATFORM_WINDOWS) if(${MSVC_STATIC}) if (${OPENAL_SOUND}) - find_library(FLAC_LIBRARY NAMES flac.lib) - find_library(VORBIS_LIBRARY NAMES vorbis.lib) - find_library(VORBISENC_LIBRARY NAMES vorbisenc.lib) - find_library(OGG_LIBRARY NAMES ogg.lib) + find_library(FLAC_LIBRARY NAMES flac) + find_library(VORBIS_LIBRARY NAMES vorbis) + find_library(VORBISENC_LIBRARY NAMES vorbisenc) + find_library(OGG_LIBRARY NAMES ogg) + find_library(OPUS_LIBRARY NAMES opus) set(OPENAL_MSVC_LIBS ${FLAC_LIBRARY} ${VORBIS_LIBRARY} ${VORBISENC_LIBRARY} ${OGG_LIBRARY} + ${OPUS_LIBRARY} ) endif() - find_library(BZ2_LIBRARY NAMES bz2.lib) - find_library(JPEG_LIBRARY NAMES jpeg.lib) - find_library(TIFF_LIBRARY NAMES tiff.lib) - find_library(WEBP_LIBRARY NAMES webp.lib) - find_library(LZMA_LIBRARY NAMES lzma.lib) - find_library(FREETYPE_LIBRARY NAMES freetype.lib) + find_library(BZ2_LIBRARY NAMES bz2) + find_library(JPEG_LIBRARY NAMES jpeg) + find_library(TIFF_LIBRARY NAMES tiff) + find_library(LZMA_LIBRARY NAMES lzma) + find_library(FREETYPE_LIBRARY NAMES freetype) + find_library(ICONV_LIBRARY NAMES iconv) + find_library(CHARSET_LIBRARY NAMES charset) + find_library(BROTLICOMMON_LIBRARY NAMES brotlicommon-static) + find_library(BROTLIENC_LIBRARY NAMES brotlienc-static) + find_library(BROTLIDEC_LIBRARY NAMES brotlidec-static) set(MSVC_LIBS ${LIBINTL_LIBRARY} ${OPENAL_MSVC_LIBS} ${JPEG_LIBRARY} ${TIFF_LIBRARY} ${BZ2_LIBRARY} - ${WEBP_LIBRARY} ${LZMA_LIBRARY} ${FREETYPE_LIBRARY} + ${ICONV_LIBRARY} + ${CHARSET_LIBRARY} + ${BROTLICOMMON_LIBRARY} + ${BROTLIENC_LIBRARY} + ${BROTLIDEC_LIBRARY} winmm.lib dxguid.lib imm32.lib @@ -83,6 +93,7 @@ elseif(PLATFORM_WINDOWS) version.lib wsock32.lib ws2_32.lib + setupapi.lib ) else(${MSVC_STATIC}) set(MSVC_LIBS ${LIBINTL_LIBRARY}) @@ -101,6 +112,10 @@ elseif(PLATFORM_MACOSX) find_library(LIBINTL_LIBRARY NAMES intl libintl) find_path(LIBINTL_INCLUDE_PATH NAMES libintl.h) set(PLATFORM_LIBS ${LIBINTL_LIBRARY}) +elseif(PLATFORM_FREEBSD) + find_library(LIBINTL_LIBRARY NAMES intl libintl) + find_path(LIBINTL_INCLUDE_PATH NAMES libintl.h) + set(PLATFORM_LIBS ${LIBINTL_LIBRARY}) endif() @@ -138,6 +153,8 @@ set(BASE_SOURCES app/controller.h app/input.cpp app/input.h + app/modman.cpp + app/modman.h app/pathman.cpp app/pathman.h app/pausemanager.cpp @@ -411,6 +428,7 @@ set(BASE_SOURCES object/object_interface_type.h object/object_manager.cpp object/object_manager.h + object/object_type.cpp object/object_type.h object/old_object.cpp object/old_object.h @@ -530,6 +548,8 @@ set(BASE_SOURCES ui/displayinfo.h ui/displaytext.cpp ui/displaytext.h + ui/filedialog.cpp + ui/filedialog.h ui/maindialog.cpp ui/maindialog.h ui/mainmap.cpp @@ -540,6 +560,8 @@ set(BASE_SOURCES ui/mainui.h ui/object_interface.cpp ui/object_interface.h + ui/particles_generator.cpp + ui/particles_generator.h ui/screen/screen.cpp ui/screen/screen.h ui/screen/screen_apperance.cpp @@ -556,6 +578,8 @@ set(BASE_SOURCES ui/screen/screen_loading.h ui/screen/screen_main_menu.cpp ui/screen/screen_main_menu.h + ui/screen/screen_mod_list.cpp + ui/screen/screen_mod_list.h ui/screen/screen_player_select.cpp ui/screen/screen_player_select.h ui/screen/screen_quit.cpp diff --git a/src/app/app.cpp b/src/app/app.cpp index 6f864572..1e4515ed 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include "app/controller.h" #include "app/input.h" +#include "app/modman.h" #include "app/pathman.h" #include "common/config_file.h" @@ -113,7 +114,8 @@ CApplication::CApplication(CSystemUtils* systemUtils) m_private(MakeUnique()), m_configFile(MakeUnique()), m_input(MakeUnique()), - m_pathManager(MakeUnique(systemUtils)) + m_pathManager(MakeUnique(systemUtils)), + m_modManager(MakeUnique(this, m_pathManager.get())) { m_exitCode = 0; m_active = false; @@ -220,6 +222,35 @@ CSoundInterface* CApplication::GetSound() return m_sound.get(); } +CModManager* CApplication::GetModManager() +{ + return m_modManager.get(); +} + +void CApplication::LoadEnvironmentVariables() +{ + auto dataDir = m_systemUtils->GetEnvVar("COLOBOT_DATA_DIR"); + if (!dataDir.empty()) + { + m_pathManager->SetDataPath(dataDir); + GetLogger()->Info("Using data dir (based on environment variable): '%s'\n", dataDir.c_str()); + } + + auto langDir = m_systemUtils->GetEnvVar("COLOBOT_LANG_DIR"); + if (!langDir.empty()) + { + m_pathManager->SetLangPath(langDir); + GetLogger()->Info("Using lang dir (based on environment variable): '%s'\n", langDir.c_str()); + } + + auto saveDir = m_systemUtils->GetEnvVar("COLOBOT_SAVE_DIR"); + if (!saveDir.empty()) + { + m_pathManager->SetSavePath(saveDir); + GetLogger()->Info("Using save dir (based on environment variable): '%s'\n", saveDir.c_str()); + } +} + ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[]) { enum OptionType @@ -286,15 +317,18 @@ ParseArgsStatus CApplication::ParseArguments(int argc, char *argv[]) GetLogger()->Message("\n"); GetLogger()->Message("%s\n", COLOBOT_FULLNAME); GetLogger()->Message("\n"); - GetLogger()->Message("List of available options:\n"); + GetLogger()->Message("List of available options and environment variables:\n"); GetLogger()->Message(" -help this help\n"); GetLogger()->Message(" -debug modes enable debug modes (more info printed in logs; see code for reference of modes)\n"); GetLogger()->Message(" -runscene sceneNNN run given scene on start\n"); GetLogger()->Message(" -scenetest win every mission right after it's loaded\n"); GetLogger()->Message(" -loglevel level set log level to level (one of: trace, debug, info, warn, error, none)\n"); GetLogger()->Message(" -langdir path set custom language directory path\n"); + GetLogger()->Message(" environment variable: COLOBOT_LANG_DIR\n"); GetLogger()->Message(" -datadir path set custom data directory path\n"); + GetLogger()->Message(" environment variable: COLOBOT_DATA_DIR\n"); GetLogger()->Message(" -savedir path set custom save directory path (must be writable)\n"); + GetLogger()->Message(" environment variable: COLOBOT_SAVE_DIR\n"); GetLogger()->Message(" -mod path load datadir mod from given path\n"); GetLogger()->Message(" -resolution WxH set resolution\n"); GetLogger()->Message(" -headless headless mode - disables graphics, sound and user interaction\n"); @@ -486,6 +520,10 @@ bool CApplication::Create() GetLogger()->Warn("Config could not be loaded. Default values will be used!\n"); } + m_modManager->FindMods(); + m_modManager->SaveMods(); + m_modManager->MountAllMods(); + // Create the sound instance. #ifdef OPENAL_SOUND if (!m_headless) @@ -511,6 +549,8 @@ bool CApplication::Create() /* SDL initialization sequence */ + // Creating the m_engine now because it holds the vsync flag + m_engine = MakeUnique(this, m_systemUtils); Uint32 initFlags = SDL_INIT_VIDEO | SDL_INIT_TIMER; @@ -655,8 +695,6 @@ bool CApplication::Create() } // Create the 3D engine - m_engine = MakeUnique(this, m_systemUtils); - m_engine->SetDevice(m_device.get()); if (! m_engine->Create() ) @@ -671,21 +709,7 @@ bool CApplication::Create() // Create the robot application. m_controller = MakeUnique(); - CThread musicLoadThread([this]() - { - GetLogger()->Debug("Cache sounds...\n"); - SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(musicLoadStart); - - m_sound->CacheAll(); - - SystemTimeStamp* musicLoadEnd = m_systemUtils->CreateTimeStamp(); - m_systemUtils->GetCurrentTimeStamp(musicLoadEnd); - float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, STU_MSEC); - GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime); - }, - "Sound loading thread"); - musicLoadThread.Start(); + StartLoadingMusic(); if (m_runSceneCategory == LevelCategory::Max) m_controller->StartApp(); @@ -699,6 +723,15 @@ bool CApplication::Create() return true; } +void CApplication::ReloadResources() +{ + GetLogger()->Info("Reloading resources\n"); + m_engine->ReloadAllTextures(); + StartLoadingMusic(); + m_controller->GetRobotMain()->UpdateCustomLevelList(); +} + + bool CApplication::CreateVideoSurface() { Uint32 videoFlags = SDL_WINDOW_OPENGL; @@ -817,24 +850,9 @@ bool CApplication::CreateVideoSurface() int vsync = 0; if (GetConfigFile().GetIntProperty("Setup", "VSync", vsync)) { - while (SDL_GL_SetSwapInterval(vsync) == -1) - { - switch(vsync) - { - case -1: //failed with adaptive sync? - GetLogger()->Warn("Adaptive sync not supported.\n"); - vsync = 1; - break; - case 1: //failed with VSync enabled? - GetLogger()->Warn("Couldn't enable VSync.\n"); - vsync = 0; - break; - case 0: //failed with VSync disabled? - GetLogger()->Warn("Couldn't disable VSync.\n"); - vsync = 1; - break; - } - } + m_engine->SetVSync(vsync); + TryToSetVSync(); + vsync = m_engine->GetVSync(); GetConfigFile().SetIntProperty("Setup", "VSync", vsync); GetLogger()->Info("Using Vsync: %s\n", (vsync == -1 ? "adaptive" : (vsync ? "true" : "false"))); @@ -843,6 +861,32 @@ bool CApplication::CreateVideoSurface() return true; } +void CApplication::TryToSetVSync() +{ + int vsync = m_engine->GetVSync(); + int result = SDL_GL_SetSwapInterval(vsync); + if (result == -1) + { + switch (vsync) + { + case -1: + GetLogger()->Warn("Adaptive sync not supported: %s\n", SDL_GetError()); + m_engine->SetVSync(1); + TryToSetVSync(); + break; + case 1: + GetLogger()->Warn("Couldn't enable VSync: %s\n", SDL_GetError()); + m_engine->SetVSync(0); + TryToSetVSync(); + break; + case 0: + GetLogger()->Warn("Couldn't disable VSync: %s\n", SDL_GetError()); + m_engine->SetVSync(SDL_GL_GetSwapInterval()); + break; + } + } +} + bool CApplication::ChangeVideoConfig(const Gfx::DeviceConfig &newConfig) { m_deviceConfig = newConfig; @@ -851,26 +895,7 @@ bool CApplication::ChangeVideoConfig(const Gfx::DeviceConfig &newConfig) SDL_SetWindowSize(m_private->window, m_deviceConfig.size.x, m_deviceConfig.size.y); SDL_SetWindowFullscreen(m_private->window, m_deviceConfig.fullScreen ? SDL_WINDOW_FULLSCREEN : 0); - int vsync = m_engine->GetVSync(); - while (SDL_GL_SetSwapInterval(vsync) == -1) - { - switch(vsync) - { - case -1: //failed with adaptive sync? - GetLogger()->Warn("Adaptive sync not supported.\n"); - vsync = 1; - break; - case 1: //failed with VSync enabled? - GetLogger()->Warn("Couldn't enable VSync.\n"); - vsync = 0; - break; - case 0: //failed with VSync disabled? - GetLogger()->Warn("Couldn't disable VSync.\n"); - vsync = 1; - break; - } - } - m_engine->SetVSync(vsync); + TryToSetVSync(); m_device->ConfigChanged(m_deviceConfig); @@ -1033,6 +1058,10 @@ int CApplication::Run() MoveMouse(Math::Point(0.5f, 0.5f)); // center mouse on start + SystemTimeStamp *previousTimeStamp = m_systemUtils->CreateTimeStamp(); + SystemTimeStamp *currentTimeStamp = m_systemUtils->CreateTimeStamp(); + SystemTimeStamp *interpolatedTimeStamp = m_systemUtils->CreateTimeStamp(); + while (true) { if (m_active) @@ -1131,21 +1160,30 @@ int CApplication::Run() CProfiler::StartPerformanceCounter(PCNT_UPDATE_ALL); - // Prepare and process step simulation event - Event event = CreateUpdateEvent(); - if (event.type != EVENT_NULL && m_controller != nullptr) + // Prepare and process step simulation event(s) + // If game speed is increased then we do extra ticks per loop iteration to improve physics accuracy. + int numTickSlices = static_cast(GetSimulationSpeed()); + if(numTickSlices < 1) numTickSlices = 1; + m_systemUtils->CopyTimeStamp(previousTimeStamp, m_curTimeStamp); + m_systemUtils->GetCurrentTimeStamp(currentTimeStamp); + for(int tickSlice = 0; tickSlice < numTickSlices; tickSlice++) { - LogEvent(event); + m_systemUtils->InterpolateTimeStamp(interpolatedTimeStamp, previousTimeStamp, currentTimeStamp, (tickSlice+1)/static_cast(numTickSlices)); + Event event = CreateUpdateEvent(interpolatedTimeStamp); + if (event.type != EVENT_NULL && m_controller != nullptr) + { + LogEvent(event); - m_sound->FrameMove(m_relTime); + m_sound->FrameMove(m_relTime); - CProfiler::StartPerformanceCounter(PCNT_UPDATE_GAME); - m_controller->ProcessEvent(event); - CProfiler::StopPerformanceCounter(PCNT_UPDATE_GAME); + CProfiler::StartPerformanceCounter(PCNT_UPDATE_GAME); + m_controller->ProcessEvent(event); + CProfiler::StopPerformanceCounter(PCNT_UPDATE_GAME); - CProfiler::StartPerformanceCounter(PCNT_UPDATE_ENGINE); - m_engine->FrameUpdate(); - CProfiler::StopPerformanceCounter(PCNT_UPDATE_ENGINE); + CProfiler::StartPerformanceCounter(PCNT_UPDATE_ENGINE); + m_engine->FrameUpdate(); + CProfiler::StopPerformanceCounter(PCNT_UPDATE_ENGINE); + } } CProfiler::StopPerformanceCounter(PCNT_UPDATE_ALL); @@ -1161,6 +1199,10 @@ int CApplication::Run() } end: + m_systemUtils->DestroyTimeStamp(previousTimeStamp); + m_systemUtils->DestroyTimeStamp(currentTimeStamp); + m_systemUtils->DestroyTimeStamp(interpolatedTimeStamp); + return m_exitCode; } @@ -1493,6 +1535,26 @@ void CApplication::InternalResumeSimulation() m_absTimeBase = m_exactAbsTime; } +void CApplication::StartLoadingMusic() +{ + CThread musicLoadThread([this]() + { + GetLogger()->Debug("Cache sounds...\n"); + SystemTimeStamp* musicLoadStart = m_systemUtils->CreateTimeStamp(); + m_systemUtils->GetCurrentTimeStamp(musicLoadStart); + + m_sound->Reset(); + m_sound->CacheAll(); + + SystemTimeStamp* musicLoadEnd = m_systemUtils->CreateTimeStamp(); + m_systemUtils->GetCurrentTimeStamp(musicLoadEnd); + float musicLoadTime = m_systemUtils->TimeStampDiff(musicLoadStart, musicLoadEnd, STU_MSEC); + GetLogger()->Debug("Sound loading took %.2f ms\n", musicLoadTime); + }, + "Sound loading thread"); + musicLoadThread.Start(); +} + bool CApplication::GetSimulationSuspended() const { return m_simulationSuspended; @@ -1502,20 +1564,20 @@ void CApplication::SetSimulationSpeed(float speed) { m_simulationSpeed = speed; - m_systemUtils->GetCurrentTimeStamp(m_baseTimeStamp); + m_systemUtils->CopyTimeStamp(m_baseTimeStamp, m_curTimeStamp); m_realAbsTimeBase = m_realAbsTime; m_absTimeBase = m_exactAbsTime; GetLogger()->Info("Simulation speed = %.2f\n", speed); } -Event CApplication::CreateUpdateEvent() +Event CApplication::CreateUpdateEvent(SystemTimeStamp *newTimeStamp) { if (m_simulationSuspended) return Event(EVENT_NULL); m_systemUtils->CopyTimeStamp(m_lastTimeStamp, m_curTimeStamp); - m_systemUtils->GetCurrentTimeStamp(m_curTimeStamp); + m_systemUtils->CopyTimeStamp(m_curTimeStamp, newTimeStamp); long long absDiff = m_systemUtils->TimeStampExactDiff(m_baseTimeStamp, m_curTimeStamp); long long newRealAbsTime = m_realAbsTimeBase + absDiff; diff --git a/src/app/app.h b/src/app/app.h index ccae3a5c..d238bde9 100644 --- a/src/app/app.h +++ b/src/app/app.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -42,6 +42,7 @@ class CEventQueue; class CController; class CSoundInterface; class CInput; +class CModManager; class CPathManager; class CConfigFile; class CSystemUtils; @@ -162,12 +163,18 @@ public: CEventQueue* GetEventQueue(); //! Returns the sound subsystem CSoundInterface* GetSound(); + //! Returns the mod manager + CModManager* GetModManager(); public: - //! Parses commandline arguments + //! Loads some data from environment variables + void LoadEnvironmentVariables(); + //! Parses commandline arguments (they take priority) ParseArgsStatus ParseArguments(int argc, char *argv[]); //! Initializes the application bool Create(); + //! Reloads the application resources, e.g. mods + void ReloadResources(); //! Main event loop int Run(); //! Returns the code to be returned at main() exit @@ -281,13 +288,16 @@ public: protected: //! Creates the window's SDL_Surface bool CreateVideoSurface(); + //! Tries to set the SDL vsync state desired by the 3D engine + //! The final state of SDL vsync is set in the 3D engine afterwards + void TryToSetVSync(); //! Processes the captured SDL event to Event struct Event ProcessSystemEvent(); //! If applicable, creates a virtual event to match the changed state as of new event Event CreateVirtualEvent(const Event& sourceEvent); //! Prepares a simulation update event - TEST_VIRTUAL Event CreateUpdateEvent(); + TEST_VIRTUAL Event CreateUpdateEvent(SystemTimeStamp *newTimeStamp); //! Logs debug data for event void LogEvent(const Event& event); @@ -299,6 +309,9 @@ protected: //! Internal procedure to reset time counters void InternalResumeSimulation(); + //! Loads music in a new thread + void StartLoadingMusic(); + protected: //! System utils instance CSystemUtils* m_systemUtils; @@ -320,6 +333,8 @@ protected: std::unique_ptr m_input; //! Path manager std::unique_ptr m_pathManager; + //! Mod manager + std::unique_ptr m_modManager; //! Code to return at exit int m_exitCode; diff --git a/src/app/controller.cpp b/src/app/controller.cpp index 91156bbf..989f87ce 100644 --- a/src/app/controller.cpp +++ b/src/app/controller.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/app/controller.h b/src/app/controller.h index 1ba39f99..dd244edd 100644 --- a/src/app/controller.h +++ b/src/app/controller.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/app/input.cpp b/src/app/input.cpp index fffa1a14..3f10cd3f 100644 --- a/src/app/input.cpp +++ b/src/app/input.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/app/input.h b/src/app/input.h index 990b4898..7bf528d3 100644 --- a/src/app/input.h +++ b/src/app/input.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/app/main.cpp b/src/app/main.cpp index 9fdb89a3..1cb8171a 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -61,7 +61,7 @@ object-oriented language, CBOT, which can be used to program the robots availabl The original version of the game was developed by [Epsitec](http://www.epsitec.ch/) and released in 2001. Later, in 2005 another version named Ceebot was released. In March 2012, through attempts by Polish Colobot fans, Epsitec agreeed to release the source code of the game on GPLv3 license. -The license was given specfifically to our community, TerranovaTeam, +The license was given specifically to our community, TerranovaTeam, part of International Colobot Community (ICC) (previously known as Polish Portal of Colobot (PPC); Polish: Polski Portal Colobota) with our website at http://colobot.info/. @@ -172,6 +172,8 @@ int main(int argc, char *argv[]) int code = 0; CApplication app(systemUtils.get()); // single instance of the application + app.LoadEnvironmentVariables(); + ParseArgsStatus status = app.ParseArguments(argc, argv); if (status == PARSE_ARGS_FAIL) { diff --git a/src/app/modman.cpp b/src/app/modman.cpp new file mode 100644 index 00000000..42ba11be --- /dev/null +++ b/src/app/modman.cpp @@ -0,0 +1,358 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include "app/modman.h" + +#include "common/config.h" + +#include "app/app.h" +#include "app/pathman.h" + +#include "common/config_file.h" +#include "common/logger.h" + +#include "common/resources/resourcemanager.h" + +#include "level/parser/parser.h" + +#include +#include +#include +#include + +using namespace boost::filesystem; + +CModManager::CModManager(CApplication* app, CPathManager* pathManager) + : m_app{app}, + m_pathManager{pathManager} +{ +} + +void CModManager::FindMods() +{ + m_mods.clear(); + m_userChanges = false; + + // Load names from the config file + std::vector savedModNames; + GetConfigFile().GetArrayProperty("Mods", "Names", savedModNames); + std::vector savedEnabled; + GetConfigFile().GetArrayProperty("Mods", "Enabled", savedEnabled); + + // Transform the data into Mod structures + m_mods.reserve(savedModNames.size()); + for (size_t i = 0; i < savedModNames.size(); ++i) + { + Mod mod{}; + mod.name = savedModNames[i]; + if (i < savedEnabled.size()) + { + mod.enabled = savedEnabled[i]; + } + mod.path = ""; // Find the path later + m_mods.push_back(mod); + } + + // Search the folders for mods + auto rawPaths = m_pathManager->FindMods(); + std::map modPaths; + for (const auto& path : rawPaths) + { + auto modName = boost::filesystem::path(path).stem().string(); + modPaths.insert(std::make_pair(modName, path)); + } + + // Find paths for already saved mods + auto it = m_mods.begin(); + while (it != m_mods.end()) + { + auto& mod = *it; + const auto pathsIt = modPaths.find(mod.name); + if (pathsIt != modPaths.end()) + { + mod.path = (*pathsIt).second; + modPaths.erase(pathsIt); + ++it; + } + else + { + GetLogger()->Warn("Could not find mod %s, removing it from the list\n", mod.name.c_str()); + it = m_mods.erase(it); + } + } + + // Add the remaining found mods to the end of the list + for (const auto& newMod : modPaths) + { + Mod mod{}; + mod.name = newMod.first; + mod.path = newMod.second; + m_mods.push_back(mod); + } + + // Load the metadata for each mod + + // Unfortunately, the paths are distinguished by their real paths, not mount points + // So we must unmount mods temporarily + for (const auto& path : m_mountedModPaths) + { + UnmountMod(path); + } + + for (auto& mod : m_mods) + { + MountMod(mod, "/temp/mod"); + LoadModData(mod); + UnmountMod(mod); + } + + // Mount back + for (const auto& path : m_mountedModPaths) + { + MountMod(path); + } +} + +void CModManager::ReloadMods() +{ + UnmountAllMountedMods(); + MountAllMods(); + ReloadResources(); +} + +void CModManager::EnableMod(size_t i) +{ + m_mods[i].enabled = true; + m_userChanges = true; +} + +void CModManager::DisableMod(size_t i) +{ + m_mods[i].enabled = false; + m_userChanges = true; +} + +size_t CModManager::MoveUp(size_t i) +{ + if (i != 0) + { + std::swap(m_mods[i - 1], m_mods[i]); + m_userChanges = true; + return i - 1; + } + else + { + return i; + } +} + +size_t CModManager::MoveDown(size_t i) +{ + if (i != m_mods.size() - 1) + { + std::swap(m_mods[i], m_mods[i + 1]); + m_userChanges = true; + return i + 1; + } + else + { + return i; + } +} + +bool CModManager::Changes() +{ + std::vector paths; + for (const auto& mod : m_mods) + { + if (mod.enabled) + { + paths.push_back(mod.path); + } + } + return paths != m_mountedModPaths || m_userChanges; +} + +void CModManager::MountAllMods() +{ + for (const auto& mod : m_mods) + { + if (mod.enabled) + { + MountMod(mod); + m_mountedModPaths.push_back(mod.path); + } + } +} + +void CModManager::ReloadResources() +{ + m_app->ReloadResources(); +} + +void CModManager::SaveMods() +{ + std::vector savedNames; + savedNames.reserve(m_mods.size()); + std::transform(m_mods.begin(), m_mods.end(), std::back_inserter(savedNames), [](const Mod& mod) { return mod.name; }); + GetConfigFile().SetArrayProperty("Mods", "Names", savedNames); + + std::vector savedEnabled; + savedEnabled.reserve(m_mods.size()); + std::transform(m_mods.begin(), m_mods.end(), std::back_inserter(savedEnabled), [](const Mod& mod) { return mod.enabled; }); + GetConfigFile().SetArrayProperty("Mods", "Enabled", savedEnabled); + + GetConfigFile().Save(); + + m_userChanges = false; +} + +size_t CModManager::CountMods() const +{ + return m_mods.size(); +} + +const Mod& CModManager::GetMod(size_t i) const +{ + return m_mods[i]; +} + +const std::vector& CModManager::GetMods() const +{ + return m_mods; +} + +void CModManager::LoadModData(Mod& mod) +{ + auto& data = mod.data; + + data.displayName = mod.name; + + try + { + CLevelParser levelParser("temp/mod/manifest.txt"); + if (levelParser.Exists()) + { + levelParser.Load(); + + CLevelParserLine* line = nullptr; + + // DisplayName + line = levelParser.GetIfDefined("DisplayName"); + if (line != nullptr && line->GetParam("text")->IsDefined()) + { + data.displayName = line->GetParam("text")->AsString(); + } + + // Author + line = levelParser.GetIfDefined("Author"); + if (line != nullptr && line->GetParam("text")->IsDefined()) + { + data.author = line->GetParam("text")->AsString(); + } + + // Version + line = levelParser.GetIfDefined("Version"); + if (line != nullptr) + { + if (line->GetParam("text")->IsDefined()) + { + data.version = line->GetParam("text")->AsString(); + } + else if (line->GetParam("major")->IsDefined() && line->GetParam("minor")->IsDefined() && line->GetParam("patch")->IsDefined()) + { + auto major = boost::lexical_cast(line->GetParam("major")->AsInt()); + auto minor = boost::lexical_cast(line->GetParam("minor")->AsInt()); + auto patch = boost::lexical_cast(line->GetParam("patch")->AsInt()); + data.version = boost::algorithm::join(std::vector{ major, minor, patch }, "."); + } + } + + // Website + line = levelParser.GetIfDefined("Website"); + if (line != nullptr && line->GetParam("text")->IsDefined()) + { + data.website = line->GetParam("text")->AsString(); + } + + // Summary + line = levelParser.GetIfDefined("Summary"); + if (line != nullptr && line->GetParam("text")->IsDefined()) + { + data.summary = line->GetParam("text")->AsString(); + } + } + else + { + GetLogger()->Warn("No manifest file for mod %s\n", mod.name.c_str()); + } + } + catch (CLevelParserException& e) + { + GetLogger()->Warn("Failed parsing manifest for mod %s: %s\n", mod.name.c_str(), e.what()); + } + + // Changes + data.changes = CResourceManager::ListDirectories("temp/mod"); + auto levelsIt = std::find(data.changes.begin(), data.changes.end(), "levels"); + if (levelsIt != data.changes.end()) + { + auto levelsDirs = CResourceManager::ListDirectories("temp/mod/levels"); + if (!levelsDirs.empty()) + { + std::transform(levelsDirs.begin(), levelsDirs.end(), levelsDirs.begin(), [](const std::string& dir) { return "levels/" + dir; }); + levelsIt = data.changes.erase(levelsIt); + data.changes.insert(levelsIt, levelsDirs.begin(), levelsDirs.end()); + } + } +} + +void CModManager::MountMod(const Mod& mod, const std::string& mountPoint) +{ + MountMod(mod.path, mountPoint); +} + +void CModManager::MountMod(const std::string& path, const std::string& mountPoint) +{ + GetLogger()->Debug("Mounting mod: '%s' at path %s\n", path.c_str(), mountPoint.c_str()); + CResourceManager::AddLocation(path, true, mountPoint); +} + +void CModManager::UnmountMod(const Mod& mod) +{ + UnmountMod(mod.path); +} + +void CModManager::UnmountMod(const std::string& path) +{ + if (CResourceManager::LocationExists(path)) + { + GetLogger()->Debug("Unmounting mod: '%s'\n", path.c_str()); + CResourceManager::RemoveLocation(path); + } +} + +void CModManager::UnmountAllMountedMods() +{ + for (const auto& path : m_mountedModPaths) + { + UnmountMod(path); + } + m_mountedModPaths.clear(); +} diff --git a/src/app/modman.h b/src/app/modman.h new file mode 100644 index 00000000..09f8b0aa --- /dev/null +++ b/src/app/modman.h @@ -0,0 +1,124 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include +#include +#include + +class CApplication; +class CPathManager; + +struct ModData +{ + std::string displayName{}; + std::string author{}; + std::string version{}; + std::string website{}; + std::string summary{}; + std::vector changes{}; +}; + +struct Mod +{ + std::string name{}; + std::string path{}; + bool enabled = false; + ModData data{}; +}; + +/** + * \class CModManager + * \brief This class handles the list of mods. + * + * The order matters since the order in which files are loaded matters, + * because some files can be overwritten. + * + * The changes in the list do not immediately apply. + */ +class CModManager +{ +public: + CModManager(CApplication* app, CPathManager* pathManager); + + //! Finds all the mods along with their metadata + void FindMods(); + + //! Applies the current configuration and reloads the application + void ReloadMods(); + + //! Removes a mod from the list of loaded mods + void EnableMod(size_t i); + + //! Adds a mod to the list of loaded mods + void DisableMod(size_t i); + + //! Moves the selected mod up in the list so that it's loaded sooner than others, returns the new index + size_t MoveUp(size_t i); + + //! Moves the selected mod down in the list so that it's loaded later than others, returns the new index + size_t MoveDown(size_t i); + + //! Checks if the list of currently used mods differs from the current configuration or there were changes made by the user + bool Changes(); + + //! Saves the current configuration of mods to the config file + void SaveMods(); + + //! Number of mods loaded + size_t CountMods() const; + + //! Returns the reference to the mod in given position + const Mod& GetMod(size_t i) const; + + //! Returns the list of mods + const std::vector& GetMods() const; + +private: + // Allow access to MountAllMods() as CApplication doesn't want to reload itself during initialization + friend CApplication; + + //! Reloads application resources so the enabled mods are applied + void ReloadResources(); + + //! Load mod data into mod + void LoadModData(Mod& mod); + + //! Updates the paths in Path Manager according to the current mod configuration + void MountAllMods(); + + void MountMod(const Mod& mod, const std::string& mountPoint = ""); + void MountMod(const std::string& path, const std::string& mountPoint = ""); + void UnmountMod(const Mod& mod); + void UnmountMod(const std::string& path); + void UnmountAllMountedMods(); + +private: + CApplication* m_app; + CPathManager* m_pathManager; + + //! Paths to mods already in the virtual filesystem + std::vector m_mountedModPaths; + + //! List of mods + std::vector m_mods; + + bool m_userChanges = false; +}; diff --git a/src/app/pathman.cpp b/src/app/pathman.cpp index 60715ac1..e4c385dd 100644 --- a/src/app/pathman.cpp +++ b/src/app/pathman.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -41,8 +41,7 @@ CPathManager::CPathManager(CSystemUtils* systemUtils) : m_dataPath(systemUtils->GetDataPath()) , m_langPath(systemUtils->GetLangPath()) , m_savePath(systemUtils->GetSaveDir()) - , m_modAutoloadDir{ m_dataPath + "/mods", m_savePath + "/mods" } - , m_mods{} + , m_modSearchDirs{} { } @@ -65,16 +64,6 @@ void CPathManager::SetSavePath(const std::string &savePath) m_savePath = savePath; } -void CPathManager::AddModAutoloadDir(const std::string &modAutoloadDirPath) -{ - m_modAutoloadDir.push_back(modAutoloadDirPath); -} - -void CPathManager::AddMod(const std::string &modPath) -{ - m_mods.push_back(modPath); -} - const std::string& CPathManager::GetDataPath() { return m_dataPath; @@ -130,37 +119,19 @@ void CPathManager::InitPaths() { GetLogger()->Info("Data path: %s\n", m_dataPath.c_str()); GetLogger()->Info("Save path: %s\n", m_savePath.c_str()); - if (!m_modAutoloadDir.empty()) + + m_modSearchDirs.push_back(m_dataPath + "/mods"); + m_modSearchDirs.push_back(m_savePath + "/mods"); + + if (!m_modSearchDirs.empty()) { - GetLogger()->Info("Mod autoload dirs:\n"); - for(const std::string& modAutoloadDir : m_modAutoloadDir) - GetLogger()->Info(" * %s\n", modAutoloadDir.c_str()); - } - if (!m_mods.empty()) - { - GetLogger()->Info("Mods:\n"); - for(const std::string& modPath : m_mods) - GetLogger()->Info(" * %s\n", modPath.c_str()); + GetLogger()->Info("Mod search dirs:\n"); + for(const std::string& modSearchDir : m_modSearchDirs) + GetLogger()->Info(" * %s\n", modSearchDir.c_str()); } CResourceManager::AddLocation(m_dataPath); - for (const std::string& modAutoloadDir : m_modAutoloadDir) - { - GetLogger()->Trace("Searching for mods in '%s'...\n", modAutoloadDir.c_str()); - for (const std::string& modPath : FindModsInDir(modAutoloadDir)) - { - GetLogger()->Info("Autoloading mod: '%s'\n", modPath.c_str()); - CResourceManager::AddLocation(modPath); - } - } - - for (const std::string& modPath : m_mods) - { - GetLogger()->Info("Loading mod: '%s'\n", modPath.c_str()); - CResourceManager::AddLocation(modPath); - } - CResourceManager::SetSaveLocation(m_savePath); CResourceManager::AddLocation(m_savePath); @@ -170,7 +141,45 @@ void CPathManager::InitPaths() GetLogger()->Debug(" * %s\n", path.c_str()); } -std::vector CPathManager::FindModsInDir(const std::string &dir) +void CPathManager::AddMod(const std::string &path) +{ + m_mods.push_back(path); +} + +std::vector CPathManager::FindMods() const +{ + std::vector mods; + GetLogger()->Info("Found mods:\n"); + for (const auto &searchPath : m_modSearchDirs) + { + for (const auto &modPath : FindModsInDir(searchPath)) + { + GetLogger()->Info(" * %s\n", modPath.c_str()); + mods.push_back(modPath); + } + } + GetLogger()->Info("Additional mod paths:\n"); + for (const auto& modPath : m_mods) + { + if (boost::filesystem::exists(modPath)) + { + GetLogger()->Info(" * %s\n", modPath.c_str()); + mods.push_back(modPath); + } + else + { + GetLogger()->Warn("Mod does not exist: %s\n", modPath.c_str()); + } + } + return mods; +} + +void CPathManager::AddModSearchDir(const std::string &modSearchDirPath) +{ + m_modSearchDirs.push_back(modSearchDirPath); +} + +std::vector CPathManager::FindModsInDir(const std::string &dir) const { std::vector ret; try diff --git a/src/app/pathman.h b/src/app/pathman.h index dd18d66e..d1ba4bbe 100644 --- a/src/app/pathman.h +++ b/src/app/pathman.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -37,8 +37,6 @@ public: void SetDataPath(const std::string &dataPath); void SetLangPath(const std::string &langPath); void SetSavePath(const std::string &savePath); - void AddModAutoloadDir(const std::string &modAutoloadDirPath); - void AddMod(const std::string &modPath); const std::string& GetDataPath(); const std::string& GetLangPath(); @@ -49,9 +47,15 @@ public: //! Loads configured paths void InitPaths(); + //! Adds a path to a mod + void AddMod(const std::string& path); + //! Find paths to mods in mod search directories + std::vector FindMods() const; + //! Adds a mod search directory + void AddModSearchDir(const std::string &modSearchDirPath); + private: - //! Loads all mods from given directory - std::vector FindModsInDir(const std::string &dir); + std::vector FindModsInDir(const std::string &dir) const; private: //! Data path @@ -60,8 +64,8 @@ private: std::string m_langPath; //! Save path std::string m_savePath; - //! Mod autoload paths - std::vector m_modAutoloadDir; - //! Mod paths + //! Mod search paths + std::vector m_modSearchDirs; + //! Additional mod paths std::vector m_mods; }; diff --git a/src/app/pausemanager.cpp b/src/app/pausemanager.cpp index f4872fdf..8c4235e8 100644 --- a/src/app/pausemanager.cpp +++ b/src/app/pausemanager.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/app/pausemanager.h b/src/app/pausemanager.h index d7a2ce03..81e792af 100644 --- a/src/app/pausemanager.h +++ b/src/app/pausemanager.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/app/signal_handlers.cpp b/src/app/signal_handlers.cpp index 03771dab..ebcfe274 100644 --- a/src/app/signal_handlers.cpp +++ b/src/app/signal_handlers.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/app/signal_handlers.h b/src/app/signal_handlers.h index 4716e6c9..613ac316 100644 --- a/src/app/signal_handlers.h +++ b/src/app/signal_handlers.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/config.h.cmake b/src/common/config.h.cmake index f6d0bcae..556e067e 100644 --- a/src/common/config.h.cmake +++ b/src/common/config.h.cmake @@ -18,5 +18,5 @@ #cmakedefine PORTABLE_SAVES @PORTABLE_SAVES@ -#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_INSTALL_DATA_DIR@" -#define COLOBOT_I18N_DIR "@COLOBOT_INSTALL_I18N_DIR@" +#define COLOBOT_DEFAULT_DATADIR "@COLOBOT_DATA_DIR@" +#define COLOBOT_I18N_DIR "@COLOBOT_I18N_DIR@" diff --git a/src/common/config_file.cpp b/src/common/config_file.cpp index 868f9511..a379a8fa 100644 --- a/src/common/config_file.cpp +++ b/src/common/config_file.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/config_file.h b/src/common/config_file.h index 10ee131f..6e95f481 100644 --- a/src/common/config_file.h +++ b/src/common/config_file.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -26,9 +26,15 @@ #include "common/singleton.h" +#include "common/logger.h" + #include +#include #include +#include +#include +#include /** @@ -100,6 +106,76 @@ public: */ bool GetBoolProperty(std::string section, std::string key, bool &value); + /** Gets an array of values of type T in section under specified key + * The value separator is ','. + * \a array will only be changed if key exists + * \return return true on success + */ + template + bool SetArrayProperty(std::string section, std::string key, const std::vector& array) + { + try + { + std::string convertedValue = ArrayToString(array); + m_propertyTree.put(section + "." + key, convertedValue); + m_needsSave = true; + } + catch (std::exception & e) + { + GetLogger()->Error("Error on editing config file: %s\n", e.what()); + return false; + } + return true; + } + + /** Sets an array of values of type T in section under specified key. + * The value separator is ','. + * \a array will only be changed if key exists + * \return return true on success + */ + template + bool GetArrayProperty(std::string section, std::string key, std::vector& array) + { + try + { + std::string readValue = m_propertyTree.get(section + "." + key); + std::vector convertedValue = StringToArray(readValue); + array = std::move(convertedValue); + } + catch (std::exception & e) + { + GetLogger()->Log(m_loaded ? LOG_INFO : LOG_TRACE, "Error on parsing config file: %s\n", e.what()); + return false; + } + return true; + } + +private: + template + std::vector StringToArray(const std::string& s) + { + std::vector result; + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, ',')) + { + result.push_back(boost::lexical_cast(item)); + } + return result; + } + + template + std::string ArrayToString(const std::vector &array) + { + std::ostringstream oss; + if (!array.empty()) + { + std::copy(array.begin(), array.end() - 1, std::ostream_iterator(oss, ",")); + oss << array.back(); + } + return oss.str(); + } + private: boost::property_tree::ptree m_propertyTree; bool m_needsSave; diff --git a/src/common/error.h b/src/common/error.h index e344d04c..fa048e43 100644 --- a/src/common/error.h +++ b/src/common/error.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -138,6 +138,7 @@ enum Error INFO_RESEARCHPHAZER = 10035, //! < research ended INFO_RESEARCHSHIELD = 10036, //! < research ended INFO_RESEARCHATOMIC = 10037, //! < research ended + INFO_RESEARCHBUILDER = 10038, //! < research ended INFO_WIN = 10040, //! < win INFO_LOST = 10041, //! < lost INFO_LOSTq = 10042, //! < lost immediately diff --git a/src/common/event.cpp b/src/common/event.cpp index 302c2702..d75c8f9c 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -167,8 +167,13 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_DIALOG_LABEL3] = "EVENT_DIALOG_LABEL3"; EVENT_TYPE_TEXT[EVENT_DIALOG_LIST] = "EVENT_DIALOG_LIST"; EVENT_TYPE_TEXT[EVENT_DIALOG_EDIT] = "EVENT_DIALOG_EDIT"; + EVENT_TYPE_TEXT[EVENT_DIALOG_EDIT2] = "EVENT_DIALOG_EDIT2"; EVENT_TYPE_TEXT[EVENT_DIALOG_CHECK1] = "EVENT_DIALOG_CHECK1"; EVENT_TYPE_TEXT[EVENT_DIALOG_CHECK2] = "EVENT_DIALOG_CHECK2"; + EVENT_TYPE_TEXT[EVENT_DIALOG_GROUP1] = "EVENT_DIALOG_GROUP1"; + EVENT_TYPE_TEXT[EVENT_DIALOG_NEWDIR] = "EVENT_DIALOG_NEWDIR"; + EVENT_TYPE_TEXT[EVENT_DIALOG_ACTION] = "EVENT_DIALOG_ACTION"; + EVENT_TYPE_TEXT[EVENT_DIALOG_STOP] = "EVENT_DIALOG_STOP"; EVENT_TYPE_TEXT[EVENT_INTERFACE_TRAINER] = "EVENT_INTERFACE_TRAINER"; EVENT_TYPE_TEXT[EVENT_INTERFACE_DEFI] = "EVENT_INTERFACE_DEFI"; @@ -185,6 +190,8 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_ABORT] = "EVENT_INTERFACE_ABORT"; EVENT_TYPE_TEXT[EVENT_INTERFACE_USER] = "EVENT_INTERFACE_USER"; EVENT_TYPE_TEXT[EVENT_INTERFACE_SATCOM] = "EVENT_INTERFACE_SATCOM"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_PLUS] = "EVENT_INTERFACE_PLUS"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS] = "EVENT_INTERFACE_MODS"; EVENT_TYPE_TEXT[EVENT_INTERFACE_CHAP] = "EVENT_INTERFACE_CHAP"; EVENT_TYPE_TEXT[EVENT_INTERFACE_LIST] = "EVENT_INTERFACE_LIST"; @@ -215,6 +222,7 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_INVERTY] = "EVENT_INTERFACE_INVERTY"; EVENT_TYPE_TEXT[EVENT_INTERFACE_EFFECT] = "EVENT_INTERFACE_EFFECT"; EVENT_TYPE_TEXT[EVENT_INTERFACE_BGPAUSE] = "EVENT_INTERFACE_BGPAUSE"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_BGMUTE] = "EVENT_INTERFACE_BGMUTE"; EVENT_TYPE_TEXT[EVENT_INTERFACE_FOG] = "EVENT_INTERFACE_FOG"; EVENT_TYPE_TEXT[EVENT_INTERFACE_EDITMODE]= "EVENT_INTERFACE_EDITMODE"; EVENT_TYPE_TEXT[EVENT_INTERFACE_EDITVALUE]= "EVENT_INTERFACE_EDITVALUE"; @@ -266,6 +274,20 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT]= "EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT"; EVENT_TYPE_TEXT[EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT]= "EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_PLUS_TRAINER] = "EVENT_INTERFACE_PLUS_TRAINER"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_PLUS_RESEARCH] = "EVENT_INTERFACE_PLUS_RESEARCH"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_PLUS_EXPLORER] = "EVENT_INTERFACE_PLUS_EXPLORER"; + + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_LIST] = "EVENT_INTERFACE_MOD_LIST"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_WORKSHOP] = "EVENT_INTERFACE_WORKSHOP"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_DIR] = "EVENT_INTERFACE_MODS_DIR"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE] = "EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_APPLY] = "EVENT_INTERFACE_MODS_APPLY"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_DETAILS] = "EVENT_INTERFACE_MOD_DETAILS"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_MOVE_UP] = "EVENT_INTERFACE_MOD_MOVE_UP"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MOD_MOVE_DOWN] = "EVENT_INTERFACE_MOD_MOVE_DOWN"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_MODS_REFRESH] = "EVENT_INTERFACE_MODS_REFRESH"; + EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTl] = "EVENT_INTERFACE_GLINTl"; EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTr] = "EVENT_INTERFACE_GLINTr"; EVENT_TYPE_TEXT[EVENT_INTERFACE_GLINTu] = "EVENT_INTERFACE_GLINTu"; @@ -399,7 +421,7 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_OBJECT_BNUCLEAR] = "EVENT_OBJECT_BNUCLEAR"; EVENT_TYPE_TEXT[EVENT_OBJECT_BPARA] = "EVENT_OBJECT_BPARA"; EVENT_TYPE_TEXT[EVENT_OBJECT_BINFO] = "EVENT_OBJECT_BINFO"; - EVENT_TYPE_TEXT[EVENT_OBJECT_BDESTROYER] = "EVENT_OBJECT_BDESTROYER"; + EVENT_TYPE_TEXT[EVENT_OBJECT_BSAFE] = "EVENT_OBJECT_BSAFE"; EVENT_TYPE_TEXT[EVENT_OBJECT_GFLAT] = "EVENT_OBJECT_GFLAT"; EVENT_TYPE_TEXT[EVENT_OBJECT_FCREATE] = "EVENT_OBJECT_FCREATE"; EVENT_TYPE_TEXT[EVENT_OBJECT_FDELETE] = "EVENT_OBJECT_FDELETE"; @@ -424,11 +446,16 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYts] = "EVENT_OBJECT_FACTORYts"; EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYfs] = "EVENT_OBJECT_FACTORYfs"; EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYis] = "EVENT_OBJECT_FACTORYis"; + EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYwb] = "EVENT_OBJECT_FACTORYwb"; + EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYtb] = "EVENT_OBJECT_FACTORYtb"; + EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYfb] = "EVENT_OBJECT_FACTORYfb"; + EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYib] = "EVENT_OBJECT_FACTORYib"; EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrt] = "EVENT_OBJECT_FACTORYrt"; EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrc] = "EVENT_OBJECT_FACTORYrc"; EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrr] = "EVENT_OBJECT_FACTORYrr"; EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYrs] = "EVENT_OBJECT_FACTORYrs"; EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYsa] = "EVENT_OBJECT_FACTORYsa"; + EVENT_TYPE_TEXT[EVENT_OBJECT_FACTORYtg] = "EVENT_OBJECT_FACTORYtg"; EVENT_TYPE_TEXT[EVENT_OBJECT_SEARCH] = "EVENT_OBJECT_SEARCH"; EVENT_TYPE_TEXT[EVENT_OBJECT_TERRAFORM] = "EVENT_OBJECT_TERRAFORM"; EVENT_TYPE_TEXT[EVENT_OBJECT_FIRE] = "EVENT_OBJECT_FIRE"; @@ -524,6 +551,10 @@ void InitializeEventTypeTexts() EVENT_TYPE_TEXT[EVENT_CODE_BATTLE_START] = "EVENT_CODE_BATTLE_START"; EVENT_TYPE_TEXT[EVENT_CODE_BATTLE_SPECTATOR] = "EVENT_CODE_BATTLE_SPECTATOR"; + EVENT_TYPE_TEXT[EVENT_OBJECT_RBUILDER] = "EVENT_OBJECT_RBUILDER"; + EVENT_TYPE_TEXT[EVENT_OBJECT_BUILD] = "EVENT_OBJECT_BUILD"; + EVENT_TYPE_TEXT[EVENT_OBJECT_RTARGET] = "EVENT_OBJECT_RTARGET"; + EVENT_TYPE_TEXT[EVENT_VIEWPOINT0] = "EVENT_VIEWPOINT0"; EVENT_TYPE_TEXT[EVENT_VIEWPOINT1] = "EVENT_VIEWPOINT1"; EVENT_TYPE_TEXT[EVENT_VIEWPOINT2] = "EVENT_VIEWPOINT2"; diff --git a/src/common/event.h b/src/common/event.h index a9353e5e..aec48ecb 100644 --- a/src/common/event.h +++ b/src/common/event.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -202,8 +202,13 @@ enum EventType EVENT_DIALOG_LABEL3 = 305, EVENT_DIALOG_LIST = 306, EVENT_DIALOG_EDIT = 307, - EVENT_DIALOG_CHECK1 = 308, - EVENT_DIALOG_CHECK2 = 309, + EVENT_DIALOG_EDIT2 = 308, + EVENT_DIALOG_CHECK1 = 309, + EVENT_DIALOG_CHECK2 = 310, + EVENT_DIALOG_GROUP1 = 320, + EVENT_DIALOG_NEWDIR = 330, + EVENT_DIALOG_ACTION = 348, + EVENT_DIALOG_STOP = 349, EVENT_INTERFACE_TRAINER = 400, EVENT_INTERFACE_DEFI = 401, @@ -220,6 +225,8 @@ enum EventType EVENT_INTERFACE_ABORT = 412, EVENT_INTERFACE_USER = 413, EVENT_INTERFACE_SATCOM = 414, + EVENT_INTERFACE_PLUS = 415, + EVENT_INTERFACE_MODS = 416, EVENT_INTERFACE_CHAP = 420, EVENT_INTERFACE_LIST = 421, @@ -252,6 +259,7 @@ enum EventType EVENT_INTERFACE_INVERTY = 469, EVENT_INTERFACE_EFFECT = 470, EVENT_INTERFACE_BGPAUSE = 471, + EVENT_INTERFACE_BGMUTE = 472, EVENT_INTERFACE_FOG = 474, EVENT_INTERFACE_EDITMODE= 476, EVENT_INTERFACE_EDITVALUE= 477, @@ -305,6 +313,21 @@ enum EventType EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT = 573, EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT = 574, + EVENT_INTERFACE_PLUS_TRAINER = 575, + EVENT_INTERFACE_PLUS_RESEARCH = 576, + EVENT_INTERFACE_PLUS_EXPLORER = 577, + + EVENT_INTERFACE_MOD_LIST = 580, + EVENT_INTERFACE_WORKSHOP = 581, + EVENT_INTERFACE_MODS_DIR = 582, + EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE = 583, + EVENT_INTERFACE_MODS_APPLY = 584, + EVENT_INTERFACE_MOD_SUMMARY = 585, + EVENT_INTERFACE_MOD_DETAILS = 586, + EVENT_INTERFACE_MOD_MOVE_UP = 587, + EVENT_INTERFACE_MOD_MOVE_DOWN = 888, + EVENT_INTERFACE_MODS_REFRESH = 589, + EVENT_INTERFACE_GLINTl = 590, EVENT_INTERFACE_GLINTr = 591, EVENT_INTERFACE_GLINTu = 592, @@ -463,7 +486,7 @@ enum EventType EVENT_OBJECT_BNUCLEAR = 1060, EVENT_OBJECT_BPARA = 1061, EVENT_OBJECT_BINFO = 1062, - EVENT_OBJECT_BDESTROYER = 1063, + EVENT_OBJECT_BSAFE = 1063, EVENT_OBJECT_GFLAT = 1070, EVENT_OBJECT_FCREATE = 1071, EVENT_OBJECT_FDELETE = 1072, @@ -493,6 +516,11 @@ enum EventType EVENT_OBJECT_FACTORYrr = 1098, EVENT_OBJECT_FACTORYrs = 1099, EVENT_OBJECT_FACTORYsa = 1100, + EVENT_OBJECT_FACTORYwb = 1101, + EVENT_OBJECT_FACTORYtb = 1102, + EVENT_OBJECT_FACTORYfb = 1103, + EVENT_OBJECT_FACTORYib = 1104, + EVENT_OBJECT_FACTORYtg = 1105, EVENT_OBJECT_SEARCH = 1200, EVENT_OBJECT_TERRAFORM = 1201, EVENT_OBJECT_FIRE = 1202, @@ -595,6 +623,10 @@ enum EventType EVENT_CODE_BATTLE_START = 2200, //!< button that starts the code battle EVENT_CODE_BATTLE_SPECTATOR = 2201, //!< button that controls the code battle spectator camera + EVENT_OBJECT_RBUILDER = 2300, + EVENT_OBJECT_BUILD = 2301, + EVENT_OBJECT_RTARGET = 2302, + //! Buttons that switch viewpoints EVENT_VIEWPOINT0 = 3000, EVENT_VIEWPOINT1 = 3001, diff --git a/src/common/font_loader.cpp b/src/common/font_loader.cpp index 79b9375c..31df90e5 100644 --- a/src/common/font_loader.cpp +++ b/src/common/font_loader.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/font_loader.h b/src/common/font_loader.h index a68fc0ad..b9cf5ec8 100644 --- a/src/common/font_loader.h +++ b/src/common/font_loader.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/global.h b/src/common/global.h index ad31e128..1d7435bb 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/image.cpp b/src/common/image.cpp index 0f82e881..8ad10734 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -22,6 +22,7 @@ #include "common/make_unique.h" +#include "common/resources/outputstream.h" #include "common/resources/resourcemanager.h" #include "math/func.h" @@ -93,8 +94,8 @@ bool PNGSaveSurface(const char *filename, SDL_Surface *surf) PNG_ERROR = ""; /* Opening output file */ - FILE *fp = fopen(filename, "wb"); - if (fp == nullptr) + COutputStream ostr(filename); + if (!ostr.is_open()) { PNG_ERROR = std::string("Could not open file '") + std::string(filename) + std::string("' for saving"); return false; @@ -104,7 +105,7 @@ bool PNGSaveSurface(const char *filename, SDL_Surface *surf) png_structp pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, PNGUserError, nullptr); if (pngPtr == nullptr) { - fclose(fp); + ostr.close(); return false; } @@ -113,18 +114,30 @@ bool PNGSaveSurface(const char *filename, SDL_Surface *surf) { png_destroy_write_struct(&pngPtr, static_cast(nullptr)); PNG_ERROR = "png_create_info_struct() error!"; - fclose(fp); + ostr.close(); return false; } if (setjmp(png_jmpbuf(pngPtr))) { png_destroy_write_struct(&pngPtr, &infoPtr); - fclose(fp); + ostr.close(); return false; } - png_init_io(pngPtr, fp); + png_set_write_fn( + pngPtr, static_cast(&ostr), + [](png_structp pngPtr, png_bytep data, png_size_t length) + { + auto* file = static_cast(png_get_io_ptr(pngPtr)); + file->write(reinterpret_cast(data), length); + }, + [](png_structp pngPtr) + { + auto* file = static_cast(png_get_io_ptr(pngPtr)); + file->flush(); + } + ); int colortype = PNGColortypeFromSurface(surf); png_set_IHDR(pngPtr, infoPtr, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, @@ -141,7 +154,7 @@ bool PNGSaveSurface(const char *filename, SDL_Surface *surf) png_write_end(pngPtr, infoPtr); png_destroy_write_struct(&pngPtr, &infoPtr); - fclose(fp); + ostr.close(); return true; } diff --git a/src/common/image.h b/src/common/image.h index 8bede4f7..3a5c8b73 100644 --- a/src/common/image.h +++ b/src/common/image.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/ioutils.h b/src/common/ioutils.h index 403f1c5a..5fa05a84 100644 --- a/src/common/ioutils.h +++ b/src/common/ioutils.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/key.cpp b/src/common/key.cpp index 59a178b9..4127fbd5 100644 --- a/src/common/key.cpp +++ b/src/common/key.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/key.h b/src/common/key.h index 2c087d73..b393aa02 100644 --- a/src/common/key.h +++ b/src/common/key.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/language.cpp b/src/common/language.cpp index 37a8dca1..801a3582 100644 --- a/src/common/language.cpp +++ b/src/common/language.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/language.h b/src/common/language.h index 0310cb73..ee5a731e 100644 --- a/src/common/language.h +++ b/src/common/language.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/logger.cpp b/src/common/logger.cpp index ba2a4aec..fcadd775 100644 --- a/src/common/logger.cpp +++ b/src/common/logger.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/logger.h b/src/common/logger.h index 852509a4..f5144beb 100644 --- a/src/common/logger.h +++ b/src/common/logger.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/make_unique.h b/src/common/make_unique.h index 7c6cd30c..14385a92 100644 --- a/src/common/make_unique.h +++ b/src/common/make_unique.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/profiler.cpp b/src/common/profiler.cpp index ff46036e..f20d3b06 100644 --- a/src/common/profiler.cpp +++ b/src/common/profiler.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/profiler.h b/src/common/profiler.h index 4caaea41..5bef64ee 100644 --- a/src/common/profiler.h +++ b/src/common/profiler.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/regex_utils.cpp b/src/common/regex_utils.cpp index a07ecc2a..a5e80442 100644 --- a/src/common/regex_utils.cpp +++ b/src/common/regex_utils.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/regex_utils.h b/src/common/regex_utils.h index 5b2f04ed..1504d4bd 100644 --- a/src/common/regex_utils.h +++ b/src/common/regex_utils.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/inputstream.cpp b/src/common/resources/inputstream.cpp index 43196682..8cf24daa 100644 --- a/src/common/resources/inputstream.cpp +++ b/src/common/resources/inputstream.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/inputstream.h b/src/common/resources/inputstream.h index 3d0e86f7..55a42dea 100644 --- a/src/common/resources/inputstream.h +++ b/src/common/resources/inputstream.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/inputstreambuffer.cpp b/src/common/resources/inputstreambuffer.cpp index 8081962f..2f9982da 100644 --- a/src/common/resources/inputstreambuffer.cpp +++ b/src/common/resources/inputstreambuffer.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/inputstreambuffer.h b/src/common/resources/inputstreambuffer.h index e3a044c0..6e7000cf 100644 --- a/src/common/resources/inputstreambuffer.h +++ b/src/common/resources/inputstreambuffer.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/outputstream.cpp b/src/common/resources/outputstream.cpp index 1f806154..6c5f3b64 100644 --- a/src/common/resources/outputstream.cpp +++ b/src/common/resources/outputstream.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/outputstream.h b/src/common/resources/outputstream.h index be3249fe..1040ad9f 100644 --- a/src/common/resources/outputstream.h +++ b/src/common/resources/outputstream.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/outputstreambuffer.cpp b/src/common/resources/outputstreambuffer.cpp index 3ca4dd13..0018abeb 100644 --- a/src/common/resources/outputstreambuffer.cpp +++ b/src/common/resources/outputstreambuffer.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/outputstreambuffer.h b/src/common/resources/outputstreambuffer.h index 4f44c964..fa5f1e0b 100644 --- a/src/common/resources/outputstreambuffer.h +++ b/src/common/resources/outputstreambuffer.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/resourcemanager.cpp b/src/common/resources/resourcemanager.cpp index 0ad82816..7c572483 100644 --- a/src/common/resources/resourcemanager.cpp +++ b/src/common/resources/resourcemanager.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -62,9 +62,9 @@ std::string CResourceManager::CleanPath(const std::string& path) } -bool CResourceManager::AddLocation(const std::string &location, bool prepend) +bool CResourceManager::AddLocation(const std::string &location, bool prepend, const std::string &mountPoint) { - if (!PHYSFS_mount(location.c_str(), nullptr, prepend ? 0 : 1)) + if (!PHYSFS_mount(location.c_str(), mountPoint.c_str(), prepend ? 0 : 1)) { GetLogger()->Error("Error while mounting \"%s\": %s\n", location.c_str(), PHYSFS_getLastError()); return false; @@ -95,6 +95,12 @@ std::vector CResourceManager::GetLocations() return ret; } +bool CResourceManager::LocationExists(const std::string& location) +{ + auto locations = GetLocations(); + auto it = std::find(locations.cbegin(), locations.cend(), location); + return it != locations.cend(); +} bool CResourceManager::SetSaveLocation(const std::string &location) { @@ -174,7 +180,7 @@ bool CResourceManager::RemoveDirectory(const std::string& directory) return false; } -std::vector CResourceManager::ListFiles(const std::string &directory) +std::vector CResourceManager::ListFiles(const std::string &directory, bool excludeDirs) { std::vector result; @@ -184,6 +190,11 @@ std::vector CResourceManager::ListFiles(const std::string &director for (char **i = files; *i != nullptr; i++) { + if (excludeDirs) + { + std::string path = CleanPath(directory) + "/" + (*i); + if (PHYSFS_isDirectory(path.c_str())) continue; + } result.push_back(*i); } diff --git a/src/common/resources/resourcemanager.h b/src/common/resources/resourcemanager.h index 95661a4f..d15a6f02 100644 --- a/src/common/resources/resourcemanager.h +++ b/src/common/resources/resourcemanager.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -36,11 +36,13 @@ public: static std::string CleanPath(const std::string &path); //! Add a location to the search path - static bool AddLocation(const std::string &location, bool prepend = true); + static bool AddLocation(const std::string &location, bool prepend = true, const std::string &mountPoint = ""); //! Remove a location from the search path static bool RemoveLocation(const std::string &location); //! List all locations in the search path static std::vector GetLocations(); + //! Check if given location is in the search path + static bool LocationExists(const std::string &location); static bool SetSaveLocation(const std::string &location); static std::string GetSaveLocation(); @@ -60,7 +62,7 @@ public: static bool RemoveDirectory(const std::string& directory); //! List files contained in directory - static std::vector ListFiles(const std::string &directory); + static std::vector ListFiles(const std::string &directory, bool excludeDirs = false); //! List directories contained in directory static std::vector ListDirectories(const std::string &directory); diff --git a/src/common/resources/sdl_file_wrapper.cpp b/src/common/resources/sdl_file_wrapper.cpp index c8c36845..13b72e27 100644 --- a/src/common/resources/sdl_file_wrapper.cpp +++ b/src/common/resources/sdl_file_wrapper.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/sdl_file_wrapper.h b/src/common/resources/sdl_file_wrapper.h index 0666b21e..fdb47b44 100644 --- a/src/common/resources/sdl_file_wrapper.h +++ b/src/common/resources/sdl_file_wrapper.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/sdl_memory_wrapper.cpp b/src/common/resources/sdl_memory_wrapper.cpp index d2663a54..ed02eb76 100644 --- a/src/common/resources/sdl_memory_wrapper.cpp +++ b/src/common/resources/sdl_memory_wrapper.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/sdl_memory_wrapper.h b/src/common/resources/sdl_memory_wrapper.h index f5218a66..b2a637c9 100644 --- a/src/common/resources/sdl_memory_wrapper.h +++ b/src/common/resources/sdl_memory_wrapper.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/sndfile_wrapper.cpp b/src/common/resources/sndfile_wrapper.cpp index f3b277f9..9c897132 100644 --- a/src/common/resources/sndfile_wrapper.cpp +++ b/src/common/resources/sndfile_wrapper.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/resources/sndfile_wrapper.h b/src/common/resources/sndfile_wrapper.h index 8bbe009d..c82f27e1 100644 --- a/src/common/resources/sndfile_wrapper.h +++ b/src/common/resources/sndfile_wrapper.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/restext.cpp b/src/common/restext.cpp index 4aa21564..d8e16a00 100644 --- a/src/common/restext.cpp +++ b/src/common/restext.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -48,8 +48,8 @@ const char* stringsCbot[CBot::CBotErrMAX] = { nullptr }; */ #define TR(x) x -/* Please run `make update-pot` after changing this file - * in order to update translation files. Thank you. +/* Please run `cmake --build --target update-pot` + * after changing this file in order to update translation files. Thank you. */ void InitializeRestext() @@ -71,12 +71,14 @@ void InitializeRestext() stringsText[RT_TITLE_MISSION] = TR("Missions"); stringsText[RT_TITLE_FREE] = TR("Free game"); stringsText[RT_TITLE_USER] = TR("User levels"); - stringsText[RT_TITLE_CODE_BATTLES]=TR("Code battles"); + stringsText[RT_TITLE_CODE_BATTLES] = TR("Code battles"); stringsText[RT_TITLE_SETUP] = TR("Options"); stringsText[RT_TITLE_NAME] = TR("Player's name"); stringsText[RT_TITLE_PERSO] = TR("Customize your appearance"); stringsText[RT_TITLE_WRITE] = TR("Save the current mission"); stringsText[RT_TITLE_READ] = TR("Load a saved mission"); + stringsText[RT_TITLE_PLUS] = TR("Missions+"); + stringsText[RT_TITLE_MODS] = TR("Mods"); stringsText[RT_PLAY_CHAP_CHAPTERS] = TR("Chapters:"); stringsText[RT_PLAY_CHAP_PLANETS] = TR("Planets:"); @@ -108,6 +110,11 @@ void InitializeRestext() stringsText[RT_DIALOG_OK] = TR("OK"); stringsText[RT_DIALOG_NOUSRLVL_TITLE] = TR("No userlevels installed!"); stringsText[RT_DIALOG_NOUSRLVL_TEXT] = TR("This menu is for userlevels from mods, but you didn't install any"); + stringsText[RT_DIALOG_OPEN_PATH_FAILED_TITLE] = TR("Could not open the file explorer!"); + stringsText[RT_DIALOG_OPEN_PATH_FAILED_TEXT] = TR("The path %s could not be opened in a file explorer."); + stringsText[RT_DIALOG_OPEN_WEBSITE_FAILED_TITLE] = TR("Could not open the web browser!"); + stringsText[RT_DIALOG_OPEN_WEBSITE_FAILED_TEXT] = TR("The address %s could not be opened in a web browser."); + stringsText[RT_DIALOG_CHANGES_QUESTION] = TR("There are unsaved changes. Do you want to save them before leaving?"); stringsText[RT_STUDIO_LISTTT] = TR("Keyword help(\\key cbot;)"); stringsText[RT_STUDIO_COMPOK] = TR("Compilation ok (0 errors)"); @@ -124,6 +131,8 @@ void InitializeRestext() stringsText[RT_IO_DIR] = TR("Folder:"); stringsText[RT_IO_PRIVATE] = TR("Private\\Private folder"); stringsText[RT_IO_PUBLIC] = TR("Public\\Common folder"); + stringsText[RT_IO_REPLACE] = TR("Overwrite existing file?"); + stringsText[RT_IO_SELECT_DIR] = TR("Select Folder"); stringsText[RT_GENERIC_DEV1] = TR("Original game developed by:"); stringsText[RT_GENERIC_DEV2] = TR("epsitec.com"); @@ -151,7 +160,18 @@ void InitializeRestext() stringsText[RT_SCOREBOARD_RESULTS_TIME]= TR("Time: %s"); stringsText[RT_SCOREBOARD_RESULTS_LINE]= TR("%s: %d pts"); - + stringsText[RT_MOD_LIST] = TR("Mods:"); + stringsText[RT_MOD_DETAILS] = TR("Information:"); + stringsText[RT_MOD_SUMMARY] = TR("Description:"); + stringsText[RT_MOD_ENABLE] = TR("Enable\\Enable the selected mod"); + stringsText[RT_MOD_DISABLE] = TR("Disable\\Disable the selected mod"); + stringsText[RT_MOD_UNKNOWN_AUTHOR] = TR("Unknown author"); + stringsText[RT_MOD_AUTHOR_FIELD_NAME] = TR("by"); + stringsText[RT_MOD_VERSION_FIELD_NAME] = TR("Version"); + stringsText[RT_MOD_WEBSITE_FIELD_NAME] = TR("Website"); + stringsText[RT_MOD_CHANGES_FIELD_NAME] = TR("Changes"); + stringsText[RT_MOD_NO_SUMMARY] = TR("No description."); + stringsText[RT_MOD_NO_CHANGES] = TR("No changes."); stringsEvent[EVENT_LABEL_CODE_BATTLE] = TR("Code battle"); @@ -162,6 +182,7 @@ void InitializeRestext() stringsEvent[EVENT_DIALOG_OK] = TR("OK"); stringsEvent[EVENT_DIALOG_CANCEL] = TR("Cancel"); + stringsEvent[EVENT_DIALOG_NEWDIR] = TR("New Folder"); stringsEvent[EVENT_INTERFACE_TRAINER] = TR("Exercises\\Programming exercises"); stringsEvent[EVENT_INTERFACE_DEFI] = TR("Challenges\\Programming challenges"); @@ -170,6 +191,7 @@ void InitializeRestext() stringsEvent[EVENT_INTERFACE_CODE_BATTLES] = TR("Code battles\\Program your robot to be the best of them all!"); stringsEvent[EVENT_INTERFACE_USER] = TR("Custom levels\\Levels from mods created by the users"); stringsEvent[EVENT_INTERFACE_SATCOM] = TR("SatCom"); + stringsEvent[EVENT_INTERFACE_MODS] = TR("Mods\\Mod manager"); stringsEvent[EVENT_INTERFACE_NAME] = TR("Change player\\Change player"); stringsEvent[EVENT_INTERFACE_SETUP] = TR("Options\\Preferences"); stringsEvent[EVENT_INTERFACE_AGAIN] = TR("Restart\\Restart the mission from the beginning"); @@ -178,7 +200,14 @@ void InitializeRestext() stringsEvent[EVENT_INTERFACE_ABORT] = TR("\\Return to Colobot: Gold Edition"); stringsEvent[EVENT_INTERFACE_QUIT] = TR("Quit\\Quit Colobot: Gold Edition"); stringsEvent[EVENT_INTERFACE_BACK] = TR("<< Back \\Back to the previous screen"); + stringsEvent[EVENT_INTERFACE_PLUS] = TR("+\\Missions with bonus content and optional challenges"); stringsEvent[EVENT_INTERFACE_PLAY] = TR("Play\\Start mission!"); + stringsEvent[EVENT_INTERFACE_WORKSHOP] = TR("Workshop\\Open the workshop to search for mods"); + stringsEvent[EVENT_INTERFACE_MODS_DIR] = TR("Open Directory\\Open the mods directory"); + stringsEvent[EVENT_INTERFACE_MODS_APPLY] = TR("Apply\\Apply the current mod configuration"); + stringsEvent[EVENT_INTERFACE_MOD_MOVE_UP] = TR("Up\\Move the selected mod up so it's loaded sooner (mods may overwrite files from the mods above them)"); + stringsEvent[EVENT_INTERFACE_MOD_MOVE_DOWN] = TR("Down\\Move the selected mod down so it's loaded later (mods may overwrite files from the mods above them)"); + stringsEvent[EVENT_INTERFACE_MODS_REFRESH] = TR("Refresh\\Refresh the list of currently installed mods"); stringsEvent[EVENT_INTERFACE_SETUPd] = TR("Device\\Driver and resolution settings"); stringsEvent[EVENT_INTERFACE_SETUPg] = TR("Graphics\\Graphics settings"); stringsEvent[EVENT_INTERFACE_SETUPp] = TR("Game\\Game settings"); @@ -204,6 +233,7 @@ void InitializeRestext() stringsEvent[EVENT_INTERFACE_INVERTY] = TR("Mouse inversion Y\\Inversion of the scrolling direction on the Y axis"); stringsEvent[EVENT_INTERFACE_EFFECT] = TR("Quake at explosions\\The screen shakes at explosions"); stringsEvent[EVENT_INTERFACE_BGPAUSE] = TR("Pause in background\\Pause the game when the window is unfocused"); + stringsEvent[EVENT_INTERFACE_BGMUTE] = TR("Mute sounds in background\\Mute all game sounds when the window is unfocused"); stringsEvent[EVENT_INTERFACE_EDITMODE] = TR("Automatic indent\\When program editing"); stringsEvent[EVENT_INTERFACE_EDITVALUE] = TR("Big indent\\Indent 2 or 4 spaces per level defined by braces"); stringsEvent[EVENT_INTERFACE_SOLUCE4] = TR("Access to solutions\\Show program \"4: Solution\" in the exercises"); @@ -271,6 +301,10 @@ void InitializeRestext() stringsEvent[EVENT_INTERFACE_JOYSTICK_CAM_Y_INVERT] = TR("Invert\\Invert values on this axis"); stringsEvent[EVENT_INTERFACE_JOYSTICK_CAM_Z_INVERT] = TR("Invert\\Invert values on this axis"); + stringsEvent[EVENT_INTERFACE_PLUS_TRAINER] = TR("Space Programmer\\Disables radio-control"); + stringsEvent[EVENT_INTERFACE_PLUS_RESEARCH] = TR("Space Researcher\\Disables using all previously researched technologies"); + stringsEvent[EVENT_INTERFACE_PLUS_EXPLORER] = TR("Space Explorer\\Disables astronaut abilities"); + stringsEvent[EVENT_INTERFACE_NEDIT] = TR("\\New player name"); stringsEvent[EVENT_INTERFACE_NOK] = TR("OK\\Choose the selected player"); stringsEvent[EVENT_INTERFACE_NDELETE] = TR("Delete player\\Deletes the player from the list"); @@ -337,7 +371,7 @@ void InitializeRestext() stringsEvent[EVENT_OBJECT_BNUCLEAR] = TR("Build a nuclear power plant"); stringsEvent[EVENT_OBJECT_BPARA] = TR("Build a lightning conductor"); stringsEvent[EVENT_OBJECT_BINFO] = TR("Build a exchange post"); - stringsEvent[EVENT_OBJECT_BDESTROYER] = TR("Build a destroyer"); + stringsEvent[EVENT_OBJECT_BSAFE] = TR("Build a vault"); stringsEvent[EVENT_OBJECT_GFLAT] = TR("Show if the ground is flat"); stringsEvent[EVENT_OBJECT_FCREATE] = TR("Plant a flag"); stringsEvent[EVENT_OBJECT_FDELETE] = TR("Remove a flag"); @@ -362,11 +396,16 @@ void InitializeRestext() stringsEvent[EVENT_OBJECT_FACTORYts] = TR("Build a tracked sniffer"); stringsEvent[EVENT_OBJECT_FACTORYws] = TR("Build a wheeled sniffer"); stringsEvent[EVENT_OBJECT_FACTORYis] = TR("Build a legged sniffer"); + stringsEvent[EVENT_OBJECT_FACTORYfb] = TR("Build a winged builder"); + stringsEvent[EVENT_OBJECT_FACTORYtb] = TR("Build a tracked builder"); + stringsEvent[EVENT_OBJECT_FACTORYwb] = TR("Build a wheeled builder"); + stringsEvent[EVENT_OBJECT_FACTORYib] = TR("Build a legged builder"); stringsEvent[EVENT_OBJECT_FACTORYrt] = TR("Build a thumper"); stringsEvent[EVENT_OBJECT_FACTORYrc] = TR("Build a phazer shooter"); stringsEvent[EVENT_OBJECT_FACTORYrr] = TR("Build a recycler"); stringsEvent[EVENT_OBJECT_FACTORYrs] = TR("Build a shielder"); stringsEvent[EVENT_OBJECT_FACTORYsa] = TR("Build a subber"); + stringsEvent[EVENT_OBJECT_FACTORYtg] = TR("Build a target bot"); stringsEvent[EVENT_OBJECT_RTANK] = TR("Run research program for tracked bots"); stringsEvent[EVENT_OBJECT_RFLY] = TR("Run research program for winged bots"); stringsEvent[EVENT_OBJECT_RTHUMP] = TR("Run research program for thumper"); @@ -377,11 +416,14 @@ void InitializeRestext() stringsEvent[EVENT_OBJECT_RATOMIC] = TR("Run research program for nuclear power"); stringsEvent[EVENT_OBJECT_RiPAW] = TR("Run research program for legged bots"); stringsEvent[EVENT_OBJECT_RiGUN] = TR("Run research program for orga shooter"); + stringsEvent[EVENT_OBJECT_RBUILDER] = TR("Run research program for builder"); + stringsEvent[EVENT_OBJECT_RTARGET] = TR("Run research program for target bot"); stringsEvent[EVENT_OBJECT_RESET] = TR("Return to start"); stringsEvent[EVENT_OBJECT_SEARCH] = TR("Sniff (\\key action;)"); stringsEvent[EVENT_OBJECT_TERRAFORM] = TR("Thump (\\key action;)"); stringsEvent[EVENT_OBJECT_FIRE] = TR("Shoot (\\key action;)"); stringsEvent[EVENT_OBJECT_SPIDEREXPLO] = TR("Explode (\\key action;)"); + stringsEvent[EVENT_OBJECT_BUILD] = TR("Build (\\key action;)"); stringsEvent[EVENT_OBJECT_RECOVER] = TR("Recycle (\\key action;)"); stringsEvent[EVENT_OBJECT_BEGSHIELD] = TR("Extend shield (\\key action;)"); stringsEvent[EVENT_OBJECT_ENDSHIELD] = TR("Withdraw shield (\\key action;)"); @@ -518,10 +560,16 @@ void InitializeRestext() stringsObject[OBJECT_MOBILEtt] = TR("Practice bot"); stringsObject[OBJECT_MOBILEwt] = TR("Practice bot"); stringsObject[OBJECT_MOBILEit] = TR("Practice bot"); + stringsObject[OBJECT_MOBILErp] = TR("Practice bot"); + stringsObject[OBJECT_MOBILEst] = TR("Practice bot"); stringsObject[OBJECT_MOBILEfa] = TR("Winged grabber"); stringsObject[OBJECT_MOBILEta] = TR("Tracked grabber"); stringsObject[OBJECT_MOBILEwa] = TR("Wheeled grabber"); stringsObject[OBJECT_MOBILEia] = TR("Legged grabber"); + stringsObject[OBJECT_MOBILEfb] = TR("Winged builder"); + stringsObject[OBJECT_MOBILEtb] = TR("Tracked builder"); + stringsObject[OBJECT_MOBILEwb] = TR("Wheeled builder"); + stringsObject[OBJECT_MOBILEib] = TR("Legged builder"); stringsObject[OBJECT_MOBILEfc] = TR("Winged shooter"); stringsObject[OBJECT_MOBILEtc] = TR("Tracked shooter"); stringsObject[OBJECT_MOBILEwc] = TR("Wheeled shooter"); @@ -621,7 +669,7 @@ void InitializeRestext() stringsErr[ERR_BASE_DLOCK] = TR("Doors blocked by a robot or another object"); stringsErr[ERR_BASE_DHUMAN] = TR("You must get on the spaceship to take off"); stringsErr[ERR_LABO_NULL] = TR("Nothing to analyze"); - stringsErr[ERR_LABO_BAD] = TR("Analyzes only organic matter"); + stringsErr[ERR_LABO_BAD] = TR("Inappropriate sample"); stringsErr[ERR_LABO_ALREADY] = TR("Analysis already performed"); stringsErr[ERR_NUCLEAR_EMPTY] = TR("No uranium to transform"); stringsErr[ERR_NUCLEAR_BAD] = TR("Transforms only uranium"); @@ -659,6 +707,7 @@ void InitializeRestext() stringsErr[INFO_RESEARCHPHAZER] = TR("Plans for phazer shooter available"); stringsErr[INFO_RESEARCHSHIELD] = TR("Plans for shielder available"); stringsErr[INFO_RESEARCHATOMIC] = TR("Plans for nuclear power plant available"); + stringsErr[INFO_RESEARCHBUILDER]= TR("Plans for builder available"); stringsErr[INFO_FACTORY] = TR("New bot available"); stringsErr[INFO_LABO] = TR("Analysis performed"); stringsErr[INFO_ENERGY] = TR("Power cell available"); @@ -742,6 +791,8 @@ void InitializeRestext() stringsCbot[CBot::CBotErrHexDigits] = TR("Missing hex digits after escape sequence"); stringsCbot[CBot::CBotErrHexRange] = TR("Hex value out of range"); stringsCbot[CBot::CBotErrUnicodeName] = TR("Invalid universal character name"); + stringsCbot[CBot::CBotErrCharEmpty] = TR("Empty character constant"); + stringsCbot[CBot::CBotErrRedefCase] = TR("Duplicate label in switch"); stringsCbot[CBot::CBotErrZeroDiv] = TR("Dividing by zero"); stringsCbot[CBot::CBotErrNotInit] = TR("Variable not initialized"); diff --git a/src/common/restext.h b/src/common/restext.h index 6acfb610..0ba5d16d 100644 --- a/src/common/restext.h +++ b/src/common/restext.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -71,6 +71,8 @@ enum ResTextType RT_TITLE_WRITE = 50, RT_TITLE_READ = 51, RT_TITLE_USER = 52, + RT_TITLE_PLUS = 53, + RT_TITLE_MODS = 54, RT_PLAY_CHAP_CHAPTERS = 60, RT_PLAY_CHAP_PLANETS = 61, @@ -102,6 +104,11 @@ enum ResTextType RT_DIALOG_OK = 110, RT_DIALOG_NOUSRLVL_TITLE = 111, RT_DIALOG_NOUSRLVL_TEXT = 112, + RT_DIALOG_OPEN_PATH_FAILED_TITLE = 113, + RT_DIALOG_OPEN_PATH_FAILED_TEXT = 114, + RT_DIALOG_OPEN_WEBSITE_FAILED_TITLE = 115, + RT_DIALOG_OPEN_WEBSITE_FAILED_TEXT = 116, + RT_DIALOG_CHANGES_QUESTION = 117, RT_STUDIO_LISTTT = 120, RT_STUDIO_COMPOK = 121, @@ -118,6 +125,8 @@ enum ResTextType RT_IO_DIR = 154, RT_IO_PRIVATE = 155, RT_IO_PUBLIC = 156, + RT_IO_REPLACE = 157, + RT_IO_SELECT_DIR = 158, RT_GENERIC_DEV1 = 170, RT_GENERIC_DEV2 = 171, @@ -145,6 +154,18 @@ enum ResTextType RT_SCOREBOARD_RESULTS_TIME= 232, RT_SCOREBOARD_RESULTS_LINE= 233, + RT_MOD_LIST = 234, + RT_MOD_DETAILS = 235, + RT_MOD_SUMMARY = 236, + RT_MOD_ENABLE = 237, + RT_MOD_DISABLE = 238, + RT_MOD_UNKNOWN_AUTHOR = 239, + RT_MOD_AUTHOR_FIELD_NAME = 240, + RT_MOD_VERSION_FIELD_NAME = 241, + RT_MOD_WEBSITE_FIELD_NAME = 242, + RT_MOD_CHANGES_FIELD_NAME = 243, + RT_MOD_NO_SUMMARY = 244, + RT_MOD_NO_CHANGES = 245, RT_MAX //! < number of values }; diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 488666d2..7c72030e 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -34,22 +34,23 @@ CSettings::CSettings() { - m_tooltips = true; + m_tooltips = true; m_interfaceGlint = true; - m_interfaceRain = true; - m_soluce4 = true; - m_movies = true; + m_mouseParticlesEnabled = true; + m_soluce4 = true; + m_movies = true; m_focusLostPause = true; + m_focusLostMute = true; - m_fontSize = 19.0f; + m_fontSize = 19.0f; m_windowPos = Math::Point(0.15f, 0.17f); m_windowDim = Math::Point(0.70f, 0.66f); m_windowMax = false; m_IOPublic = false; - m_IODim = Math::Point(320.0f/640.0f, (121.0f+18.0f*8)/480.0f); - m_IOPos.x = (1.0f-m_IODim.x)/2.0f; // in the middle - m_IOPos.y = (1.0f-m_IODim.y)/2.0f; + m_IODim = Math::Point(320.0f / 640.0f, (121.0f + 18.0f * 8) / 480.0f); + m_IOPos.x = (1.0f - m_IODim.x) / 2.0f; // in the middle + m_IOPos.y = (1.0f - m_IODim.y) / 2.0f; m_language = LANGUAGE_ENV; } @@ -71,11 +72,10 @@ void CSettings::SaveSettings() CRobotMain* main = CRobotMain::GetInstancePointer(); Gfx::CEngine* engine = Gfx::CEngine::GetInstancePointer(); Gfx::CCamera* camera = main->GetCamera(); - CSoundInterface* sound = app->GetSound(); GetConfigFile().SetBoolProperty("Setup", "Tooltips", m_tooltips); GetConfigFile().SetBoolProperty("Setup", "InterfaceGlint", m_interfaceGlint); - GetConfigFile().SetBoolProperty("Setup", "InterfaceRain", m_interfaceRain); + GetConfigFile().SetBoolProperty("Setup", "MouseParticlesEnabled", m_mouseParticlesEnabled); GetConfigFile().SetBoolProperty("Setup", "Soluce4", m_soluce4); GetConfigFile().SetBoolProperty("Setup", "Movies", m_movies); GetConfigFile().SetBoolProperty("Setup", "FocusLostPause", m_focusLostPause); @@ -93,8 +93,6 @@ void CSettings::SaveSettings() GetConfigFile().SetIntProperty("Setup", "JoystickIndex", app->GetJoystickEnabled() ? app->GetJoystick().index : -1); GetConfigFile().SetFloatProperty("Setup", "ParticleDensity", engine->GetParticleDensity()); GetConfigFile().SetFloatProperty("Setup", "ClippingDistance", engine->GetClippingDistance()); - GetConfigFile().SetIntProperty("Setup", "AudioVolume", sound->GetAudioVolume()); - GetConfigFile().SetIntProperty("Setup", "MusicVolume", sound->GetMusicVolume()); GetConfigFile().SetBoolProperty("Setup", "EditIndentMode", engine->GetEditIndentMode()); GetConfigFile().SetIntProperty("Setup", "EditIndentValue", engine->GetEditIndentValue()); GetConfigFile().SetBoolProperty("Setup", "PauseBlur", engine->GetPauseBlurEnabled()); @@ -108,7 +106,10 @@ void CSettings::SaveSettings() GetConfigFile().SetBoolProperty("Setup", "ShadowMapping", engine->GetShadowMapping()); GetConfigFile().SetBoolProperty("Setup", "ShadowMappingQuality", engine->GetShadowMappingQuality()); GetConfigFile().SetIntProperty("Setup", "ShadowMappingResolution", - engine->GetShadowMappingOffscreen() ? engine->GetShadowMappingOffscreenResolution() : 0); + engine->GetShadowMappingOffscreen() ? engine->GetShadowMappingOffscreenResolution() : 0); + + // Save Audio settings + SaveAudioSettings(); // Experimental settings GetConfigFile().SetBoolProperty("Experimental", "TerrainShadows", engine->GetTerrainShadows()); @@ -123,7 +124,7 @@ void CSettings::SaveSettings() GetConfigFile().SetFloatProperty("Edit", "WindowPosY", m_windowPos.y); GetConfigFile().SetFloatProperty("Edit", "WindowDimX", m_windowDim.x); GetConfigFile().SetFloatProperty("Edit", "WindowDimY", m_windowDim.y); - GetConfigFile().SetBoolProperty ("Edit", "WindowMaximized", m_windowMax); + GetConfigFile().SetBoolProperty("Edit", "WindowMaximized", m_windowMax); GetConfigFile().SetBoolProperty("Edit", "IOPublic", m_IOPublic); GetConfigFile().SetFloatProperty("Edit", "IOPosX", m_IOPos.x); @@ -138,6 +139,16 @@ void CSettings::SaveSettings() GetConfigFile().Save(); } +void CSettings::SaveAudioSettings() +{ + CApplication* app = CApplication::GetInstancePointer(); + CSoundInterface* sound = app->GetSound(); + + GetConfigFile().SetIntProperty("Setup", "AudioVolume", sound->GetAudioVolume()); + GetConfigFile().SetIntProperty("Setup", "MusicVolume", sound->GetMusicVolume()); + GetConfigFile().SetBoolProperty("Setup", "FocusLostMute", m_focusLostMute); +} + void CSettings::LoadSettings() { CApplication* app = CApplication::GetInstancePointer(); @@ -153,10 +164,11 @@ void CSettings::LoadSettings() GetConfigFile().GetBoolProperty("Setup", "Tooltips", m_tooltips); GetConfigFile().GetBoolProperty("Setup", "InterfaceGlint", m_interfaceGlint); - GetConfigFile().GetBoolProperty("Setup", "InterfaceRain", m_interfaceRain); + GetConfigFile().GetBoolProperty("Setup", "MouseParticlesEnabled", m_mouseParticlesEnabled); GetConfigFile().GetBoolProperty("Setup", "Soluce4", m_soluce4); GetConfigFile().GetBoolProperty("Setup", "Movies", m_movies); GetConfigFile().GetBoolProperty("Setup", "FocusLostPause", m_focusLostPause); + GetConfigFile().GetBoolProperty("Setup", "FocusLostMute", m_focusLostMute); if (GetConfigFile().GetBoolProperty("Setup", "OldCameraScroll", bValue)) camera->SetOldCameraScroll(bValue); @@ -199,7 +211,7 @@ void CSettings::LoadSettings() if (iValue >= 0) { auto joysticks = app->GetJoystickList(); - for(const auto& joystick : joysticks) + for (const auto& joystick : joysticks) { if (joystick.index == iValue) { @@ -284,18 +296,18 @@ void CSettings::LoadSettings() - GetConfigFile().GetFloatProperty("Edit", "FontSize", m_fontSize); - GetConfigFile().GetFloatProperty("Edit", "WindowPosX", m_windowPos.x); - GetConfigFile().GetFloatProperty("Edit", "WindowPosY", m_windowPos.y); - GetConfigFile().GetFloatProperty("Edit", "WindowDimX", m_windowDim.x); - GetConfigFile().GetFloatProperty("Edit", "WindowDimY", m_windowDim.y); - GetConfigFile().GetBoolProperty ("Edit", "WindowMaximized", m_windowMax); + GetConfigFile().GetFloatProperty("Edit", "FontSize", m_fontSize); + GetConfigFile().GetFloatProperty("Edit", "WindowPosX", m_windowPos.x); + GetConfigFile().GetFloatProperty("Edit", "WindowPosY", m_windowPos.y); + GetConfigFile().GetFloatProperty("Edit", "WindowDimX", m_windowDim.x); + GetConfigFile().GetFloatProperty("Edit", "WindowDimY", m_windowDim.y); + GetConfigFile().GetBoolProperty("Edit", "WindowMaximized", m_windowMax); - GetConfigFile().GetBoolProperty ("Edit", "IOPublic", m_IOPublic); - GetConfigFile().GetFloatProperty("Edit", "IOPosX", m_IOPos.x); - GetConfigFile().GetFloatProperty("Edit", "IOPosY", m_IOPos.y); - GetConfigFile().GetFloatProperty("Edit", "IODimX", m_IODim.x); - GetConfigFile().GetFloatProperty("Edit", "IODimY", m_IODim.y); + GetConfigFile().GetBoolProperty("Edit", "IOPublic", m_IOPublic); + GetConfigFile().GetFloatProperty("Edit", "IOPosX", m_IOPos.x); + GetConfigFile().GetFloatProperty("Edit", "IOPosY", m_IOPos.y); + GetConfigFile().GetFloatProperty("Edit", "IODimX", m_IODim.x); + GetConfigFile().GetFloatProperty("Edit", "IODimY", m_IODim.y); m_language = LANGUAGE_ENV; if (GetConfigFile().GetStringProperty("Language", "Lang", sValue)) @@ -303,7 +315,7 @@ void CSettings::LoadSettings() if (!sValue.empty() && !ParseLanguage(sValue, m_language)) { GetLogger()->Error("Failed to parse language '%s' from config file. Default language will be used.\n", - sValue.c_str()); + sValue.c_str()); } } app->SetLanguage(m_language); @@ -327,13 +339,13 @@ bool CSettings::GetInterfaceGlint() return m_interfaceGlint; } -void CSettings::SetInterfaceRain(bool interfaceRain) +void CSettings::SetMouseParticlesEnabled(bool mouseParticlesEnabled) { - m_interfaceRain = interfaceRain; + m_mouseParticlesEnabled = mouseParticlesEnabled; } -bool CSettings::GetInterfaceRain() +bool CSettings::GetMouseParticlesEnabled() { - return m_interfaceRain; + return m_mouseParticlesEnabled; } void CSettings::SetSoluce4(bool soluce4) @@ -363,6 +375,14 @@ bool CSettings::GetFocusLostPause() return m_focusLostPause; } +void CSettings::SetFocusLostMute(bool focusLostMute) +{ + m_focusLostMute = focusLostMute; +} +bool CSettings::GetFocusLostMute() +{ + return m_focusLostMute; +} void CSettings::SetFontSize(float size) { diff --git a/src/common/settings.h b/src/common/settings.h index 6d085b29..010fd036 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -26,7 +26,7 @@ namespace Gfx { -struct DeviceConfig; + struct DeviceConfig; } class CSettings : public CSingleton @@ -37,6 +37,7 @@ public: void SaveSettings(); void LoadSettings(); + void SaveAudioSettings(); void SetTooltips(bool tooltips); bool GetTooltips(); @@ -44,8 +45,8 @@ public: void SetInterfaceGlint(bool interfaceGlint); bool GetInterfaceGlint(); - void SetInterfaceRain(bool interfaceRain); - bool GetInterfaceRain(); + void SetMouseParticlesEnabled(bool mouseParticlesEnabled); + bool GetMouseParticlesEnabled(); void SetSoluce4(bool soluce4); bool GetSoluce4(); @@ -56,6 +57,8 @@ public: void SetFocusLostPause(bool focusLostPause); bool GetFocusLostPause(); + void SetFocusLostMute(bool focusLostMute); + bool GetFocusLostMute(); //! Managing the size of the default fonts //@{ @@ -93,10 +96,11 @@ public: protected: bool m_tooltips; bool m_interfaceGlint; - bool m_interfaceRain; + bool m_mouseParticlesEnabled; bool m_soluce4; bool m_movies; bool m_focusLostPause; + bool m_focusLostMute; float m_fontSize; Math::Point m_windowPos; diff --git a/src/common/singleton.h b/src/common/singleton.h index 88d121ee..99f90ed6 100644 --- a/src/common/singleton.h +++ b/src/common/singleton.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/stringutils.cpp b/src/common/stringutils.cpp index b8639df3..1aa97920 100644 --- a/src/common/stringutils.cpp +++ b/src/common/stringutils.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -22,6 +22,7 @@ #include #include +#include #include @@ -173,14 +174,19 @@ int StrUtils::Utf8CharSizeAt(const std::string &str, unsigned int pos) if (pos >= str.size()) return 0; - if ((str[pos] & 0x80) == 0) - return 1; - else if ((str[pos] & 0xC0) == 0xC0) - return 2; - else + const char c = str[pos]; + if((c & 0xF8) == 0xF0) + return 4; + if((c & 0xF0) == 0xE0) return 3; + if((c & 0xE0) == 0xC0) + return 2; - return 0; + // Invalid char - unexpected continuation byte + if((c & 0xC0) == 0x80) + throw std::invalid_argument("Unexpected UTF-8 continuation byte"); + + return 1; } std::size_t StrUtils::Utf8StringLength(const std::string &str) diff --git a/src/common/stringutils.h b/src/common/stringutils.h index 8e4d0dee..bdb24049 100644 --- a/src/common/stringutils.h +++ b/src/common/stringutils.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/system/system.cpp b/src/common/system/system.cpp index 12dc1d36..b4893655 100644 --- a/src/common/system/system.cpp +++ b/src/common/system/system.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -36,6 +36,7 @@ #include #include +#include std::unique_ptr CSystemUtils::Create() { @@ -176,17 +177,51 @@ float CSystemUtils::TimeStampDiff(SystemTimeStamp *before, SystemTimeStamp *afte return result; } +std::string CSystemUtils::GetBasePath() +{ + if (m_basePath.empty()) + { + auto* path = SDL_GetBasePath(); + m_basePath = path; + SDL_free(path); + } + return m_basePath; +} + std::string CSystemUtils::GetDataPath() { +#ifdef USE_RELATIVE_PATHS + return GetBasePath() + COLOBOT_DEFAULT_DATADIR; +#else return COLOBOT_DEFAULT_DATADIR; +#endif } std::string CSystemUtils::GetLangPath() { +#ifdef USE_RELATIVE_PATHS + return GetBasePath() + COLOBOT_I18N_DIR; +#else return COLOBOT_I18N_DIR; +#endif } std::string CSystemUtils::GetSaveDir() { - return "./saves"; + return GetBasePath() + "saves"; +} + +std::string CSystemUtils::GetEnvVar(const std::string& name) +{ + return ""; +} + +bool CSystemUtils::OpenPath(const std::string& path) +{ + return false; +} + +bool CSystemUtils::OpenWebsite(const std::string& url) +{ + return false; } diff --git a/src/common/system/system.h b/src/common/system/system.h index 36e736c9..f20ee443 100644 --- a/src/common/system/system.h +++ b/src/common/system/system.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -116,6 +116,9 @@ public: //! Copies the time stamp from \a src to \a dst TEST_VIRTUAL void CopyTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *src); + //! Interpolates between two timestamps. If i=0 then dst=a. If i=1 then dst=b. If i=0.5 then dst is halfway between. + virtual void InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) = 0; + //! Returns a time stamp associated with current time virtual void GetCurrentTimeStamp(SystemTimeStamp *stamp) = 0; @@ -127,6 +130,9 @@ public: /** The difference is \a after - \a before. */ virtual long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) = 0; + //! Returns the path where the executable binary is located (ends with the path separator) + virtual std::string GetBasePath(); + //! Returns the data path (containing textures, levels, helpfiles, etc) virtual std::string GetDataPath(); @@ -136,9 +142,21 @@ public: //! Returns the save dir location virtual std::string GetSaveDir(); + //! Returns the environment variable with the given name or an empty string if it does not exist + virtual std::string GetEnvVar(const std::string &name); + + //! Opens a path with default file browser + /** \returns true if successful */ + virtual bool OpenPath(const std::string& path); + + //! Opens a website with default web browser + /** \returns true if successful */ + virtual bool OpenWebsite(const std::string& url); + //! Sleep for given amount of microseconds virtual void Usleep(int usecs) = 0; private: + std::string m_basePath; std::vector> m_timeStamps; }; diff --git a/src/common/system/system_linux.cpp b/src/common/system/system_linux.cpp index 9bfe431a..2b7d99fa 100644 --- a/src/common/system/system_linux.cpp +++ b/src/common/system/system_linux.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -83,6 +83,19 @@ SystemDialogResult CSystemUtilsLinux::SystemDialog(SystemDialogType type, const return result; } +void CSystemUtilsLinux::InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) +{ + long long delta = TimeStampExactDiff(a, b); + delta *= i; // truncates + dst->clockTime.tv_sec = a->clockTime.tv_sec + delta / 1000000000; + dst->clockTime.tv_nsec = a->clockTime.tv_nsec + delta % 1000000000; + if(dst->clockTime.tv_nsec >= 1000000000) + { + dst->clockTime.tv_nsec -= 1000000000; + dst->clockTime.tv_sec++; + } +} + void CSystemUtilsLinux::GetCurrentTimeStamp(SystemTimeStamp *stamp) { clock_gettime(CLOCK_MONOTONIC_RAW, &stamp->clockTime); @@ -102,23 +115,23 @@ std::string CSystemUtilsLinux::GetSaveDir() std::string savegameDir; // Determine savegame dir according to XDG Base Directory Specification - char *envXDG_DATA_HOME = getenv("XDG_DATA_HOME"); - if (envXDG_DATA_HOME == nullptr) + auto envXDG_DATA_HOME = GetEnvVar("XDG_DATA_HOME"); + if (envXDG_DATA_HOME.empty()) { - char *envHOME = getenv("HOME"); - if (envHOME == nullptr) + auto envHOME = GetEnvVar("HOME"); + if (envHOME.empty()) { - GetLogger()->Warn("Unable to find directory for saves - using current directory"); - savegameDir = "./saves"; + GetLogger()->Warn("Unable to find directory for saves - using default directory"); + savegameDir = CSystemUtils::GetSaveDir(); } else { - savegameDir = std::string(envHOME) + "/.local/share/colobot"; + savegameDir = envHOME + "/.local/share/colobot"; } } else { - savegameDir = std::string(envXDG_DATA_HOME) + "/colobot"; + savegameDir = envXDG_DATA_HOME + "/colobot"; } GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str()); @@ -126,6 +139,39 @@ std::string CSystemUtilsLinux::GetSaveDir() #endif } +std::string CSystemUtilsLinux::GetEnvVar(const std::string& name) +{ + char* envVar = getenv(name.c_str()); + if (envVar != nullptr) + { + GetLogger()->Trace("Detected environment variable %s = %s\n", name.c_str(), envVar); + return std::string(envVar); + } + return ""; +} + +bool CSystemUtilsLinux::OpenPath(const std::string& path) +{ + int result = system(("xdg-open \"" + path + "\"").c_str()); + if (result != 0) + { + GetLogger()->Error("Failed to open path: %s, error code: %i\n", path.c_str(), result); + return false; + } + return true; +} + +bool CSystemUtilsLinux::OpenWebsite(const std::string& url) +{ + int result = system(("xdg-open \"" + url + "\"").c_str()); + if (result != 0) + { + GetLogger()->Error("Failed to open website: %s, error code: %i\n", url.c_str(), result); + return false; + } + return true; +} + void CSystemUtilsLinux::Usleep(int usec) { usleep(usec); diff --git a/src/common/system/system_linux.h b/src/common/system/system_linux.h index f1576f31..6607b150 100644 --- a/src/common/system/system_linux.h +++ b/src/common/system/system_linux.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -40,11 +40,17 @@ public: SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; + void InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) override; void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; std::string GetSaveDir() override; + std::string GetEnvVar(const std::string& name) override; + + bool OpenPath(const std::string& path) override; + bool OpenWebsite(const std::string& url) override; + void Usleep(int usec) override; private: diff --git a/src/common/system/system_macosx.cpp b/src/common/system/system_macosx.cpp index 9ef7ce1d..d65fb6dc 100644 --- a/src/common/system/system_macosx.cpp +++ b/src/common/system/system_macosx.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -113,6 +113,34 @@ std::string CSystemUtilsMacOSX::GetSaveDir() #endif } +std::string CSystemUtilsMacOSX::GetEnvVar(const std::string& str) +{ + // TODO: I have no Mac + return std::string(); +} + +bool CSystemUtilsMacOSX::OpenPath(const std::string& path) +{ + int result = system(("open \"" + path + "\"").c_str()); // TODO: Test on macOS + if (result != 0) + { + GetLogger()->Error("Failed to open path: %s, error code: %i\n", path.c_str(), result); + return false; + } + return true; +} + +bool CSystemUtilsMacOSX::OpenWebsite(const std::string& url) +{ + int result = system(("open \"" + url + "\"").c_str()); // TODO: Test on macOS + if (result != 0) + { + GetLogger()->Error("Failed to open website: %s, error code: %i\n", website.c_str(), result); + return false; + } + return true; +} + void CSystemUtilsMacOSX::Usleep(int usec) { usleep(usec); diff --git a/src/common/system/system_macosx.h b/src/common/system/system_macosx.h index 5b572ec4..523e52e8 100644 --- a/src/common/system/system_macosx.h +++ b/src/common/system/system_macosx.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -36,6 +36,11 @@ public: std::string GetLangPath() override; std::string GetSaveDir() override; + std::string GetEnvVar(const std::string& name) override; + + bool OpenPath(const std::string& path) override; + bool OpenWebsite(const std::string& url) override; + void Usleep(int usec) override; private: diff --git a/src/common/system/system_other.cpp b/src/common/system/system_other.cpp index a3311a74..865db847 100644 --- a/src/common/system/system_other.cpp +++ b/src/common/system/system_other.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -34,6 +34,11 @@ void CSystemUtilsOther::GetCurrentTimeStamp(SystemTimeStamp* stamp) stamp->sdlTicks = SDL_GetTicks(); } +void CSystemUtilsOther::InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) +{ + dst->sdlTicks = a->sdlTicks + static_cast((b->sdlTicks - a->sdlTicks) * i); +} + long long int CSystemUtilsOther::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after) { return (after->sdlTicks - before->sdlTicks) * 1000000ll; diff --git a/src/common/system/system_other.h b/src/common/system/system_other.h index ac80701b..5964b585 100644 --- a/src/common/system/system_other.h +++ b/src/common/system/system_other.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -46,6 +46,7 @@ public: void Init() override; SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; + void InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) override; void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; diff --git a/src/common/system/system_windows.cpp b/src/common/system/system_windows.cpp index a20bfcf1..989d359b 100644 --- a/src/common/system/system_windows.cpp +++ b/src/common/system/system_windows.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include "common/logger.h" +#include #include @@ -83,6 +84,11 @@ void CSystemUtilsWindows::GetCurrentTimeStamp(SystemTimeStamp* stamp) stamp->counterValue = value.QuadPart; } +void CSystemUtilsWindows::InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) +{ + dst->counterValue = a->counterValue + static_cast((b->counterValue - a->counterValue) * static_cast(i)); +} + long long int CSystemUtilsWindows::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after) { float floatValue = static_cast(after->counterValue - before->counterValue) * (1e9 / static_cast(m_counterFrequency)); @@ -115,15 +121,15 @@ std::string CSystemUtilsWindows::GetSaveDir() #else std::string savegameDir; - wchar_t* envUSERPROFILE = _wgetenv(L"USERPROFILE"); - if (envUSERPROFILE == nullptr) + auto envUSERPROFILE = GetEnvVar("USERPROFILE"); + if (envUSERPROFILE.empty()) { - GetLogger()->Warn("Unable to find directory for saves - using current directory"); - savegameDir = "./saves"; + GetLogger()->Warn("Unable to find directory for saves - using default directory"); + savegameDir = CSystemUtils::GetSaveDir(); } else { - savegameDir = UTF8_Encode(std::wstring(envUSERPROFILE)) + "\\colobot"; + savegameDir = envUSERPROFILE + "\\colobot"; } GetLogger()->Trace("Saved game files are going to %s\n", savegameDir.c_str()); @@ -131,6 +137,44 @@ std::string CSystemUtilsWindows::GetSaveDir() #endif } +std::string CSystemUtilsWindows::GetEnvVar(const std::string& name) +{ + std::wstring wname(name.begin(), name.end()); + wchar_t* envVar = _wgetenv(wname.c_str()); + if (envVar == nullptr) + { + return ""; + } + else + { + std::string var = UTF8_Encode(std::wstring(envVar)); + GetLogger()->Trace("Detected environment variable %s = %s\n", name.c_str(), var.c_str()); + return var; + } +} + +bool CSystemUtilsWindows::OpenPath(const std::string& path) +{ + int result = system(("start explorer \"" + boost::filesystem::path(path).make_preferred().string() + "\"").c_str()); + if (result != 0) + { + GetLogger()->Error("Failed to open path: %s, error code: %i\n", path.c_str(), result); + return false; + } + return true; +} + +bool CSystemUtilsWindows::OpenWebsite(const std::string& url) +{ + int result = system(("rundll32 url.dll,FileProtocolHandler \"" + url + "\"").c_str()); + if (result != 0) + { + GetLogger()->Error("Failed to open website: %s, error code: %i\n", url.c_str(), result); + return false; + } + return true; +} + void CSystemUtilsWindows::Usleep(int usec) { LARGE_INTEGER ft; diff --git a/src/common/system/system_windows.h b/src/common/system/system_windows.h index 74f02455..90ef6b91 100644 --- a/src/common/system/system_windows.h +++ b/src/common/system/system_windows.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -38,11 +38,17 @@ public: SystemDialogResult SystemDialog(SystemDialogType type, const std::string& title, const std::string& message) override; + void InterpolateTimeStamp(SystemTimeStamp *dst, SystemTimeStamp *a, SystemTimeStamp *b, float i) override; void GetCurrentTimeStamp(SystemTimeStamp *stamp) override; long long TimeStampExactDiff(SystemTimeStamp *before, SystemTimeStamp *after) override; std::string GetSaveDir() override; + std::string GetEnvVar(const std::string& name) override; + + bool OpenPath(const std::string& path) override; + bool OpenWebsite(const std::string& url) override; + void Usleep(int usec) override; public: diff --git a/src/common/thread/resource_owning_thread.h b/src/common/thread/resource_owning_thread.h index 995cf4cb..a6f515a3 100644 --- a/src/common/thread/resource_owning_thread.h +++ b/src/common/thread/resource_owning_thread.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/thread/sdl_cond_wrapper.h b/src/common/thread/sdl_cond_wrapper.h index 1be681cf..597e7fe7 100644 --- a/src/common/thread/sdl_cond_wrapper.h +++ b/src/common/thread/sdl_cond_wrapper.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/thread/sdl_mutex_wrapper.h b/src/common/thread/sdl_mutex_wrapper.h index 476ddcae..0c446010 100644 --- a/src/common/thread/sdl_mutex_wrapper.h +++ b/src/common/thread/sdl_mutex_wrapper.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/thread/thread.h b/src/common/thread/thread.h index 59433ae3..12af2919 100644 --- a/src/common/thread/thread.h +++ b/src/common/thread/thread.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/common/thread/worker_thread.h b/src/common/thread/worker_thread.h index ad127556..a877a754 100644 --- a/src/common/thread/worker_thread.h +++ b/src/common/thread/worker_thread.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/color.cpp b/src/graphics/core/color.cpp index 1250b827..0b33c72f 100644 --- a/src/graphics/core/color.cpp +++ b/src/graphics/core/color.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h index cd4d541a..66193748 100644 --- a/src/graphics/core/color.h +++ b/src/graphics/core/color.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 2cc94992..6bfa8218 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/framebuffer.cpp b/src/graphics/core/framebuffer.cpp index 40937128..590b07a2 100644 --- a/src/graphics/core/framebuffer.cpp +++ b/src/graphics/core/framebuffer.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/framebuffer.h b/src/graphics/core/framebuffer.h index 3c5e6de8..11769dae 100644 --- a/src/graphics/core/framebuffer.h +++ b/src/graphics/core/framebuffer.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/light.h b/src/graphics/core/light.h index 3615cdb8..88100005 100644 --- a/src/graphics/core/light.h +++ b/src/graphics/core/light.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/material.h b/src/graphics/core/material.h index ac8f8bf3..41b6e284 100644 --- a/src/graphics/core/material.h +++ b/src/graphics/core/material.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/nulldevice.cpp b/src/graphics/core/nulldevice.cpp index cf9f5a67..6644d7a2 100644 --- a/src/graphics/core/nulldevice.cpp +++ b/src/graphics/core/nulldevice.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/nulldevice.h b/src/graphics/core/nulldevice.h index 0d6c7ab8..d1fbbe0f 100644 --- a/src/graphics/core/nulldevice.h +++ b/src/graphics/core/nulldevice.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/texture.h b/src/graphics/core/texture.h index 696261a2..0f11d9f9 100644 --- a/src/graphics/core/texture.h +++ b/src/graphics/core/texture.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/type.cpp b/src/graphics/core/type.cpp index 9ccafae7..aca29821 100644 --- a/src/graphics/core/type.cpp +++ b/src/graphics/core/type.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/type.h b/src/graphics/core/type.h index 5fc8decb..269b9262 100644 --- a/src/graphics/core/type.h +++ b/src/graphics/core/type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/core/vertex.h b/src/graphics/core/vertex.h index e5b71733..da338b90 100644 --- a/src/graphics/core/vertex.h +++ b/src/graphics/core/vertex.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/camera.cpp b/src/graphics/engine/camera.cpp index 461f46a0..f3b96186 100644 --- a/src/graphics/engine/camera.cpp +++ b/src/graphics/engine/camera.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -59,14 +59,14 @@ static void SetTransparency(CObject* obj, float value) if (obj->Implements(ObjectInterfaceType::Carrier)) { - CObject* cargo = dynamic_cast(obj)->GetCargo(); + CObject* cargo = dynamic_cast(*obj).GetCargo(); if (cargo != nullptr) cargo->SetTransparency(value); } if (obj->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(obj)->GetPower(); + CObject* power = dynamic_cast(*obj).GetPower(); if (power != nullptr) power->SetTransparency(value); } @@ -1233,7 +1233,7 @@ bool CCamera::EventFrameBack(const Event &event) bool ground = true; if (m_cameraObj->Implements(ObjectInterfaceType::Movable)) - ground = dynamic_cast(m_cameraObj)->GetPhysics()->GetLand(); + ground = dynamic_cast(*m_cameraObj).GetPhysics()->GetLand(); if ( ground ) // ground? { Math::Vector pos = lookatPt + (lookatPt - m_eyePt); @@ -1326,7 +1326,7 @@ bool CCamera::EventFrameOnBoard(const Event &event) { assert(m_cameraObj->Implements(ObjectInterfaceType::Controllable)); Math::Vector lookatPt, upVec; - dynamic_cast(m_cameraObj)->AdjustCamera(m_eyePt, m_directionH, m_directionV, lookatPt, upVec, m_type); + dynamic_cast(*m_cameraObj).AdjustCamera(m_eyePt, m_directionH, m_directionV, lookatPt, upVec, m_type); Math::Vector eye = m_effectOffset * 0.3f + m_eyePt; Math::Vector lookat = m_effectOffset * 0.3f + lookatPt; diff --git a/src/graphics/engine/camera.h b/src/graphics/engine/camera.h index 40fde096..b4f2aaad 100644 --- a/src/graphics/engine/camera.h +++ b/src/graphics/engine/camera.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/cloud.cpp b/src/graphics/engine/cloud.cpp index bc3210ba..63510bd0 100644 --- a/src/graphics/engine/cloud.cpp +++ b/src/graphics/engine/cloud.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/cloud.h b/src/graphics/engine/cloud.h index 4171627a..79a3ceb3 100644 --- a/src/graphics/engine/cloud.h +++ b/src/graphics/engine/cloud.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 348514bb..c146d767 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -408,6 +408,7 @@ void CEngine::ReloadAllTextures() { FlushTextureCache(); m_text->FlushCache(); + m_text->ReloadFonts(); m_app->GetEventQueue()->AddEvent(Event(EVENT_RELOAD_TEXTURES)); UpdateGroundSpotTextures(); @@ -2310,6 +2311,7 @@ bool CEngine::LoadAllTextures() LoadTexture("textures/interface/button1.png"); LoadTexture("textures/interface/button2.png"); LoadTexture("textures/interface/button3.png"); + LoadTexture("textures/interface/button4.png"); LoadTexture("textures/effect00.png"); LoadTexture("textures/effect01.png"); LoadTexture("textures/effect02.png"); diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 88a35dda..aee24f34 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -1189,6 +1189,10 @@ public: void EnablePauseBlur(); void DisablePauseBlur(); + //! Reloads all textures + /** This additionally sends EVENT_RELOAD_TEXTURES to reload all textures not maintained by CEngine **/ + void ReloadAllTextures(); + protected: //! Resets some states and flushes textures after device was changed (e.g. resoulution changed) /** Instead of calling this directly, send EVENT_RESOLUTION_CHANGED event **/ @@ -1287,10 +1291,6 @@ protected: }; static void WriteScreenShotThread(std::unique_ptr data); - //! Reloads all textures - /** This additionally sends EVENT_RELOAD_TEXTURES to reload all textures not maintained by CEngine **/ - void ReloadAllTextures(); - protected: CApplication* m_app; CSystemUtils* m_systemUtils; diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp index 2a504754..99885f1a 100644 --- a/src/graphics/engine/lightman.cpp +++ b/src/graphics/engine/lightman.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h index 398a33e6..880a3f27 100644 --- a/src/graphics/engine/lightman.h +++ b/src/graphics/engine/lightman.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/lightning.cpp b/src/graphics/engine/lightning.cpp index 9c1a64bd..8b101e53 100644 --- a/src/graphics/engine/lightning.cpp +++ b/src/graphics/engine/lightning.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -323,7 +323,7 @@ CObject* CLightning::SearchObject(Math::Vector pos) if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue; - float detect = m_magnetic * dynamic_cast(obj)->GetLightningHitProbability(); + float detect = m_magnetic * dynamic_cast(*obj).GetLightningHitProbability(); if (detect == 0.0f) continue; Math::Vector oPos = obj->GetPosition(); diff --git a/src/graphics/engine/lightning.h b/src/graphics/engine/lightning.h index dc278bc2..72f7ade1 100644 --- a/src/graphics/engine/lightning.h +++ b/src/graphics/engine/lightning.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/oldmodelmanager.cpp b/src/graphics/engine/oldmodelmanager.cpp index e7ac426b..7207cc7b 100644 --- a/src/graphics/engine/oldmodelmanager.cpp +++ b/src/graphics/engine/oldmodelmanager.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -57,7 +57,18 @@ bool COldModelManager::LoadModel(const std::string& fileName, bool mirrored, int if (!stream.is_open()) throw CModelIOException(std::string("Could not open file '") + fileName + "'"); - model = ModelInput::Read(stream, ModelFormat::Old); + std::string::size_type extension_index = fileName.find_last_of('.'); + if (extension_index == std::string::npos) + throw CModelIOException(std::string("Filename '") + fileName + "' has no extension"); + + std::string extension = fileName.substr(extension_index + 1); + + if (extension == "mod") + model = ModelInput::Read(stream, ModelFormat::Old); + else if (extension == "txt") + model = ModelInput::Read(stream, ModelFormat::Text); + else + throw CModelIOException(std::string("Filename '") + fileName + "' has unknown extension"); } catch (const CModelIOException& e) { @@ -193,6 +204,7 @@ void COldModelManager::ChangeVariant(std::vector& triangles, int triangles[i].tex1Name == "factory.png" || triangles[i].tex1Name == "lemt.png" || triangles[i].tex1Name == "roller.png" || + triangles[i].tex1Name == "rollert.png" || triangles[i].tex1Name == "search.png" || triangles[i].tex1Name == "drawer.png" || triangles[i].tex1Name == "subm.png" ) diff --git a/src/graphics/engine/oldmodelmanager.h b/src/graphics/engine/oldmodelmanager.h index 2360d31c..502dc501 100644 --- a/src/graphics/engine/oldmodelmanager.h +++ b/src/graphics/engine/oldmodelmanager.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 5c6d169f..fa430488 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -67,7 +67,6 @@ static bool IsAlien(ObjectType type) type == OBJECT_NEST || type == OBJECT_BULLET || type == OBJECT_EGG || - type == OBJECT_MOBILEtg || type == OBJECT_TEEN28 || type == OBJECT_TEEN31 ); } @@ -877,7 +876,7 @@ void CParticle::FrameParticle(float rTime) m_track[r].drawParticle = (progress < 1.0f); } - if (m_particle[i].type == PARTITRACK1) // explosion technique? + if (m_particle[i].type == PARTITRACK1) // technical explosion? { m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); @@ -954,7 +953,7 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr && object->Implements(ObjectInterfaceType::Damageable)) { - dynamic_cast(object)->DamageObject(DamageType::Phazer, 0.002f, m_particle[i].objFather); + dynamic_cast(*object).DamageObject(DamageType::Phazer, 0.002f, m_particle[i].objFather); } m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration); @@ -1157,7 +1156,7 @@ void CParticle::FrameParticle(float rTime) { if (object->Implements(ObjectInterfaceType::Damageable)) { - dynamic_cast(object)->DamageObject(DamageType::Fire, 0.001f, m_particle[i].objFather); + dynamic_cast(*object).DamageObject(DamageType::Fire, 0.001f, m_particle[i].objFather); } m_exploGunCounter++; @@ -1223,7 +1222,7 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr) { - if (object->GetType() == OBJECT_MOBILErs && dynamic_cast(object)->GetActiveShieldRadius() > 0.0f) // protected by shield? + if (object->GetType() == OBJECT_MOBILErs && dynamic_cast(*object).GetActiveShieldRadius() > 0.0f) // protected by shield? { CreateParticle(m_particle[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f); if (m_lastTimeGunDel > 0.2f) @@ -1241,7 +1240,7 @@ void CParticle::FrameParticle(float rTime) if (object->Implements(ObjectInterfaceType::Damageable)) { - dynamic_cast(object)->DamageObject(DamageType::Organic, 0.1f, m_particle[i].objFather); // starts explosion + dynamic_cast(*object).DamageObject(DamageType::Organic, 0.1f, m_particle[i].objFather); // starts explosion } } } @@ -1271,7 +1270,7 @@ void CParticle::FrameParticle(float rTime) m_particle[i].goal = m_particle[i].pos; if (object != nullptr) { - if (object->GetType() == OBJECT_MOBILErs && dynamic_cast(object)->GetActiveShieldRadius() > 0.0f) + if (object->GetType() == OBJECT_MOBILErs && dynamic_cast(*object).GetActiveShieldRadius() > 0.0f) { CreateParticle(m_particle[i].pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f); if (m_lastTimeGunDel > 0.2f) @@ -1286,7 +1285,7 @@ void CParticle::FrameParticle(float rTime) { if (object->Implements(ObjectInterfaceType::Damageable)) { - dynamic_cast(object)->DamageObject(DamageType::Fire, std::numeric_limits::infinity(), m_particle[i].objFather); // starts explosion + dynamic_cast(*object).DamageObject(DamageType::Fire, std::numeric_limits::infinity(), m_particle[i].objFather); // starts explosion } } } @@ -1345,7 +1344,7 @@ void CParticle::FrameParticle(float rTime) { if (object->Implements(ObjectInterfaceType::Damageable)) { - dynamic_cast(object)->DamageObject(DamageType::Organic, 0.001f, m_particle[i].objFather); + dynamic_cast(*object).DamageObject(DamageType::Organic, 0.001f, m_particle[i].objFather); } m_exploGunCounter ++; @@ -2407,7 +2406,7 @@ void CParticle::FrameParticle(float rTime) ti.y = ts.y+0.125f; } - if (m_particle[i].type == PARTIRAY1) // rayon tour ? + if (m_particle[i].type == PARTIRAY1) // tower ray ? { if (progress >= 1.0f) { @@ -2423,7 +2422,7 @@ void CParticle::FrameParticle(float rTime) if (object != nullptr) { assert(object->Implements(ObjectInterfaceType::Damageable)); - dynamic_cast(object)->DamageObject(DamageType::Tower, std::numeric_limits::infinity(), m_particle[i].objFather); + dynamic_cast(*object).DamageObject(DamageType::Tower, std::numeric_limits::infinity(), m_particle[i].objFather); } } @@ -2517,7 +2516,7 @@ void CParticle::TrackDraw(int i, ParticleType type) Math::Point texInf, texSup; - if (type == PARTITRACK1) // explosion technique? + if (type == PARTITRACK1) // technical explosion? { texInf.x = 64.5f/256.0f; texInf.y = 21.0f/256.0f; @@ -3544,6 +3543,7 @@ CObject* CParticle::SearchObjectGun(Math::Vector old, Math::Vector pos, continue; } if (!obj->Implements(ObjectInterfaceType::Damageable) && !obj->IsBulletWall()) continue; + if (obj->Implements(ObjectInterfaceType::Jostleable)) continue; Math::Vector oPos = obj->GetPosition(); diff --git a/src/graphics/engine/particle.h b/src/graphics/engine/particle.h index b4fada39..b97dd693 100644 --- a/src/graphics/engine/particle.h +++ b/src/graphics/engine/particle.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/planet.cpp b/src/graphics/engine/planet.cpp index 5da1ed64..6a59a3b5 100644 --- a/src/graphics/engine/planet.cpp +++ b/src/graphics/engine/planet.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/planet.h b/src/graphics/engine/planet.h index 41760176..3efe4ee8 100644 --- a/src/graphics/engine/planet.h +++ b/src/graphics/engine/planet.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/planet_type.h b/src/graphics/engine/planet_type.h index 7c6a2259..8f92bf83 100644 --- a/src/graphics/engine/planet_type.h +++ b/src/graphics/engine/planet_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp index 6eedf854..33c144b8 100644 --- a/src/graphics/engine/pyro.cpp +++ b/src/graphics/engine/pyro.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -129,7 +129,7 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) CObject* power = nullptr; if (obj->Implements(ObjectInterfaceType::Powered)) - power = dynamic_cast(obj)->GetPower(); + power = dynamic_cast(*obj).GetPower(); if (power == nullptr) { @@ -223,6 +223,10 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) { m_sound->Play(SOUND_EXPLOi, m_pos); } + if ( type == PT_FRAGV ) + { + m_sound->Play(SOUND_BOUMv, m_pos); + } if ( type == PT_BURNT || type == PT_BURNO ) { @@ -256,7 +260,7 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) m_sound->Play(SOUND_DEADw, m_pos); } assert(m_object->Implements(ObjectInterfaceType::Controllable)); - if ( type == PT_SHOTH && dynamic_cast(m_object)->GetSelect() ) + if ( type == PT_SHOTH && dynamic_cast(*m_object).GetSelect() ) { m_sound->Play(SOUND_AIE, m_pos); m_sound->Play(SOUND_AIE, m_engine->GetEyePt()); @@ -265,7 +269,8 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) if ( m_type == PT_FRAGT || m_type == PT_FRAGO || - m_type == PT_FRAGW ) + m_type == PT_FRAGW || + m_type == PT_FRAGV ) { m_engine->DeleteShadowSpot(m_object->GetObjectRank(0)); } @@ -273,10 +278,10 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) if ( m_type == PT_DEADG ) { assert(m_object->Implements(ObjectInterfaceType::Destroyable)); - dynamic_cast(m_object)->SetDying(DeathType::Dead); + dynamic_cast(*m_object).SetDying(DeathType::Dead); assert(obj->Implements(ObjectInterfaceType::Movable)); - dynamic_cast(obj)->GetMotion()->SetAction(MHS_DEADg, 1.0f); + dynamic_cast(*obj).GetMotion()->SetAction(MHS_DEADg, 1.0f); m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 1.5f); m_camera->StartOver(CAM_OVER_EFFECT_FADEOUT_WHITE, m_pos, 1.0f); @@ -286,10 +291,10 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) if ( m_type == PT_DEADW ) { assert(m_object->Implements(ObjectInterfaceType::Destroyable)); - dynamic_cast(m_object)->SetDying(DeathType::Dead); + dynamic_cast(*m_object).SetDying(DeathType::Dead); assert(obj->Implements(ObjectInterfaceType::Movable)); - dynamic_cast(obj)->GetMotion()->SetAction(MHS_DEADw, 1.0f); + dynamic_cast(*obj).GetMotion()->SetAction(MHS_DEADw, 1.0f); m_camera->StartCentering(m_object, Math::PI*0.5f, 99.9f, 0.0f, 3.0f); m_camera->StartOver(CAM_OVER_EFFECT_FADEOUT_BLACK, m_pos, 1.0f); @@ -307,7 +312,7 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) if ( m_type == PT_SHOTH ) { assert(m_object->Implements(ObjectInterfaceType::Controllable)); - if ( m_camera->GetBlood() && dynamic_cast(m_object)->GetSelect() ) + if ( m_camera->GetBlood() && dynamic_cast(*m_object).GetSelect() ) { m_camera->StartOver(CAM_OVER_EFFECT_BLOOD, m_pos, force); } @@ -351,6 +356,12 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) if (oType == OBJECT_APOLLO2) limit = 2.0f; m_speed = 1.0f/limit; } + if ( m_type == PT_SQUASH ) + { + m_speed = 1.0f/2.0f; + m_object->SetLock(true); + } + if ( m_type == PT_EXPLOT || m_type == PT_EXPLOO || @@ -391,9 +402,11 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) m_engine->DeleteShadowSpot(m_object->GetObjectRank(0)); } - if ( m_type != PT_EGG && - m_type != PT_WIN && - m_type != PT_LOST ) + if ( m_type != PT_FRAGV && + m_type != PT_EGG && + m_type != PT_WIN && + m_type != PT_LOST && + m_type != PT_SQUASH) { float h = 40.0f; if ( m_type == PT_FRAGO || @@ -448,7 +461,8 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) m_type != PT_FLCREATE && m_type != PT_FLDELETE && m_type != PT_RESET && - m_type != PT_FINDING ) + m_type != PT_FINDING && + m_type != PT_SQUASH ) { m_camera->StartEffect(CAM_EFFECT_EXPLO, m_pos, force); } @@ -460,6 +474,7 @@ bool CPyro::Create(PyroType type, CObject* obj, float force) if ( m_type == PT_FRAGT || m_type == PT_FRAGO || m_type == PT_FRAGW || + m_type == PT_FRAGV || m_type == PT_SPIDER || m_type == PT_EGG || (m_type == PT_EXPLOT && oType == OBJECT_MOBILEtg) || @@ -1042,6 +1057,11 @@ bool CPyro::EventProcess(const Event &event) } } + if ( m_type == PT_SQUASH && m_object != nullptr ) + { + m_object->SetScaleY(1.0f-sinf(m_progress)*0.5f); + } + if ( (m_type == PT_BURNT || m_type == PT_BURNO) && m_object != nullptr ) { @@ -1169,6 +1189,7 @@ Error CPyro::IsEnded() if ( m_type == PT_FRAGT || m_type == PT_FRAGO || m_type == PT_FRAGW || + m_type == PT_FRAGV || m_type == PT_SPIDER || m_type == PT_EGG ) { @@ -1221,6 +1242,11 @@ Error CPyro::IsEnded() m_object->SetScale(1.0f); } + if ( m_type == PT_SQUASH ) + { + m_object->SetType(OBJECT_PLANT19); + } + if ( m_lightRank != -1 ) { m_lightMan->DeleteLight(m_lightRank); @@ -1260,6 +1286,10 @@ void CPyro::DisplayError(PyroType type, CObject* obj) oType == OBJECT_MOBILEta || oType == OBJECT_MOBILEfa || oType == OBJECT_MOBILEia || + oType == OBJECT_MOBILEwb || + oType == OBJECT_MOBILEtb || + oType == OBJECT_MOBILEfb || + oType == OBJECT_MOBILEib || oType == OBJECT_MOBILEwc || oType == OBJECT_MOBILEtc || oType == OBJECT_MOBILEfc || @@ -1281,6 +1311,8 @@ void CPyro::DisplayError(PyroType type, CObject* obj) oType == OBJECT_MOBILEtt || oType == OBJECT_MOBILEft || oType == OBJECT_MOBILEit || + oType == OBJECT_MOBILErp || + oType == OBJECT_MOBILEst || oType == OBJECT_MOBILEdr ) { err = ERR_DELETEMOBILE; @@ -1381,7 +1413,7 @@ void CPyro::DeleteObject(bool primary, bool secondary) if (m_object->Implements(ObjectInterfaceType::Transportable)) { // TODO: this should be handled in the object's destructor - CObject* transporter = dynamic_cast(m_object)->GetTransporter(); + CObject* transporter = dynamic_cast(*m_object).GetTransporter(); if (transporter != nullptr) { if (transporter->Implements(ObjectInterfaceType::Powered)) @@ -1416,7 +1448,11 @@ void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part) float percent = 0.10f; if (total < 50) percent = 0.25f; if (total < 20) percent = 0.50f; - if (m_type == PT_EGG) percent = 0.30f; + + if ( m_type == PT_FRAGV || m_type == PT_EGG ) + { + percent = 0.30f; + } if (oType == OBJECT_POWER || oType == OBJECT_ATOMIC || @@ -1507,7 +1543,7 @@ void CPyro::CreateTriangle(CObject* obj, ObjectType oType, int part) Math::Matrix* mat = obj->GetWorldMatrix(part); Math::Vector pos = Math::Transform(*mat, offset); - if ( m_type == PT_EGG ) + if ( m_type == PT_FRAGV || m_type == PT_EGG ) { speed.x = (Math::Rand()-0.5f)*10.0f; speed.z = (Math::Rand()-0.5f)*10.0f; @@ -1546,12 +1582,12 @@ void CPyro::ExploStart() m_object->Simplify(); m_object->SetLock(true); // ruin not usable yet assert(m_object->Implements(ObjectInterfaceType::Destroyable)); - dynamic_cast(m_object)->SetDying(DeathType::Exploding); // being destroyed + dynamic_cast(*m_object).SetDying(DeathType::Exploding); // being destroyed m_object->FlatParent(); - if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(m_object)->GetSelect() ) + if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(*m_object).GetSelect() ) { - dynamic_cast(m_object)->SetSelect(false); // deselects the object + dynamic_cast(*m_object).SetSelect(false); // deselects the object m_camera->SetType(CAM_TYPE_EXPLO); m_main->DeselectAll(); } @@ -1575,7 +1611,7 @@ void CPyro::ExploStart() // TODO: temporary hack (hopefully) assert(m_object->Implements(ObjectInterfaceType::Old)); - Math::Vector pos = dynamic_cast(m_object)->GetPartPosition(i); + Math::Vector pos = dynamic_cast(*m_object).GetPartPosition(i); Math::Vector speed; float weight; @@ -1622,9 +1658,9 @@ void CPyro::BurnStart() m_object->Simplify(); m_object->SetLock(true); // ruin not usable yet - if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(m_object)->GetSelect() ) + if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(*m_object).GetSelect() ) { - dynamic_cast(m_object)->SetSelect(false); // deselects the object + dynamic_cast(*m_object).SetSelect(false); // deselects the object m_camera->SetType(CAM_TYPE_EXPLO); m_main->DeselectAll(); } @@ -1717,6 +1753,7 @@ void CPyro::BurnStart() angle.z = (Math::Rand()-0.5f)*0.4f; } else if ( m_burnType == OBJECT_MOBILEwa || + m_burnType == OBJECT_MOBILEwb || m_burnType == OBJECT_MOBILEwc || m_burnType == OBJECT_MOBILEwi || m_burnType == OBJECT_MOBILEws || @@ -1921,6 +1958,20 @@ void CPyro::BurnStart() BurnAddPart(1, pos, angle); // down the insect-cannon } + if ( m_burnType == OBJECT_MOBILEfb || + m_burnType == OBJECT_MOBILEtb || + m_burnType == OBJECT_MOBILEwb || + m_burnType == OBJECT_MOBILEib ) + { + pos.x = -1.5f; + pos.y = -5.0f; + pos.z = 0.0f; + angle.x = (Math::Rand()-0.5f)*0.2f; + angle.y = (Math::Rand()-0.5f)*0.2f; + angle.z = -25.0f*Math::PI/180.0f; + BurnAddPart(1, pos, angle); // down the neutron gun + } + if ( m_burnType == OBJECT_MOBILErt || m_burnType == OBJECT_MOBILErc ) { @@ -2007,6 +2058,7 @@ void CPyro::BurnStart() } if ( m_burnType == OBJECT_MOBILEwa || + m_burnType == OBJECT_MOBILEwb || m_burnType == OBJECT_MOBILEwc || m_burnType == OBJECT_MOBILEwi || m_burnType == OBJECT_MOBILEws || @@ -2029,14 +2081,18 @@ void CPyro::BurnStart() } if ( m_burnType == OBJECT_MOBILEta || + m_burnType == OBJECT_MOBILEtb || m_burnType == OBJECT_MOBILEtc || m_burnType == OBJECT_MOBILEti || m_burnType == OBJECT_MOBILEts || + m_burnType == OBJECT_MOBILEtt || m_burnType == OBJECT_MOBILErt || m_burnType == OBJECT_MOBILErc || m_burnType == OBJECT_MOBILErr || m_burnType == OBJECT_MOBILErs || + m_burnType == OBJECT_MOBILErp || m_burnType == OBJECT_MOBILEsa || + m_burnType == OBJECT_MOBILEst || m_burnType == OBJECT_MOBILEdr ) // caterpillars? { pos.x = 0.0f; @@ -2057,6 +2113,7 @@ void CPyro::BurnStart() } if ( m_burnType == OBJECT_MOBILEfa || + m_burnType == OBJECT_MOBILEfb || m_burnType == OBJECT_MOBILEfc || m_burnType == OBJECT_MOBILEfi || m_burnType == OBJECT_MOBILEfs || @@ -2077,9 +2134,11 @@ void CPyro::BurnStart() } if ( m_burnType == OBJECT_MOBILEia || + m_burnType == OBJECT_MOBILEib || m_burnType == OBJECT_MOBILEic || m_burnType == OBJECT_MOBILEii || - m_burnType == OBJECT_MOBILEis ) // legs? + m_burnType == OBJECT_MOBILEis || + m_burnType == OBJECT_MOBILEit ) // legs? { for (int i = 0; i < 6; i++) { @@ -2139,7 +2198,7 @@ void CPyro::BurnProgress() if (m_object->Implements(ObjectInterfaceType::Powered)) { - CObject* sub = dynamic_cast(m_object)->GetPower(); + CObject* sub = dynamic_cast(*m_object).GetPower(); if (sub != nullptr) // is there a battery? sub->SetScaleY(1.0f - m_progress); // complete flattening } @@ -2202,6 +2261,7 @@ void CPyro::BurnTerminate() { m_object->SetType(OBJECT_RUINmobilew1); // Wreck (recoverable by Recycler) } + dynamic_cast(m_object)->SetDying(DeathType::Alive); m_object->SetLock(false); } @@ -2232,7 +2292,7 @@ CObject* CPyro::FallSearchBeeExplo() if (obj->GetType() == OBJECT_MOBILErs) { - float shieldRadius = dynamic_cast(obj)->GetActiveShieldRadius(); + float shieldRadius = dynamic_cast(*obj).GetActiveShieldRadius(); if ( shieldRadius > 0.0f ) { float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos); @@ -2300,12 +2360,12 @@ void CPyro::FallProgress(float rTime) { assert(m_object->Implements(ObjectInterfaceType::Destroyable)); // TODO: implement "killer"? - dynamic_cast(m_object)->DestroyObject(DestructionType::Explosion); + dynamic_cast(*m_object).DestroyObject(DestructionType::Explosion); } } else { - if (obj->GetType() == OBJECT_MOBILErs && dynamic_cast(obj)->GetActiveShieldRadius() > 0.0f) // protected by shield? + if (obj->GetType() == OBJECT_MOBILErs && dynamic_cast(*obj).GetActiveShieldRadius() > 0.0f) // protected by shield? { m_particle->CreateParticle(pos, Math::Vector(0.0f, 0.0f, 0.0f), Math::Point(6.0f, 6.0f), PARTIGUNDEL, 2.0f, 0.0f, 0.0f); @@ -2316,7 +2376,7 @@ void CPyro::FallProgress(float rTime) else { assert(obj->Implements(ObjectInterfaceType::Damageable)); - if (dynamic_cast(obj)->DamageObject(DamageType::FallingObject)) + if (dynamic_cast(*obj).DamageObject(DamageType::FallingObject)) { DeleteObject(true, true); // removes the ball } @@ -2324,7 +2384,7 @@ void CPyro::FallProgress(float rTime) { assert(m_object->Implements(ObjectInterfaceType::Destroyable)); // TODO: implement "killer"? - dynamic_cast(m_object)->DestroyObject(DestructionType::Explosion); + dynamic_cast(*m_object).DestroyObject(DestructionType::Explosion); } } } diff --git a/src/graphics/engine/pyro.h b/src/graphics/engine/pyro.h index 34fd543c..84e29529 100644 --- a/src/graphics/engine/pyro.h +++ b/src/graphics/engine/pyro.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/pyro_manager.cpp b/src/graphics/engine/pyro_manager.cpp index bc194862..4ffd0c76 100644 --- a/src/graphics/engine/pyro_manager.cpp +++ b/src/graphics/engine/pyro_manager.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/pyro_manager.h b/src/graphics/engine/pyro_manager.h index 98940566..613e73fc 100644 --- a/src/graphics/engine/pyro_manager.h +++ b/src/graphics/engine/pyro_manager.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/pyro_type.h b/src/graphics/engine/pyro_type.h index ad2daffd..0336be71 100644 --- a/src/graphics/engine/pyro_type.h +++ b/src/graphics/engine/pyro_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -58,6 +58,8 @@ enum PyroType PT_DEADG = 24, //! < shooting death PT_DEADW = 25, //! < drowning death PT_FINDING = 26, //! < object discovered + PT_FRAGV = 27, //! < fragmentation of plant object + PT_SQUASH = 28, //! < flattening plants }; } // namespace Gfx diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index 23f1c226..07f8f956 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/terrain.h b/src/graphics/engine/terrain.h index 139a44dd..1d0fd685 100644 --- a/src/graphics/engine/terrain.h +++ b/src/graphics/engine/terrain.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/engine/text.cpp b/src/graphics/engine/text.cpp index df284160..fef37333 100644 --- a/src/graphics/engine/text.cpp +++ b/src/graphics/engine/text.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -191,17 +191,32 @@ CText::~CText() bool CText::Create() { - CFontLoader fontLoader; - if (!fontLoader.Init()) - { - GetLogger()->Warn("Error on parsing fonts config file: failed to open file\n"); - } if (TTF_Init() != 0) { m_error = std::string("TTF_Init error: ") + std::string(TTF_GetError()); return false; } + if (!ReloadFonts()) + { + return false; + } + + return true; +} + +bool CText::ReloadFonts() +{ + CFontLoader fontLoader; + if (!fontLoader.Init()) + { + GetLogger()->Debug("Error on parsing fonts config file: failed to open file\n"); + } + + // Backup previous fonts + auto fonts = std::move(m_fonts); + m_fonts.clear(); + for (auto type : {FONT_COMMON, FONT_STUDIO, FONT_SATCOM}) { m_fonts[static_cast(type)] = MakeUnique(fontLoader.GetFont(type)); @@ -214,7 +229,10 @@ bool CText::Create() FontType type = (*it).first; CachedFont* cf = GetOrOpenFont(type, m_defaultSize); if (cf == nullptr || cf->font == nullptr) + { + m_fonts = std::move(fonts); return false; + } } return true; @@ -430,7 +448,7 @@ float CText::GetStringWidth(const std::string &text, UTF8Char ch; - int len = StrUtils::Utf8CharSizeAt(text, index); + int len = GetCharSizeAt(font, text, index); if (len >= 1) ch.c1 = text[index]; if (len >= 2) @@ -441,7 +459,7 @@ float CText::GetStringWidth(const std::string &text, width += GetCharWidth(ch, font, size, width); index += len; - fmtIndex++; + fmtIndex += len; } return width; @@ -565,7 +583,7 @@ int CText::Justify(const std::string &text, std::vector::iterator UTF8Char ch; - int len = StrUtils::Utf8CharSizeAt(text, index); + int len = GetCharSizeAt(font, text, index); if (len >= 1) ch.c1 = text[index]; if (len >= 2) @@ -589,7 +607,7 @@ int CText::Justify(const std::string &text, std::vector::iterator } index += len; - fmtIndex++; + fmtIndex += len; } return index; @@ -606,7 +624,7 @@ int CText::Justify(const std::string &text, FontType font, float size, float wid { UTF8Char ch; - int len = StrUtils::Utf8CharSizeAt(text, index); + int len = GetCharSizeAt(font, text, index); if (len >= 1) ch.c1 = text[index]; if (len >= 2) @@ -648,12 +666,9 @@ int CText::Detect(const std::string &text, std::vector::iterator f if (format + fmtIndex != end) font = static_cast(*(format + fmtIndex) & FONT_MASK_FONT); - // TODO: if (font == FONT_BUTTON) - //if (font == FONT_BUTTON) continue; - UTF8Char ch; - int len = StrUtils::Utf8CharSizeAt(text, index); + int len = GetCharSizeAt(font, text, index); if (len >= 1) ch.c1 = text[index]; if (len >= 2) @@ -670,7 +685,7 @@ int CText::Detect(const std::string &text, std::vector::iterator f pos += width; index += len; - fmtIndex++; + fmtIndex += len; } return index; @@ -686,7 +701,7 @@ int CText::Detect(const std::string &text, FontType font, float size, float offs { UTF8Char ch; - int len = StrUtils::Utf8CharSizeAt(text, index); + int len = GetCharSizeAt(font, text, index); if (len >= 1) ch.c1 = text[index]; if (len >= 2) @@ -898,16 +913,7 @@ void CText::StringToUTFCharList(const std::string &text, std::vector & if (format + index != end) font = static_cast(*(format + index) & FONT_MASK_FONT); - int len; - - if(font == FONT_BUTTON) - { - len = 1; - } - else - { - len = StrUtils::Utf8CharSizeAt(text, index); - } + int len = GetCharSizeAt(font, text, index); if (len >= 1) ch.c1 = text[index]; @@ -922,6 +928,20 @@ void CText::StringToUTFCharList(const std::string &text, std::vector & } } +int CText::GetCharSizeAt(Gfx::FontType font, const std::string& text, unsigned int index) const +{ + int len = 0; + if (font == FONT_BUTTON) + { + len = 1; + } + else + { + len = StrUtils::Utf8CharSizeAt(text, index); + } + return len; +} + void CText::DrawString(const std::string &text, FontType font, float size, Math::IntPoint pos, int width, int eol, Color color) { diff --git a/src/graphics/engine/text.h b/src/graphics/engine/text.h index 0405c7d2..dc1be3db 100644 --- a/src/graphics/engine/text.h +++ b/src/graphics/engine/text.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -256,6 +256,8 @@ public: //! Flushes cached textures void FlushCache(); + //! Try to load new font files + bool ReloadFonts(); //@{ //! Tab size management @@ -337,6 +339,8 @@ protected: void StringToUTFCharList(const std::string &text, std::vector &chars); void StringToUTFCharList(const std::string &text, std::vector &chars, std::vector::iterator format, std::vector::iterator end); + int GetCharSizeAt(Gfx::FontType font, const std::string& text, unsigned int index) const; + protected: CEngine* m_engine; CDevice* m_device; diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index a890e377..b824c280 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -566,6 +566,10 @@ float CWater::GetLevel(CObject* object) type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEwc || @@ -588,6 +592,8 @@ float CWater::GetLevel(CObject* object) type == OBJECT_MOBILEtt || type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEst || type == OBJECT_MOBILEdr ) { return m_level-2.0f; diff --git a/src/graphics/engine/water.h b/src/graphics/engine/water.h index f2373d69..3c1b7611 100644 --- a/src/graphics/engine/water.h +++ b/src/graphics/engine/water.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model.cpp b/src/graphics/model/model.cpp index a5cf9351..e03986c3 100644 --- a/src/graphics/model/model.cpp +++ b/src/graphics/model/model.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model.h b/src/graphics/model/model.h index 26e19bde..a3f323a5 100644 --- a/src/graphics/model/model.h +++ b/src/graphics/model/model.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_crash_sphere.h b/src/graphics/model/model_crash_sphere.h index 8617c605..535c394f 100644 --- a/src/graphics/model/model_crash_sphere.h +++ b/src/graphics/model/model_crash_sphere.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_format.h b/src/graphics/model/model_format.h index afac0b36..32171fda 100644 --- a/src/graphics/model/model_format.h +++ b/src/graphics/model/model_format.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_input.cpp b/src/graphics/model/model_input.cpp index a7a73544..33bc2419 100644 --- a/src/graphics/model/model_input.cpp +++ b/src/graphics/model/model_input.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_input.h b/src/graphics/model/model_input.h index 415a0e33..161ed3d5 100644 --- a/src/graphics/model/model_input.h +++ b/src/graphics/model/model_input.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_io_exception.h b/src/graphics/model/model_io_exception.h index 1831bdfe..8095e996 100644 --- a/src/graphics/model/model_io_exception.h +++ b/src/graphics/model/model_io_exception.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_io_structs.h b/src/graphics/model/model_io_structs.h index 5646bafd..b5e1f8eb 100644 --- a/src/graphics/model/model_io_structs.h +++ b/src/graphics/model/model_io_structs.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_manager.cpp b/src/graphics/model/model_manager.cpp index aa424fe1..a2652645 100644 --- a/src/graphics/model/model_manager.cpp +++ b/src/graphics/model/model_manager.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_manager.h b/src/graphics/model/model_manager.h index b0cb1520..bb78a24d 100644 --- a/src/graphics/model/model_manager.h +++ b/src/graphics/model/model_manager.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_mesh.cpp b/src/graphics/model/model_mesh.cpp index 0de7d3a5..fa96b299 100644 --- a/src/graphics/model/model_mesh.cpp +++ b/src/graphics/model/model_mesh.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_mesh.h b/src/graphics/model/model_mesh.h index 3a5a7d5f..e375a590 100644 --- a/src/graphics/model/model_mesh.h +++ b/src/graphics/model/model_mesh.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_output.cpp b/src/graphics/model/model_output.cpp index ef94a3a5..e15d447d 100644 --- a/src/graphics/model/model_output.cpp +++ b/src/graphics/model/model_output.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_output.h b/src/graphics/model/model_output.h index 9bdfab67..dbad3e13 100644 --- a/src/graphics/model/model_output.h +++ b/src/graphics/model/model_output.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_shadow_spot.h b/src/graphics/model/model_shadow_spot.h index 7a46c456..98d6ae76 100644 --- a/src/graphics/model/model_shadow_spot.h +++ b/src/graphics/model/model_shadow_spot.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/model/model_triangle.h b/src/graphics/model/model_triangle.h index 74a61677..ef96eeea 100644 --- a/src/graphics/model/model_triangle.h +++ b/src/graphics/model/model_triangle.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/gl14device.cpp b/src/graphics/opengl/gl14device.cpp index 3a8b6dca..90f2e8f5 100644 --- a/src/graphics/opengl/gl14device.cpp +++ b/src/graphics/opengl/gl14device.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/gl14device.h b/src/graphics/opengl/gl14device.h index 39785efd..f0e7e950 100644 --- a/src/graphics/opengl/gl14device.h +++ b/src/graphics/opengl/gl14device.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/gl21device.cpp b/src/graphics/opengl/gl21device.cpp index 41660578..e0782271 100644 --- a/src/graphics/opengl/gl21device.cpp +++ b/src/graphics/opengl/gl21device.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -388,6 +388,7 @@ bool CGL21Device::Create() uni.modelMatrix = glGetUniformLocation(m_normalProgram, "uni_ModelMatrix"); uni.normalMatrix = glGetUniformLocation(m_normalProgram, "uni_NormalMatrix"); uni.shadowMatrix = glGetUniformLocation(m_normalProgram, "uni_ShadowMatrix"); + uni.cameraPosition = glGetUniformLocation(m_normalProgram, "uni_CameraPosition"); uni.primaryTexture = glGetUniformLocation(m_normalProgram, "uni_PrimaryTexture"); uni.secondaryTexture = glGetUniformLocation(m_normalProgram, "uni_SecondaryTexture"); @@ -408,6 +409,7 @@ bool CGL21Device::Create() uni.fogColor = glGetUniformLocation(m_normalProgram, "uni_FogColor"); uni.shadowColor = glGetUniformLocation(m_normalProgram, "uni_ShadowColor"); + uni.shadowTexelSize = glGetUniformLocation(m_normalProgram, "uni_ShadowTexelSize"); uni.lightCount = glGetUniformLocation(m_normalProgram, "uni_LightCount"); uni.ambientColor = glGetUniformLocation(m_normalProgram, "uni_Material.ambient"); @@ -441,6 +443,7 @@ bool CGL21Device::Create() glUniformMatrix4fv(uni.modelMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni.normalMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni.shadowMatrix, 1, GL_FALSE, matrix.Array()); + glUniform3f(uni.cameraPosition, 0.0f, 0.0f, 0.0f); glUniform1i(uni.primaryTexture, 0); glUniform1i(uni.secondaryTexture, 1); @@ -457,6 +460,7 @@ bool CGL21Device::Create() glUniform4f(uni.fogColor, 0.8f, 0.8f, 0.8f, 1.0f); glUniform1f(uni.shadowColor, 0.5f); + glUniform1f(uni.shadowTexelSize, 0.5f); glUniform1i(uni.lightCount, 0); } @@ -653,6 +657,7 @@ void CGL21Device::SetTransform(TransformType type, const Math::Matrix &matrix) else if (type == TRANSFORM_VIEW) { Math::Matrix scale; + Math::Vector cameraPosition; scale.Set(3, 3, -1.0f); m_viewMat = Math::MultiplyMatrices(scale, matrix); @@ -660,6 +665,13 @@ void CGL21Device::SetTransform(TransformType type, const Math::Matrix &matrix) m_combinedMatrix = Math::MultiplyMatrices(m_projectionMat, m_modelviewMat); glUniformMatrix4fv(m_uniforms[m_mode].viewMatrix, 1, GL_FALSE, m_viewMat.Array()); + + if (m_uniforms[m_mode].cameraPosition >= 0) + { + cameraPosition.LoadZero(); + cameraPosition = MatrixVectorMultiply(m_viewMat.Inverse(), cameraPosition); + glUniform3fv(m_uniforms[m_mode].cameraPosition, 1, cameraPosition.Array()); + } } else if (type == TRANSFORM_PROJECTION) { @@ -1439,6 +1451,7 @@ void CGL21Device::SetRenderState(RenderState state, bool enabled) } else if (state == RENDER_STATE_SHADOW_MAPPING) { + glUniform1f(m_uniforms[m_mode].shadowTexelSize, 1.0/m_currentTextures[TEXTURE_SHADOW].size.x); SetTextureEnabled(TEXTURE_SHADOW, enabled); return; diff --git a/src/graphics/opengl/gl21device.h b/src/graphics/opengl/gl21device.h index 873afdf7..52af3f04 100644 --- a/src/graphics/opengl/gl21device.h +++ b/src/graphics/opengl/gl21device.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/gl33device.cpp b/src/graphics/opengl/gl33device.cpp index 0180f247..bd26d35b 100644 --- a/src/graphics/opengl/gl33device.cpp +++ b/src/graphics/opengl/gl33device.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -363,6 +363,7 @@ bool CGL33Device::Create() uni.modelMatrix = glGetUniformLocation(m_normalProgram, "uni_ModelMatrix"); uni.normalMatrix = glGetUniformLocation(m_normalProgram, "uni_NormalMatrix"); uni.shadowMatrix = glGetUniformLocation(m_normalProgram, "uni_ShadowMatrix"); + uni.cameraPosition = glGetUniformLocation(m_normalProgram, "uni_CameraPosition"); uni.primaryTexture = glGetUniformLocation(m_normalProgram, "uni_PrimaryTexture"); uni.secondaryTexture = glGetUniformLocation(m_normalProgram, "uni_SecondaryTexture"); @@ -420,6 +421,7 @@ bool CGL33Device::Create() glUniformMatrix4fv(uni.modelMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni.normalMatrix, 1, GL_FALSE, matrix.Array()); glUniformMatrix4fv(uni.shadowMatrix, 1, GL_FALSE, matrix.Array()); + glUniform3f(uni.cameraPosition, 0.0f, 0.0f, 0.0f); glUniform1i(uni.primaryTexture, 0); glUniform1i(uni.secondaryTexture, 1); @@ -660,6 +662,7 @@ void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix) else if (type == TRANSFORM_VIEW) { Math::Matrix scale; + Math::Vector cameraPosition; scale.Set(3, 3, -1.0f); m_viewMat = Math::MultiplyMatrices(scale, matrix); @@ -667,6 +670,13 @@ void CGL33Device::SetTransform(TransformType type, const Math::Matrix &matrix) m_combinedMatrixOutdated = true; glUniformMatrix4fv(m_uni->viewMatrix, 1, GL_FALSE, m_viewMat.Array()); + + if (m_uni->cameraPosition >= 0) + { + cameraPosition.LoadZero(); + cameraPosition = MatrixVectorMultiply(m_viewMat.Inverse(), cameraPosition); + glUniform3fv(m_uni->cameraPosition, 1, cameraPosition.Array()); + } } else if (type == TRANSFORM_PROJECTION) { @@ -876,6 +886,8 @@ void CGL33Device::UpdateTexture(const Texture& texture, Math::IntPoint offset, I glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, texData.actualSurface->w, texData.actualSurface->h, texData.sourceFormat, GL_UNSIGNED_BYTE, texData.actualSurface->pixels); + glGenerateMipmap(GL_TEXTURE_2D); + SDL_FreeSurface(texData.convertedSurface); } diff --git a/src/graphics/opengl/gl33device.h b/src/graphics/opengl/gl33device.h index 7b3aa26a..5fcd4e2a 100644 --- a/src/graphics/opengl/gl33device.h +++ b/src/graphics/opengl/gl33device.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/glframebuffer.cpp b/src/graphics/opengl/glframebuffer.cpp index 75fe020a..41ce771a 100644 --- a/src/graphics/opengl/glframebuffer.cpp +++ b/src/graphics/opengl/glframebuffer.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/glframebuffer.h b/src/graphics/opengl/glframebuffer.h index 4e3dff76..13c85d04 100644 --- a/src/graphics/opengl/glframebuffer.h +++ b/src/graphics/opengl/glframebuffer.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/glutil.cpp b/src/graphics/opengl/glutil.cpp index 0060b4db..fabce21c 100644 --- a/src/graphics/opengl/glutil.cpp +++ b/src/graphics/opengl/glutil.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/graphics/opengl/glutil.h b/src/graphics/opengl/glutil.h index 977bc9c3..f92888a4 100644 --- a/src/graphics/opengl/glutil.h +++ b/src/graphics/opengl/glutil.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -167,6 +167,8 @@ struct UniformLocations GLint shadowMatrix = -1; //! Normal matrix GLint normalMatrix = -1; + //! Camera position + GLint cameraPosition = -1; //! Primary texture sampler GLint primaryTexture = -1; @@ -193,6 +195,8 @@ struct UniformLocations //! Shadow color GLint shadowColor = -1; + //! Shadow texel size + GLint shadowTexelSize = -1; // Number of enabled lights GLint lightCount = -1; diff --git a/src/graphics/opengl/shaders/gl21/fs_normal.glsl b/src/graphics/opengl/shaders/gl21/fs_normal.glsl index d21bc9cf..1aeffcbe 100644 --- a/src/graphics/opengl/shaders/gl21/fs_normal.glsl +++ b/src/graphics/opengl/shaders/gl21/fs_normal.glsl @@ -35,6 +35,7 @@ uniform vec2 uni_FogRange; uniform vec4 uni_FogColor; uniform float uni_ShadowColor; +uniform float uni_ShadowTexelSize; struct LightParams { @@ -56,6 +57,7 @@ uniform Material uni_Material; uniform int uni_LightCount; uniform LightParams uni_Light[4]; +varying vec3 pass_CameraDirection; varying float pass_Distance; varying vec4 pass_Color; varying vec3 pass_Normal; @@ -76,16 +78,17 @@ void main() vec4 specular = vec4(0.0f); vec3 normal = normalize(pass_Normal); + vec3 camera = normalize(pass_CameraDirection); for (int i = 0; i < uni_LightCount; i++) { LightParams light = uni_Light[i]; vec3 lightDirection = light.Position.xyz; - vec3 reflectDirection = -reflect(lightDirection, normal); + vec3 reflectAxis = normalize(normalize(lightDirection) + camera); float diffuseComponent = clamp(dot(normal, lightDirection), 0.0f, 1.0f); - float specularComponent = clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f); + float specularComponent = pow(clamp(dot(normal, reflectAxis), 0.0f, 1.0f), 10.0f); ambient += light.Ambient; diffuse += diffuseComponent * light.Diffuse; @@ -97,13 +100,11 @@ void main() if (uni_TextureEnabled[2]) { #ifdef CONFIG_QUALITY_SHADOWS - float offset = 0.00025f; - float value = (1.0f / 5.0f) * (shadow2D(uni_ShadowTexture, pass_TexCoord2).x - + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( offset, 0.0f, 0.0f)).x - + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3(-offset, 0.0f, 0.0f)).x - + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( 0.0f, offset, 0.0f)).x - + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( 0.0f, -offset, 0.0f)).x); + + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( uni_ShadowTexelSize, 0.0f, 0.0f)).x + + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3(-uni_ShadowTexelSize, 0.0f, 0.0f)).x + + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( 0.0f, uni_ShadowTexelSize, 0.0f)).x + + shadow2D(uni_ShadowTexture, pass_TexCoord2 + vec3( 0.0f, -uni_ShadowTexelSize, 0.0f)).x); shadow = mix(uni_ShadowColor, 1.0f, value); #else diff --git a/src/graphics/opengl/shaders/gl21/vs_normal.glsl b/src/graphics/opengl/shaders/gl21/vs_normal.glsl index 9195cd20..41141c4b 100644 --- a/src/graphics/opengl/shaders/gl21/vs_normal.glsl +++ b/src/graphics/opengl/shaders/gl21/vs_normal.glsl @@ -24,7 +24,9 @@ uniform mat4 uni_ViewMatrix; uniform mat4 uni_ModelMatrix; uniform mat4 uni_ShadowMatrix; uniform mat4 uni_NormalMatrix; +uniform vec3 uni_CameraPosition; +varying vec3 pass_CameraDirection; varying float pass_Distance; varying vec4 pass_Color; varying vec3 pass_Normal; @@ -40,6 +42,7 @@ void main() gl_Position = uni_ProjectionMatrix * eyeSpace; + pass_CameraDirection = uni_CameraPosition - position.xyz; pass_Color = gl_Color; pass_Normal = normalize((uni_NormalMatrix * vec4(gl_Normal, 0.0f)).xyz); pass_Distance = abs(eyeSpace.z / eyeSpace.w); diff --git a/src/graphics/opengl/shaders/gl33/fs_normal.glsl b/src/graphics/opengl/shaders/gl33/fs_normal.glsl index e6fd1e07..be58f4fd 100644 --- a/src/graphics/opengl/shaders/gl33/fs_normal.glsl +++ b/src/graphics/opengl/shaders/gl33/fs_normal.glsl @@ -63,6 +63,7 @@ in VertexData vec4 ShadowCoord; vec4 LightColor; float Distance; + vec3 CameraDirection; } data; out vec4 out_FragColor; @@ -78,17 +79,17 @@ void main() vec4 specular = vec4(0.0f); vec3 normal = normalize(data.Normal); + vec3 camera = normalize(data.CameraDirection); for (int i = 0; i < uni_LightCount; i++) { vec3 lightDirection = uni_Light[i].Position.xyz; - - vec3 reflectDirection = -reflect(lightDirection, normal); + vec3 reflectAxis = normalize(normalize(lightDirection) + camera); ambient += uni_Light[i].Ambient; diffuse += clamp(dot(normal, lightDirection), 0.0f, 1.0f) * uni_Light[i].Diffuse; - specular += clamp(pow(dot(normal, lightDirection + reflectDirection), 10.0f), 0.0f, 1.0f) + specular += pow(clamp(dot(normal, reflectAxis), 0.0f, 1.0f), 10.0f) * uni_Light[i].Specular; } diff --git a/src/graphics/opengl/shaders/gl33/vs_normal.glsl b/src/graphics/opengl/shaders/gl33/vs_normal.glsl index aeed3c60..216682f7 100644 --- a/src/graphics/opengl/shaders/gl33/vs_normal.glsl +++ b/src/graphics/opengl/shaders/gl33/vs_normal.glsl @@ -25,6 +25,7 @@ uniform mat4 uni_ViewMatrix; uniform mat4 uni_ModelMatrix; uniform mat4 uni_ShadowMatrix; uniform mat4 uni_NormalMatrix; +uniform vec3 uni_CameraPosition; layout(location = 0) in vec4 in_VertexCoord; layout(location = 1) in vec3 in_Normal; @@ -41,6 +42,7 @@ out VertexData vec4 ShadowCoord; vec4 LightColor; float Distance; + vec3 CameraDirection; } data; void main() @@ -56,4 +58,5 @@ void main() data.Normal = normalize((uni_NormalMatrix * vec4(in_Normal, 0.0f)).xyz); data.ShadowCoord = vec4(shadowCoord.xyz / shadowCoord.w, 1.0f); data.Distance = abs(eyeSpace.z); + data.CameraDirection = uni_CameraPosition - position.xyz; } diff --git a/src/level/build_type.h b/src/level/build_type.h index 9ba6befd..26c595e4 100644 --- a/src/level/build_type.h +++ b/src/level/build_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -41,7 +41,8 @@ enum BuildType BUILD_LABO = (1<<10), //! < AutoLab BUILD_PARA = (1<<11), //! < PowerCaptor BUILD_INFO = (1<<12), //! < ExchangePost - BUILD_DESTROYER = (1<<13), //! < Destroyer + BUILD_SAFE = (1<<13), //! < Vault + BUILD_DESTROYER = (1<<14), //! < Destroyer BUILD_GFLAT = (1<<16), //! < checking flat ground BUILD_FLAG = (1<<17) //! < putting / removing flags }; diff --git a/src/level/level_category.cpp b/src/level/level_category.cpp index 6735b951..e34925a3 100644 --- a/src/level/level_category.cpp +++ b/src/level/level_category.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -25,10 +25,11 @@ // TODO: I'm not sure about "challenges" + "custom". It may be messing things up already right now. const std::map CATEGORY_DIR_MAP = { { LevelCategory::Missions, "missions" }, - { LevelCategory::FreeGame, "freemissions" }, + { LevelCategory::FreeGame, "free" }, { LevelCategory::Exercises, "exercises" }, { LevelCategory::Challenges, "challenges" }, { LevelCategory::CodeBattles, "battles" }, + { LevelCategory::GamePlus, "plus" }, { LevelCategory::CustomLevels, "custom" }, }; diff --git a/src/level/level_category.h b/src/level/level_category.h index 43ef5156..39920914 100644 --- a/src/level/level_category.h +++ b/src/level/level_category.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ enum class LevelCategory Missions, FreeGame, CodeBattles, + GamePlus, CustomLevels, Max, }; diff --git a/src/level/mainmovie.cpp b/src/level/mainmovie.cpp index 4aa4245a..6a34510d 100644 --- a/src/level/mainmovie.cpp +++ b/src/level/mainmovie.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -90,7 +90,7 @@ bool CMainMovie::Start(MainMovieType type, float time) } assert(pObj->Implements(ObjectInterfaceType::Movable)); - dynamic_cast(pObj)->GetMotion()->SetAction(MHS_SATCOM, 0.5f); // reads the SatCom + dynamic_cast(*pObj).GetMotion()->SetAction(MHS_SATCOM, 0.5f); // reads the SatCom m_camera->GetCamera(m_initialEye, m_initialLookat); m_camera->SetType(Gfx::CAM_TYPE_SCRIPT); @@ -110,7 +110,7 @@ bool CMainMovie::Start(MainMovieType type, float time) if ( pObj != nullptr ) { assert(pObj->Implements(ObjectInterfaceType::Movable)); - dynamic_cast(pObj)->GetMotion()->SetAction(-1); // finishes reading SatCom + dynamic_cast(*pObj).GetMotion()->SetAction(-1); // finishes reading SatCom } m_camera->SetType(Gfx::CAM_TYPE_BACK); @@ -132,7 +132,7 @@ bool CMainMovie::Stop() if ( pObj != nullptr ) { assert(pObj->Implements(ObjectInterfaceType::Movable)); - dynamic_cast(pObj)->GetMotion()->SetAction(-1); // finishes reading SatCom + dynamic_cast(*pObj).GetMotion()->SetAction(-1); // finishes reading SatCom } } diff --git a/src/level/mainmovie.h b/src/level/mainmovie.h index effd5ff6..c27971ef 100644 --- a/src/level/mainmovie.h +++ b/src/level/mainmovie.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/parser/parser.cpp b/src/level/parser/parser.cpp index 89152246..1bf78a24 100644 --- a/src/level/parser/parser.cpp +++ b/src/level/parser/parser.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -41,6 +41,7 @@ #include #include #include +#include CLevelParser::CLevelParser() { @@ -172,13 +173,28 @@ void CLevelParser::Load() boost::replace_all(line, "\t", " "); // replace tab by space // ignore comments - std::size_t comment = line.find("//"); - if (comment != std::string::npos) - line = line.substr(0, comment); + size_t pos = 0; + std::string linesuffix = line; + boost::regex commentRegex{ R"(("[^"]*")|('[^']*')|(//.*$))" }; + boost::smatch matches; + while (boost::regex_search(linesuffix, matches, commentRegex)) + { + if (matches[3].matched) + { + pos += std::distance(linesuffix.cbegin(), matches.prefix().second); + line = line.substr(0, pos); + linesuffix = ""; + } + else + { + pos += std::distance(linesuffix.cbegin(), matches.suffix().first); + linesuffix = matches.suffix().str(); + } + } boost::algorithm::trim(line); - std::size_t pos = line.find_first_of(" \t\n"); + pos = line.find_first_of(" \t\n"); std::string command = line.substr(0, pos); if (pos != std::string::npos) { diff --git a/src/level/parser/parser.h b/src/level/parser/parser.h index 08157119..7e06a367 100644 --- a/src/level/parser/parser.h +++ b/src/level/parser/parser.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/parser/parserexceptions.cpp b/src/level/parser/parserexceptions.cpp index 471b1158..4e301dd0 100644 --- a/src/level/parser/parserexceptions.cpp +++ b/src/level/parser/parserexceptions.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/parser/parserexceptions.h b/src/level/parser/parserexceptions.h index b9d40fd4..10a4054a 100644 --- a/src/level/parser/parserexceptions.h +++ b/src/level/parser/parserexceptions.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/parser/parserline.cpp b/src/level/parser/parserline.cpp index 59c85d21..bfe2fe0d 100644 --- a/src/level/parser/parserline.cpp +++ b/src/level/parser/parserline.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/parser/parserline.h b/src/level/parser/parserline.h index d9920824..21770659 100644 --- a/src/level/parser/parserline.h +++ b/src/level/parser/parserline.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/parser/parserparam.cpp b/src/level/parser/parserparam.cpp index c4ee9b31..159ab5f7 100644 --- a/src/level/parser/parserparam.cpp +++ b/src/level/parser/parserparam.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -340,6 +340,12 @@ ObjectType CLevelParserParam::ToObjectType(std::string value) if (value == "Portico" ) return OBJECT_PORTICO; if (value == "SpaceShip" ) return OBJECT_BASE; if (value == "PracticeBot" ) return OBJECT_MOBILEwt; + if (value == "WingedTrainer" ) return OBJECT_MOBILEft; + if (value == "TrackedTrainer" ) return OBJECT_MOBILEtt; + if (value == "WheeledTrainer" ) return OBJECT_MOBILEwt; + if (value == "LeggedTrainer" ) return OBJECT_MOBILEit; + if (value == "HeavyTrainer" ) return OBJECT_MOBILErp; + if (value == "AmphibiousTrainer" ) return OBJECT_MOBILEst; if (value == "WingedGrabber" ) return OBJECT_MOBILEfa; if (value == "TrackedGrabber" ) return OBJECT_MOBILEta; if (value == "WheeledGrabber" ) return OBJECT_MOBILEwa; @@ -356,6 +362,10 @@ ObjectType CLevelParserParam::ToObjectType(std::string value) if (value == "TrackedSniffer" ) return OBJECT_MOBILEts; if (value == "WheeledSniffer" ) return OBJECT_MOBILEws; if (value == "LeggedSniffer" ) return OBJECT_MOBILEis; + if (value == "WingedBuilder" ) return OBJECT_MOBILEfb; + if (value == "TrackedBuilder" ) return OBJECT_MOBILEtb; + if (value == "WheeledBuilder" ) return OBJECT_MOBILEwb; + if (value == "LeggedBuilder" ) return OBJECT_MOBILEib; if (value == "Thumper" ) return OBJECT_MOBILErt; if (value == "PhazerShooter" ) return OBJECT_MOBILErc; if (value == "Recycler" ) return OBJECT_MOBILErr; @@ -540,7 +550,12 @@ const std::string CLevelParserParam::FromObjectType(ObjectType value) { if (value == OBJECT_PORTICO ) return "Portico"; if (value == OBJECT_BASE ) return "SpaceShip"; - if (value == OBJECT_MOBILEwt ) return "PracticeBot"; + if (value == OBJECT_MOBILEwt ) return "WheeledTrainer"; + if (value == OBJECT_MOBILEft ) return "WingedTrainer"; + if (value == OBJECT_MOBILEtt ) return "TrackedTrainer"; + if (value == OBJECT_MOBILEit ) return "LeggedTrainer"; + if (value == OBJECT_MOBILErp ) return "HeavyTrainer"; + if (value == OBJECT_MOBILEst ) return "AmphibiousTrainer"; if (value == OBJECT_MOBILEfa ) return "WingedGrabber"; if (value == OBJECT_MOBILEta ) return "TrackedGrabber"; if (value == OBJECT_MOBILEwa ) return "WheeledGrabber"; @@ -557,6 +572,10 @@ const std::string CLevelParserParam::FromObjectType(ObjectType value) if (value == OBJECT_MOBILEts ) return "TrackedSniffer"; if (value == OBJECT_MOBILEws ) return "WheeledSniffer"; if (value == OBJECT_MOBILEis ) return "LeggedSniffer"; + if (value == OBJECT_MOBILEfb ) return "WingedBuilder"; + if (value == OBJECT_MOBILEtb ) return "TrackedBuilder"; + if (value == OBJECT_MOBILEwb ) return "WheeledBuilder"; + if (value == OBJECT_MOBILEib ) return "LeggedBuilder"; if (value == OBJECT_MOBILErt ) return "Thumper"; if (value == OBJECT_MOBILErc ) return "PhazerShooter"; if (value == OBJECT_MOBILErr ) return "Recycler"; @@ -750,12 +769,13 @@ ObjectType CLevelParserParam::AsObjectType(ObjectType def) DriveType CLevelParserParam::ToDriveType(std::string value) { - if (value == "Wheeled") return DriveType::Wheeled; - if (value == "Tracked") return DriveType::Tracked; - if (value == "Winged" ) return DriveType::Winged; - if (value == "Legged" ) return DriveType::Legged; - if (value == "BigTracked") return DriveType::BigTracked; - if (value == "Other" ) return DriveType::Other; + if (value == "Wheeled" ) return DriveType::Wheeled; + if (value == "Tracked" ) return DriveType::Tracked; + if (value == "Winged" ) return DriveType::Winged; + if (value == "Legged" ) return DriveType::Legged; + if (value == "Heavy" ) return DriveType::Heavy; + if (value == "Amphibious") return DriveType::Amphibious; + if (value == "Other" ) return DriveType::Other; return static_cast(Cast(value, "drive")); } @@ -780,6 +800,7 @@ ToolType CLevelParserParam::ToToolType(std::string value) if (value == "Sniffer" ) return ToolType::Sniffer; if (value == "Shooter" ) return ToolType::Shooter; if (value == "OrgaShooter") return ToolType::OrganicShooter; + if (value == "Builder" ) return ToolType::Builder; if (value == "Other" ) return ToolType::Other; return static_cast(Cast(value, "tool")); } @@ -864,6 +885,7 @@ int CLevelParserParam::ToBuildFlag(std::string value) if (value == "AutoLab" ) return BUILD_LABO; if (value == "PowerCaptor" ) return BUILD_PARA; if (value == "ExchangePost" ) return BUILD_INFO; + if (value == "Vault" ) return BUILD_SAFE; if (value == "Destroyer" ) return BUILD_DESTROYER; if (value == "FlatGround" ) return BUILD_GFLAT; if (value == "Flag" ) return BUILD_FLAG; @@ -900,6 +922,8 @@ int CLevelParserParam::ToResearchFlag(std::string value) if (value == "RECYCLER") return RESEARCH_RECYCLER; if (value == "SUBBER" ) return RESEARCH_SUBM; if (value == "SNIFFER" ) return RESEARCH_SNIFFER; + if (value == "BUILDER" ) return RESEARCH_BUILDER; + if (value == "TARGET" ) return RESEARCH_TARGET; /* /9j/4AAQSkZJRgABAQEAYABgAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/2wBDACAWGBwYFCAcGhwk * IiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBD diff --git a/src/level/parser/parserparam.h b/src/level/parser/parserparam.h index 62838dc7..ca16022d 100644 --- a/src/level/parser/parserparam.h +++ b/src/level/parser/parserparam.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/player_profile.cpp b/src/level/player_profile.cpp index 9abd20a8..cd7a1a3b 100644 --- a/src/level/player_profile.cpp +++ b/src/level/player_profile.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -478,13 +478,20 @@ std::vector CPlayerProfile::GetSavedSceneList() for (auto dir : saveDirs) { std::string savegameFile = GetSaveFile(dir+"/data.sav"); - if (CResourceManager::Exists(savegameFile)) + if (CResourceManager::Exists(savegameFile) && CResourceManager::GetFileSize(savegameFile) > 0) { CLevelParser levelParser(savegameFile); levelParser.Load(); CLevelParserLine* line = levelParser.GetIfDefined("Created"); int time = line != nullptr ? line->GetParam("date")->AsInt() : 0; - sortedSaveDirs[time] = SavedScene(GetSaveFile(dir), levelParser.Get("Title")->GetParam("text")->AsString()); + try + { + sortedSaveDirs[time] = SavedScene(GetSaveFile(dir), levelParser.Get("Title")->GetParam("text")->AsString()); + } + catch (CLevelParserException &e) + { + GetLogger()->Error("Error trying to load savegame title: %s\n", e.what()); + } } } diff --git a/src/level/player_profile.h b/src/level/player_profile.h index 46745677..9f50a323 100644 --- a/src/level/player_profile.h +++ b/src/level/player_profile.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/research_type.h b/src/level/research_type.h index add78a56..daa10916 100644 --- a/src/level/research_type.h +++ b/src/level/research_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -38,5 +38,7 @@ enum ResearchType RESEARCH_iGUN = (1<<9), //! < cannon of insects RESEARCH_RECYCLER = (1<<10), //! < recycler RESEARCH_SUBM = (1<<11), //! < submarine - RESEARCH_SNIFFER = (1<<12) //! < sniffer + RESEARCH_SNIFFER = (1<<12), //! < sniffer + RESEARCH_BUILDER = (1<<13), //! < builder + RESEARCH_TARGET = (1<<14) //! < target bot }; diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 58d90541..af04448c 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -320,6 +320,7 @@ std::string PhaseToString(Phase phase) if (phase == PHASE_APPERANCE) return "PHASE_APPERANCE"; if (phase == PHASE_MAIN_MENU) return "PHASE_MAIN_MENU"; if (phase == PHASE_LEVEL_LIST) return "PHASE_LEVEL_LIST"; + if (phase == PHASE_MOD_LIST) return "PHASE_MOD_LIST"; if (phase == PHASE_SIMUL) return "PHASE_SIMUL"; if (phase == PHASE_SETUPd) return "PHASE_SETUPd"; if (phase == PHASE_SETUPg) return "PHASE_SETUPg"; @@ -714,6 +715,12 @@ bool CRobotMain::ProcessEvent(Event &event) { m_focusPause = m_pause->ActivatePause(PAUSE_ENGINE); } + + if (m_settings->GetFocusLostMute()) + { + m_sound->SetAudioVolume(0); + m_sound->SetMusicVolume(0); + } return false; } @@ -725,6 +732,30 @@ bool CRobotMain::ProcessEvent(Event &event) m_pause->DeactivatePause(m_focusPause); m_focusPause = nullptr; } + + if (m_settings->GetFocusLostMute()) + { + int volume; + // Set music volume + if (GetConfigFile().GetIntProperty("Setup", "MusicVolume", volume)) + { + m_sound->SetMusicVolume(volume); + } + else + { + m_sound->SetMusicVolume(MAXVOLUME*3/4); + } + // Set audio volume + if (GetConfigFile().GetIntProperty("Setup", "AudioVolume", volume)) + { + m_sound->SetAudioVolume(volume); + } + else + { + m_sound->SetAudioVolume(MAXVOLUME); + } + } + return false; } @@ -1330,7 +1361,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd) { CObject* object = GetSelect(); if (object != nullptr && object->Implements(ObjectInterfaceType::Shielded)) - dynamic_cast(object)->SetMagnifyDamage(dynamic_cast(object)->GetMagnifyDamage()*0.1f); + dynamic_cast(*object).SetMagnifyDamage(dynamic_cast(*object).GetMagnifyDamage()*0.1f); return; } @@ -1338,7 +1369,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd) { CObject* object = GetSelect(); if (object != nullptr && object->Implements(ObjectInterfaceType::JetFlying)) - dynamic_cast(object)->SetRange(dynamic_cast(object)->GetRange()*10.0f); + dynamic_cast(*object).SetRange(dynamic_cast(*object).GetRange()*10.0f); return; } @@ -1363,16 +1394,16 @@ void CRobotMain::ExecuteCmd(const std::string& cmd) { if (object->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(object)->GetPower(); + CObject* power = dynamic_cast(*object).GetPower(); if (power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer)) - dynamic_cast(power)->SetEnergyLevel(1.0f); + dynamic_cast(*power).SetEnergyLevel(1.0f); } if (object->Implements(ObjectInterfaceType::Shielded)) - dynamic_cast(object)->SetShield(1.0f); + dynamic_cast(*object).SetShield(1.0f); if (object->Implements(ObjectInterfaceType::JetFlying)) - dynamic_cast(object)->SetReactorRange(1.0f); + dynamic_cast(*object).SetReactorRange(1.0f); } return; } @@ -1385,9 +1416,9 @@ void CRobotMain::ExecuteCmd(const std::string& cmd) { if (object->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(object)->GetPower(); + CObject* power = dynamic_cast(*object).GetPower(); if (power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer)) - dynamic_cast(power)->SetEnergyLevel(1.0f); + dynamic_cast(*power).SetEnergyLevel(1.0f); } } return; @@ -1397,7 +1428,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd) { CObject* object = GetSelect(); if (object != nullptr && object->Implements(ObjectInterfaceType::Shielded)) - dynamic_cast(object)->SetShield(1.0f); + dynamic_cast(*object).SetShield(1.0f); return; } @@ -1407,7 +1438,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd) if (object != nullptr) { if (object->Implements(ObjectInterfaceType::JetFlying)) - dynamic_cast(object)->SetReactorRange(1.0f); + dynamic_cast(*object).SetReactorRange(1.0f); } return; } @@ -1507,7 +1538,7 @@ void CRobotMain::StartDisplayInfo(int index, bool movie) if (!m_editLock && movie && !m_movie->IsExist() && human) { assert(obj->Implements(ObjectInterfaceType::Movable)); - if (dynamic_cast(obj)->GetMotion()->GetAction() == -1) + if (dynamic_cast(*obj).GetMotion()->GetAction() == -1) { m_movieInfoIndex = index; m_movie->Start(MM_SATCOMopen, 2.5f); @@ -1821,7 +1852,7 @@ CObject* CRobotMain::DeselectAll() void CRobotMain::SelectOneObject(CObject* obj, bool displayError) { assert(obj->Implements(ObjectInterfaceType::Controllable)); - dynamic_cast(obj)->SetSelect(true, displayError); + dynamic_cast(*obj).SetSelect(true, displayError); m_camera->SetControllingObject(obj); ObjectType type = obj->GetType(); @@ -1830,6 +1861,10 @@ void CRobotMain::SelectOneObject(CObject* obj, bool displayError) type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEwc || @@ -1851,10 +1886,12 @@ void CRobotMain::SelectOneObject(CObject* obj, bool displayError) type == OBJECT_MOBILEtt || type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEst || type == OBJECT_MOBILEdr || type == OBJECT_APOLLO2 ) { - m_camera->SetType(dynamic_cast(obj)->GetCameraType()); + m_camera->SetType(dynamic_cast(*obj).GetCameraType()); } else { @@ -1870,7 +1907,7 @@ bool CRobotMain::SelectObject(CObject* obj, bool displayError) if (m_movieLock || m_editLock) return false; if (m_movie->IsExist()) return false; if (obj != nullptr && - (!obj->Implements(ObjectInterfaceType::Controllable) || !(dynamic_cast(obj)->GetSelectable() || m_cheatSelectInsect))) return false; + (!obj->Implements(ObjectInterfaceType::Controllable) || !(dynamic_cast(*obj).GetSelectable() || m_cheatSelectInsect))) return false; if (m_missionType == MISSION_CODE_BATTLE && m_codeBattleStarted && m_codeBattleSpectator) { @@ -1946,7 +1983,7 @@ CObject* CRobotMain::GetSelect() for (CObject* obj : m_objMan->GetAllObjects()) { if (!obj->Implements(ObjectInterfaceType::Controllable)) continue; - if (dynamic_cast(obj)->GetSelect()) + if (dynamic_cast(*obj).GetSelect()) return obj; } return nullptr; @@ -1964,7 +2001,7 @@ CObject* CRobotMain::DetectObject(Math::Point pos) CObject* transporter = nullptr; if (obj->Implements(ObjectInterfaceType::Transportable)) - transporter = dynamic_cast(obj)->GetTransporter(); + transporter = dynamic_cast(*obj).GetTransporter(); if (transporter != nullptr && !transporter->GetDetectable()) continue; if (obj->GetProxyActivate()) continue; @@ -1972,14 +2009,14 @@ CObject* CRobotMain::DetectObject(Math::Point pos) CObject* target = obj; if (obj->Implements(ObjectInterfaceType::PowerContainer) && obj->Implements(ObjectInterfaceType::Transportable)) { - target = dynamic_cast(obj)->GetTransporter(); // battery connected + target = dynamic_cast(*obj).GetTransporter(); // battery connected if (target == nullptr) { target = obj; // standalone battery } else { - if (!target->Implements(ObjectInterfaceType::Powered) || dynamic_cast(target)->GetPower() != obj) + if (!target->Implements(ObjectInterfaceType::Powered) || dynamic_cast(*target).GetPower() != obj) { // transported, but not in the power slot target = obj; @@ -2009,7 +2046,7 @@ bool CRobotMain::DestroySelectedObject() m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, obj); - dynamic_cast(obj)->SetSelect(false); // deselects the object + dynamic_cast(*obj).SetSelect(false); // deselects the object m_camera->SetType(Gfx::CAM_TYPE_EXPLO); DeselectAll(); RemoveFromSelectionHistory(obj); @@ -2032,7 +2069,7 @@ void CRobotMain::HiliteClear() for (CObject* obj : m_objMan->GetAllObjects()) { if (!obj->Implements(ObjectInterfaceType::Controllable)) continue; - dynamic_cast(obj)->SetHighlight(false); + dynamic_cast(*obj).SetHighlight(false); } m_map->SetHighlight(nullptr); m_short->SetHighlight(nullptr); @@ -2092,12 +2129,12 @@ void CRobotMain::HiliteObject(Math::Point pos) } } - if (obj->Implements(ObjectInterfaceType::Controllable) && (dynamic_cast(obj)->GetSelectable() || m_cheatSelectInsect)) + if (obj->Implements(ObjectInterfaceType::Controllable) && (dynamic_cast(*obj).GetSelectable() || m_cheatSelectInsect)) { - if (dynamic_cast(obj)->GetSelectable()) + if (dynamic_cast(*obj).GetSelectable()) { // Don't highlight objects that would not be selectable without selectinsect - dynamic_cast(obj)->SetHighlight(true); + dynamic_cast(*obj).SetHighlight(true); } m_map->SetHighlight(obj); m_short->SetHighlight(obj); @@ -2211,6 +2248,10 @@ void CRobotMain::ChangeCamera() oType != OBJECT_MOBILEta && oType != OBJECT_MOBILEwa && oType != OBJECT_MOBILEia && + oType != OBJECT_MOBILEfb && + oType != OBJECT_MOBILEtb && + oType != OBJECT_MOBILEwb && + oType != OBJECT_MOBILEib && oType != OBJECT_MOBILEfc && oType != OBJECT_MOBILEtc && oType != OBJECT_MOBILEwc && @@ -2233,6 +2274,8 @@ void CRobotMain::ChangeCamera() oType != OBJECT_MOBILEtt && oType != OBJECT_MOBILEwt && oType != OBJECT_MOBILEit && + oType != OBJECT_MOBILErp && + oType != OBJECT_MOBILEst && oType != OBJECT_MOBILEdr && oType != OBJECT_APOLLO2 ) return; @@ -2348,7 +2391,7 @@ bool CRobotMain::EventFrame(const Event &event) if (obj->GetType() == OBJECT_TOTO) toto = obj; else if (obj->Implements(ObjectInterfaceType::Interactive)) - dynamic_cast(obj)->EventProcess(event); + dynamic_cast(*obj).EventProcess(event); if ( obj->GetProxyActivate() ) // active if it is near? { @@ -2371,7 +2414,7 @@ bool CRobotMain::EventFrame(const Event &event) continue; if (obj->Implements(ObjectInterfaceType::Interactive)) - dynamic_cast(obj)->EventProcess(event); + dynamic_cast(*obj).EventProcess(event); } m_engine->GetPyroManager()->EventProcess(event); @@ -2395,7 +2438,7 @@ bool CRobotMain::EventFrame(const Event &event) // Advances toto following the camera, because its position depends on the camera. if (toto != nullptr) - dynamic_cast(toto)->EventProcess(event); + dynamic_cast(*toto).EventProcess(event); // NOTE: m_movieLock is set only after the first update of CAutoBase finishes @@ -2419,6 +2462,7 @@ bool CRobotMain::EventFrame(const Event &event) { if (m_levelCategory == LevelCategory::Missions || m_levelCategory == LevelCategory::FreeGame || + m_levelCategory == LevelCategory::GamePlus || m_levelCategory == LevelCategory::CustomLevels) { if (!IOIsBusy() && m_missionType != MISSION_CODE_BATTLE) @@ -2628,7 +2672,7 @@ bool CRobotMain::EventObject(const Event &event) { if (obj->Implements(ObjectInterfaceType::Interactive)) { - dynamic_cast(obj)->EventProcess(event); + dynamic_cast(*obj).EventProcess(event); } } @@ -2669,7 +2713,7 @@ void CRobotMain::ScenePerso() obj->SetDrawFront(true); // draws the interface assert(obj->Implements(ObjectInterfaceType::Movable)); - CMotionHuman* mh = static_cast(dynamic_cast(obj)->GetMotion()); + CMotionHuman* mh = static_cast(dynamic_cast(*obj).GetMotion()); mh->StartDisplayPerso(); } } @@ -3107,6 +3151,8 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) m_missionType = line->GetParam("type")->AsMissionType(MISSION_NORMAL); m_globalMagnifyDamage = line->GetParam("magnifyDamage")->AsFloat(1.0f); + m_globalNuclearCapacity = line->GetParam("nuclearCapacity")->AsFloat(10.0f); + m_globalCellCapacity = line->GetParam("cellCapacity")->AsFloat(1.0f); continue; } @@ -3337,7 +3383,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) assert(m_controller->Implements(ObjectInterfaceType::ProgramStorage)); assert(m_controller->Implements(ObjectInterfaceType::Old)); - dynamic_cast(m_controller)->SetCheckToken(false); + dynamic_cast(*m_controller).SetCheckToken(false); if (line->GetParam("script")->IsDefined()) { @@ -3345,7 +3391,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) Program* program = programStorage->AddProgram(); programStorage->ReadProgram(program, line->GetParam("script")->AsPath("ai")); program->readOnly = true; - dynamic_cast(m_controller)->RunProgram(program); + dynamic_cast(*m_controller).RunProgram(program); } continue; } @@ -3370,7 +3416,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (m_fixScene && obj->GetType() == OBJECT_HUMAN) { assert(obj->Implements(ObjectInterfaceType::Movable)); - CMotion* motion = dynamic_cast(obj)->GetMotion(); + CMotion* motion = dynamic_cast(*obj).GetMotion(); if (m_phase == PHASE_WIN ) motion->SetAction(MHS_WIN, 0.4f); if (m_phase == PHASE_LOST) motion->SetAction(MHS_LOST, 0.5f); } @@ -3385,7 +3431,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) { CProgramStorageObject* programStorage = dynamic_cast(obj); - if (obj->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(obj)->GetSelectable() && obj->GetType() != OBJECT_HUMAN) + if (obj->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(*obj).GetSelectable() && obj->GetType() != OBJECT_HUMAN) { programStorage->SetProgramStorageIndex(rankObj); } @@ -3739,6 +3785,12 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) m_build |= BUILD_FLAG; } + if (m_levelCategory == LevelCategory::GamePlus && !m_ui->GetPlusResearch() && !resetObject) // new game plus? + { + m_researchDone[0] |= m_playerProfile->GetFreeGameResearchUnlock(); + m_build |= m_playerProfile->GetFreeGameBuildUnlock(); + } + if (!resetObject) { m_short->SetMode(false); // vehicles? @@ -3768,7 +3820,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) assert(obj->Implements(ObjectInterfaceType::Controllable)); SelectObject(obj); m_camera->SetControllingObject(obj); - m_camera->SetType(dynamic_cast(obj)->GetCameraType()); + m_camera->SetType(dynamic_cast(*obj).GetCameraType()); } } @@ -3869,6 +3921,7 @@ void CRobotMain::ChangeColor() m_phase != PHASE_SETUPps && m_phase != PHASE_SETUPcs && m_phase != PHASE_SETUPss && + m_phase != PHASE_MOD_LIST && m_phase != PHASE_WIN && m_phase != PHASE_LOST && m_phase != PHASE_APPERANCE ) return; @@ -3971,6 +4024,7 @@ void CRobotMain::ChangeColor() m_engine->ChangeTextureColor("textures/objects/lemt.png"+teamStr, "textures/objects/lemt.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); m_engine->ChangeTextureColor("textures/objects/roller.png"+teamStr, "textures/objects/roller.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); m_engine->ChangeTextureColor("textures/objects/search.png"+teamStr, "textures/objects/search.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + m_engine->ChangeTextureColor("textures/objects/rollert.png"+teamStr, "textures/objects/rollert.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); exclu[0] = Math::Point( 0.0f/256.0f, 160.0f/256.0f); exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // pencils @@ -4363,7 +4417,7 @@ void CRobotMain::StartShowLimit() CObject* obj = GetSelect(); if (obj == nullptr) return; if (!obj->Implements(ObjectInterfaceType::Ranged)) return; - float range = dynamic_cast(obj)->GetShowLimitRadius(); + float range = dynamic_cast(*obj).GetShowLimitRadius(); if (range == 0.0f) return; SetShowLimit(0, Gfx::PARTILIMIT1, obj, obj->GetPosition(), range); } @@ -4449,10 +4503,8 @@ void CRobotMain::SaveOneScript(CObject *obj) } //! Saves the stack of the program in execution of a robot -bool CRobotMain::SaveFileStack(CObject *obj, FILE *file, int objRank) +bool CRobotMain::SaveFileStack(CObject *obj, std::ostream &ostr) { - if (objRank == -1) return true; - if (! obj->Implements(ObjectInterfaceType::Programmable)) return true; CProgrammableObject* programmable = dynamic_cast(obj); @@ -4460,14 +4512,24 @@ bool CRobotMain::SaveFileStack(CObject *obj, FILE *file, int objRank) ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return true; - return programmable->WriteStack(file); + long status = 1; + std::stringstream sstr(""); + + if (!programmable->WriteStack(sstr)) + { + GetLogger()->Error("WriteStack failed at object id = %i\n", obj->GetID()); + status = 100; // marked bad + } + + if (!CBot::WriteLong(ostr, status)) return false; + if (!CBot::WriteStream(ostr, sstr)) return false; + + return true; } //! Resumes the execution stack of the program in a robot -bool CRobotMain::ReadFileStack(CObject *obj, FILE *file, int objRank) +bool CRobotMain::ReadFileStack(CObject *obj, std::istream &istr) { - if (objRank == -1) return true; - if (! obj->Implements(ObjectInterfaceType::Programmable)) return true; CProgrammableObject* programmable = dynamic_cast(obj); @@ -4475,7 +4537,29 @@ bool CRobotMain::ReadFileStack(CObject *obj, FILE *file, int objRank) ObjectType type = obj->GetType(); if (type == OBJECT_HUMAN) return true; - return programmable->ReadStack(file); + long status; + if (!CBot::ReadLong(istr, status)) return false; + + if (status == 100) // was marked bad ? + { + if (!CBot::ReadLong(istr, status)) return false; + if (!istr.seekg(status, istr.cur)) return false; + return true; // next program + } + + if (status == 1) + { + std::stringstream sstr(""); + if (!CBot::ReadStream(istr, sstr)) return false; + + if (!programmable->ReadStack(sstr)) + { + GetLogger()->Error("ReadStack failed at object id = %i\n", obj->GetID()); + } + return true; // next program + } + + return false; // error: status == ?? } std::vector CRobotMain::GetNewScriptNames(ObjectType type) @@ -4503,8 +4587,8 @@ bool CRobotMain::IOIsBusy() { if (! obj->Implements(ObjectInterfaceType::TaskExecutor)) continue; - if (obj->Implements(ObjectInterfaceType::Programmable) && dynamic_cast(obj)->IsProgram()) continue; // TODO: I'm not sure if this is correct but this is how it worked earlier - if (dynamic_cast(obj)->IsForegroundTask()) return true; + if (obj->Implements(ObjectInterfaceType::Programmable) && dynamic_cast(*obj).IsProgram()) continue; // TODO: I'm not sure if this is correct but this is how it worked earlier + if (dynamic_cast(*obj).IsForegroundTask()) return true; } return false; } @@ -4555,7 +4639,7 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj, const std:: if (obj->Implements(ObjectInterfaceType::Programmable)) { - int run = dynamic_cast(obj)->GetProgramIndex(dynamic_cast(obj)->GetCurrentProgram()); + int run = dynamic_cast(*obj).GetProgramIndex(dynamic_cast(*obj).GetCurrentProgram()); if (run != -1) { line->AddParam("run", MakeUnique(run+1)); @@ -4630,11 +4714,11 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s { if (obj->GetType() == OBJECT_TOTO) continue; if (IsObjectBeingTransported(obj)) continue; - if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(obj)->IsDying()) continue; + if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(*obj).IsDying()) continue; if (obj->Implements(ObjectInterfaceType::Carrier)) { - CObject* cargo = dynamic_cast(obj)->GetCargo(); + CObject* cargo = dynamic_cast(*obj).GetCargo(); if (cargo != nullptr) // object transported? { line = MakeUnique("CreateFret"); @@ -4645,7 +4729,7 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s if (obj->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(obj)->GetPower(); + CObject* power = dynamic_cast(*obj).GetPower(); if (power != nullptr) // battery transported? { line = MakeUnique("CreatePower"); @@ -4665,30 +4749,41 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s } catch (CLevelParserException& e) { - GetLogger()->Error("Failed to save level state - %s\n", e.what()); + GetLogger()->Error("Failed to save level state - %s\n", e.what()); // TODO add visual error to notify user that save failed return false; } // Writes the file of stacks of execution. - FILE* file = CBot::fOpen((CResourceManager::GetSaveLocation() + "/" + filecbot).c_str(), "wb"); - if (file == nullptr) return false; + COutputStream ostr(filecbot); + if (!ostr.is_open()) return false; + bool bError = false; long version = 1; - CBot::fWrite(&version, sizeof(long), 1, file); // version of COLOBOT + CBot::WriteLong(ostr, version); // version of COLOBOT version = CBot::CBotProgram::GetVersion(); - CBot::fWrite(&version, sizeof(long), 1, file); // version of CBOT + CBot::WriteLong(ostr, version); // version of CBOT + CBot::WriteWord(ostr, 0); // TODO - objRank = 0; for (CObject* obj : m_objMan->GetAllObjects()) { if (obj->GetType() == OBJECT_TOTO) continue; if (IsObjectBeingTransported(obj)) continue; - if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(obj)->IsDying()) continue; + if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(*obj).IsDying()) continue; - if (!SaveFileStack(obj, file, objRank++)) break; + if (!SaveFileStack(obj, ostr)) + { + GetLogger()->Error("SaveFileStack failed at object id = %i\n", obj->GetID()); + bError = true; + break; + } } - CBot::CBotClass::SaveStaticState(file); - CBot::fClose(file); + + if (!bError && !CBot::CBotClass::SaveStaticState(ostr)) + { + GetLogger()->Error("CBotClass save static state failed\n"); + } + + ostr.close(); if (!emergencySave) { @@ -4699,7 +4794,7 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s m_engine->SetScreenshotMode(true); m_engine->Render(); // update (but don't show, we're not swapping buffers here!) - m_engine->WriteScreenShot(CResourceManager::GetSaveLocation() + "/" + filescreenshot); //TODO: Use PHYSFS? + m_engine->WriteScreenShot(filescreenshot); m_shotSaving++; m_engine->SetScreenshotMode(false); @@ -4824,7 +4919,7 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot) { assert(obj->Implements(ObjectInterfaceType::Carrier)); // TODO: exception? assert(obj->Implements(ObjectInterfaceType::Old)); - dynamic_cast(obj)->SetCargo(cargo); + dynamic_cast(*obj).SetCargo(cargo); auto task = MakeUnique(dynamic_cast(obj)); task->Start(TMO_AUTO, TMA_GRAB); // holds the object! } @@ -4832,9 +4927,9 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot) if (power != nullptr) { assert(obj->Implements(ObjectInterfaceType::Powered)); - dynamic_cast(obj)->SetPower(power); + dynamic_cast(*obj).SetPower(power); assert(power->Implements(ObjectInterfaceType::Transportable)); - dynamic_cast(power)->SetTransporter(obj); + dynamic_cast(*power).SetTransporter(obj); } cargo = nullptr; power = nullptr; @@ -4846,29 +4941,48 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot) m_ui->GetLoadingScreen()->SetProgress(0.95f, RT_LOADING_CBOT_SAVE); // Reads the file of stacks of execution. - FILE* file = CBot::fOpen((CResourceManager::GetSaveLocation() + "/" + filecbot).c_str(), "rb"); - if (file != nullptr) + CInputStream istr(filecbot); + + if (istr.is_open()) { - long version; - CBot::fRead(&version, sizeof(long), 1, file); // version of COLOBOT + bool bError = false; + long version = 0; + CBot::ReadLong(istr, version); // version of COLOBOT if (version == 1) { - CBot::fRead(&version, sizeof(long), 1, file); // version of CBOT + CBot::ReadLong(istr, version); // version of CBOT if (version == CBot::CBotProgram::GetVersion()) { - objRank = 0; - for (CObject* obj : m_objMan->GetAllObjects()) + unsigned short flag; + CBot::ReadWord(istr, flag); // TODO + bError = (flag != 0); + + if (!bError) for (CObject* obj : m_objMan->GetAllObjects()) { if (obj->GetType() == OBJECT_TOTO) continue; if (IsObjectBeingTransported(obj)) continue; - if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(obj)->IsDying()) continue; + if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(*obj).IsDying()) continue; - if (!ReadFileStack(obj, file, objRank++)) break; + if (!ReadFileStack(obj, istr)) + { + GetLogger()->Error("ReadFileStack failed at object id = %i\n", obj->GetID()); + bError = true; + break; + } + } + + if (!bError && !CBot::CBotClass::RestoreStaticState(istr)) + { + GetLogger()->Error("CBotClass restore static state failed\n"); + bError = true; } } + else + GetLogger()->Error("cbot.run file is wrong version: %i\n", version); } - CBot::CBotClass::RestoreStaticState(file); - CBot::fClose(file); + + if (bError) GetLogger()->Error("Restoring CBOT state failed at stream position: %li\n", istr.tellg()); + istr.close(); } m_ui->GetLoadingScreen()->SetProgress(1.0f, RT_LOADING_FINISHED); @@ -5204,7 +5318,7 @@ Error CRobotMain::CheckEndMission(bool frame) if (m_base != nullptr && !m_endTakeImmediat) { assert(m_base->Implements(ObjectInterfaceType::Controllable)); - if(dynamic_cast(m_base)->GetSelectable()) + if(dynamic_cast(*m_base).GetSelectable()) return ERR_MISSION_NOTERM; } } @@ -5244,6 +5358,16 @@ bool CRobotMain::GetTrainerPilot() return m_cheatTrainerPilot; } +bool CRobotMain::GetPlusTrainer() +{ + return m_ui->GetPlusTrainer(); +} + +bool CRobotMain::GetPlusExplorer() +{ + return m_ui->GetPlusExplorer(); +} + //! Indicates whether the scene is fixed, without interaction bool CRobotMain::GetFixScene() { @@ -5767,6 +5891,7 @@ bool CRobotMain::IsBuildingEnabled(ObjectType type) if(type == OBJECT_NUCLEAR) return IsBuildingEnabled(BUILD_NUCLEAR); if(type == OBJECT_INFO) return IsBuildingEnabled(BUILD_INFO); if(type == OBJECT_PARA) return IsBuildingEnabled(BUILD_PARA); + if(type == OBJECT_SAFE) return IsBuildingEnabled(BUILD_SAFE); if(type == OBJECT_DESTROYER) return IsBuildingEnabled(BUILD_DESTROYER); return false; @@ -5822,17 +5947,22 @@ Error CRobotMain::CanFactoryError(ObjectType type, int team) if (tool == ToolType::Sniffer && !IsResearchDone(RESEARCH_SNIFFER, team)) return ERR_BUILD_RESEARCH; if (tool == ToolType::Shooter && !IsResearchDone(RESEARCH_CANON, team)) return ERR_BUILD_RESEARCH; if (tool == ToolType::OrganicShooter && !IsResearchDone(RESEARCH_iGUN, team)) return ERR_BUILD_RESEARCH; + if (tool == ToolType::Builder && !IsResearchDone(RESEARCH_BUILDER, team)) return ERR_BUILD_RESEARCH; if (drive == DriveType::Tracked && !IsResearchDone(RESEARCH_TANK, team)) return ERR_BUILD_RESEARCH; if (drive == DriveType::Winged && !IsResearchDone(RESEARCH_FLY, team)) return ERR_BUILD_RESEARCH; if (drive == DriveType::Legged && !IsResearchDone(RESEARCH_iPAW, team)) return ERR_BUILD_RESEARCH; - if (drive == DriveType::BigTracked && !IsResearchDone(RESEARCH_TANK, team)) return ERR_BUILD_RESEARCH; // NOTE: Subber is not BigTracked! It currently counts as Other + if (drive == DriveType::Heavy && !IsResearchDone(RESEARCH_TANK, team)) return ERR_BUILD_RESEARCH; if (type == OBJECT_MOBILErt && !IsResearchDone(RESEARCH_THUMP, team)) return ERR_BUILD_RESEARCH; if (type == OBJECT_MOBILErc && !IsResearchDone(RESEARCH_PHAZER, team)) return ERR_BUILD_RESEARCH; if (type == OBJECT_MOBILErr && !IsResearchDone(RESEARCH_RECYCLER, team)) return ERR_BUILD_RESEARCH; if (type == OBJECT_MOBILErs && !IsResearchDone(RESEARCH_SHIELD, team)) return ERR_BUILD_RESEARCH; if (type == OBJECT_MOBILEsa && !IsResearchDone(RESEARCH_SUBM, team)) return ERR_BUILD_DISABLED; // Can be only researched manually in Scene file + if (type == OBJECT_MOBILEst && !IsResearchDone(RESEARCH_SUBM, team)) return ERR_BUILD_DISABLED; + if (type == OBJECT_MOBILEtg && !IsResearchDone(RESEARCH_TARGET, team)) return ERR_BUILD_RESEARCH; + + if (tool == ToolType::Other && drive == DriveType::Other && type != OBJECT_MOBILEtg) return ERR_WRONG_OBJ; return ERR_OK; } @@ -5870,6 +6000,16 @@ float CRobotMain::GetGlobalMagnifyDamage() return m_globalMagnifyDamage; } +float CRobotMain::GetGlobalNuclearCapacity() +{ + return m_globalNuclearCapacity; +} + +float CRobotMain::GetGlobalCellCapacity() +{ + return m_globalCellCapacity; +} + // Beginning of the effect when the instruction "detect" is used. void CRobotMain::StartDetectEffect(COldObject* object, CObject* target) diff --git a/src/level/robotmain.h b/src/level/robotmain.h index 2614f2cc..42590b50 100644 --- a/src/level/robotmain.h +++ b/src/level/robotmain.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -55,6 +55,7 @@ enum Phase PHASE_APPERANCE, PHASE_MAIN_MENU, PHASE_LEVEL_LIST, + PHASE_MOD_LIST, PHASE_SIMUL, PHASE_SETUPd, PHASE_SETUPg, @@ -266,6 +267,8 @@ public: const std::string& GetScriptName(); const std::string& GetScriptFile(); bool GetTrainerPilot(); + bool GetPlusTrainer(); + bool GetPlusExplorer(); bool GetFixScene(); bool GetShowSoluce(); bool GetSceneSoluce(); @@ -308,8 +311,8 @@ public: void SaveAllScript(); void SaveOneScript(CObject *obj); - bool SaveFileStack(CObject *obj, FILE *file, int objRank); - bool ReadFileStack(CObject *obj, FILE *file, int objRank); + bool SaveFileStack(CObject *obj, std::ostream &ostr); + bool ReadFileStack(CObject *obj, std::istream &istr); //! Return list of scripts to load to robot created in BotFactory std::vector GetNewScriptNames(ObjectType type); @@ -467,6 +470,11 @@ public: //! Returns global magnifyDamage setting float GetGlobalMagnifyDamage(); + //! Returns global NuclearCell capacity Setting + float GetGlobalNuclearCapacity(); + //! Returns global PowerCell capacity setting + float GetGlobalCellCapacity(); + void StartDetectEffect(COldObject* object, CObject* target); //! Enable crash sphere debug rendering @@ -649,6 +657,9 @@ protected: float m_globalMagnifyDamage = 0.0f; + float m_globalNuclearCapacity = 10.0f; + float m_globalCellCapacity = 1.0f; + bool m_exitAfterMission = false; bool m_codeBattleInit = false; diff --git a/src/level/scene_conditions.cpp b/src/level/scene_conditions.cpp index 263ee399..36e2bdd9 100644 --- a/src/level/scene_conditions.cpp +++ b/src/level/scene_conditions.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -82,7 +82,7 @@ bool CObjectCondition::CheckForObject(CObject* obj) } else if (obj->Implements(ObjectInterfaceType::Powered)) { - CObject* powerObj = dynamic_cast(obj)->GetPower(); + CObject* powerObj = dynamic_cast(*obj).GetPower(); if(powerObj != nullptr && powerObj->Implements(ObjectInterfaceType::PowerContainer)) { power = dynamic_cast(powerObj); @@ -98,7 +98,7 @@ bool CObjectCondition::CheckForObject(CObject* obj) Math::Vector oPos; if (IsObjectBeingTransported(obj)) - oPos = dynamic_cast(obj)->GetTransporter()->GetPosition(); + oPos = dynamic_cast(*obj).GetTransporter()->GetPosition(); else oPos = obj->GetPosition(); oPos.y = 0.0f; diff --git a/src/level/scene_conditions.h b/src/level/scene_conditions.h index 218c668d..1cff0c34 100644 --- a/src/level/scene_conditions.h +++ b/src/level/scene_conditions.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/scoreboard.cpp b/src/level/scoreboard.cpp index 3fa006cb..3013b291 100644 --- a/src/level/scoreboard.cpp +++ b/src/level/scoreboard.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/level/scoreboard.h b/src/level/scoreboard.h index 98f94b60..9a18b2d0 100644 --- a/src/level/scoreboard.h +++ b/src/level/scoreboard.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/all.h b/src/math/all.h index a482eae4..047148eb 100644 --- a/src/math/all.h +++ b/src/math/all.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/const.h b/src/math/const.h index c5d24e5a..bf32b674 100644 --- a/src/math/const.h +++ b/src/math/const.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/func.h b/src/math/func.h index 6fd9d6e9..ee5e00d4 100644 --- a/src/math/func.h +++ b/src/math/func.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/geometry.h b/src/math/geometry.h index 3e676c01..f7c85130 100644 --- a/src/math/geometry.h +++ b/src/math/geometry.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/half.cpp b/src/math/half.cpp index 4795b7b2..d42468b5 100644 --- a/src/math/half.cpp +++ b/src/math/half.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/half.h b/src/math/half.h index d5324bab..1d196f09 100644 --- a/src/math/half.h +++ b/src/math/half.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/intpoint.h b/src/math/intpoint.h index 0a0cf525..e2fbf811 100644 --- a/src/math/intpoint.h +++ b/src/math/intpoint.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/matrix.h b/src/math/matrix.h index 235ebb87..51e6fc65 100644 --- a/src/math/matrix.h +++ b/src/math/matrix.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/point.h b/src/math/point.h index e5779373..de3bc88a 100644 --- a/src/math/point.h +++ b/src/math/point.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/sphere.h b/src/math/sphere.h index ea009332..676ef2b3 100644 --- a/src/math/sphere.h +++ b/src/math/sphere.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/math/vector.h b/src/math/vector.h index dc547953..9f3a286f 100644 --- a/src/math/vector.h +++ b/src/math/vector.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/auto.cpp b/src/object/auto/auto.cpp index db5ce2c4..a3ea98ee 100644 --- a/src/object/auto/auto.cpp +++ b/src/object/auto/auto.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/auto.h b/src/object/auto/auto.h index 5e42bd27..0c8de5bd 100644 --- a/src/object/auto/auto.h +++ b/src/object/auto/auto.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autobase.cpp b/src/object/auto/autobase.cpp index 32b2428b..7b908095 100644 --- a/src/object/auto/autobase.cpp +++ b/src/object/auto/autobase.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -169,7 +169,7 @@ begin: else { assert(pObj->Implements(ObjectInterfaceType::Controllable)); - m_camera->SetType(dynamic_cast(pObj)->GetCameraType()); + m_camera->SetType(dynamic_cast(*pObj).GetCameraType()); } m_main->StartMusic(); @@ -594,7 +594,7 @@ begin: else { assert(pObj->Implements(ObjectInterfaceType::Controllable)); - m_camera->SetType(dynamic_cast(pObj)->GetCameraType()); + m_camera->SetType(dynamic_cast(*pObj).GetCameraType()); } m_sound->Play(SOUND_BOUM, m_object->GetPosition()); m_soundChannel = -1; @@ -1124,7 +1124,7 @@ bool CAutoBase::Abort() else { assert(pObj->Implements(ObjectInterfaceType::Controllable)); - m_camera->SetType(dynamic_cast(pObj)->GetCameraType()); + m_camera->SetType(dynamic_cast(*pObj).GetCameraType()); } m_engine->SetFogStart(m_fogStart); @@ -1187,25 +1187,27 @@ bool CAutoBase::CreateInterface(bool bSelect) oy = 3.0f/480.0f; sx = 33.0f/640.0f; sy = 33.0f/480.0f; - - ddim.x = dim.x*1.5f; - ddim.y = dim.y*1.5f; - -//? pos.x = ox+sx*7.25f; -//? pos.y = oy+sy*0.25f; -//? pw->CreateButton(pos, ddim, 63, EVENT_OBJECT_BHELP); - - pos.x = ox+sx*8.00f; - pos.y = oy+sy*0.25f; - pw->CreateButton(pos, ddim, 28, EVENT_OBJECT_BTAKEOFF); - - if ( m_lightning->GetStatus(sleep, delay, magnetic, progress) ) + if( !m_object->GetTrainer() ) { - pos.x = ox+sx*10.2f; - pos.y = oy+sy*0.5f; - ddim.x = dim.x*1.0f; - ddim.y = dim.y*1.0f; - pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT); + ddim.x = dim.x*1.5f; + ddim.y = dim.y*1.5f; + + //? pos.x = ox+sx*7.25f; + //? pos.y = oy+sy*0.25f; + //? pw->CreateButton(pos, ddim, 63, EVENT_OBJECT_BHELP); + + pos.x = ox+sx*8.00f; + pos.y = oy+sy*0.25f; + pw->CreateButton(pos, ddim, 28, EVENT_OBJECT_BTAKEOFF); + + if ( m_lightning->GetStatus(sleep, delay, magnetic, progress) ) + { + pos.x = ox+sx*10.2f; + pos.y = oy+sy*0.5f; + ddim.x = dim.x*1.0f; + ddim.y = dim.y*1.0f; + pw->CreateButton(pos, ddim, 41, EVENT_OBJECT_LIMIT); + } } pos.x = ox+sx*0.0f; @@ -1246,7 +1248,7 @@ void CAutoBase::FreezeCargo(bool freeze) m_cargoObjects.insert(obj); if ( obj->Implements(ObjectInterfaceType::Movable) ) { - CPhysics* physics = dynamic_cast(obj)->GetPhysics(); + CPhysics* physics = dynamic_cast(*obj).GetPhysics(); physics->SetFreeze(freeze); } } diff --git a/src/object/auto/autobase.h b/src/object/auto/autobase.h index ca4a3ca5..9fc3e22f 100644 --- a/src/object/auto/autobase.h +++ b/src/object/auto/autobase.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoconvert.cpp b/src/object/auto/autoconvert.cpp index 97aaf981..0f4cf5a7 100644 --- a/src/object/auto/autoconvert.cpp +++ b/src/object/auto/autoconvert.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoconvert.h b/src/object/auto/autoconvert.h index 135f8dcf..726ebc4a 100644 --- a/src/object/auto/autoconvert.h +++ b/src/object/auto/autoconvert.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoderrick.cpp b/src/object/auto/autoderrick.cpp index be632f85..f97938a1 100644 --- a/src/object/auto/autoderrick.cpp +++ b/src/object/auto/autoderrick.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoderrick.h b/src/object/auto/autoderrick.h index 10b63cde..91250c52 100644 --- a/src/object/auto/autoderrick.h +++ b/src/object/auto/autoderrick.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp index ccb3cbd7..717a1f2b 100644 --- a/src/object/auto/autodestroyer.cpp +++ b/src/object/auto/autodestroyer.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -176,7 +176,7 @@ bool CAutoDestroyer::EventProcess(const Event &event) if ( scrap != nullptr ) { assert(scrap->Implements(ObjectInterfaceType::Destroyable)); - dynamic_cast(scrap)->DestroyObject(DestructionType::Explosion); + dynamic_cast(*scrap).DestroyObject(DestructionType::Explosion); } m_bExplo = true; } diff --git a/src/object/auto/autodestroyer.h b/src/object/auto/autodestroyer.h index e7594724..c4f1af8b 100644 --- a/src/object/auto/autodestroyer.h +++ b/src/object/auto/autodestroyer.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp index 7ea3e750..6c0026d8 100644 --- a/src/object/auto/autoegg.cpp +++ b/src/object/auto/autoegg.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -74,7 +74,7 @@ void CAutoEgg::DeleteObject(bool all) alien->SetLock(false); if (alien->Implements(ObjectInterfaceType::Programmable)) { - dynamic_cast(alien)->SetActivity(true); // the insect is active + dynamic_cast(*alien).SetActivity(true); // the insect is active } } else @@ -123,7 +123,7 @@ void CAutoEgg::Init() if (alien->Implements(ObjectInterfaceType::Programmable)) { - dynamic_cast(alien)->SetActivity(false); + dynamic_cast(*alien).SetActivity(false); } } @@ -204,7 +204,7 @@ bool CAutoEgg::EventProcess(const Event &event) if ( alien == nullptr ) return true; if (alien->Implements(ObjectInterfaceType::Programmable)) { - dynamic_cast(alien)->SetActivity(false); + dynamic_cast(*alien).SetActivity(false); } m_progress += event.rTime*m_speed; @@ -265,7 +265,7 @@ Error CAutoEgg::IsEnded() alien->SetLock(false); if(alien->Implements(ObjectInterfaceType::Programmable)) { - dynamic_cast(alien)->SetActivity(true); // the insect is active + dynamic_cast(*alien).SetActivity(true); // the insect is active } } diff --git a/src/object/auto/autoegg.h b/src/object/auto/autoegg.h index 049f85a8..2ca25e86 100644 --- a/src/object/auto/autoegg.h +++ b/src/object/auto/autoegg.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp index 343d57b9..a6061a32 100644 --- a/src/object/auto/autofactory.cpp +++ b/src/object/auto/autofactory.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -186,11 +186,16 @@ static ObjectType ObjectTypeFromFactoryButton(EventType eventType) if ( eventType == EVENT_OBJECT_FACTORYti ) return OBJECT_MOBILEti; if ( eventType == EVENT_OBJECT_FACTORYfi ) return OBJECT_MOBILEfi; if ( eventType == EVENT_OBJECT_FACTORYii ) return OBJECT_MOBILEii; + if ( eventType == EVENT_OBJECT_FACTORYwb ) return OBJECT_MOBILEwb; + if ( eventType == EVENT_OBJECT_FACTORYtb ) return OBJECT_MOBILEtb; + if ( eventType == EVENT_OBJECT_FACTORYfb ) return OBJECT_MOBILEfb; + if ( eventType == EVENT_OBJECT_FACTORYib ) return OBJECT_MOBILEib; if ( eventType == EVENT_OBJECT_FACTORYrt ) return OBJECT_MOBILErt; if ( eventType == EVENT_OBJECT_FACTORYrc ) return OBJECT_MOBILErc; if ( eventType == EVENT_OBJECT_FACTORYrr ) return OBJECT_MOBILErr; if ( eventType == EVENT_OBJECT_FACTORYrs ) return OBJECT_MOBILErs; if ( eventType == EVENT_OBJECT_FACTORYsa ) return OBJECT_MOBILEsa; + if ( eventType == EVENT_OBJECT_FACTORYtg ) return OBJECT_MOBILEtg; return OBJECT_NULL; } @@ -392,7 +397,7 @@ bool CAutoFactory::EventProcess(const Event &event) if ( vehicle != nullptr ) { assert(vehicle->Implements(ObjectInterfaceType::Movable)); - physics = dynamic_cast(vehicle)->GetPhysics(); + physics = dynamic_cast(*vehicle).GetPhysics(); physics->SetFreeze(false); // can move vehicle->SetLock(false); // vehicle useable @@ -403,7 +408,7 @@ bool CAutoFactory::EventProcess(const Event &event) { if (vehicle->Implements(ObjectInterfaceType::Programmable) && vehicle->Implements(ObjectInterfaceType::ProgramStorage)) { - Program* program = dynamic_cast(vehicle)->AddProgram(); + Program* program = dynamic_cast(*vehicle).AddProgram(); if (boost::regex_match(m_program, boost::regex("[A-Za-z0-9_]+"))) // Public function name? { @@ -419,7 +424,7 @@ bool CAutoFactory::EventProcess(const Event &event) program->script->SendScript(m_program.c_str()); } - dynamic_cast(vehicle)->RunProgram(program); + dynamic_cast(*vehicle).RunProgram(program); } } } @@ -587,6 +592,10 @@ bool CAutoFactory::NearestVehicle() type != OBJECT_MOBILEta && type != OBJECT_MOBILEwa && type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfb && + type != OBJECT_MOBILEtb && + type != OBJECT_MOBILEwb && + type != OBJECT_MOBILEib && type != OBJECT_MOBILEfc && type != OBJECT_MOBILEtc && type != OBJECT_MOBILEwc && @@ -609,6 +618,8 @@ bool CAutoFactory::NearestVehicle() type != OBJECT_MOBILEtt && type != OBJECT_MOBILEwt && type != OBJECT_MOBILEit && + type != OBJECT_MOBILErp && + type != OBJECT_MOBILEst && type != OBJECT_MOBILEdr && type != OBJECT_MOTHER && type != OBJECT_ANT && @@ -653,12 +664,13 @@ bool CAutoFactory::CreateVehicle() params.angle = angle; params.type = m_type; params.team = m_object->GetTeam(); + params.trainer = m_object->GetTrainer(); CObject* vehicle = CObjectManager::GetInstancePointer()->CreateObject(params); vehicle->SetLock(true); // not usable assert(vehicle->Implements(ObjectInterfaceType::Movable)); - CPhysics* physics = dynamic_cast(vehicle)->GetPhysics(); + CPhysics* physics = dynamic_cast(*vehicle).GetPhysics(); physics->SetFreeze(true); // it doesn't move if (vehicle->Implements(ObjectInterfaceType::ProgramStorage)) @@ -718,66 +730,80 @@ bool CAutoFactory::CreateInterface(bool bSelect) oy = 3.0f/480.0f; sx = 33.0f/640.0f; sy = 33.0f/480.0f; + if( !m_object->GetTrainer() ) + { + pos.x = 0.0f; + pos.y = oy+sy*2.6f; + ddim.x = 138.0f/640.0f; + ddim.y = 258.0f/480.0f; + pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3); - pos.x = 0.0f; - pos.y = oy+sy*2.6f; - ddim.x = 138.0f/640.0f; - ddim.y = 222.0f/480.0f; - pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3); + pos.x = ox+sx*0.0f; + pos.y = oy+sy*9.3f; + pw->CreateButton(pos, dim, 128+9, EVENT_OBJECT_FACTORYwa); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+10, EVENT_OBJECT_FACTORYta); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+11, EVENT_OBJECT_FACTORYfa); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+22, EVENT_OBJECT_FACTORYia); - pos.x = ox+sx*0.0f; - pos.y = oy+sy*8.2f; - pw->CreateButton(pos, dim, 128+9, EVENT_OBJECT_FACTORYwa); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+10, EVENT_OBJECT_FACTORYta); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+11, EVENT_OBJECT_FACTORYfa); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+22, EVENT_OBJECT_FACTORYia); + pos.x = ox+sx*0.0f; + pos.y = oy+sy*8.2f; + pw->CreateButton(pos, dim, 128+12, EVENT_OBJECT_FACTORYws); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+13, EVENT_OBJECT_FACTORYts); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+14, EVENT_OBJECT_FACTORYfs); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+24, EVENT_OBJECT_FACTORYis); - pos.x = ox+sx*0.0f; - pos.y = oy+sy*7.1f; - pw->CreateButton(pos, dim, 128+12, EVENT_OBJECT_FACTORYws); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+13, EVENT_OBJECT_FACTORYts); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+14, EVENT_OBJECT_FACTORYfs); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+24, EVENT_OBJECT_FACTORYis); + pos.x = ox+sx*0.0f; + pos.y = oy+sy*7.1f; + pw->CreateButton(pos, dim, 128+15, EVENT_OBJECT_FACTORYwc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+16, EVENT_OBJECT_FACTORYtc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+17, EVENT_OBJECT_FACTORYfc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+23, EVENT_OBJECT_FACTORYic); - pos.x = ox+sx*0.0f; - pos.y = oy+sy*6.0f; - pw->CreateButton(pos, dim, 128+15, EVENT_OBJECT_FACTORYwc); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+16, EVENT_OBJECT_FACTORYtc); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+17, EVENT_OBJECT_FACTORYfc); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+23, EVENT_OBJECT_FACTORYic); + pos.x = ox+sx*0.0f; + pos.y = oy+sy*6.0f; + pw->CreateButton(pos, dim, 128+25, EVENT_OBJECT_FACTORYwi); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+26, EVENT_OBJECT_FACTORYti); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+27, EVENT_OBJECT_FACTORYfi); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+28, EVENT_OBJECT_FACTORYii); - pos.x = ox+sx*0.0f; - pos.y = oy+sy*4.9f; - pw->CreateButton(pos, dim, 128+25, EVENT_OBJECT_FACTORYwi); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+26, EVENT_OBJECT_FACTORYti); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+27, EVENT_OBJECT_FACTORYfi); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+28, EVENT_OBJECT_FACTORYii); + pos.x = ox+sx*0.0f; + pos.y = oy+sy*4.9f; + pw->CreateButton(pos, dim, 192+0, EVENT_OBJECT_FACTORYwb); + pos.x += dim.x; + pw->CreateButton(pos, dim, 192+1, EVENT_OBJECT_FACTORYtb); + pos.x += dim.x; + pw->CreateButton(pos, dim, 192+2, EVENT_OBJECT_FACTORYfb); + pos.x += dim.x; + pw->CreateButton(pos, dim, 192+3, EVENT_OBJECT_FACTORYib); - pos.x = ox+sx*0.0f; - pos.y = oy+sy*3.8f; - pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_FACTORYrt); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+19, EVENT_OBJECT_FACTORYrc); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_FACTORYrr); - pos.x += dim.x; - pw->CreateButton(pos, dim, 128+29, EVENT_OBJECT_FACTORYrs); + pos.x = ox+sx*0.0f; + pos.y = oy+sy*3.8f; + pw->CreateButton(pos, dim, 128+18, EVENT_OBJECT_FACTORYrt); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+19, EVENT_OBJECT_FACTORYrc); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+20, EVENT_OBJECT_FACTORYrr); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+29, EVENT_OBJECT_FACTORYrs); - pos.x = ox+sx*0.0f; - pos.y = oy+sy*2.7f; - pw->CreateButton(pos, dim, 128+21, EVENT_OBJECT_FACTORYsa); + pos.x = ox+sx*0.0f; + pos.y = oy+sy*2.7f; + pw->CreateButton(pos, dim, 128+21, EVENT_OBJECT_FACTORYsa); + pos.x += dim.x; + pw->CreateButton(pos, dim, 128+45, EVENT_OBJECT_FACTORYtg); + } pos.x = ox+sx*0.0f; pos.y = oy+sy*0; @@ -817,11 +843,16 @@ void CAutoFactory::UpdateInterface() UpdateButton(pw, EVENT_OBJECT_FACTORYti, m_bBusy); UpdateButton(pw, EVENT_OBJECT_FACTORYfi, m_bBusy); UpdateButton(pw, EVENT_OBJECT_FACTORYii, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYwb, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYtb, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYfb, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYib, m_bBusy); UpdateButton(pw, EVENT_OBJECT_FACTORYrt, m_bBusy); UpdateButton(pw, EVENT_OBJECT_FACTORYrc, m_bBusy); UpdateButton(pw, EVENT_OBJECT_FACTORYrr, m_bBusy); UpdateButton(pw, EVENT_OBJECT_FACTORYrs, m_bBusy); UpdateButton(pw, EVENT_OBJECT_FACTORYsa, m_bBusy); + UpdateButton(pw, EVENT_OBJECT_FACTORYtg, m_bBusy); } // Updates the status of one interface button. diff --git a/src/object/auto/autofactory.h b/src/object/auto/autofactory.h index 12b9fd5b..7fceca5a 100644 --- a/src/object/auto/autofactory.h +++ b/src/object/auto/autofactory.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoflag.cpp b/src/object/auto/autoflag.cpp index 7db6aeab..1930a7db 100644 --- a/src/object/auto/autoflag.cpp +++ b/src/object/auto/autoflag.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoflag.h b/src/object/auto/autoflag.h index 39e2bb01..f57769a7 100644 --- a/src/object/auto/autoflag.h +++ b/src/object/auto/autoflag.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autohouston.cpp b/src/object/auto/autohouston.cpp index a9b14fbb..6a2d2716 100644 --- a/src/object/auto/autohouston.cpp +++ b/src/object/auto/autohouston.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autohouston.h b/src/object/auto/autohouston.h index b6cd30c3..9a4b5f29 100644 --- a/src/object/auto/autohouston.h +++ b/src/object/auto/autohouston.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autojostle.cpp b/src/object/auto/autojostle.cpp index 60bda1cf..4c304e3a 100644 --- a/src/object/auto/autojostle.cpp +++ b/src/object/auto/autojostle.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autojostle.h b/src/object/auto/autojostle.h index 453274f1..7e94ad68 100644 --- a/src/object/auto/autojostle.h +++ b/src/object/auto/autojostle.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autokid.cpp b/src/object/auto/autokid.cpp index 0a885dd3..1977c33f 100644 --- a/src/object/auto/autokid.cpp +++ b/src/object/auto/autokid.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autokid.h b/src/object/auto/autokid.h index 1ded7de8..9ad16544 100644 --- a/src/object/auto/autokid.h +++ b/src/object/auto/autokid.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autolabo.cpp b/src/object/auto/autolabo.cpp index 39fb5245..0cdb4a57 100644 --- a/src/object/auto/autolabo.cpp +++ b/src/object/auto/autolabo.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -136,7 +136,11 @@ Error CAutoLabo::StartAction(int param) { return ERR_LABO_NULL; } - if ( power->GetType() != OBJECT_BULLET ) + if ( m_research != RESEARCH_TARGET && power->GetType() != OBJECT_BULLET ) + { + return ERR_LABO_BAD; + } + if ( m_research == RESEARCH_TARGET && power->GetType() != OBJECT_TNT ) { return ERR_LABO_BAD; } @@ -177,6 +181,7 @@ bool CAutoLabo::EventProcess(const Event &event) if ( m_object->GetSelect() ) // center selected? { Error err = ERR_UNKNOWN; + if ( event.type == EVENT_OBJECT_RTARGET ) err = StartAction(RESEARCH_TARGET); if ( event.type == EVENT_OBJECT_RiPAW ) err = StartAction(RESEARCH_iPAW); if ( event.type == EVENT_OBJECT_RiGUN ) err = StartAction(RESEARCH_iGUN); @@ -455,7 +460,7 @@ Error CAutoLabo::GetError() CObject* obj = m_object->GetPower(); if (obj == nullptr) return ERR_LABO_NULL; ObjectType type = obj->GetType(); - if ( type != OBJECT_BULLET ) return ERR_LABO_BAD; + if ( type != OBJECT_BULLET && type != OBJECT_TNT ) return ERR_LABO_BAD; return ERR_OK; } @@ -482,14 +487,20 @@ bool CAutoLabo::CreateInterface(bool bSelect) oy = 3.0f/480.0f; sx = 33.0f/640.0f; sy = 33.0f/480.0f; + if( !m_object->GetTrainer() ) + { + pos.x = ox+sx*6.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 192+8, EVENT_OBJECT_RTARGET); - pos.x = ox+sx*7.0f; - pos.y = oy+sy*0.5f; - pw->CreateButton(pos, dim, 64+45, EVENT_OBJECT_RiPAW); + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+45, EVENT_OBJECT_RiPAW); - pos.x = ox+sx*8.0f; - pos.y = oy+sy*0.5f; - pw->CreateButton(pos, dim, 64+46, EVENT_OBJECT_RiGUN); + pos.x = ox+sx*8.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+46, EVENT_OBJECT_RiGUN); + } pos.x = ox+sx*0.0f; pos.y = oy+sy*0; @@ -515,14 +526,17 @@ void CAutoLabo::UpdateInterface() pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0)); if ( pw == nullptr ) return; - DeadInterface(pw, EVENT_OBJECT_RiPAW, m_main->IsResearchEnabled(RESEARCH_iPAW)); - DeadInterface(pw, EVENT_OBJECT_RiGUN, m_main->IsResearchEnabled(RESEARCH_iGUN)); + DeadInterface(pw, EVENT_OBJECT_RTARGET, m_main->IsResearchEnabled(RESEARCH_TARGET)); + DeadInterface(pw, EVENT_OBJECT_RiPAW, m_main->IsResearchEnabled(RESEARCH_iPAW)); + DeadInterface(pw, EVENT_OBJECT_RiGUN, m_main->IsResearchEnabled(RESEARCH_iGUN)); + OkayButton(pw, EVENT_OBJECT_RTARGET); OkayButton(pw, EVENT_OBJECT_RiPAW); OkayButton(pw, EVENT_OBJECT_RiGUN); - VisibleInterface(pw, EVENT_OBJECT_RiPAW, !m_bBusy); - VisibleInterface(pw, EVENT_OBJECT_RiGUN, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RTARGET, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RiPAW, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RiGUN, !m_bBusy); } // Indicates the research conducted for a button. @@ -542,8 +556,9 @@ void CAutoLabo::OkayButton(Ui::CWindow *pw, EventType event) bool CAutoLabo::TestResearch(EventType event) { - if ( event == EVENT_OBJECT_RiPAW ) return m_main->IsResearchDone(RESEARCH_iPAW, m_object->GetTeam()); - if ( event == EVENT_OBJECT_RiGUN ) return m_main->IsResearchDone(RESEARCH_iGUN, m_object->GetTeam()); + if ( event == EVENT_OBJECT_RTARGET ) return m_main->IsResearchDone(RESEARCH_TARGET, m_object->GetTeam()); + if ( event == EVENT_OBJECT_RiPAW ) return m_main->IsResearchDone(RESEARCH_iPAW, m_object->GetTeam()); + if ( event == EVENT_OBJECT_RiGUN ) return m_main->IsResearchDone(RESEARCH_iGUN, m_object->GetTeam()); return m_main; } diff --git a/src/object/auto/autolabo.h b/src/object/auto/autolabo.h index d9a36d85..a1b22ec7 100644 --- a/src/object/auto/autolabo.h +++ b/src/object/auto/autolabo.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/automush.cpp b/src/object/auto/automush.cpp index acff24fc..9b87fe1e 100644 --- a/src/object/auto/automush.cpp +++ b/src/object/auto/automush.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -236,6 +236,10 @@ bool CAutoMush::SearchTarget() type != OBJECT_MOBILEta && type != OBJECT_MOBILEwa && type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfb && + type != OBJECT_MOBILEtb && + type != OBJECT_MOBILEwb && + type != OBJECT_MOBILEib && type != OBJECT_MOBILEfc && type != OBJECT_MOBILEtc && type != OBJECT_MOBILEwc && @@ -258,6 +262,8 @@ bool CAutoMush::SearchTarget() type != OBJECT_MOBILEtt && type != OBJECT_MOBILEwt && type != OBJECT_MOBILEit && + type != OBJECT_MOBILErp && + type != OBJECT_MOBILEst && type != OBJECT_MOBILEdr && type != OBJECT_DERRICK && type != OBJECT_STATION && diff --git a/src/object/auto/automush.h b/src/object/auto/automush.h index 9ea9eb53..b9ab4790 100644 --- a/src/object/auto/automush.h +++ b/src/object/auto/automush.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autonest.cpp b/src/object/auto/autonest.cpp index 0b680f87..c7b3e15c 100644 --- a/src/object/auto/autonest.cpp +++ b/src/object/auto/autonest.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autonest.h b/src/object/auto/autonest.h index 53761c15..ffaff24b 100644 --- a/src/object/auto/autonest.h +++ b/src/object/auto/autonest.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autonuclearplant.cpp b/src/object/auto/autonuclearplant.cpp index a341c45f..2c138c61 100644 --- a/src/object/auto/autonuclearplant.cpp +++ b/src/object/auto/autonuclearplant.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -345,6 +345,10 @@ bool CAutoNuclearPlant::SearchVehicle() type != OBJECT_MOBILEta && type != OBJECT_MOBILEwa && type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfb && + type != OBJECT_MOBILEtb && + type != OBJECT_MOBILEwb && + type != OBJECT_MOBILEib && type != OBJECT_MOBILEfc && type != OBJECT_MOBILEtc && type != OBJECT_MOBILEwc && @@ -367,6 +371,8 @@ bool CAutoNuclearPlant::SearchVehicle() type != OBJECT_MOBILEtt && type != OBJECT_MOBILEwt && type != OBJECT_MOBILEit && + type != OBJECT_MOBILErp && + type != OBJECT_MOBILEst && type != OBJECT_MOBILEdr && type != OBJECT_MOTHER && type != OBJECT_ANT && @@ -394,7 +400,7 @@ void CAutoNuclearPlant::CreatePower() float powerLevel = 1.0f; CObject* power = CObjectManager::GetInstancePointer()->CreateObject(pos, angle, OBJECT_ATOMIC, powerLevel); - dynamic_cast(power)->SetTransporter(m_object); + dynamic_cast(*power).SetTransporter(m_object); power->SetPosition(Math::Vector(22.0f, 3.0f, 0.0f)); m_object->SetPower(power); } diff --git a/src/object/auto/autonuclearplant.h b/src/object/auto/autonuclearplant.h index f15891a4..0ba5e441 100644 --- a/src/object/auto/autonuclearplant.h +++ b/src/object/auto/autonuclearplant.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoportico.cpp b/src/object/auto/autoportico.cpp index 2a8bf372..04f4d349 100644 --- a/src/object/auto/autoportico.cpp +++ b/src/object/auto/autoportico.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -47,8 +47,8 @@ const float PORTICO_TIME_OPEN = 12.0f; -// Si progress=0, return a. -// Si progress=1, return b. +// if progress=0, return a. +// if progress=1, return b. static float Progress(float a, float b, float progress) { diff --git a/src/object/auto/autoportico.h b/src/object/auto/autoportico.h index bebfcc1f..eb5db333 100644 --- a/src/object/auto/autoportico.h +++ b/src/object/auto/autoportico.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autopowercaptor.cpp b/src/object/auto/autopowercaptor.cpp index fea4586b..614c5da4 100644 --- a/src/object/auto/autopowercaptor.cpp +++ b/src/object/auto/autopowercaptor.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -269,7 +269,7 @@ void CAutoPowerCaptor::ChargeObject(float rTime) if (obj->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(obj)->GetPower(); + CObject* power = dynamic_cast(*obj).GetPower(); if ( power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer) ) { CPowerContainerObject* powerContainer = dynamic_cast(power); @@ -285,7 +285,7 @@ void CAutoPowerCaptor::ChargeObject(float rTime) if (obj->Implements(ObjectInterfaceType::Carrier)) { - CObject* power = dynamic_cast(obj)->GetCargo(); + CObject* power = dynamic_cast(*obj).GetCargo(); if ( power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer) ) { CPowerContainerObject* powerContainer = dynamic_cast(power); diff --git a/src/object/auto/autopowercaptor.h b/src/object/auto/autopowercaptor.h index b79827ef..ad23eaee 100644 --- a/src/object/auto/autopowercaptor.h +++ b/src/object/auto/autopowercaptor.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autopowerplant.cpp b/src/object/auto/autopowerplant.cpp index d7294b93..d0006e2d 100644 --- a/src/object/auto/autopowerplant.cpp +++ b/src/object/auto/autopowerplant.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -331,7 +331,7 @@ bool CAutoPowerPlant::EventProcess(const Event &event) cargo->SetScale(1.0f); cargo->SetLock(false); // usable battery - dynamic_cast(cargo)->SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporter(m_object); cargo->SetPosition(Math::Vector(0.0f, 3.0f, 0.0f)); m_object->SetPower(cargo); @@ -410,6 +410,10 @@ bool CAutoPowerPlant::SearchVehicle() type != OBJECT_MOBILEta && type != OBJECT_MOBILEwa && type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfb && + type != OBJECT_MOBILEtb && + type != OBJECT_MOBILEwb && + type != OBJECT_MOBILEib && type != OBJECT_MOBILEfc && type != OBJECT_MOBILEtc && type != OBJECT_MOBILEwc && @@ -432,6 +436,8 @@ bool CAutoPowerPlant::SearchVehicle() type != OBJECT_MOBILEtt && type != OBJECT_MOBILEwt && type != OBJECT_MOBILEit && + type != OBJECT_MOBILErp && + type != OBJECT_MOBILEst && type != OBJECT_MOBILEdr && type != OBJECT_MOTHER && type != OBJECT_ANT && diff --git a/src/object/auto/autopowerplant.h b/src/object/auto/autopowerplant.h index 474ef643..5bf6608f 100644 --- a/src/object/auto/autopowerplant.h +++ b/src/object/auto/autopowerplant.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autopowerstation.cpp b/src/object/auto/autopowerstation.cpp index 5b90b6fa..96bed578 100644 --- a/src/object/auto/autopowerstation.cpp +++ b/src/object/auto/autopowerstation.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -138,7 +138,7 @@ bool CAutoPowerStation::EventProcess(const Event &event) { if (vehicle->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(vehicle)->GetPower(); + CObject* power = dynamic_cast(*vehicle).GetPower(); if ( power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer) ) { CPowerContainerObject* powerContainer = dynamic_cast(power); @@ -158,7 +158,7 @@ bool CAutoPowerStation::EventProcess(const Event &event) if (vehicle->Implements(ObjectInterfaceType::Carrier)) { - CObject* power = dynamic_cast(vehicle)->GetCargo(); + CObject* power = dynamic_cast(*vehicle).GetCargo(); if ( power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer) ) { CPowerContainerObject* powerContainer = dynamic_cast(power); @@ -253,6 +253,10 @@ CObject* CAutoPowerStation::SearchVehicle() type != OBJECT_MOBILEta && type != OBJECT_MOBILEwa && type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfb && + type != OBJECT_MOBILEtb && + type != OBJECT_MOBILEwb && + type != OBJECT_MOBILEib && type != OBJECT_MOBILEfc && type != OBJECT_MOBILEtc && type != OBJECT_MOBILEwc && @@ -274,6 +278,9 @@ CObject* CAutoPowerStation::SearchVehicle() type != OBJECT_MOBILEtt && type != OBJECT_MOBILEwt && type != OBJECT_MOBILEit && + type != OBJECT_MOBILErp && + type != OBJECT_MOBILEst && + type != OBJECT_MOBILEtg && type != OBJECT_MOBILEdr ) continue; Math::Vector oPos = obj->GetPosition(); @@ -302,9 +309,7 @@ Error CAutoPowerStation::GetError() return ERR_OK; } - -// Crée toute l'interface lorsque l'objet est sélectionné . - +// Create the all interface when the object is selected. bool CAutoPowerStation::CreateInterface(bool bSelect) { Ui::CWindow* pw; diff --git a/src/object/auto/autopowerstation.h b/src/object/auto/autopowerstation.h index 2bdab493..f2a6a035 100644 --- a/src/object/auto/autopowerstation.h +++ b/src/object/auto/autopowerstation.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoradar.cpp b/src/object/auto/autoradar.cpp index 93b5ff8c..8a39f4fb 100644 --- a/src/object/auto/autoradar.cpp +++ b/src/object/auto/autoradar.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoradar.h b/src/object/auto/autoradar.h index fc2c5163..def37bab 100644 --- a/src/object/auto/autoradar.h +++ b/src/object/auto/autoradar.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autorepair.cpp b/src/object/auto/autorepair.cpp index d580ce8b..39b41d42 100644 --- a/src/object/auto/autorepair.cpp +++ b/src/object/auto/autorepair.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -148,7 +148,7 @@ bool CAutoRepair::EventProcess(const Event &event) assert(vehicle->Implements(ObjectInterfaceType::Shielded)); if ( m_progress < 1.0f || - (vehicle != nullptr && dynamic_cast(vehicle)->GetShield() < 1.0f) ) + (vehicle != nullptr && dynamic_cast(*vehicle).GetShield() < 1.0f) ) { if ( vehicle != nullptr ) { @@ -243,9 +243,9 @@ CObject* CAutoRepair::SearchVehicle() { if (obj == m_object) continue; if ( !obj->Implements(ObjectInterfaceType::Shielded) ) continue; - if ( !dynamic_cast(obj)->IsRepairable() ) continue; + if ( !dynamic_cast(*obj).IsRepairable() ) continue; - if ( obj->Implements(ObjectInterfaceType::Movable) && !dynamic_cast(obj)->GetPhysics()->GetLand() ) continue; // in flight? + if ( obj->Implements(ObjectInterfaceType::Movable) && !dynamic_cast(*obj).GetPhysics()->GetLand() ) continue; // in flight? Math::Vector oPos = obj->GetPosition(); float dist = Math::Distance(oPos, sPos); diff --git a/src/object/auto/autorepair.h b/src/object/auto/autorepair.h index 53ddfdd1..2c91f568 100644 --- a/src/object/auto/autorepair.h +++ b/src/object/auto/autorepair.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoresearch.cpp b/src/object/auto/autoresearch.cpp index ccc24c85..83d39c66 100644 --- a/src/object/auto/autoresearch.cpp +++ b/src/object/auto/autoresearch.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -179,6 +179,7 @@ bool CAutoResearch::EventProcess(const Event &event) if ( event.type == EVENT_OBJECT_RPHAZER ) err = StartAction(RESEARCH_PHAZER); if ( event.type == EVENT_OBJECT_RSHIELD ) err = StartAction(RESEARCH_SHIELD); if ( event.type == EVENT_OBJECT_RATOMIC ) err = StartAction(RESEARCH_ATOMIC); + if ( event.type == EVENT_OBJECT_RBUILDER ) err = StartAction(RESEARCH_BUILDER); if( err != ERR_OK && err != ERR_UNKNOWN ) m_main->DisplayError(err, m_object); @@ -268,6 +269,7 @@ bool CAutoResearch::EventProcess(const Event &event) if ( m_research == RESEARCH_PHAZER ) message = INFO_RESEARCHPHAZER; if ( m_research == RESEARCH_SHIELD ) message = INFO_RESEARCHSHIELD; if ( m_research == RESEARCH_ATOMIC ) message = INFO_RESEARCHATOMIC; + if ( m_research == RESEARCH_BUILDER ) message = INFO_RESEARCHBUILDER; if ( message != ERR_OK ) { m_main->DisplayError(message, m_object); @@ -339,38 +341,44 @@ bool CAutoResearch::CreateInterface(bool bSelect) oy = 3.0f/480.0f; sx = 33.0f/640.0f; sy = 33.0f/480.0f; + if( !m_object->GetTrainer() ) + { + pos.x = ox+sx*3.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK); - pos.x = ox+sx*7.0f; - pos.y = oy+sy*1.0f; - pw->CreateButton(pos, dim, 64+0, EVENT_OBJECT_RTANK); + pos.x = ox+sx*4.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY); - pos.x = ox+sx*8.0f; - pos.y = oy+sy*1.0f; - pw->CreateButton(pos, dim, 64+1, EVENT_OBJECT_RFLY); + pos.x = ox+sx*5.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON); - pos.x = ox+sx*9.0f; - pos.y = oy+sy*1.0f; - pw->CreateButton(pos, dim, 64+3, EVENT_OBJECT_RCANON); + pos.x = ox+sx*6.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER); - pos.x = ox+sx*10.0f; - pos.y = oy+sy*1.0f; - pw->CreateButton(pos, dim, 64+4, EVENT_OBJECT_RTOWER); + pos.x = ox+sx*7.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC); - pos.x = ox+sx*7.0f; - pos.y = oy+sy*0.0f; - pw->CreateButton(pos, dim, 64+7, EVENT_OBJECT_RATOMIC); + pos.x = ox+sx*8.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP); - pos.x = ox+sx*8.0f; - pos.y = oy+sy*0.0f; - pw->CreateButton(pos, dim, 64+2, EVENT_OBJECT_RTHUMP); + pos.x = ox+sx*9.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD); - pos.x = ox+sx*9.0f; - pos.y = oy+sy*0.0f; - pw->CreateButton(pos, dim, 64+6, EVENT_OBJECT_RSHIELD); + pos.x = ox+sx*10.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER); - pos.x = ox+sx*10.0f; - pos.y = oy+sy*0.0f; - pw->CreateButton(pos, dim, 64+5, EVENT_OBJECT_RPHAZER); + pos.x = ox+sx*11.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 192+4, EVENT_OBJECT_RBUILDER); + } pos.x = ox+sx*14.5f; pos.y = oy+sy*0; @@ -410,6 +418,7 @@ void CAutoResearch::UpdateInterface() DeadInterface(pw, EVENT_OBJECT_RPHAZER, m_main->IsResearchEnabled(RESEARCH_PHAZER)); DeadInterface(pw, EVENT_OBJECT_RSHIELD, m_main->IsResearchEnabled(RESEARCH_SHIELD)); DeadInterface(pw, EVENT_OBJECT_RATOMIC, m_main->IsResearchEnabled(RESEARCH_ATOMIC)); + DeadInterface(pw, EVENT_OBJECT_RBUILDER, m_main->IsResearchEnabled(RESEARCH_BUILDER)); OkayButton(pw, EVENT_OBJECT_RTANK); OkayButton(pw, EVENT_OBJECT_RFLY); @@ -419,6 +428,7 @@ void CAutoResearch::UpdateInterface() OkayButton(pw, EVENT_OBJECT_RPHAZER); OkayButton(pw, EVENT_OBJECT_RSHIELD); OkayButton(pw, EVENT_OBJECT_RATOMIC); + OkayButton(pw, EVENT_OBJECT_RBUILDER); VisibleInterface(pw, EVENT_OBJECT_RTANK, !m_bBusy); VisibleInterface(pw, EVENT_OBJECT_RFLY, !m_bBusy); @@ -428,6 +438,7 @@ void CAutoResearch::UpdateInterface() VisibleInterface(pw, EVENT_OBJECT_RPHAZER, !m_bBusy); VisibleInterface(pw, EVENT_OBJECT_RSHIELD, !m_bBusy); VisibleInterface(pw, EVENT_OBJECT_RATOMIC, !m_bBusy); + VisibleInterface(pw, EVENT_OBJECT_RBUILDER, !m_bBusy); } // Updates the state of all buttons on the interface, @@ -478,6 +489,7 @@ bool CAutoResearch::TestResearch(EventType event) if ( event == EVENT_OBJECT_RPHAZER ) return m_main->IsResearchDone(RESEARCH_PHAZER, m_object->GetTeam()); if ( event == EVENT_OBJECT_RSHIELD ) return m_main->IsResearchDone(RESEARCH_SHIELD, m_object->GetTeam()); if ( event == EVENT_OBJECT_RATOMIC ) return m_main->IsResearchDone(RESEARCH_ATOMIC, m_object->GetTeam()); + if ( event == EVENT_OBJECT_RBUILDER ) return m_main->IsResearchDone(RESEARCH_BUILDER, m_object->GetTeam()); return false; } @@ -502,7 +514,7 @@ void CAutoResearch::FireStopUpdate(float progress, bool bLightOn) 4.7f, -8.2f, }; - if ( !bLightOn ) // �teint ? + if ( !bLightOn ) // light-off ? { for ( i=0 ; i<6 ; i++ ) { diff --git a/src/object/auto/autoresearch.h b/src/object/auto/autoresearch.h index f5f00f3d..4fa8894f 100644 --- a/src/object/auto/autoresearch.h +++ b/src/object/auto/autoresearch.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoroot.cpp b/src/object/auto/autoroot.cpp index 1a76ee5d..330fcae6 100644 --- a/src/object/auto/autoroot.cpp +++ b/src/object/auto/autoroot.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autoroot.h b/src/object/auto/autoroot.h index de7a0967..fdad9fb2 100644 --- a/src/object/auto/autoroot.h +++ b/src/object/auto/autoroot.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autotower.cpp b/src/object/auto/autotower.cpp index 053d29df..b509e7e9 100644 --- a/src/object/auto/autotower.cpp +++ b/src/object/auto/autotower.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -289,7 +289,7 @@ CObject* CAutoTower::SearchTarget(Math::Vector &impact) { if ( obj->Implements(ObjectInterfaceType::Movable) ) { - CPhysics* physics = dynamic_cast(obj)->GetPhysics(); + CPhysics* physics = dynamic_cast(*obj).GetPhysics(); float speed = fabs(physics->GetLinMotionX(MO_REASPEED)); if ( speed > 20.0f ) continue; // moving too fast? } @@ -302,8 +302,7 @@ CObject* CAutoTower::SearchTarget(Math::Vector &impact) if ( distance > TOWER_SCOPE ) continue; // too far if ( distance < min ) { - min = distance; - best = obj; + min = distance; best = obj; } } if ( best == nullptr ) return nullptr; @@ -327,7 +326,7 @@ Error CAutoTower::GetError() return ERR_TOWER_POWER; // no battery } - if ( dynamic_cast(m_object->GetPower())->GetEnergy() < ENERGY_FIRE ) + if ( dynamic_cast(*m_object->GetPower()).GetEnergy() < ENERGY_FIRE ) { return ERR_TOWER_ENERGY; // not enough energy } diff --git a/src/object/auto/autotower.h b/src/object/auto/autotower.h index f1020cca..89a0a4e7 100644 --- a/src/object/auto/autotower.h +++ b/src/object/auto/autotower.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autovault.cpp b/src/object/auto/autovault.cpp index d744a4c4..463def58 100644 --- a/src/object/auto/autovault.cpp +++ b/src/object/auto/autovault.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/auto/autovault.h b/src/object/auto/autovault.h index 284d5c7b..ea272a75 100644 --- a/src/object/auto/autovault.h +++ b/src/object/auto/autovault.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/crash_sphere.h b/src/object/crash_sphere.h index 4c0ddf97..629a6df7 100644 --- a/src/object/crash_sphere.h +++ b/src/object/crash_sphere.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/drive_type.cpp b/src/object/drive_type.cpp index 7083f35e..b30f4eb7 100644 --- a/src/object/drive_type.cpp +++ b/src/object/drive_type.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ DriveType GetDriveFromObject(ObjectType type) case OBJECT_MOBILEwc: case OBJECT_MOBILEwi: case OBJECT_MOBILEws: + case OBJECT_MOBILEwb: return DriveType::Wheeled; case OBJECT_MOBILEtt: @@ -35,6 +36,7 @@ DriveType GetDriveFromObject(ObjectType type) case OBJECT_MOBILEtc: case OBJECT_MOBILEti: case OBJECT_MOBILEts: + case OBJECT_MOBILEtb: return DriveType::Tracked; case OBJECT_MOBILEft: @@ -42,6 +44,7 @@ DriveType GetDriveFromObject(ObjectType type) case OBJECT_MOBILEfc: case OBJECT_MOBILEfi: case OBJECT_MOBILEfs: + case OBJECT_MOBILEfb: return DriveType::Winged; case OBJECT_MOBILEit: @@ -49,14 +52,19 @@ DriveType GetDriveFromObject(ObjectType type) case OBJECT_MOBILEic: case OBJECT_MOBILEii: case OBJECT_MOBILEis: + case OBJECT_MOBILEib: return DriveType::Legged; + case OBJECT_MOBILErp: case OBJECT_MOBILErt: case OBJECT_MOBILErc: case OBJECT_MOBILErr: case OBJECT_MOBILErs: - // NOTE: Subber is not BigTracked! - return DriveType::BigTracked; + return DriveType::Heavy; + + case OBJECT_MOBILEst: + case OBJECT_MOBILEsa: + return DriveType::Amphibious; default: return DriveType::Other; diff --git a/src/object/drive_type.h b/src/object/drive_type.h index 9b8ca80a..7407a65b 100644 --- a/src/object/drive_type.h +++ b/src/object/drive_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -28,7 +28,8 @@ enum class DriveType : unsigned int Tracked, Winged, Legged, - BigTracked, + Heavy, + Amphibious }; DriveType GetDriveFromObject(ObjectType type); diff --git a/src/object/implementation/power_container_impl.cpp b/src/object/implementation/power_container_impl.cpp index f747ce7d..8449e761 100644 --- a/src/object/implementation/power_container_impl.cpp +++ b/src/object/implementation/power_container_impl.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/implementation/power_container_impl.h b/src/object/implementation/power_container_impl.h index 874aed22..0d410abb 100644 --- a/src/object/implementation/power_container_impl.h +++ b/src/object/implementation/power_container_impl.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/implementation/program_storage_impl.cpp b/src/object/implementation/program_storage_impl.cpp index 8d59a86f..d5a914ff 100644 --- a/src/object/implementation/program_storage_impl.cpp +++ b/src/object/implementation/program_storage_impl.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -270,7 +270,7 @@ void CProgramStorageObjectImpl::LoadAllProgramsForLevel(CLevelParserLine* levelS if (m_object->Implements(ObjectInterfaceType::Programmable) && i == run) { - dynamic_cast(m_object)->RunProgram(program); + dynamic_cast(*m_object).RunProgram(program); } } else @@ -327,7 +327,7 @@ void CProgramStorageObjectImpl::SaveAllProgramsForSavedScene(CLevelParserLine* l } if (m_programStorageIndex < 0) return; - if (!m_object->Implements(ObjectInterfaceType::Controllable) || !dynamic_cast(m_object)->GetSelectable() || m_object->GetType() == OBJECT_HUMAN) return; + if (!m_object->Implements(ObjectInterfaceType::Controllable) || !dynamic_cast(*m_object).GetSelectable() || m_object->GetType() == OBJECT_HUMAN) return; GetLogger()->Debug("Saving saved scene programs to '%s/prog%.3d___.txt'\n", levelSource.c_str(), m_programStorageIndex); for (unsigned int i = 0; i < m_program.size(); i++) @@ -379,7 +379,7 @@ void CProgramStorageObjectImpl::LoadAllProgramsForSavedScene(CLevelParserLine* l if (m_object->Implements(ObjectInterfaceType::Programmable) && i == run) { - dynamic_cast(m_object)->RunProgram(program); + dynamic_cast(*m_object).RunProgram(program); } } } @@ -403,7 +403,7 @@ void CProgramStorageObjectImpl::LoadAllProgramsForSavedScene(CLevelParserLine* l if (m_object->Implements(ObjectInterfaceType::Programmable) && i == run) { - dynamic_cast(m_object)->RunProgram(program); + dynamic_cast(*m_object).RunProgram(program); } } } diff --git a/src/object/implementation/program_storage_impl.h b/src/object/implementation/program_storage_impl.h index fc1ee97d..67b2ca89 100644 --- a/src/object/implementation/program_storage_impl.h +++ b/src/object/implementation/program_storage_impl.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/implementation/programmable_impl.cpp b/src/object/implementation/programmable_impl.cpp index 5e370bdb..8748f040 100644 --- a/src/object/implementation/programmable_impl.cpp +++ b/src/object/implementation/programmable_impl.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -68,7 +68,7 @@ bool CProgrammableObjectImpl::EventProcess(const Event &event) { if (event.type == EVENT_FRAME) { - if ( m_object->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(m_object)->IsDying() && IsProgram() ) + if ( m_object->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(*m_object).IsDying() && IsProgram() ) { StopProgram(); } @@ -113,7 +113,7 @@ void CProgrammableObjectImpl::RunProgram(Program* program) { m_currentProgram = program; // start new program m_object->UpdateInterface(); - if (m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(m_object)->GetTrainer()) + if (m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(*m_object).GetTrainer()) CRobotMain::GetInstancePointer()->StartMissionTimer(); } } @@ -143,24 +143,43 @@ bool CProgrammableObjectImpl::IsProgram() // Load a stack of script implementation from a file. -bool CProgrammableObjectImpl::ReadStack(FILE *file) +bool CProgrammableObjectImpl::ReadStack(std::istream &istr) { short op; - CBot::fRead(&op, sizeof(short), 1, file); + if (!CBot::ReadShort(istr, op)) return false; if ( op == 1 ) // run ? { - CBot::fRead(&op, sizeof(short), 1, file); // program rank + if (!CBot::ReadShort(istr, op)) return false; // program rank if ( op >= 0 ) { if (m_object->Implements(ObjectInterfaceType::ProgramStorage)) { - assert(op < static_cast(dynamic_cast(m_object)->GetProgramCount())); - m_currentProgram = dynamic_cast(m_object)->GetProgram(op); - if ( !m_currentProgram->script->ReadStack(file) ) return false; + int count = static_cast(dynamic_cast(*m_object).GetProgramCount()); + if (!(op < count)) + { + GetLogger()->Info("Object program count: %i\n", count); + GetLogger()->Error("Error in file: program index out of range: %i\n", op); + return false; + } + + m_currentProgram = dynamic_cast(*m_object).GetProgram(op); + if (!m_currentProgram->script->ReadStack(istr)) + { + GetLogger()->Error("Restore state failed at program index: %i\n", op); + int errNum = m_currentProgram->script->GetError(); + if (errNum != 0) + { + std::string errStr; + m_currentProgram->script->GetError(errStr); + GetLogger()->Error("Program reports error: %i:(%s)\n", errNum, errStr.c_str()); + } + return false; + } } else { + GetLogger()->Error("Object is not a program storage object\n"); return false; } } @@ -171,7 +190,7 @@ bool CProgrammableObjectImpl::ReadStack(FILE *file) // Save the script implementation stack of a file. -bool CProgrammableObjectImpl::WriteStack(FILE *file) +bool CProgrammableObjectImpl::WriteStack(std::ostream &ostr) { short op; @@ -179,21 +198,25 @@ bool CProgrammableObjectImpl::WriteStack(FILE *file) m_currentProgram->script->IsRunning() ) { op = 1; // run - CBot::fWrite(&op, sizeof(short), 1, file); + if (!CBot::WriteShort(ostr, op)) return false; op = -1; if (m_object->Implements(ObjectInterfaceType::ProgramStorage)) { - op = dynamic_cast(m_object)->GetProgramIndex(m_currentProgram); + op = dynamic_cast(*m_object).GetProgramIndex(m_currentProgram); } - CBot::fWrite(&op, sizeof(short), 1, file); + if (!CBot::WriteShort(ostr, op)) return false; - return m_currentProgram->script->WriteStack(file); + if (!m_currentProgram->script->WriteStack(ostr)) + { + GetLogger()->Error("Save state failed at program index: %i\n", op); + return false; + } + return true; } op = 0; // stop - CBot::fWrite(&op, sizeof(short), 1, file); - return true; + return CBot::WriteShort(ostr, op); } @@ -243,7 +266,7 @@ void CProgrammableObjectImpl::TraceRecordFrame() assert(m_object->Implements(ObjectInterfaceType::TraceDrawing)); CTraceDrawingObject* traceDrawing = dynamic_cast(m_object); - CPhysics* physics = dynamic_cast(m_object)->GetPhysics(); + CPhysics* physics = dynamic_cast(*m_object).GetPhysics(); speed = physics->GetLinMotionX(MO_REASPEED); if ( speed > 0.0f ) oper = TO_ADVANCE; @@ -330,7 +353,7 @@ void CProgrammableObjectImpl::TraceRecordStop() buffer << "}\n"; assert(m_object->Implements(ObjectInterfaceType::ProgramStorage)); - Program* prog = dynamic_cast(m_object)->AddProgram(); + Program* prog = dynamic_cast(*m_object).AddProgram(); prog->script->SendScript(buffer.str().c_str()); } diff --git a/src/object/implementation/programmable_impl.h b/src/object/implementation/programmable_impl.h index a0b78096..802db459 100644 --- a/src/object/implementation/programmable_impl.h +++ b/src/object/implementation/programmable_impl.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -58,8 +58,8 @@ public: Program* GetCurrentProgram() override; void StopProgram() override; - bool ReadStack(FILE *file) override; - bool WriteStack(FILE *file) override; + bool ReadStack(std::istream &istr) override; + bool WriteStack(std::ostream &ostr) override; void TraceRecordStart() override; void TraceRecordStop() override; diff --git a/src/object/implementation/task_executor_impl.cpp b/src/object/implementation/task_executor_impl.cpp index 827eee96..fe869d0b 100644 --- a/src/object/implementation/task_executor_impl.cpp +++ b/src/object/implementation/task_executor_impl.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/implementation/task_executor_impl.h b/src/object/implementation/task_executor_impl.h index 6a9e5988..69e4a0a3 100644 --- a/src/object/implementation/task_executor_impl.h +++ b/src/object/implementation/task_executor_impl.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/carrier_object.h b/src/object/interface/carrier_object.h index b534fd4a..2cbf3d73 100644 --- a/src/object/interface/carrier_object.h +++ b/src/object/interface/carrier_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -51,5 +51,5 @@ public: inline bool IsObjectCarryingCargo(CObject* obj) { return obj->Implements(ObjectInterfaceType::Carrier) && - dynamic_cast(obj)->IsCarryingCargo(); + dynamic_cast(*obj).IsCarryingCargo(); } diff --git a/src/object/interface/controllable_object.h b/src/object/interface/controllable_object.h index 05d354fb..2949144d 100644 --- a/src/object/interface/controllable_object.h +++ b/src/object/interface/controllable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/damageable_object.h b/src/object/interface/damageable_object.h index 8b545c2b..3de61ff1 100644 --- a/src/object/interface/damageable_object.h +++ b/src/object/interface/damageable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/destroyable_object.h b/src/object/interface/destroyable_object.h index a81411a2..fd83a87e 100644 --- a/src/object/interface/destroyable_object.h +++ b/src/object/interface/destroyable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -33,6 +33,7 @@ enum class DestructionType Burn = 3, //!< burning Drowned = 4, //!< drowned (only for Me) Win = 5, //!< used when removing objects from a team that won + Squash = 6, //!< flatten }; /** diff --git a/src/object/interface/flying_object.h b/src/object/interface/flying_object.h index 4949e446..ce475ef6 100644 --- a/src/object/interface/flying_object.h +++ b/src/object/interface/flying_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/fragile_object.h b/src/object/interface/fragile_object.h index 1513040f..a4fd3d1e 100644 --- a/src/object/interface/fragile_object.h +++ b/src/object/interface/fragile_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/interactive_object.h b/src/object/interface/interactive_object.h index cc2aaefd..af438a4e 100644 --- a/src/object/interface/interactive_object.h +++ b/src/object/interface/interactive_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/jet_flying_object.h b/src/object/interface/jet_flying_object.h index a0ee94cf..0f257709 100644 --- a/src/object/interface/jet_flying_object.h +++ b/src/object/interface/jet_flying_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/jostleable_object.h b/src/object/interface/jostleable_object.h index e0f7aeb4..ff8b1543 100644 --- a/src/object/interface/jostleable_object.h +++ b/src/object/interface/jostleable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/movable_object.h b/src/object/interface/movable_object.h index 41455842..e99f606c 100644 --- a/src/object/interface/movable_object.h +++ b/src/object/interface/movable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/power_container_object.h b/src/object/interface/power_container_object.h index a54d7921..472aaf8d 100644 --- a/src/object/interface/power_container_object.h +++ b/src/object/interface/power_container_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/powered_object.h b/src/object/interface/powered_object.h index 54b6dd1e..3aea3296 100644 --- a/src/object/interface/powered_object.h +++ b/src/object/interface/powered_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -61,10 +61,10 @@ inline float GetObjectEnergy(CObject* object) if (object->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(object)->GetPower(); + CObject* power = dynamic_cast(*object).GetPower(); if (power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer)) { - energy = dynamic_cast(power)->GetEnergy(); + energy = dynamic_cast(*power).GetEnergy(); } } @@ -77,10 +77,10 @@ inline float GetObjectEnergyLevel(CObject* object) if (object->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(object)->GetPower(); + CObject* power = dynamic_cast(*object).GetPower(); if (power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer)) { - energy = dynamic_cast(power)->GetEnergyLevel(); + energy = dynamic_cast(*power).GetEnergyLevel(); } } @@ -90,5 +90,5 @@ inline float GetObjectEnergyLevel(CObject* object) inline bool ObjectHasPowerCell(CObject* object) { return object->Implements(ObjectInterfaceType::Powered) && - dynamic_cast(object)->GetPower() != nullptr; + dynamic_cast(*object).GetPower() != nullptr; } diff --git a/src/object/interface/program_storage_object.h b/src/object/interface/program_storage_object.h index a1a275d5..00b05012 100644 --- a/src/object/interface/program_storage_object.h +++ b/src/object/interface/program_storage_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/programmable_object.h b/src/object/interface/programmable_object.h index 05f1a92c..ab1a8075 100644 --- a/src/object/interface/programmable_object.h +++ b/src/object/interface/programmable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -53,9 +53,9 @@ public: virtual bool IsProgram() = 0; //! Save current execution status to file - virtual bool WriteStack(FILE *file) = 0; + virtual bool WriteStack(std::ostream &ostr) = 0; //! Read current execution status from file - virtual bool ReadStack(FILE *file) = 0; + virtual bool ReadStack(std::istream &istr) = 0; //! Start recording trace virtual void TraceRecordStart() = 0; diff --git a/src/object/interface/ranged_object.h b/src/object/interface/ranged_object.h index 2b218114..79af7fd6 100644 --- a/src/object/interface/ranged_object.h +++ b/src/object/interface/ranged_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/shielded_auto_regen_object.h b/src/object/interface/shielded_auto_regen_object.h index 0b598f9f..37ff26ca 100644 --- a/src/object/interface/shielded_auto_regen_object.h +++ b/src/object/interface/shielded_auto_regen_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/shielded_object.h b/src/object/interface/shielded_object.h index 92bd3baf..30380cdf 100644 --- a/src/object/interface/shielded_object.h +++ b/src/object/interface/shielded_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/task_executor_object.h b/src/object/interface/task_executor_object.h index b724d409..3b3eb08f 100644 --- a/src/object/interface/task_executor_object.h +++ b/src/object/interface/task_executor_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/interface/trace_drawing_object.cpp b/src/object/interface/trace_drawing_object.cpp index 057c2840..b0c8343d 100644 --- a/src/object/interface/trace_drawing_object.cpp +++ b/src/object/interface/trace_drawing_object.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -27,21 +27,22 @@ std::string TraceColorName(TraceColor color) { switch(color) { + case TraceColor::Blue: return "Blue"; + case TraceColor::Red: return "Red"; + case TraceColor::Green: return "Green"; + case TraceColor::Yellow: return "Yellow"; + case TraceColor::Violet: return "Violet"; case TraceColor::White: return "White"; case TraceColor::Black: return "Black"; case TraceColor::Gray: return "Gray"; case TraceColor::LightGray: return "LightGray"; - case TraceColor::Red: return "Red"; case TraceColor::Pink: return "Pink"; case TraceColor::Purple: return "Purple"; case TraceColor::Orange: return "Orange"; - case TraceColor::Yellow: return "Yellow"; case TraceColor::Beige: return "Beige"; case TraceColor::Brown: return "Brown"; case TraceColor::Skin: return "Skin"; - case TraceColor::Green: return "Green"; case TraceColor::LightGreen: return "LightGreen"; - case TraceColor::Blue: return "Blue"; case TraceColor::LightBlue: return "LightBlue"; case TraceColor::RedArrow: return "RedArrow"; case TraceColor::BlackArrow: return "BlackArrow"; @@ -55,21 +56,22 @@ Gfx::Color TraceColorColor(TraceColor color) { switch(color) { + case TraceColor::Blue: return Gfx::Color(0.000f, 0.000f, 0.753f, 1.0f); + case TraceColor::Red: return Gfx::Color(1.000f, 0.000f, 0.000f, 1.0f); + case TraceColor::Green: return Gfx::Color(0.000f, 0.627f, 0.000f, 1.0f); + case TraceColor::Yellow: return Gfx::Color(1.000f, 1.000f, 0.000f, 1.0f); + case TraceColor::Violet: return Gfx::Color(0.820f, 0.000f, 0.997f, 1.0f); case TraceColor::White: return Gfx::Color(1.000f, 1.000f, 1.000f, 1.0f); case TraceColor::Black: return Gfx::Color(0.000f, 0.000f, 0.000f, 1.0f); case TraceColor::Gray: return Gfx::Color(0.549f, 0.549f, 0.549f, 1.0f); case TraceColor::LightGray: return Gfx::Color(0.753f, 0.753f, 0.753f, 1.0f); - case TraceColor::Red: return Gfx::Color(1.000f, 0.000f, 0.000f, 1.0f); case TraceColor::Pink: return Gfx::Color(1.000f, 0.627f, 0.753f, 1.0f); case TraceColor::Purple: return Gfx::Color(0.878f, 0.000f, 0.753f, 1.0f); case TraceColor::Orange: return Gfx::Color(1.000f, 0.627f, 0.000f, 1.0f); - case TraceColor::Yellow: return Gfx::Color(1.000f, 1.000f, 0.000f, 1.0f); case TraceColor::Beige: return Gfx::Color(0.878f, 0.753f, 0.000f, 1.0f); case TraceColor::Brown: return Gfx::Color(0.627f, 0.361f, 0.000f, 1.0f); case TraceColor::Skin: return Gfx::Color(0.961f, 0.839f, 0.714f, 1.0f); - case TraceColor::Green: return Gfx::Color(0.000f, 0.627f, 0.000f, 1.0f); case TraceColor::LightGreen: return Gfx::Color(0.000f, 1.000f, 0.000f, 1.0f); - case TraceColor::Blue: return Gfx::Color(0.000f, 0.000f, 0.753f, 1.0f); case TraceColor::LightBlue: return Gfx::Color(0.000f, 0.871f, 1.000f, 1.0f); case TraceColor::BlackArrow: return TraceColorColor(TraceColor::Black); case TraceColor::RedArrow: return TraceColorColor(TraceColor::Red); //TODO: We could probably have all the colors available as arrows now diff --git a/src/object/interface/trace_drawing_object.h b/src/object/interface/trace_drawing_object.h index 56169cb9..36e05463 100644 --- a/src/object/interface/trace_drawing_object.h +++ b/src/object/interface/trace_drawing_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -32,24 +32,25 @@ enum class TraceColor { Default = -1, - White = 0, - Black = 1, - Gray = 2, - LightGray = 3, - Red = 4, - Pink = 5, - Purple = 6, - Orange = 7, - Yellow = 8, - Beige = 9, - Brown = 10, - Skin = 11, - Green = 12, - LightGreen = 13, - Blue = 14, - LightBlue = 15, - BlackArrow = 16, - RedArrow = 17, + Blue = 0, + Red = 1, + Green = 2, + Yellow = 3, + Violet = 4, + White = 5, + Black = 6, + Gray = 7, + LightGray = 8, + Pink = 9, + Purple = 10, + Orange = 11, + Beige = 12, + Brown = 13, + Skin = 14, + LightGreen = 15, + LightBlue = 16, + BlackArrow = 17, + RedArrow = 18, Max, }; //! Convert TraceColor to a std::string diff --git a/src/object/interface/transportable_object.h b/src/object/interface/transportable_object.h index 2d0f90f3..38e88dc5 100644 --- a/src/object/interface/transportable_object.h +++ b/src/object/interface/transportable_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -54,5 +54,5 @@ public: inline bool IsObjectBeingTransported(CObject* obj) { return obj->Implements(ObjectInterfaceType::Transportable) && - dynamic_cast(obj)->IsBeingTransported(); + dynamic_cast(*obj).IsBeingTransported(); } diff --git a/src/object/mission_type.h b/src/object/mission_type.h index 91670a98..2e2e891e 100644 --- a/src/object/mission_type.h +++ b/src/object/mission_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motion.cpp b/src/object/motion/motion.cpp index b3bd03d5..0462ba6e 100644 --- a/src/object/motion/motion.cpp +++ b/src/object/motion/motion.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motion.h b/src/object/motion/motion.h index 614bf8c7..59ea0e17 100644 --- a/src/object/motion/motion.h +++ b/src/object/motion/motion.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionant.cpp b/src/object/motion/motionant.cpp index bee3114a..2b4cf2c7 100644 --- a/src/object/motion/motionant.cpp +++ b/src/object/motion/motionant.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -429,7 +429,7 @@ bool CMotionAnt::EventFrame(const Event &event) assert(m_object->Implements(ObjectInterfaceType::Destroyable)); if ( dynamic_cast(m_object)->GetDying() == DeathType::Burning ) // burning? { - if ( dynamic_cast(m_object)->GetFixed() ) + if ( dynamic_cast(*m_object).GetFixed() ) { m_actionType = MAS_BURN; } @@ -724,7 +724,7 @@ bool CMotionAnt::EventFrame(const Event &event) if ( m_progress >= 1.0f ) { SetAction(-1); - dynamic_cast(m_object)->SetFixed(false); // moving again + dynamic_cast(*m_object).SetFixed(false); // moving again } } else diff --git a/src/object/motion/motionant.h b/src/object/motion/motionant.h index 5d5d1d6f..b7387455 100644 --- a/src/object/motion/motionant.h +++ b/src/object/motion/motionant.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionbee.cpp b/src/object/motion/motionbee.cpp index 1b45eaf5..ceaf9869 100644 --- a/src/object/motion/motionbee.cpp +++ b/src/object/motion/motionbee.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionbee.h b/src/object/motion/motionbee.h index ce4ad243..1dcc18e1 100644 --- a/src/object/motion/motionbee.h +++ b/src/object/motion/motionbee.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionhuman.cpp b/src/object/motion/motionhuman.cpp index 9d9c1b42..aef056c6 100644 --- a/src/object/motion/motionhuman.cpp +++ b/src/object/motion/motionhuman.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -314,7 +314,7 @@ void CMotionHuman::Create(Math::Vector pos, float angle, ObjectType type, m_object->SetPartRotation(13, Math::Vector(10.0f*Math::PI/180.0f, -5.0f*Math::PI/180.0f, 5.0f*Math::PI/180.0f)); // Creates the neutron gun. - if ( option != 2 ) // with backpack? + if ( option != 2 && !m_main->GetPlusExplorer()) // with backpack? { rank = m_engine->CreateObject(); m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); diff --git a/src/object/motion/motionhuman.h b/src/object/motion/motionhuman.h index d3fc67d4..f07f85df 100644 --- a/src/object/motion/motionhuman.h +++ b/src/object/motion/motionhuman.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionlevelcontroller.cpp b/src/object/motion/motionlevelcontroller.cpp index f2cad48f..eed15cbc 100644 --- a/src/object/motion/motionlevelcontroller.cpp +++ b/src/object/motion/motionlevelcontroller.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionlevelcontroller.h b/src/object/motion/motionlevelcontroller.h index 4e6bca9f..601af0f1 100644 --- a/src/object/motion/motionlevelcontroller.h +++ b/src/object/motion/motionlevelcontroller.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionqueen.cpp b/src/object/motion/motionqueen.cpp index 27b7ce29..c385d4ac 100644 --- a/src/object/motion/motionqueen.cpp +++ b/src/object/motion/motionqueen.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionqueen.h b/src/object/motion/motionqueen.h index fe2fe8c3..dfcdb9b6 100644 --- a/src/object/motion/motionqueen.h +++ b/src/object/motion/motionqueen.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionspider.cpp b/src/object/motion/motionspider.cpp index 4aa046a9..c65807f1 100644 --- a/src/object/motion/motionspider.cpp +++ b/src/object/motion/motionspider.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -364,7 +364,7 @@ bool CMotionSpider::EventFrame(const Event &event) assert(m_object->Implements(ObjectInterfaceType::Destroyable)); if (dynamic_cast(m_object)->GetDying() == DeathType::Burning ) // burning? { - if ( dynamic_cast(m_object)->GetFixed() ) + if ( dynamic_cast(*m_object).GetFixed() ) { m_actionType = MSS_BURN; } @@ -648,7 +648,7 @@ bool CMotionSpider::EventFrame(const Event &event) if ( m_progress >= 1.0f ) { SetAction(-1); - dynamic_cast(m_object)->SetFixed(false); // moving again + dynamic_cast(*m_object).SetFixed(false); // moving again } } else diff --git a/src/object/motion/motionspider.h b/src/object/motion/motionspider.h index fa1281a6..30647234 100644 --- a/src/object/motion/motionspider.h +++ b/src/object/motion/motionspider.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motiontoto.cpp b/src/object/motion/motiontoto.cpp index ee7a685f..5c763b07 100644 --- a/src/object/motion/motiontoto.cpp +++ b/src/object/motion/motiontoto.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -335,6 +335,10 @@ bool CMotionToto::EventFrame(const Event &event) type == OBJECT_MOBILEta || type == OBJECT_MOBILEfa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEfc || @@ -356,6 +360,9 @@ bool CMotionToto::EventFrame(const Event &event) type == OBJECT_MOBILEtt || type == OBJECT_MOBILEft || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEst || + type == OBJECT_MOBILEtg || type == OBJECT_MOBILEdr ) ) // vehicle? { m_clownTime += event.rTime; diff --git a/src/object/motion/motiontoto.h b/src/object/motion/motiontoto.h index 8857d86f..2a180113 100644 --- a/src/object/motion/motiontoto.h +++ b/src/object/motion/motiontoto.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp index fa631fde..b9719c34 100644 --- a/src/object/motion/motionvehicle.cpp +++ b/src/object/motion/motionvehicle.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -100,49 +100,128 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_VEHICLE); // this is a moving object m_object->SetObjectRank(0, rank); + if ((m_object->GetTrainer() && type == OBJECT_MOBILEsa) || type == OBJECT_MOBILEst) + { + modelManager->AddModelReference("trainers.mod", false, rank, m_object->GetTeam()); + } + else if ((m_object->GetTrainer() && + ( type == OBJECT_MOBILErt || + type == OBJECT_MOBILErc || + type == OBJECT_MOBILErr || + type == OBJECT_MOBILErs)) || type == OBJECT_MOBILErp) + { + modelManager->AddModelReference("trainerr.mod", false, rank, m_object->GetTeam()); + } + else if (m_object->GetTrainer() || + type == OBJECT_MOBILEwt || + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEft || + type == OBJECT_MOBILEit) + { + modelManager->AddModelReference("trainer.mod", false, rank, m_object->GetTeam()); + } + if (type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfb || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEfi || type == OBJECT_MOBILEfs) { - modelManager->AddModelReference("lem1f.mod", false, rank, m_object->GetTeam()); + if (!m_object->GetTrainer()) + modelManager->AddModelReference("lem1f.mod", false, rank, m_object->GetTeam()); + else + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); + modelManager->AddModelReference("trainerf.mod", false, rank, m_object->GetTeam()); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(29, rank); + m_object->SetObjectParent(29, 0); + modelManager->AddModelReference("trainera.mod", false, rank, m_object->GetTeam()); + } } else if (type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || type == OBJECT_MOBILEts) { - modelManager->AddModelReference("lem1t.mod", false, rank, m_object->GetTeam()); + if (!m_object->GetTrainer()) + modelManager->AddModelReference("lem1t.mod", false, rank, m_object->GetTeam()); + else + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); + modelManager->AddModelReference("trainert.mod", false, rank, m_object->GetTeam()); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(29, rank); + m_object->SetObjectParent(29, 0); + modelManager->AddModelReference("trainera.mod", false, rank, m_object->GetTeam()); + } } else if (type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwb || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEwi || type == OBJECT_MOBILEws) { - if (m_object->GetTrainer()) - { - modelManager->AddModelReference("lem1wt.mod", false, rank, m_object->GetTeam()); - } + if (!m_object->GetTrainer()) + modelManager->AddModelReference("lem1w.mod", false, rank, m_object->GetTeam()); else { - modelManager->AddModelReference("lem1w.mod", false, rank, m_object->GetTeam()); + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); + modelManager->AddModelReference("trainerw.mod", false, rank, m_object->GetTeam()); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(29, rank); + m_object->SetObjectParent(29, 0); + modelManager->AddModelReference("trainera.mod", false, rank, m_object->GetTeam()); } } else if (type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEii || type == OBJECT_MOBILEis) { - modelManager->AddModelReference("lem1i.mod", false, rank, m_object->GetTeam()); + if (!m_object->GetTrainer()) + modelManager->AddModelReference("lem1i.mod", false, rank, m_object->GetTeam()); + else + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); + modelManager->AddModelReference("traineri.mod", false, rank, m_object->GetTeam()); + + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(29, rank); + m_object->SetObjectParent(29, 0); + modelManager->AddModelReference("trainera.mod", false, rank, m_object->GetTeam()); + } } - else if (type == OBJECT_MOBILErt || + else if (!m_object->GetTrainer() && + (type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs) + type == OBJECT_MOBILErs)) { modelManager->AddModelReference("roller1.mod", false, rank, m_object->GetTeam()); } - else if (type == OBJECT_MOBILEsa) + else if (type == OBJECT_MOBILEsa && !m_object->GetTrainer()) { modelManager->AddModelReference("subm1.mod", false, rank, m_object->GetTeam()); } @@ -152,18 +231,34 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, } else if (type == OBJECT_MOBILEwt) { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); modelManager->AddModelReference("trainerw.mod", false, rank, m_object->GetTeam()); } else if (type == OBJECT_MOBILEft) { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); modelManager->AddModelReference("trainerf.mod", false, rank, m_object->GetTeam()); } else if (type == OBJECT_MOBILEtt) { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); modelManager->AddModelReference("trainert.mod", false, rank, m_object->GetTeam()); } else if (type == OBJECT_MOBILEit) { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(28, rank); + m_object->SetObjectParent(28, 0); modelManager->AddModelReference("traineri.mod", false, rank, m_object->GetTeam()); } else if (type == OBJECT_MOBILEdr) @@ -183,12 +278,14 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, if (type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs) + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp) { m_object->AddCrashSphere(CrashSphere(Math::Vector(0.0f, 4.0f, 0.0f), 6.5f, SOUND_BOUMm, 0.45f)); m_object->SetCameraCollisionSphere(Math::Sphere(Math::Vector(0.0f, 3.0f, 0.0f), 7.0f)); } - else if (type == OBJECT_MOBILEsa) + else if (type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst) { m_object->AddCrashSphere(CrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 4.5f, SOUND_BOUMm, 0.45f)); m_object->SetCameraCollisionSphere(Math::Sphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f)); @@ -332,7 +429,24 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, m_object->SetPartRotationZ(2, 0.0f); } + if (type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib) + { + // Creates the neutron gun. + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(1, rank); + m_object->SetObjectParent(1, 0); + modelManager->AddModelReference("neutron.mod", false, rank, m_object->GetTeam()); +//? m_object->SetPartPosition(1, Math::Vector(0.0f, 5.3f, 0.0f)); + m_object->SetPartPosition(1, Math::Vector(0.0f, 5.3f, 0.0f)); + m_object->SetPartRotationZ(1, 0.0f); + } + if (type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwb || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEws || type == OBJECT_MOBILEwi || @@ -411,9 +525,11 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, } if (type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || - type == OBJECT_MOBILEts) // caterpillars? + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEtt) // caterpillars? { // Creates the right caterpillar. rank = m_engine->CreateObject(); @@ -421,7 +537,13 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, m_object->SetObjectRank(6, rank); m_object->SetObjectParent(6, 0); modelManager->AddModelCopy("lem2t.mod", false, rank, m_object->GetTeam()); - m_object->SetPartPosition(6, Math::Vector(0.0f, 2.0f, -3.0f)); + if (m_object->GetTrainer() || type == OBJECT_MOBILEtt) + { + m_object->SetPartPosition(6, Math::Vector(0.0f, 2.0f, -3.55f)); + m_object->SetPartScaleZ(6, 0.725f); + } + else + m_object->SetPartPosition(6, Math::Vector(0.0f, 2.0f, -3.0f)); // Creates the left caterpillar. rank = m_engine->CreateObject(); @@ -429,13 +551,20 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, m_object->SetObjectRank(7, rank); m_object->SetObjectParent(7, 0); modelManager->AddModelCopy("lem3t.mod", false, rank, m_object->GetTeam()); - m_object->SetPartPosition(7, Math::Vector(0.0f, 2.0f, 3.0f)); + if (m_object->GetTrainer() || type == OBJECT_MOBILEtt) + { + m_object->SetPartPosition(7, Math::Vector(0.0f, 2.0f, 3.55f)); + m_object->SetPartScaleZ(7, 0.725f); + } + else + m_object->SetPartPosition(7, Math::Vector(0.0f, 2.0f, 3.0f)); } if (type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs) // large caterpillars? + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp) // large caterpillars? { // Creates the right caterpillar. rank = m_engine->CreateObject(); @@ -454,7 +583,8 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, m_object->SetPartPosition(7, Math::Vector(0.0f, 2.0f, 3.0f)); } - if (type == OBJECT_MOBILEsa) // underwater caterpillars? + if (type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst) // underwater caterpillars? { // Creates the right caterpillar. rank = m_engine->CreateObject(); @@ -493,6 +623,7 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, } if (type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfb || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEfs || type == OBJECT_MOBILEfi || @@ -526,9 +657,11 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, } if (type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEis || - type == OBJECT_MOBILEii) // insect legs? + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEit) // insect legs? { float table[] = { @@ -725,6 +858,15 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, m_object->SetObjectParent(3, 1); modelManager->AddModelReference("subm3.mod", true, rank, m_object->GetTeam()); m_object->SetPartPosition(3, Math::Vector(0.5f, 0.0f, 1.5f)); + + if (m_object->GetTrainer()) + { + rank = m_engine->CreateObject(); + m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT); + m_object->SetObjectRank(4, rank); + m_object->SetObjectParent(4, 0); + modelManager->AddModelReference("trainerg.mod", true, rank, m_object->GetTeam()); + } } if (type == OBJECT_MOBILEdr) @@ -862,15 +1004,19 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, if (type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs) + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp) { m_object->CreateShadowCircle(6.0f, 1.0f); } else if (type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || type == OBJECT_MOBILEts || - type == OBJECT_MOBILEsa) + type == OBJECT_MOBILEtt || + type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst) { m_object->CreateShadowCircle(5.0f, 1.0f); } @@ -888,6 +1034,7 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, } if (type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfb || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEfi || type == OBJECT_MOBILEfs || @@ -928,7 +1075,7 @@ void CMotionVehicle::Create(Math::Vector pos, float angle, ObjectType type, powerCell->SetPosition(powerCellPos); powerCell->SetRotation(Math::Vector(0.0f, powerCellAngle, 0.0f)); - dynamic_cast(powerCell)->SetTransporter(m_object); + dynamic_cast(*powerCell).SetTransporter(m_object); assert(m_object->Implements(ObjectInterfaceType::Powered)); m_object->SetPower(powerCell); } @@ -948,6 +1095,7 @@ void CMotionVehicle::CreatePhysics(ObjectType type) character = m_object->GetCharacter(); if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwb || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEwi || type == OBJECT_MOBILEws || @@ -1004,9 +1152,11 @@ void CMotionVehicle::CreatePhysics(ObjectType type) } if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || - type == OBJECT_MOBILEts ) // caterpillars? + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEtt ) // caterpillars? { character->wheelFront = 4.0f; character->wheelBack = 4.0f; @@ -1033,9 +1183,11 @@ void CMotionVehicle::CreatePhysics(ObjectType type) } if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEii || - type == OBJECT_MOBILEis ) // legs? + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEit) // legs? { character->wheelFront = 4.0f; character->wheelBack = 4.0f; @@ -1063,6 +1215,7 @@ void CMotionVehicle::CreatePhysics(ObjectType type) } if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfb || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEfi || type == OBJECT_MOBILEfs || @@ -1100,7 +1253,8 @@ void CMotionVehicle::CreatePhysics(ObjectType type) if ( type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) // large caterpillars? + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp) // large caterpillars? { character->wheelFront = 5.0f; character->wheelBack = 5.0f; @@ -1126,7 +1280,8 @@ void CMotionVehicle::CreatePhysics(ObjectType type) m_physics->SetCirMotionY(MO_STOACCEL, 4.0f); } - if ( type == OBJECT_MOBILEsa ) + if ( type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst ) { character->wheelFront = 4.0f; character->wheelBack = 4.0f; @@ -1240,6 +1395,7 @@ bool CMotionVehicle::EventFrame(const Event &event) type = m_object->GetType(); if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwb || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEwi || type == OBJECT_MOBILEws || @@ -1406,14 +1562,18 @@ bool CMotionVehicle::EventFrame(const Event &event) } if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || type == OBJECT_MOBILEts || + type == OBJECT_MOBILEtt || type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp || type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst || type == OBJECT_MOBILEdr ) // caterpillars? { s = m_physics->GetLinMotionX(MO_MOTSPEED)*0.7f; @@ -1439,12 +1599,14 @@ bool CMotionVehicle::EventFrame(const Event &event) if ( type == OBJECT_MOBILEta || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || - type == OBJECT_MOBILEts ) + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEtt ) { limit[0] = 8.0f*Math::PI/180.0f; limit[1] = -12.0f*Math::PI/180.0f; } - else if ( type == OBJECT_MOBILEsa ) + else if ( type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst ) { limit[0] = 15.0f*Math::PI/180.0f; limit[1] = -15.0f*Math::PI/180.0f; @@ -1524,6 +1686,7 @@ bool CMotionVehicle::EventFrame(const Event &event) } if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfb || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEfi || type == OBJECT_MOBILEfs || @@ -1533,9 +1696,11 @@ bool CMotionVehicle::EventFrame(const Event &event) } if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEii || - type == OBJECT_MOBILEis ) // legs? + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEit ) // legs? { EventFrameInsect(event); } diff --git a/src/object/motion/motionvehicle.h b/src/object/motion/motionvehicle.h index 79335706..98869322 100644 --- a/src/object/motion/motionvehicle.h +++ b/src/object/motion/motionvehicle.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionworm.cpp b/src/object/motion/motionworm.cpp index ad40b98b..64d1a5bb 100644 --- a/src/object/motion/motionworm.cpp +++ b/src/object/motion/motionworm.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/motion/motionworm.h b/src/object/motion/motionworm.h index 766f706e..2bc16964 100644 --- a/src/object/motion/motionworm.h +++ b/src/object/motion/motionworm.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/object.cpp b/src/object/object.cpp index d514d8c3..20b9fca1 100644 --- a/src/object/object.cpp +++ b/src/object/object.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/object.h b/src/object/object.h index 1de9da17..b86d6478 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/object_create_exception.h b/src/object/object_create_exception.h index 215039bc..3f57e8bc 100644 --- a/src/object/object_create_exception.h +++ b/src/object/object_create_exception.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/object_create_params.h b/src/object/object_create_params.h index 89d177e7..69830faa 100644 --- a/src/object/object_create_params.h +++ b/src/object/object_create_params.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/object_factory.cpp b/src/object/object_factory.cpp index 25b0e9ed..00c80f04 100644 --- a/src/object/object_factory.cpp +++ b/src/object/object_factory.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -284,6 +284,10 @@ CObjectUPtr CObjectFactory::CreateObject(const ObjectCreateParams& params) case OBJECT_MOBILEta: case OBJECT_MOBILEwa: case OBJECT_MOBILEia: + case OBJECT_MOBILEfb: + case OBJECT_MOBILEtb: + case OBJECT_MOBILEwb: + case OBJECT_MOBILEib: case OBJECT_MOBILEfc: case OBJECT_MOBILEtc: case OBJECT_MOBILEwc: @@ -305,6 +309,8 @@ CObjectUPtr CObjectFactory::CreateObject(const ObjectCreateParams& params) case OBJECT_MOBILEtt: case OBJECT_MOBILEwt: case OBJECT_MOBILEit: + case OBJECT_MOBILErp: + case OBJECT_MOBILEst: case OBJECT_MOBILEdr: case OBJECT_APOLLO2: case OBJECT_CONTROLLER: diff --git a/src/object/object_factory.h b/src/object/object_factory.h index cb260412..06033b26 100644 --- a/src/object/object_factory.h +++ b/src/object/object_factory.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/object_interface_type.h b/src/object/object_interface_type.h index 1216ab0c..fdd90233 100644 --- a/src/object/object_interface_type.h +++ b/src/object/object_interface_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/object_manager.cpp b/src/object/object_manager.cpp index 0b4daed9..58c7475e 100644 --- a/src/object/object_manager.cpp +++ b/src/object/object_manager.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -142,6 +142,8 @@ CObject* CObjectManager::CreateObject(ObjectCreateParams params) } } + params.power = ClampPower(params.type,params.power); + assert(m_objects.find(params.id) == m_objects.end()); auto objectUPtr = m_objectFactory->CreateObject(params); @@ -163,10 +165,20 @@ CObject* CObjectManager::CreateObject(Math::Vector pos, float angle, ObjectType params.angle = angle; params.type = type; params.power = power; - return CreateObject(params); } +float CObjectManager::ClampPower(ObjectType type, float power) +{ + float min = 0; + float max = 100; + if (type == OBJECT_POWER || type == OBJECT_ATOMIC) + { + max = 1; + } + return Math::Clamp(power, min, max); +} + std::vector CObjectManager::GetObjectsOfTeam(int team) { std::vector result; @@ -205,7 +217,7 @@ void CObjectManager::DestroyTeam(int team, DestructionType destructionType) { if (object->Implements(ObjectInterfaceType::Destroyable)) { - dynamic_cast(object)->DestroyObject(destructionType); + dynamic_cast(*object).DestroyObject(destructionType); } else { @@ -303,7 +315,7 @@ std::vector CObjectManager::RadarAll(CObject* pThis, Math::Vector this oType == OBJECT_RUINmobiler1 || oType == OBJECT_RUINmobiler2 ) { - oType = OBJECT_RUINmobilew1; // any ruin + oType = OBJECT_RUINmobilew1; // any wreck } if ( oType == OBJECT_BARRIER2 || @@ -313,6 +325,33 @@ std::vector CObjectManager::RadarAll(CObject* pThis, Math::Vector this { oType = OBJECT_BARRIER1; // any barrier } + + if ( oType == OBJECT_RUINdoor || + oType == OBJECT_RUINsupport || + oType == OBJECT_RUINradar || + oType == OBJECT_RUINconvert ) // ruins? + { + oType = OBJECT_RUINfactory; // any ruin + } + + if ( oType == OBJECT_PLANT1 || + oType == OBJECT_PLANT2 || + oType == OBJECT_PLANT3 || + oType == OBJECT_PLANT4 || + oType == OBJECT_PLANT15 || + oType == OBJECT_PLANT16 || + oType == OBJECT_PLANT17 || + oType == OBJECT_PLANT18 ) // bushes? + { + oType = OBJECT_PLANT0; // any bush + } + + if ( oType == OBJECT_QUARTZ1 || + oType == OBJECT_QUARTZ2 || + oType == OBJECT_QUARTZ3 ) // crystals? + { + oType = OBJECT_QUARTZ0; // any crystal + } // END OF TODO } @@ -324,7 +363,7 @@ std::vector CObjectManager::RadarAll(CObject* pThis, Math::Vector this { if ( pObj->Implements(ObjectInterfaceType::Movable) ) { - CPhysics* physics = dynamic_cast(pObj)->GetPhysics(); + CPhysics* physics = dynamic_cast(*pObj).GetPhysics(); if ( physics != nullptr ) { if ( !physics->GetLand() ) continue; @@ -334,7 +373,7 @@ std::vector CObjectManager::RadarAll(CObject* pThis, Math::Vector this if ( filter_flying == FILTER_ONLYFLYING ) { if ( !pObj->Implements(ObjectInterfaceType::Movable) ) continue; - CPhysics* physics = dynamic_cast(pObj)->GetPhysics(); + CPhysics* physics = dynamic_cast(*pObj).GetPhysics(); if ( physics == nullptr ) continue; if ( physics->GetLand() ) continue; } diff --git a/src/object/object_manager.h b/src/object/object_manager.h index 722812fa..3ae55c84 100644 --- a/src/object/object_manager.h +++ b/src/object/object_manager.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -303,6 +303,8 @@ public: //@} private: + //! Prevents creation of overcharged power cells + float ClampPower(ObjectType type, float power); void CleanRemovedObjectsIfNeeded(); private: diff --git a/src/object/object_type.cpp b/src/object/object_type.cpp new file mode 100644 index 00000000..ca452bc0 --- /dev/null +++ b/src/object/object_type.cpp @@ -0,0 +1,236 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include "object/object_type.h" + +#include + +bool IsValidObjectTypeId(int id) +{ + static const std::unordered_set validIds{ + OBJECT_NULL, + OBJECT_PORTICO, + OBJECT_BASE, + OBJECT_DERRICK, + OBJECT_FACTORY, + OBJECT_STATION, + OBJECT_CONVERT, + OBJECT_REPAIR, + OBJECT_TOWER, + OBJECT_NEST, + OBJECT_RESEARCH, + OBJECT_RADAR, + OBJECT_ENERGY, + OBJECT_LABO, + OBJECT_NUCLEAR, + OBJECT_START, + OBJECT_END, + OBJECT_INFO, + OBJECT_PARA, + OBJECT_TARGET1, + OBJECT_TARGET2, + OBJECT_SAFE, + OBJECT_HUSTON, + OBJECT_DESTROYER, + OBJECT_STONE, + OBJECT_URANIUM, + OBJECT_METAL, + OBJECT_POWER, + OBJECT_ATOMIC, + OBJECT_BULLET, + OBJECT_BBOX, + OBJECT_TNT, + OBJECT_MARKPOWER, + OBJECT_MARKSTONE, + OBJECT_MARKURANIUM, + OBJECT_MARKKEYa, + OBJECT_MARKKEYb, + OBJECT_MARKKEYc, + OBJECT_MARKKEYd, + OBJECT_BOMB, + OBJECT_WINFIRE, + OBJECT_SHOW, + OBJECT_BAG, + OBJECT_PLANT0, + OBJECT_PLANT1, + OBJECT_PLANT2, + OBJECT_PLANT3, + OBJECT_PLANT4, + OBJECT_PLANT5, + OBJECT_PLANT6, + OBJECT_PLANT7, + OBJECT_PLANT8, + OBJECT_PLANT9, + OBJECT_PLANT10, + OBJECT_PLANT11, + OBJECT_PLANT12, + OBJECT_PLANT13, + OBJECT_PLANT14, + OBJECT_PLANT15, + OBJECT_PLANT16, + OBJECT_PLANT17, + OBJECT_PLANT18, + OBJECT_PLANT19, + OBJECT_TREE0, + OBJECT_TREE1, + OBJECT_TREE2, + OBJECT_TREE3, + OBJECT_TREE4, + OBJECT_TREE5, + OBJECT_MOBILEwt, + OBJECT_MOBILEtt, + OBJECT_MOBILEft, + OBJECT_MOBILEit, + OBJECT_MOBILErp, + OBJECT_MOBILEst, + OBJECT_MOBILEwa, + OBJECT_MOBILEta, + OBJECT_MOBILEfa, + OBJECT_MOBILEia, + OBJECT_MOBILEwc, + OBJECT_MOBILEtc, + OBJECT_MOBILEfc, + OBJECT_MOBILEic, + OBJECT_MOBILEwi, + OBJECT_MOBILEti, + OBJECT_MOBILEfi, + OBJECT_MOBILEii, + OBJECT_MOBILEws, + OBJECT_MOBILEts, + OBJECT_MOBILEfs, + OBJECT_MOBILEis, + OBJECT_MOBILErt, + OBJECT_MOBILErc, + OBJECT_MOBILErr, + OBJECT_MOBILErs, + OBJECT_MOBILEsa, + OBJECT_MOBILEtg, + OBJECT_MOBILEdr, + OBJECT_CONTROLLER, + OBJECT_MOBILEwb, + OBJECT_MOBILEtb, + OBJECT_MOBILEfb, + OBJECT_MOBILEib, + OBJECT_MOBILEpr, + OBJECT_WAYPOINT, + OBJECT_FLAGb, + OBJECT_FLAGr, + OBJECT_FLAGg, + OBJECT_FLAGy, + OBJECT_FLAGv, + OBJECT_KEYa, + OBJECT_KEYb, + OBJECT_KEYc, + OBJECT_KEYd, + OBJECT_HUMAN, + OBJECT_TOTO, + OBJECT_TECH, + OBJECT_BARRIER0, + OBJECT_BARRIER1, + OBJECT_BARRIER2, + OBJECT_BARRIER3, + OBJECT_BARRICADE0, + OBJECT_BARRICADE1, + OBJECT_MOTHER, + OBJECT_EGG, + OBJECT_ANT, + OBJECT_SPIDER, + OBJECT_BEE, + OBJECT_WORM, + OBJECT_RUINmobilew1, + OBJECT_RUINmobilew2, + OBJECT_RUINmobilet1, + OBJECT_RUINmobilet2, + OBJECT_RUINmobiler1, + OBJECT_RUINmobiler2, + OBJECT_RUINfactory, + OBJECT_RUINdoor, + OBJECT_RUINsupport, + OBJECT_RUINradar, + OBJECT_RUINconvert, + OBJECT_RUINbase, + OBJECT_RUINhead, + OBJECT_TEEN0, + OBJECT_TEEN1, + OBJECT_TEEN2, + OBJECT_TEEN3, + OBJECT_TEEN4, + OBJECT_TEEN5, + OBJECT_TEEN6, + OBJECT_TEEN7, + OBJECT_TEEN8, + OBJECT_TEEN9, + OBJECT_TEEN10, + OBJECT_TEEN11, + OBJECT_TEEN12, + OBJECT_TEEN13, + OBJECT_TEEN14, + OBJECT_TEEN15, + OBJECT_TEEN16, + OBJECT_TEEN17, + OBJECT_TEEN18, + OBJECT_TEEN19, + OBJECT_TEEN20, + OBJECT_TEEN21, + OBJECT_TEEN22, + OBJECT_TEEN23, + OBJECT_TEEN24, + OBJECT_TEEN25, + OBJECT_TEEN26, + OBJECT_TEEN27, + OBJECT_TEEN28, + OBJECT_TEEN29, + OBJECT_TEEN30, + OBJECT_TEEN31, + OBJECT_TEEN32, + OBJECT_TEEN33, + OBJECT_TEEN34, + OBJECT_TEEN35, + OBJECT_TEEN36, + OBJECT_TEEN37, + OBJECT_TEEN38, + OBJECT_TEEN39, + OBJECT_TEEN40, + OBJECT_TEEN41, + OBJECT_TEEN42, + OBJECT_TEEN43, + OBJECT_TEEN44, + OBJECT_QUARTZ0, + OBJECT_QUARTZ1, + OBJECT_QUARTZ2, + OBJECT_QUARTZ3, + OBJECT_ROOT0, + OBJECT_ROOT1, + OBJECT_ROOT2, + OBJECT_ROOT3, + OBJECT_ROOT4, + OBJECT_ROOT5, + OBJECT_MUSHROOM1, + OBJECT_MUSHROOM2, + OBJECT_APOLLO1, + OBJECT_APOLLO2, + OBJECT_APOLLO3, + OBJECT_APOLLO4, + OBJECT_APOLLO5, + OBJECT_HOME1, + + OBJECT_MAX + }; + return validIds.count(id); +} diff --git a/src/object/object_type.h b/src/object/object_type.h index d8c3c8de..7f78e304 100644 --- a/src/object/object_type.h +++ b/src/object/object_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -101,10 +101,12 @@ enum ObjectType OBJECT_TREE3 = 93, //!< Tree3 OBJECT_TREE4 = 94, //!< Tree4 OBJECT_TREE5 = 95, //!< Tree5 - OBJECT_MOBILEwt = 100, //!< PracticeBot - OBJECT_MOBILEtt = 101, //!< track-trainer (unused) - OBJECT_MOBILEft = 102, //!< fly-trainer (unused) - OBJECT_MOBILEit = 103, //!< insect-trainer (unused) + OBJECT_MOBILEwt = 100, //!< WheeledTrainer (PracticeBot) + OBJECT_MOBILEtt = 101, //!< TrackedTrainer + OBJECT_MOBILEft = 102, //!< WingedTrainer + OBJECT_MOBILEit = 103, //!< LeggedTrainer + OBJECT_MOBILErp = 104, //!< HeavyTrainer + OBJECT_MOBILEst = 105, //!< AmphibiousTrainer OBJECT_MOBILEwa = 110, //!< WheeledGrabber OBJECT_MOBILEta = 111, //!< TrackedGrabber OBJECT_MOBILEfa = 112, //!< WingedGrabber @@ -129,6 +131,11 @@ enum ObjectType OBJECT_MOBILEtg = 211, //!< TargetBot OBJECT_MOBILEdr = 212, //!< Scribbler OBJECT_CONTROLLER = 213, //!< MissionController + OBJECT_MOBILEwb = 220, //!< WheeledBuilder + OBJECT_MOBILEtb = 221, //!< TrackedBuilder + OBJECT_MOBILEfb = 222, //!< WingedBuilder + OBJECT_MOBILEib = 223, //!< LeggedBuilder + OBJECT_MOBILEpr = 224, //!< PracticeBot (alias) OBJECT_WAYPOINT = 250, //!< WayPoint OBJECT_FLAGb = 260, //!< BlueFlag OBJECT_FLAGr = 261, //!< RedFlag @@ -241,3 +248,5 @@ struct ObjectTypeHash return std::hash()(t); } }; + +bool IsValidObjectTypeId(int id); diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 3ecbb0e8..7dedda8a 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -285,8 +285,8 @@ void COldObject::DeleteObject(bool bAll) { if (m_power->Implements(ObjectInterfaceType::Old)) { - dynamic_cast(m_power)->SetTransporter(nullptr); - dynamic_cast(m_power)->DeleteObject(bAll); + dynamic_cast(*m_power).SetTransporter(nullptr); + dynamic_cast(*m_power).DeleteObject(bAll); } m_power = nullptr; } @@ -294,8 +294,8 @@ void COldObject::DeleteObject(bool bAll) { if (m_cargo->Implements(ObjectInterfaceType::Old)) { - dynamic_cast(m_cargo)->SetTransporter(nullptr); - dynamic_cast(m_cargo)->DeleteObject(bAll); + dynamic_cast(*m_cargo).SetTransporter(nullptr); + dynamic_cast(*m_cargo).DeleteObject(bAll); } m_cargo = nullptr; } @@ -351,6 +351,7 @@ bool COldObject::DamageObject(DamageType type, float force, CObject* killer) assert(!Implements(ObjectInterfaceType::Destroyable) || Implements(ObjectInterfaceType::Shielded) || Implements(ObjectInterfaceType::Fragile)); if ( IsDying() ) return false; + if ( Implements(ObjectInterfaceType::Jostleable) ) return false; if ( m_type == OBJECT_ANT || m_type == OBJECT_WORM || @@ -363,7 +364,18 @@ bool COldObject::DamageObject(DamageType type, float force, CObject* killer) } else if ( Implements(ObjectInterfaceType::Fragile) ) { - if ( m_type == OBJECT_BOMB && type != DamageType::Explosive ) return false; // Mine can't be destroyed by shooting + if ((m_type == OBJECT_BOMB || + m_type == OBJECT_RUINmobilew1 || + m_type == OBJECT_RUINmobilew2 || + m_type == OBJECT_RUINmobilet1 || + m_type == OBJECT_RUINmobilet2 || + m_type == OBJECT_RUINmobiler1 || + m_type == OBJECT_RUINmobiler2 || + m_type == OBJECT_RUINfactory || + m_type == OBJECT_RUINdoor || + m_type == OBJECT_RUINsupport || + m_type == OBJECT_RUINradar || + m_type == OBJECT_RUINconvert ) && type != DamageType::Explosive ) return false; // Mines and ruins can't be destroyed by shooting if ( m_type == OBJECT_URANIUM && (type == DamageType::Fire || type == DamageType::Organic) ) return false; // UraniumOre is not destroyable by shooting or aliens (see #777) if ( m_type == OBJECT_STONE && (type == DamageType::Fire || type == DamageType::Organic) ) return false; // TitaniumOre is not destroyable either // PowerCell, NuclearCell and Titanium are destroyable by shooting, but not by collisions! @@ -505,7 +517,12 @@ void COldObject::DestroyObject(DestructionType type, CObject* killer) m_type == OBJECT_SAFE || m_type == OBJECT_HUSTON || m_type == OBJECT_START || - m_type == OBJECT_END ) // building? + m_type == OBJECT_END || + m_type == OBJECT_RUINfactory || + m_type == OBJECT_RUINdoor || + m_type == OBJECT_RUINsupport || + m_type == OBJECT_RUINradar || + m_type == OBJECT_RUINconvert ) // building? { pyroType = Gfx::PT_FRAGT; } @@ -553,6 +570,11 @@ void COldObject::DestroyObject(DestructionType type, CObject* killer) { pyroType = Gfx::PT_WPCHECK; } + else if ( type == DestructionType::Squash ) + { + pyroType = Gfx::PT_SQUASH; + DeleteAllCrashSpheres(); + } assert(pyroType != Gfx::PT_NULL); if (pyroType == Gfx::PT_FRAGT || pyroType == Gfx::PT_FRAGO || @@ -694,10 +716,11 @@ void COldObject::SetType(ObjectType type) // TODO: Temporary hack if ( m_type == OBJECT_MOBILEfa || // WingedGrabber + m_type == OBJECT_MOBILEfb || // WingedBuilder m_type == OBJECT_MOBILEfs || // WingedSniffer m_type == OBJECT_MOBILEfc || // WingedShooter m_type == OBJECT_MOBILEfi || // WingedOrgaShooter - m_type == OBJECT_MOBILEft || // winged PracticeBot (unused) + m_type == OBJECT_MOBILEft || // WingedTrainer m_type == OBJECT_HUMAN || // Me m_type == OBJECT_TECH || // Tech m_type == OBJECT_CONTROLLER) @@ -721,6 +744,10 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_MOBILEta || m_type == OBJECT_MOBILEwa || m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEib || m_type == OBJECT_MOBILEfc || m_type == OBJECT_MOBILEtc || m_type == OBJECT_MOBILEwc || @@ -743,6 +770,8 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_MOBILEtt || m_type == OBJECT_MOBILEwt || m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILErp || + m_type == OBJECT_MOBILEst || m_type == OBJECT_TOWER || m_type == OBJECT_RESEARCH || m_type == OBJECT_ENERGY || @@ -783,6 +812,10 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_MOBILEta || m_type == OBJECT_MOBILEwa || m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEib || m_type == OBJECT_MOBILEfc || m_type == OBJECT_MOBILEtc || m_type == OBJECT_MOBILEwc || @@ -804,6 +837,8 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_MOBILEtt || m_type == OBJECT_MOBILEwt || m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILErp || + m_type == OBJECT_MOBILEst || m_type == OBJECT_FACTORY || m_type == OBJECT_REPAIR || m_type == OBJECT_DESTROYER|| @@ -833,6 +868,38 @@ void COldObject::SetType(ObjectType type) m_implementedInterfaces[static_cast(ObjectInterfaceType::Fragile)] = false; m_implementedInterfaces[static_cast(ObjectInterfaceType::Shielded)] = false; } + else if (m_type == OBJECT_RUINmobilew1 || + m_type == OBJECT_RUINmobilew2 || + m_type == OBJECT_RUINmobilet1 || + m_type == OBJECT_RUINmobilet2 || + m_type == OBJECT_RUINmobiler1 || + m_type == OBJECT_RUINmobiler2 || + m_type == OBJECT_RUINfactory || + m_type == OBJECT_RUINdoor || + m_type == OBJECT_RUINsupport || + m_type == OBJECT_RUINradar || + m_type == OBJECT_RUINconvert ) + { + m_implementedInterfaces[static_cast(ObjectInterfaceType::Damageable)] = true; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Destroyable)] = true; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Fragile)] = true; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Shielded)] = false; + } + else if (m_type == OBJECT_PLANT0 || + m_type == OBJECT_PLANT1 || + m_type == OBJECT_PLANT2 || + m_type == OBJECT_PLANT3 || + m_type == OBJECT_PLANT4 || + m_type == OBJECT_PLANT15 || + m_type == OBJECT_PLANT16 || + m_type == OBJECT_PLANT17 || + m_type == OBJECT_PLANT18 ) + { + m_implementedInterfaces[static_cast(ObjectInterfaceType::Damageable)] = true; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Destroyable)] = true; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Fragile)] = true; + m_implementedInterfaces[static_cast(ObjectInterfaceType::Shielded)] = false; + } else { m_implementedInterfaces[static_cast(ObjectInterfaceType::Damageable)] = false; @@ -872,6 +939,10 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_MOBILEta || m_type == OBJECT_MOBILEwa || m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEib || m_type == OBJECT_MOBILEfc || m_type == OBJECT_MOBILEtc || m_type == OBJECT_MOBILEwc || @@ -893,6 +964,9 @@ void COldObject::SetType(ObjectType type) m_type == OBJECT_MOBILEtt || m_type == OBJECT_MOBILEwt || m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILErp || + m_type == OBJECT_MOBILEst || + m_type == OBJECT_MOBILEtg || m_type == OBJECT_MOBILEdr || m_type == OBJECT_APOLLO2 || m_type == OBJECT_BASE || @@ -1221,7 +1295,7 @@ int COldObject::SearchDescendant(int parent, int n) void COldObject::TransformCrashSphere(Math::Sphere& crashSphere) { - crashSphere.radius *= GetScaleX(); + if(!Implements(ObjectInterfaceType::Jostleable)) crashSphere.radius *= GetScaleX(); // Returns to the sphere collisions, // which ignores the tilt of the vehicle. @@ -1553,6 +1627,11 @@ bool COldObject::GetTrainer() return m_bTrainer; } +bool COldObject::GetPlusTrainer() +{ + return m_main->GetPlusTrainer(); +} + void COldObject::SetToy(bool bEnable) { m_bToy = bEnable; @@ -2297,7 +2376,8 @@ void COldObject::AdjustCamera(Math::Vector &eye, float &dirH, float &dirV, } else if ( m_type == OBJECT_MOBILErt || m_type == OBJECT_MOBILErr || - m_type == OBJECT_MOBILErs ) + m_type == OBJECT_MOBILErs || + m_type == OBJECT_MOBILErp ) { eye.x = -1.1f; // on the cap eye.y = 7.9f; @@ -2339,7 +2419,8 @@ void COldObject::AdjustCamera(Math::Vector &eye, float &dirH, float &dirV, eye.y = 11.0f; eye.z = 0.0f; } - else if ( m_type == OBJECT_MOBILEsa ) + else if ( m_type == OBJECT_MOBILEsa || + m_type == OBJECT_MOBILEst ) { eye.x = 3.0f; eye.y = 4.5f; @@ -2424,7 +2505,7 @@ float COldObject::GetAbsTime() float COldObject::GetCapacity() { - return m_type == OBJECT_ATOMIC ? 10.0f : 1.0f; + return m_type == OBJECT_ATOMIC ? m_main->GetGlobalNuclearCapacity() : m_main->GetGlobalCellCapacity() ; } bool COldObject::IsRechargeable() @@ -2744,7 +2825,11 @@ void COldObject::SetGunGoalV(float gunGoal) if ( m_type == OBJECT_MOBILEfc || m_type == OBJECT_MOBILEtc || m_type == OBJECT_MOBILEwc || - m_type == OBJECT_MOBILEic ) // fireball? + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEib) // fireball? { if ( gunGoal > 10.0f*Math::PI/180.0f ) gunGoal = 10.0f*Math::PI/180.0f; if ( gunGoal < -20.0f*Math::PI/180.0f ) gunGoal = -20.0f*Math::PI/180.0f; @@ -2778,7 +2863,11 @@ void COldObject::SetGunGoalH(float gunGoal) if ( m_type == OBJECT_MOBILEfc || m_type == OBJECT_MOBILEtc || m_type == OBJECT_MOBILEwc || - m_type == OBJECT_MOBILEic ) // fireball? + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEib) // fireball? { if ( gunGoal > 40.0f*Math::PI/180.0f ) gunGoal = 40.0f*Math::PI/180.0f; if ( gunGoal < -40.0f*Math::PI/180.0f ) gunGoal = -40.0f*Math::PI/180.0f; @@ -2852,6 +2941,10 @@ void COldObject::CreateSelectParticle() m_type == OBJECT_MOBILEta || m_type == OBJECT_MOBILEwa || m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEib || m_type == OBJECT_MOBILEfc || m_type == OBJECT_MOBILEtc || m_type == OBJECT_MOBILEwc || @@ -2874,6 +2967,8 @@ void COldObject::CreateSelectParticle() m_type == OBJECT_MOBILEtt || m_type == OBJECT_MOBILEwt || m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILErp || + m_type == OBJECT_MOBILEst || m_type == OBJECT_MOBILEdr ) // vehicle? { pos = Math::Vector(0.0f, 0.0f, 0.0f); @@ -2910,24 +3005,16 @@ void COldObject::UpdateSelectParticle() if ( m_type == OBJECT_MOBILErt || m_type == OBJECT_MOBILErc || m_type == OBJECT_MOBILErr || - m_type == OBJECT_MOBILErs ) // large caterpillars? + m_type == OBJECT_MOBILErs || + m_type == OBJECT_MOBILErp ) // large caterpillars? { pos[0] = Math::Vector(4.2f, 2.8f, 1.5f); pos[1] = Math::Vector(4.2f, 2.8f, -1.5f); dim[0].x = 1.5f; dim[1].x = 1.5f; } - else if ( m_type == OBJECT_MOBILEwt || - m_type == OBJECT_MOBILEtt || - m_type == OBJECT_MOBILEft || - m_type == OBJECT_MOBILEit ) // trainer ? - { - pos[0] = Math::Vector(4.2f, 2.5f, 1.2f); - pos[1] = Math::Vector(4.2f, 2.5f, -1.2f); - dim[0].x = 1.5f; - dim[1].x = 1.5f; - } - else if ( m_type == OBJECT_MOBILEsa ) // submarine? + else if ( m_type == OBJECT_MOBILEsa || + m_type == OBJECT_MOBILEst ) // submarine? { pos[0] = Math::Vector(3.6f, 4.0f, 2.0f); pos[1] = Math::Vector(3.6f, 4.0f, -2.0f); @@ -2942,6 +3029,17 @@ void COldObject::UpdateSelectParticle() pos[0] = Math::Vector(4.9f, 3.5f, 2.5f); pos[1] = Math::Vector(4.9f, 3.5f, -2.5f); } + else if ( m_type == OBJECT_MOBILEwt || + m_type == OBJECT_MOBILEtt || + m_type == OBJECT_MOBILEft || + m_type == OBJECT_MOBILEit || + GetTrainer()) // trainer ? + { + pos[0] = Math::Vector(4.2f, 2.5f, 1.2f); + pos[1] = Math::Vector(4.2f, 2.5f, -1.2f); + dim[0].x = 1.5f; + dim[1].x = 1.5f; + } else { pos[0] = Math::Vector(4.2f, 2.5f, 1.5f); @@ -2949,57 +3047,72 @@ void COldObject::UpdateSelectParticle() } // Red back lens - if ( m_type == OBJECT_MOBILEfa || - m_type == OBJECT_MOBILEfc || - m_type == OBJECT_MOBILEfi || - m_type == OBJECT_MOBILEfs || - m_type == OBJECT_MOBILEft ) // flying? + if ( m_type == OBJECT_MOBILEwt || + m_type == OBJECT_MOBILEtt || + m_type == OBJECT_MOBILEft || + m_type == OBJECT_MOBILEit || + GetTrainer()) // trainer? + { + pos[2] = Math::Vector(-4.0f, 2.5f, 2.2f); + pos[3] = Math::Vector(-4.0f, 2.5f, -2.2f); + } + else if ( m_type == OBJECT_MOBILEfa || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEfc || + m_type == OBJECT_MOBILEfi || + m_type == OBJECT_MOBILEfs ) // flying? { pos[2] = Math::Vector(-4.0f, 3.1f, 4.5f); pos[3] = Math::Vector(-4.0f, 3.1f, -4.5f); dim[2].x = 0.6f; dim[3].x = 0.6f; } - if ( m_type == OBJECT_MOBILEwa || - m_type == OBJECT_MOBILEwc || - m_type == OBJECT_MOBILEwi || - m_type == OBJECT_MOBILEws ) // wheels? + else if ( m_type == OBJECT_MOBILEwa || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEwc || + m_type == OBJECT_MOBILEwi || + m_type == OBJECT_MOBILEws ) // wheels? { pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f); pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f); } - if ( m_type == OBJECT_MOBILEwt ) // wheels? - { - pos[2] = Math::Vector(-4.0f, 2.5f, 2.2f); - pos[3] = Math::Vector(-4.0f, 2.5f, -2.2f); - } - if ( m_type == OBJECT_MOBILEia || - m_type == OBJECT_MOBILEic || - m_type == OBJECT_MOBILEii || - m_type == OBJECT_MOBILEis || - m_type == OBJECT_MOBILEit ) // legs? + else if ( m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEib || + m_type == OBJECT_MOBILEic || + m_type == OBJECT_MOBILEii || + m_type == OBJECT_MOBILEis ) // legs? { pos[2] = Math::Vector(-4.5f, 2.7f, 2.8f); pos[3] = Math::Vector(-4.5f, 2.7f, -2.8f); } - if ( m_type == OBJECT_MOBILEta || - m_type == OBJECT_MOBILEtc || - m_type == OBJECT_MOBILEti || - m_type == OBJECT_MOBILEts || - m_type == OBJECT_MOBILEtt ) // caterpillars? + else if ( m_type == OBJECT_MOBILEta || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEtc || + m_type == OBJECT_MOBILEti || + m_type == OBJECT_MOBILEts ) // caterpillars? { pos[2] = Math::Vector(-3.6f, 4.2f, 3.0f); pos[3] = Math::Vector(-3.6f, 4.2f, -3.0f); } - if ( m_type == OBJECT_MOBILErt || - m_type == OBJECT_MOBILErc || - m_type == OBJECT_MOBILErr || - m_type == OBJECT_MOBILErs ) // large caterpillars? + else if ( m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs ) // large caterpillars? { pos[2] = Math::Vector(-5.0f, 5.2f, 2.5f); pos[3] = Math::Vector(-5.0f, 5.2f, -2.5f); } - if ( m_type == OBJECT_MOBILEsa ) // submarine? + if ( m_type == OBJECT_MOBILErp || ( GetTrainer() && + ( m_type == OBJECT_MOBILErt || + m_type == OBJECT_MOBILErc || + m_type == OBJECT_MOBILErr || + m_type == OBJECT_MOBILErs))) // large caterpillars (trainer)? + { + pos[2] = Math::Vector(-4.6f, 5.2f, 2.6f); + pos[3] = Math::Vector(-4.6f, 5.2f, -2.6f); + } + if ( m_type == OBJECT_MOBILEsa || + m_type == OBJECT_MOBILEst ) // submarine? { pos[2] = Math::Vector(-3.6f, 4.0f, 2.0f); pos[3] = Math::Vector(-3.6f, 4.0f, -2.0f); @@ -3218,6 +3331,10 @@ float COldObject::GetLightningHitProbability() m_type == OBJECT_MOBILEta || m_type == OBJECT_MOBILEwa || m_type == OBJECT_MOBILEia || + m_type == OBJECT_MOBILEfb || + m_type == OBJECT_MOBILEtb || + m_type == OBJECT_MOBILEwb || + m_type == OBJECT_MOBILEib || m_type == OBJECT_MOBILEfc || m_type == OBJECT_MOBILEtc || m_type == OBJECT_MOBILEwc || @@ -3239,6 +3356,9 @@ float COldObject::GetLightningHitProbability() m_type == OBJECT_MOBILEtt || m_type == OBJECT_MOBILEwt || m_type == OBJECT_MOBILEit || + m_type == OBJECT_MOBILErp || + m_type == OBJECT_MOBILEst || + m_type == OBJECT_MOBILEtg || m_type == OBJECT_MOBILEdr ) // robot? { return 0.5f; @@ -3252,8 +3372,7 @@ bool COldObject::IsSelectableByDefault(ObjectType type) type == OBJECT_ANT || type == OBJECT_SPIDER || type == OBJECT_BEE || - type == OBJECT_WORM || - type == OBJECT_MOBILEtg ) + type == OBJECT_WORM ) { return false; } diff --git a/src/object/old_object.h b/src/object/old_object.h index f2873757..cbb25684 100644 --- a/src/object/old_object.h +++ b/src/object/old_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -165,6 +165,7 @@ public: void SetTrainer(bool bEnable) override; bool GetTrainer() override; + bool GetPlusTrainer(); void SetToy(bool bEnable); bool GetToy(); diff --git a/src/object/old_object_interface.cpp b/src/object/old_object_interface.cpp index 49ebdcfa..dbaf0768 100644 --- a/src/object/old_object_interface.cpp +++ b/src/object/old_object_interface.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/old_object_interface.h b/src/object/old_object_interface.h index a1a4bb97..f2c93fdc 100644 --- a/src/object/old_object_interface.h +++ b/src/object/old_object_interface.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/base_alien.cpp b/src/object/subclass/base_alien.cpp index 7c090afc..c18b649f 100644 --- a/src/object/subclass/base_alien.cpp +++ b/src/object/subclass/base_alien.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/base_alien.h b/src/object/subclass/base_alien.h index c7e1205c..2cdd1418 100644 --- a/src/object/subclass/base_alien.h +++ b/src/object/subclass/base_alien.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/base_building.cpp b/src/object/subclass/base_building.cpp index 38faea1b..e60c2381 100644 --- a/src/object/subclass/base_building.cpp +++ b/src/object/subclass/base_building.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -64,6 +64,7 @@ std::unique_ptr CBaseBuilding::Create( { auto obj = MakeUnique(params.id, params.type); + obj->SetTrainer(params.trainer || obj->GetPlusTrainer()); obj->SetTeam(params.team); float height = params.height; diff --git a/src/object/subclass/base_building.h b/src/object/subclass/base_building.h index f4ead94c..780151dc 100644 --- a/src/object/subclass/base_building.h +++ b/src/object/subclass/base_building.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/base_robot.cpp b/src/object/subclass/base_robot.cpp index ac67a185..3f5a21f6 100644 --- a/src/object/subclass/base_robot.cpp +++ b/src/object/subclass/base_robot.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -65,7 +65,7 @@ std::unique_ptr CBaseRobot::Create( } else { - obj->SetTrainer(params.trainer); + obj->SetTrainer(params.trainer || obj->GetPlusTrainer()); } obj->SetToy(params.toy); diff --git a/src/object/subclass/base_robot.h b/src/object/subclass/base_robot.h index 073d36d1..90d79f83 100644 --- a/src/object/subclass/base_robot.h +++ b/src/object/subclass/base_robot.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/base_vehicle.cpp b/src/object/subclass/base_vehicle.cpp index 07601ac6..d0083d7a 100644 --- a/src/object/subclass/base_vehicle.cpp +++ b/src/object/subclass/base_vehicle.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/base_vehicle.h b/src/object/subclass/base_vehicle.h index b35597d7..7f8493d4 100644 --- a/src/object/subclass/base_vehicle.h +++ b/src/object/subclass/base_vehicle.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/exchange_post.cpp b/src/object/subclass/exchange_post.cpp index 6059bc57..940419f6 100644 --- a/src/object/subclass/exchange_post.cpp +++ b/src/object/subclass/exchange_post.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/exchange_post.h b/src/object/subclass/exchange_post.h index 48113cc7..05989863 100644 --- a/src/object/subclass/exchange_post.h +++ b/src/object/subclass/exchange_post.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/shielder.cpp b/src/object/subclass/shielder.cpp index 7cb79af0..e52b8779 100644 --- a/src/object/subclass/shielder.cpp +++ b/src/object/subclass/shielder.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -52,7 +52,7 @@ std::unique_ptr CShielder::Create( auto obj = MakeUnique(params.id); obj->SetTeam(params.team); - obj->SetTrainer(params.trainer); + obj->SetTrainer(params.trainer || obj->GetPlusTrainer()); obj->SetToy(params.toy); auto physics = MakeUnique(obj.get()); diff --git a/src/object/subclass/shielder.h b/src/object/subclass/shielder.h index 4179e43d..e1648c9e 100644 --- a/src/object/subclass/shielder.h +++ b/src/object/subclass/shielder.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/static_object.cpp b/src/object/subclass/static_object.cpp index 5b96a5aa..fbbaf09e 100644 --- a/src/object/subclass/static_object.cpp +++ b/src/object/subclass/static_object.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/subclass/static_object.h b/src/object/subclass/static_object.h index c894ef2e..6ef19f36 100644 --- a/src/object/subclass/static_object.h +++ b/src/object/subclass/static_object.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/task.cpp b/src/object/task/task.cpp index 72f507a5..6fd858ac 100644 --- a/src/object/task/task.cpp +++ b/src/object/task/task.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/task.h b/src/object/task/task.h index 3132b13a..2b77fa80 100644 --- a/src/object/task/task.h +++ b/src/object/task/task.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskadvance.cpp b/src/object/task/taskadvance.cpp index 98483a92..ed72eccc 100644 --- a/src/object/task/taskadvance.cpp +++ b/src/object/task/taskadvance.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskadvance.h b/src/object/task/taskadvance.h index 689f4b88..6569b26d 100644 --- a/src/object/task/taskadvance.h +++ b/src/object/task/taskadvance.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp index 76df10d2..b1ee0037 100644 --- a/src/object/task/taskbuild.cpp +++ b/src/object/task/taskbuild.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -86,7 +86,7 @@ CTaskBuild::~CTaskBuild() // Creates a building. -void CTaskBuild::CreateBuilding(Math::Vector pos, float angle) +void CTaskBuild::CreateBuilding(Math::Vector pos, float angle, bool trainer) { ObjectCreateParams params; params.pos = pos; @@ -94,6 +94,7 @@ void CTaskBuild::CreateBuilding(Math::Vector pos, float angle) params.type = m_type; params.power = 0.0f; params.team = m_object->GetTeam(); + params.trainer = trainer; m_building = CObjectManager::GetInstancePointer()->CreateObject(params); m_building->SetLock(true); // not yet usable @@ -110,6 +111,7 @@ void CTaskBuild::CreateBuilding(Math::Vector pos, float angle) if ( m_type == OBJECT_NUCLEAR ) m_buildingHeight = 40.0f; if ( m_type == OBJECT_PARA ) m_buildingHeight = 68.0f; if ( m_type == OBJECT_INFO ) m_buildingHeight = 19.0f; + if ( m_type == OBJECT_SAFE ) m_buildingHeight = 16.0f; if ( m_type == OBJECT_DESTROYER) m_buildingHeight = 35.0f; if ( m_type == OBJECT_HUSTON ) m_buildingHeight = 45.0f; m_buildingHeight *= 0.25f; @@ -202,9 +204,9 @@ void CTaskBuild::BlackLight() bool CTaskBuild::EventProcess(const Event &event) { Math::Matrix* mat; - Math::Vector pos, dir, speed; + Math::Vector pos, dir, speed, pv, pm, tilt; Math::Point dim; - float a, g, cirSpeed, dist, linSpeed; + float a, g, cirSpeed, dist, linSpeed, diff; if ( m_engine->GetPause() ) return true; if ( event.type != EVENT_FRAME ) return true; @@ -246,8 +248,16 @@ bool CTaskBuild::EventProcess(const Event &event) { dist = Math::Distance(m_object->GetPosition(), m_metal->GetPosition()); linSpeed = 0.0f; - if ( dist > 30.0f ) linSpeed = 1.0f; - if ( dist < 30.0f ) linSpeed = -1.0f; + if ( m_physics->GetLand() ) + { + if ( dist > 30.0f ) linSpeed = 1.0f; + if ( dist < 30.0f ) linSpeed = -1.0f; + } + else + { + if ( dist > 55.0f ) linSpeed = 0.5f; + if ( dist < 35.0f ) linSpeed = -0.5f; + } m_physics->SetMotorSpeedX(linSpeed); // forward/backward return true; } @@ -279,7 +289,7 @@ bool CTaskBuild::EventProcess(const Event &event) pos = m_metal->GetPosition(); a = m_object->GetRotationY(); - CreateBuilding(pos, a+Math::PI); + CreateBuilding(pos, a+Math::PI, m_object->GetTrainer()); CreateLight(); } @@ -321,11 +331,12 @@ bool CTaskBuild::EventProcess(const Event &event) mat = m_object->GetWorldMatrix(14); break; - case OBJECT_MOBILEfa: - case OBJECT_MOBILEta: - case OBJECT_MOBILEwa: - case OBJECT_MOBILEia: - mat = m_object->GetWorldMatrix(3); + case OBJECT_MOBILEfb: + case OBJECT_MOBILEtb: + case OBJECT_MOBILEwb: + case OBJECT_MOBILEib: + mat = m_object->GetWorldMatrix(1); + pos.y += 2.0f; break; default: @@ -347,6 +358,16 @@ bool CTaskBuild::EventProcess(const Event &event) } } + if(m_object->GetType() == OBJECT_MOBILEfb && m_object->GetReactorRange()<0.2f && m_phase != TBP_MOVE) + { + pv = m_object->GetPosition(); + pm = m_metal->GetPosition(); + dist = Math::Distance(pv, pm); + diff = pm.y - 8.0f - pv.y; + tilt = m_object->GetRotation(); + m_object->StartTaskGunGoal(asin(diff/dist)-tilt.z, 0.0f); + } + return true; } @@ -372,7 +393,7 @@ Error CTaskBuild::Start(ObjectType type) pos = m_object->GetPosition(); if ( pos.y < m_water->GetLevel() ) return ERR_BUILD_WATER; - if ( !m_physics->GetLand() ) return ERR_BUILD_FLY; + if ( !m_physics->GetLand() && m_object->GetType()!=OBJECT_MOBILEfb) return ERR_BUILD_FLY; speed = m_physics->GetMotorSpeed(); if ( speed.x != 0.0f || @@ -392,15 +413,17 @@ Error CTaskBuild::Start(ObjectType type) err = FlatFloor(); if ( err != ERR_OK ) return err; + pv = m_object->GetPosition(); + pm = m_metal->GetPosition(); + if(!m_physics->GetLand() && fabs(pm.y-pv.y)>8.0f) return ERR_BUILD_METALAWAY; + m_metal->SetLock(true); // not usable m_camera->StartCentering(m_object, Math::PI*0.15f, 99.9f, 0.0f, 1.0f); m_phase = TBP_TURN; // rotation necessary preliminary m_angleY = oAngle; // angle was reached - pv = m_object->GetPosition(); pv.y += 8.3f; - pm = m_metal->GetPosition(); m_angleZ = Math::RotateAngle(Math::DistanceProjected(pv, pm), fabs(pv.y-pm.y)); m_physics->SetFreeze(true); // it does not move @@ -415,7 +438,8 @@ Error CTaskBuild::Start(ObjectType type) Error CTaskBuild::IsEnded() { CAuto* automat; - float angle, dist, time; + float angle, dist, time, diff; + Math::Vector pv, pm, tilt; if ( m_engine->GetPause() ) return ERR_CONTINUE; if ( m_bError ) return ERR_STOP; @@ -450,7 +474,19 @@ Error CTaskBuild::IsEnded() { dist = Math::Distance(m_object->GetPosition(), m_metal->GetPosition()); - if ( dist >= 25.0f && dist <= 35.0f ) + if ( !m_physics->GetLand()) + { + if(dist >= 35.0f && dist <= 55.0f) + { + m_physics->SetMotorSpeedX(0.0f); + m_motion->SetAction(MHS_GUN); // takes gun + + m_phase = TBP_TAKE; + m_speed = 1.0f/1.0f; + m_progress = 0.0f; + } + } + else if ( dist >= 25.0f && dist <= 35.0f) { m_physics->SetMotorSpeedX(0.0f); m_motion->SetAction(MHS_GUN); // takes gun @@ -482,6 +518,19 @@ Error CTaskBuild::IsEnded() m_object->SetPartPosition(14, Math::Vector(0.6f, 0.1f, 0.3f)); m_object->SetPartRotationZ(14, 0.0f); } + if (m_object->GetType() == OBJECT_MOBILEfb || + m_object->GetType() == OBJECT_MOBILEib || + m_object->GetType() == OBJECT_MOBILEtb || + m_object->GetType() == OBJECT_MOBILEwb) + { + m_object->SetObjectParent(1, 0); + pv = m_object->GetPosition(); + pm = m_metal->GetPosition(); + dist = Math::Distance(pv, pm); + diff = pm.y - 8.0f - pv.y; + tilt = m_object->GetRotation(); + if(dist) m_object->StartTaskGunGoal(asin(diff/dist)-tilt.z, 0.0f); + } m_phase = TBP_PREP; m_speed = 1.0f/1.0f; @@ -542,6 +591,8 @@ Error CTaskBuild::IsEnded() m_object->SetPartPosition(14, Math::Vector(-1.5f, 0.3f, -1.35f)); m_object->SetPartRotationZ(14, Math::PI); } + else + m_object->StartTaskGunGoal(0.0f, 0.0f); if ( m_type == OBJECT_FACTORY || m_type == OBJECT_RESEARCH || @@ -632,6 +683,7 @@ Error CTaskBuild::FlatFloor() if ( m_type == OBJECT_NUCLEAR ) radius = 20.0f; if ( m_type == OBJECT_PARA ) radius = 20.0f; if ( m_type == OBJECT_INFO ) radius = 5.0f; + if ( m_type == OBJECT_SAFE ) radius = 20.0f; if ( m_type == OBJECT_DESTROYER) radius = 20.0f; //if ( radius == 0.0f ) return ERR_UNKNOWN; diff --git a/src/object/task/taskbuild.h b/src/object/task/taskbuild.h index 977da0f2..a1ede52e 100644 --- a/src/object/task/taskbuild.h +++ b/src/object/task/taskbuild.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -61,7 +61,7 @@ public: protected: Error FlatFloor(); - void CreateBuilding(Math::Vector pos, float angle); + void CreateBuilding(Math::Vector pos, float angle, bool trainer); void CreateLight(); void BlackLight(); CObject* SearchMetalObject(float &angle, float dMin, float dMax, float aLimit, Error &err); diff --git a/src/object/task/taskdeletemark.cpp b/src/object/task/taskdeletemark.cpp index 2e87f829..4b9ced5e 100644 --- a/src/object/task/taskdeletemark.cpp +++ b/src/object/task/taskdeletemark.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include "common/global.h" #include "graphics/engine/particle.h" +#include "graphics/engine/pyro_manager.h" #include "graphics/engine/terrain.h" #include "level/robotmain.h" @@ -88,6 +89,6 @@ void CTaskDeleteMark::DeleteMark() if (obj != nullptr) { - CObjectManager::GetInstancePointer()->DeleteObject(obj); + m_engine->GetPyroManager()->Create(Gfx::PT_WPCHECK, obj); } } diff --git a/src/object/task/taskdeletemark.h b/src/object/task/taskdeletemark.h index de2967b4..1e7b7f1c 100644 --- a/src/object/task/taskdeletemark.h +++ b/src/object/task/taskdeletemark.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskfire.cpp b/src/object/task/taskfire.cpp index 590ce94e..87730880 100644 --- a/src/object/task/taskfire.cpp +++ b/src/object/task/taskfire.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -317,7 +317,7 @@ Error CTaskFire::Start(float delay) CObject* power = dynamic_cast(m_object)->GetPower(); if (power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer)) return ERR_FIRE_ENERGY; - energy = dynamic_cast(power)->GetEnergy(); + energy = dynamic_cast(*power).GetEnergy(); if ( m_bOrganic ) fire = m_delay*ENERGY_FIREi; else if ( m_bRay ) fire = m_delay*ENERGY_FIREr; else fire = m_delay*ENERGY_FIRE; diff --git a/src/object/task/taskfire.h b/src/object/task/taskfire.h index a1a5550c..bc0a6f06 100644 --- a/src/object/task/taskfire.h +++ b/src/object/task/taskfire.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskfireant.cpp b/src/object/task/taskfireant.cpp index 35ddac79..99bc7d0b 100644 --- a/src/object/task/taskfireant.cpp +++ b/src/object/task/taskfireant.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -60,7 +60,7 @@ bool CTaskFireAnt::EventProcess(const Event &event) if ( event.type != EVENT_FRAME ) return true; if ( m_bError ) return false; - if ( dynamic_cast(m_object)->GetFixed() ) // insect on its back? + if ( dynamic_cast(*m_object).GetFixed() ) // insect on its back? { m_bError = true; return false; @@ -100,7 +100,7 @@ Error CTaskFireAnt::Start(Math::Vector impact) if ( type != OBJECT_ANT ) return ERR_WRONG_BOT; // Insect on its back? - if ( dynamic_cast(m_object)->GetFixed() ) return ERR_WRONG_BOT; + if ( dynamic_cast(*m_object).GetFixed() ) return ERR_WRONG_BOT; m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); @@ -130,7 +130,7 @@ Error CTaskFireAnt::IsEnded() if ( m_engine->GetPause() ) return ERR_CONTINUE; if ( m_bError ) return ERR_STOP; - if ( dynamic_cast(m_object)->GetFixed() ) return ERR_STOP; // insect on its back? + if ( dynamic_cast(*m_object).GetFixed() ) return ERR_STOP; // insect on its back? if ( m_phase == TFA_TURN ) // rotation ? { diff --git a/src/object/task/taskfireant.h b/src/object/task/taskfireant.h index 949a8935..8d57fca5 100644 --- a/src/object/task/taskfireant.h +++ b/src/object/task/taskfireant.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskflag.cpp b/src/object/task/taskflag.cpp index 8a4d58b6..b2872159 100644 --- a/src/object/task/taskflag.cpp +++ b/src/object/task/taskflag.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -61,6 +61,24 @@ bool CTaskFlag::EventProcess(const Event &event) m_time += event.rTime; + ObjectType type = m_object->GetType(); + if ( type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis ) + { + float angle = 110.0f*Math::PI/180.0f; + float diff = -10.0f*Math::PI/180.0f; + if ( m_time <= 0.5f ) + { + m_object->SetPartRotationZ(1, angle+diff*m_time*2.0f); + } + else if ( m_time >= 1.5f && m_time < 2.0f ) + { + m_object->SetPartRotationZ(1, angle+diff*(2.0f-m_time)*2.0f); + } + } + return true; } @@ -104,7 +122,32 @@ Error CTaskFlag::Start(TaskFlagOrder order, int rank) m_bError = false; - m_motion->SetAction(MHS_FLAG); // sets/removes flag + switch ( m_object->GetType() ) // sets/removes flag + { + case OBJECT_HUMAN: + case OBJECT_TECH: + m_motion->SetAction(MHS_FLAG); + break; + + case OBJECT_MOBILEws: + case OBJECT_MOBILEts: + case OBJECT_MOBILEfs: + case OBJECT_MOBILEis: + { + int i = m_sound->Play(SOUND_MANIP, m_object->GetPosition(), 0.0f, 0.3f, true); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.3f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f, 1.0f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.1f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.5f, 1.0f, 0.3f, SOPER_CONTINUE); + m_sound->AddEnvelope(i, 0.0f, 0.3f, 0.1f, SOPER_STOP); + break; + } + + default: + break; + } m_camera->StartCentering(m_object, Math::PI*0.3f, 99.9f, 0.0f, 0.5f); return ERR_OK; @@ -127,7 +170,23 @@ Error CTaskFlag::IsEnded() bool CTaskFlag::Abort() { - m_motion->SetAction(-1); + switch ( m_object->GetType() ) + { + case OBJECT_HUMAN: + case OBJECT_TECH: + m_motion->SetAction(-1); + break; + + case OBJECT_MOBILEws: + case OBJECT_MOBILEts: + case OBJECT_MOBILEfs: + case OBJECT_MOBILEis: + m_object->SetPartRotationZ(1, 110.0f*Math::PI/180.0f); + break; + + default: + break; + } m_camera->StopCentering(m_object, 2.0f); return true; } @@ -190,7 +249,18 @@ Error CTaskFlag::CreateFlag(int rank) }; Math::Matrix* mat = m_object->GetWorldMatrix(0); - Math::Vector pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f)); + Math::Vector pos; + switch ( m_object->GetType() ) + { + case OBJECT_HUMAN: + case OBJECT_TECH: + pos = Transform(*mat, Math::Vector(4.0f, 0.0f, 0.0f)); + break; + + default: + pos = Transform(*mat, Math::Vector(6.0f, 0.0f, 0.0f)); + break; + } CObject* pObj = SearchNearest(pos, OBJECT_NULL); if ( pObj != nullptr ) diff --git a/src/object/task/taskflag.h b/src/object/task/taskflag.h index 00658ce5..dc1621bf 100644 --- a/src/object/task/taskflag.h +++ b/src/object/task/taskflag.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp index e1b39540..d2e64667 100644 --- a/src/object/task/taskgoto.cpp +++ b/src/object/task/taskgoto.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -556,6 +556,10 @@ CObject* CTaskGoto::WormSearch(Math::Vector &impact) oType != OBJECT_MOBILEta && oType != OBJECT_MOBILEwa && oType != OBJECT_MOBILEia && + oType != OBJECT_MOBILEfb && + oType != OBJECT_MOBILEtb && + oType != OBJECT_MOBILEwb && + oType != OBJECT_MOBILEib && oType != OBJECT_MOBILEfc && oType != OBJECT_MOBILEtc && oType != OBJECT_MOBILEwc && @@ -578,6 +582,8 @@ CObject* CTaskGoto::WormSearch(Math::Vector &impact) oType != OBJECT_MOBILEtt && oType != OBJECT_MOBILEwt && oType != OBJECT_MOBILEit && + oType != OBJECT_MOBILErp && + oType != OBJECT_MOBILEst && oType != OBJECT_MOBILEdr && oType != OBJECT_DERRICK && oType != OBJECT_STATION && @@ -721,7 +727,8 @@ Error CTaskGoto::Start(Math::Vector goal, float altitude, type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp ) { m_bApprox = true; } @@ -1164,6 +1171,10 @@ bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance) type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEfs || type == OBJECT_MOBILEts || type == OBJECT_MOBILEws || @@ -1186,10 +1197,12 @@ bool CTaskGoto::AdjustTarget(CObject* pObj, Math::Vector &pos, float &distance) type == OBJECT_MOBILEtt || type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEst || type == OBJECT_MOBILEdr ) { assert(pObj->Implements(ObjectInterfaceType::Powered)); - pos = dynamic_cast(pObj)->GetPowerPosition(); + pos = dynamic_cast(*pObj).GetPowerPosition(); pos.x -= TAKE_DIST+TAKE_DIST_OTHER+distance; mat = pObj->GetWorldMatrix(0); pos = Transform(*mat, pos); @@ -1432,6 +1445,7 @@ void CTaskGoto::ComputeRepulse(Math::Point &dir) fac = 2.0f; if ( iType == OBJECT_MOBILEwa || + iType == OBJECT_MOBILEwb || iType == OBJECT_MOBILEwc || iType == OBJECT_MOBILEwi || iType == OBJECT_MOBILEws || @@ -1441,6 +1455,7 @@ void CTaskGoto::ComputeRepulse(Math::Point &dir) fac = 1.5f; } if ( iType == OBJECT_MOBILEta || + iType == OBJECT_MOBILEtb || iType == OBJECT_MOBILEtc || iType == OBJECT_MOBILEti || iType == OBJECT_MOBILEts || @@ -1451,6 +1466,7 @@ void CTaskGoto::ComputeRepulse(Math::Point &dir) fac = 1.5f; } if ( iType == OBJECT_MOBILEfa || + iType == OBJECT_MOBILEfb || iType == OBJECT_MOBILEfc || iType == OBJECT_MOBILEfi || iType == OBJECT_MOBILEfs || @@ -1468,6 +1484,7 @@ void CTaskGoto::ComputeRepulse(Math::Point &dir) } } if ( iType == OBJECT_MOBILEia || + iType == OBJECT_MOBILEib || iType == OBJECT_MOBILEic || iType == OBJECT_MOBILEii || iType == OBJECT_MOBILEis || @@ -1962,6 +1979,7 @@ void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy) type = m_object->GetType(); if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwb || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEws || type == OBJECT_MOBILEwi || @@ -1972,6 +1990,7 @@ void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy) } if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || type == OBJECT_MOBILEts ) // caterpillars? @@ -1982,12 +2001,14 @@ void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy) if ( type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) // large caterpillars? + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp ) // large caterpillars? { aLimit = 35.0f*Math::PI/180.0f; } - if ( type == OBJECT_MOBILEsa ) // submarine caterpillars? + if ( type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst ) // submarine caterpillars? { aLimit = 35.0f*Math::PI/180.0f; bAcceptWater = true; @@ -1999,6 +2020,7 @@ void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy) } if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfb || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEfs || type == OBJECT_MOBILEfi || @@ -2009,6 +2031,7 @@ void CTaskGoto::BitmapTerrain(int minx, int miny, int maxx, int maxy) } if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEis || type == OBJECT_MOBILEii ) // insect legs? diff --git a/src/object/task/taskgoto.h b/src/object/task/taskgoto.h index 296fec92..9b9f58c4 100644 --- a/src/object/task/taskgoto.h +++ b/src/object/task/taskgoto.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -147,7 +147,7 @@ protected: int m_bmTotal = 0; // number of points in m_bmPoints int m_bmIndex = 0; // index in m_bmPoints Math::Vector m_bmPoints[MAXPOINTS+2]; - char m_bmIter[MAXPOINTS+2] = {}; + signed char m_bmIter[MAXPOINTS+2] = {}; int m_bmIterCounter = 0; CObject* m_bmCargoObject = nullptr; float m_bmFinalMove = 0.0f; // final advance distance diff --git a/src/object/task/taskgungoal.cpp b/src/object/task/taskgungoal.cpp index 72595509..33e4f8a2 100644 --- a/src/object/task/taskgungoal.cpp +++ b/src/object/task/taskgungoal.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskgungoal.h b/src/object/task/taskgungoal.h index 3a9d65a7..c60311ec 100644 --- a/src/object/task/taskgungoal.h +++ b/src/object/task/taskgungoal.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskinfo.cpp b/src/object/task/taskinfo.cpp index 9ce99298..242e5e2c 100644 --- a/src/object/task/taskinfo.cpp +++ b/src/object/task/taskinfo.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskinfo.h b/src/object/task/taskinfo.h index 3a66faf9..3caf3af5 100644 --- a/src/object/task/taskinfo.h +++ b/src/object/task/taskinfo.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskmanip.cpp b/src/object/task/taskmanip.cpp index 16615ebd..aa62ef9e 100644 --- a/src/object/task/taskmanip.cpp +++ b/src/object/task/taskmanip.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -259,7 +259,7 @@ void CTaskManip::InitAngle() float energy = GetObjectEnergy(m_object); if ( energy == 0.0f ) { - m_speed *= 0.7f; // slower if more energy! + m_speed *= 0.7f; // slower if no more energy! } } @@ -304,8 +304,8 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm) assert(other->Implements(ObjectInterfaceType::Transportable)); m_object->SetCargo(other); // takes the ball - dynamic_cast(other)->SetTransporter(m_object); - dynamic_cast(other)->SetTransporterPart(0); // taken with the base + dynamic_cast(*other).SetTransporter(m_object); + dynamic_cast(*other).SetTransporterPart(0); // taken with the base other->SetPosition(Math::Vector(0.0f, -3.0f, 0.0f)); } else @@ -314,7 +314,7 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm) assert(other->Implements(ObjectInterfaceType::Transportable)); m_object->SetCargo(nullptr); // lick the ball - dynamic_cast(other)->SetTransporter(nullptr); + dynamic_cast(*other).SetTransporter(nullptr); pos = m_object->GetPosition(); pos.y -= 3.0f; other->SetPosition(pos); @@ -903,7 +903,7 @@ CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos, ObjectType type = pObj->GetType(); if ( !pObj->Implements(ObjectInterfaceType::Powered) ) continue; - CObject* power = dynamic_cast(pObj)->GetPower(); + CObject* power = dynamic_cast(*pObj).GetPower(); if (power != nullptr) { if (power->GetLock()) continue; @@ -911,7 +911,7 @@ CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos, } mat = pObj->GetWorldMatrix(0); - Math::Vector oPos = Transform(*mat, dynamic_cast(pObj)->GetPowerPosition()); + Math::Vector oPos = Transform(*mat, dynamic_cast(*pObj).GetPowerPosition()); oAngle = pObj->GetRotationY(); if ( type == OBJECT_TOWER || @@ -946,7 +946,7 @@ CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos, angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) { - Math::Vector powerPos = dynamic_cast(pObj)->GetPowerPosition(); + Math::Vector powerPos = dynamic_cast(*pObj).GetPowerPosition(); height = powerPos.y; pos = oPos; return pObj; @@ -974,8 +974,8 @@ bool CTaskManip::TransporterTakeObject() if ( m_object->GetType() == OBJECT_HUMAN || m_object->GetType() == OBJECT_TECH ) { - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(4); // takes with the hand + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(4); // takes with the hand cargo->SetPosition(Math::Vector(1.7f, -0.5f, 1.1f)); cargo->SetRotationY(0.1f); @@ -984,8 +984,8 @@ bool CTaskManip::TransporterTakeObject() } else if ( m_bSubm ) { - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(2); // takes with the right claw + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(2); // takes with the right claw Math::Vector pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative cargo->SetPosition(pos); @@ -995,8 +995,8 @@ bool CTaskManip::TransporterTakeObject() } else { - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(3); // takes with the hand + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(3); // takes with the hand Math::Vector pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) cargo->SetPosition(pos); @@ -1020,8 +1020,8 @@ bool CTaskManip::TransporterTakeObject() if ( m_bSubm ) { - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(2); // takes with the right claw + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(2); // takes with the right claw pos = Math::Vector(1.1f, -1.0f, 1.0f); // relative cargo->SetPosition(pos); @@ -1031,8 +1031,8 @@ bool CTaskManip::TransporterTakeObject() } else { - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(3); // takes with the hand + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(3); // takes with the hand pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) cargo->SetPosition(pos); @@ -1054,8 +1054,8 @@ bool CTaskManip::TransporterTakeObject() m_cargoType = cargo->GetType(); - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(3); // takes with the hand + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(3); // takes with the hand pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) cargo->SetPosition(pos); @@ -1080,7 +1080,7 @@ bool CTaskManip::TransporterTakeObject() cargo->SetRotationX(0.0f); cargo->SetRotationZ(Math::PI/2.0f); cargo->SetRotationY(0.0f); - dynamic_cast(cargo)->SetTransporterPart(3); // takes with the hand + dynamic_cast(*cargo).SetTransporterPart(3); // takes with the hand m_object->SetPower(nullptr); m_object->SetCargo(cargo); // takes @@ -1094,15 +1094,15 @@ bool CTaskManip::TransporterTakeObject() if (other == nullptr) return false; assert(other->Implements(ObjectInterfaceType::Powered)); - CObject* cargo = dynamic_cast(other)->GetPower(); + CObject* cargo = dynamic_cast(*other).GetPower(); if (cargo == nullptr) return false; // the other does not have a battery? assert(cargo->Implements(ObjectInterfaceType::Transportable)); m_cargoType = cargo->GetType(); - dynamic_cast(other)->SetPower(nullptr); - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(3); // takes with the hand + dynamic_cast(*other).SetPower(nullptr); + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(3); // takes with the hand pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4) cargo->SetPosition(pos); @@ -1137,7 +1137,7 @@ bool CTaskManip::TransporterDeposeObject() cargo->SetRotationZ(0.0f); cargo->FloorAdjust(); // plate well on the ground - dynamic_cast(cargo)->SetTransporter(nullptr); + dynamic_cast(*cargo).SetTransporter(nullptr); m_object->SetCargo(nullptr); // deposit } @@ -1157,7 +1157,7 @@ bool CTaskManip::TransporterDeposeObject() cargo->SetRotationX(0.0f); cargo->SetRotationZ(0.0f); - dynamic_cast(cargo)->SetTransporter(nullptr); + dynamic_cast(*cargo).SetTransporter(nullptr); m_object->SetCargo(nullptr); // deposit } @@ -1172,8 +1172,8 @@ bool CTaskManip::TransporterDeposeObject() if (m_object->GetPower() != nullptr) return false; - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(0); // carried by the base + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(0); // carried by the base cargo->SetPosition(m_object->GetPowerPosition()); cargo->SetRotationY(0.0f); @@ -1193,7 +1193,7 @@ bool CTaskManip::TransporterDeposeObject() if (other == nullptr) return false; assert(other->Implements(ObjectInterfaceType::Powered)); - CObject* cargo = dynamic_cast(other)->GetPower(); + CObject* cargo = dynamic_cast(*other).GetPower(); if (cargo != nullptr) return false; // the other already has a battery? cargo = m_object->GetCargo(); @@ -1202,14 +1202,14 @@ bool CTaskManip::TransporterDeposeObject() m_cargoType = cargo->GetType(); - dynamic_cast(other)->SetPower(cargo); - dynamic_cast(cargo)->SetTransporter(other); + dynamic_cast(*other).SetPower(cargo); + dynamic_cast(*cargo).SetTransporter(other); - cargo->SetPosition(dynamic_cast(other)->GetPowerPosition()); + cargo->SetPosition(dynamic_cast(*other).GetPowerPosition()); cargo->SetRotationY(0.0f); cargo->SetRotationX(0.0f); cargo->SetRotationZ(0.0f); - dynamic_cast(cargo)->SetTransporterPart(0); // carried by the base + dynamic_cast(*cargo).SetTransporterPart(0); // carried by the base m_object->SetCargo(nullptr); // deposit } diff --git a/src/object/task/taskmanip.h b/src/object/task/taskmanip.h index 946a3ec6..165ff653 100644 --- a/src/object/task/taskmanip.h +++ b/src/object/task/taskmanip.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskpen.cpp b/src/object/task/taskpen.cpp index 93defbf1..a653ad49 100644 --- a/src/object/task/taskpen.cpp +++ b/src/object/task/taskpen.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskpen.h b/src/object/task/taskpen.h index 91ba541d..758791e0 100644 --- a/src/object/task/taskpen.h +++ b/src/object/task/taskpen.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskrecover.cpp b/src/object/task/taskrecover.cpp index 872632ed..f56503d5 100644 --- a/src/object/task/taskrecover.cpp +++ b/src/object/task/taskrecover.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -194,7 +194,7 @@ Error CTaskRecover::Start() CObject* power = dynamic_cast(m_object)->GetPower(); if (power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer)) return ERR_RECOVER_ENERGY; - float energy = dynamic_cast(power)->GetEnergy(); + float energy = dynamic_cast(*power).GetEnergy(); if ( energy < ENERGY_RECOVER+0.05f ) return ERR_RECOVER_ENERGY; Math::Matrix* mat = m_object->GetWorldMatrix(0); @@ -376,5 +376,5 @@ bool CTaskRecover::Abort() CObject* CTaskRecover::SearchRuin() { - return CObjectManager::GetInstancePointer()->FindNearest(nullptr, m_recoverPos, {OBJECT_RUINmobilew1, OBJECT_RUINmobilew2, OBJECT_RUINmobilet1, OBJECT_RUINmobilet2, OBJECT_RUINmobiler1, OBJECT_RUINmobiler2, OBJECT_RUINdoor, OBJECT_RUINsupport, OBJECT_RUINradar}, 40.0f/g_unit); + return CObjectManager::GetInstancePointer()->FindNearest(nullptr, m_recoverPos, {OBJECT_RUINmobilew1, OBJECT_RUINmobilew2, OBJECT_RUINmobilet1, OBJECT_RUINmobilet2, OBJECT_RUINmobiler1, OBJECT_RUINmobiler2}, 40.0f/g_unit); } diff --git a/src/object/task/taskrecover.h b/src/object/task/taskrecover.h index 001f14e9..98eb4e8a 100644 --- a/src/object/task/taskrecover.h +++ b/src/object/task/taskrecover.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/tasksearch.cpp b/src/object/task/tasksearch.cpp index e8a5596e..1cc310fe 100644 --- a/src/object/task/tasksearch.cpp +++ b/src/object/task/tasksearch.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/tasksearch.h b/src/object/task/tasksearch.h index d4c9c4d9..3b6f3146 100644 --- a/src/object/task/tasksearch.h +++ b/src/object/task/tasksearch.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp index 54089418..916a5158 100644 --- a/src/object/task/taskshield.cpp +++ b/src/object/task/taskshield.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -309,7 +309,7 @@ Error CTaskShield::Start(TaskShieldMode mode, float delay) CObject* power = m_object->GetPower(); if (power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer)) return ERR_SHIELD_ENERGY; - float energy = dynamic_cast(power)->GetEnergy(); + float energy = dynamic_cast(*power).GetEnergy(); if ( energy == 0.0f ) return ERR_SHIELD_ENERGY; Math::Matrix* mat = m_object->GetWorldMatrix(0); diff --git a/src/object/task/taskshield.h b/src/object/task/taskshield.h index 97533bfb..e800ac03 100644 --- a/src/object/task/taskshield.h +++ b/src/object/task/taskshield.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskspiderexplo.cpp b/src/object/task/taskspiderexplo.cpp index 03abddb6..2acab5fd 100644 --- a/src/object/task/taskspiderexplo.cpp +++ b/src/object/task/taskspiderexplo.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -57,7 +57,7 @@ bool CTaskSpiderExplo::EventProcess(const Event &event) if ( event.type != EVENT_FRAME ) return true; // Momentarily stationary object (ant on the back)? - if ( dynamic_cast(m_object)->GetFixed() ) + if ( dynamic_cast(*m_object).GetFixed() ) { m_bError = true; return true; diff --git a/src/object/task/taskspiderexplo.h b/src/object/task/taskspiderexplo.h index ebcf3a25..73374aef 100644 --- a/src/object/task/taskspiderexplo.h +++ b/src/object/task/taskspiderexplo.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/tasktake.cpp b/src/object/task/tasktake.cpp index c67a7e56..6f7360bd 100644 --- a/src/object/task/tasktake.cpp +++ b/src/object/task/tasktake.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -131,9 +131,9 @@ Error CTaskTake::Start() CObject* other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f); if (other != nullptr) assert(other->Implements(ObjectInterfaceType::Powered)); - if (other != nullptr && dynamic_cast(other)->GetPower() != nullptr) + if (other != nullptr && dynamic_cast(*other).GetPower() != nullptr) { - CObject* power = dynamic_cast(other)->GetPower(); + CObject* power = dynamic_cast(*other).GetPower(); type = power->GetType(); if ( type == OBJECT_URANIUM ) return ERR_MANIP_RADIO; assert(power->Implements(ObjectInterfaceType::Transportable)); @@ -161,7 +161,7 @@ Error CTaskTake::Start() CObject* other = SearchFriendObject(oAngle, 1.5f, Math::PI*0.50f); if (other != nullptr) assert(other->Implements(ObjectInterfaceType::Powered)); - if (other != nullptr && dynamic_cast(other)->GetPower() == nullptr ) + if (other != nullptr && dynamic_cast(*other).GetPower() == nullptr ) { //? m_camera->StartCentering(m_object, Math::PI*0.3f, -Math::PI*0.1f, 0.0f, 0.8f); m_arm = TTA_FRIEND; @@ -354,6 +354,10 @@ CObject* CTaskTake::SearchFriendObject(float &angle, type != OBJECT_MOBILEta && type != OBJECT_MOBILEwa && type != OBJECT_MOBILEia && + type != OBJECT_MOBILEfb && + type != OBJECT_MOBILEtb && + type != OBJECT_MOBILEwb && + type != OBJECT_MOBILEib && type != OBJECT_MOBILEfc && type != OBJECT_MOBILEtc && type != OBJECT_MOBILEwc && @@ -376,6 +380,8 @@ CObject* CTaskTake::SearchFriendObject(float &angle, type != OBJECT_MOBILEtt && type != OBJECT_MOBILEwt && type != OBJECT_MOBILEit && + type != OBJECT_MOBILErp && + type != OBJECT_MOBILEst && type != OBJECT_TOWER && type != OBJECT_RESEARCH && type != OBJECT_ENERGY && @@ -384,7 +390,7 @@ CObject* CTaskTake::SearchFriendObject(float &angle, assert(pObj->Implements(ObjectInterfaceType::Powered)); - CObject* power = dynamic_cast(pObj)->GetPower(); + CObject* power = dynamic_cast(*pObj).GetPower(); if (power != nullptr) { if ( power->GetLock() ) continue; @@ -392,7 +398,7 @@ CObject* CTaskTake::SearchFriendObject(float &angle, } Math::Matrix* mat = pObj->GetWorldMatrix(0); - Math::Vector oPos = Math::Transform(*mat, dynamic_cast(pObj)->GetPowerPosition()); + Math::Vector oPos = Math::Transform(*mat, dynamic_cast(*pObj).GetPowerPosition()); float distance = fabs(Math::Distance(oPos, iPos) - (iRad+1.0f)); if ( distance <= dLimit ) @@ -400,7 +406,7 @@ CObject* CTaskTake::SearchFriendObject(float &angle, angle = Math::RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) ) { - Math::Vector powerPos = dynamic_cast(pObj)->GetPowerPosition(); + Math::Vector powerPos = dynamic_cast(*pObj).GetPowerPosition(); m_height = powerPos.y; return pObj; } @@ -419,13 +425,13 @@ bool CTaskTake::TransporterTakeObject() //? cargo = SearchTakeObject(angle, 1.5f, Math::PI*0.04f); float angle = 0.0f; CObject* cargo = SearchTakeObject(angle, 1.5f, Math::PI*0.15f); //OK 1.9 - if (cargo == nullptr) return false; // rien � prendre ? + if (cargo == nullptr) return false; // nothing to take ? assert(cargo->Implements(ObjectInterfaceType::Transportable)); m_cargoType = cargo->GetType(); - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(4); // takes with the hand + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(4); // takes with the hand //? cargo->SetPosition(Math::Vector(2.2f, -1.0f, 1.1f)); cargo->SetPosition(Math::Vector(1.7f, -0.5f, 1.1f)); @@ -443,15 +449,15 @@ bool CTaskTake::TransporterTakeObject() if (other == nullptr) return false; assert(other->Implements(ObjectInterfaceType::Powered)); - CObject* cargo = dynamic_cast(other)->GetPower(); + CObject* cargo = dynamic_cast(*other).GetPower(); if (cargo == nullptr) return false; // the other does not have a battery? assert(cargo->Implements(ObjectInterfaceType::Transportable)); m_cargoType = cargo->GetType(); - dynamic_cast(other)->SetPower(nullptr); - dynamic_cast(cargo)->SetTransporter(m_object); - dynamic_cast(cargo)->SetTransporterPart(4); // takes with the hand + dynamic_cast(*other).SetPower(nullptr); + dynamic_cast(*cargo).SetTransporter(m_object); + dynamic_cast(*cargo).SetTransporterPart(4); // takes with the hand //? cargo->SetPosition(Math::Vector(2.2f, -1.0f, 1.1f)); cargo->SetPosition(Math::Vector(1.7f, -0.5f, 1.1f)); @@ -486,7 +492,7 @@ bool CTaskTake::TransporterDeposeObject() cargo->SetRotationZ(0.0f); cargo->FloorAdjust(); // plate well on the ground - dynamic_cast(cargo)->SetTransporter(nullptr); + dynamic_cast(*cargo).SetTransporter(nullptr); m_object->SetCargo(nullptr); // deposit } @@ -497,7 +503,7 @@ bool CTaskTake::TransporterDeposeObject() if (other == nullptr) return false; assert(other->Implements(ObjectInterfaceType::Powered)); - CObject* cargo = dynamic_cast(other)->GetPower(); + CObject* cargo = dynamic_cast(*other).GetPower(); if (cargo != nullptr) return false; // the other already has a battery? cargo = m_object->GetCargo(); @@ -505,14 +511,14 @@ bool CTaskTake::TransporterDeposeObject() assert(cargo->Implements(ObjectInterfaceType::Transportable)); m_cargoType = cargo->GetType(); - dynamic_cast(other)->SetPower(cargo); - dynamic_cast(cargo)->SetTransporter(other); + dynamic_cast(*other).SetPower(cargo); + dynamic_cast(*cargo).SetTransporter(other); - cargo->SetPosition(dynamic_cast(other)->GetPowerPosition()); + cargo->SetPosition(dynamic_cast(*other).GetPowerPosition()); cargo->SetRotationY(0.0f); cargo->SetRotationX(0.0f); cargo->SetRotationZ(0.0f); - dynamic_cast(cargo)->SetTransporterPart(0); // carried by the base + dynamic_cast(*cargo).SetTransporterPart(0); // carried by the base m_object->SetCargo(nullptr); // deposit } diff --git a/src/object/task/tasktake.h b/src/object/task/tasktake.h index 53813c56..9b461359 100644 --- a/src/object/task/tasktake.h +++ b/src/object/task/tasktake.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp index 6718bb7c..c0160bf8 100644 --- a/src/object/task/taskterraform.cpp +++ b/src/object/task/taskterraform.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -215,7 +215,7 @@ Error CTaskTerraform::Start() power = m_object->GetPower(); if ( power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer) ) return ERR_TERRA_ENERGY; - energy = dynamic_cast(power)->GetEnergy(); + energy = dynamic_cast(*power).GetEnergy(); if ( energy < ENERGY_TERRA+0.05f ) return ERR_TERRA_ENERGY; speed = m_physics->GetMotorSpeed(); @@ -363,7 +363,12 @@ bool CTaskTerraform::Terraform() type = pObj->GetType(); if ( type == OBJECT_NULL ) continue; - if ( type == OBJECT_TEEN34 || + if ( type == OBJECT_TEEN0 || + type == OBJECT_TEEN1 || + type == OBJECT_TEEN2 || + type == OBJECT_TEEN4 || + type == OBJECT_TEEN5 || + type == OBJECT_TEEN34 || type == OBJECT_POWER || type == OBJECT_ATOMIC || type == OBJECT_STONE || @@ -378,6 +383,8 @@ bool CTaskTerraform::Terraform() type == OBJECT_TNT || type == OBJECT_NEST || type == OBJECT_BOMB || + type == OBJECT_WINFIRE || + type == OBJECT_BAG || type == OBJECT_PLANT0 || type == OBJECT_PLANT1 || type == OBJECT_PLANT2 || @@ -391,18 +398,6 @@ bool CTaskTerraform::Terraform() type == OBJECT_PLANT17 || type == OBJECT_PLANT18 || type == OBJECT_PLANT19 || - type == OBJECT_MUSHROOM1 || - type == OBJECT_MUSHROOM2 || - type == OBJECT_FACTORY || - type == OBJECT_STATION || - type == OBJECT_CONVERT || - type == OBJECT_REPAIR || - type == OBJECT_DESTROYER || - type == OBJECT_ENERGY || - type == OBJECT_LABO || - type == OBJECT_PARA || - type == OBJECT_START || - type == OBJECT_END || type == OBJECT_EGG || type == OBJECT_RUINmobilew1 || type == OBJECT_RUINmobilew2 || @@ -412,54 +407,44 @@ bool CTaskTerraform::Terraform() type == OBJECT_RUINsupport || type == OBJECT_RUINradar || type == OBJECT_BARRIER0 || - type == OBJECT_APOLLO4 ) // almost everything? + type == OBJECT_BARRIER1 || + type == OBJECT_BARRIER2 || + type == OBJECT_BARRIER3 || + type == OBJECT_APOLLO4 ) // everything what fits? { dist = Math::Distance(m_terraPos, pObj->GetPosition()); - if (type == OBJECT_BULLET || - type == OBJECT_NEST || - type == OBJECT_EGG) // Alien Organic? + if ( type == OBJECT_BULLET || + type == OBJECT_NEST || + type == OBJECT_EGG ) // Alien Organic? { if ( dist > 5.0f ) continue; m_engine->GetPyroManager()->Create(Gfx::PT_FRAGO, pObj); } - else if (type == OBJECT_TNT || - type == OBJECT_BOMB) // Explosives? + else if ( type == OBJECT_TNT || + type == OBJECT_BOMB ) // Explosives? { if ( dist > 5.0f ) continue; m_engine->GetPyroManager()->Create(Gfx::PT_EXPLOT, pObj); - dynamic_cast(m_object)->DamageObject(DamageType::Explosive, 0.9f); + dynamic_cast(*m_object).DamageObject(DamageType::Explosive, 0.9f); } - else if (type == OBJECT_PLANT0 || - type == OBJECT_PLANT1 || - type == OBJECT_PLANT2 || - type == OBJECT_PLANT3 || - type == OBJECT_PLANT4 || - type == OBJECT_PLANT5 || - type == OBJECT_PLANT6 || - type == OBJECT_PLANT7 || - type == OBJECT_PLANT15 || - type == OBJECT_PLANT16 || - type == OBJECT_PLANT17 || - type == OBJECT_PLANT18 || - type == OBJECT_PLANT19 || - type == OBJECT_MUSHROOM1 || - type == OBJECT_MUSHROOM2) // Plants? + else if ( type == OBJECT_PLANT0 || + type == OBJECT_PLANT1 || + type == OBJECT_PLANT2 || + type == OBJECT_PLANT3 || + type == OBJECT_PLANT4 || + type == OBJECT_PLANT5 || + type == OBJECT_PLANT6 || + type == OBJECT_PLANT7 || + type == OBJECT_PLANT15 || + type == OBJECT_PLANT16 || + type == OBJECT_PLANT17 || + type == OBJECT_PLANT18 || + type == OBJECT_PLANT19 ) // Plants? { if ( dist > 7.5f ) continue; - m_engine->GetPyroManager()->Create(Gfx::PT_EGG, pObj); - } - else if (type == OBJECT_FACTORY || - type == OBJECT_STATION || - type == OBJECT_CONVERT || - type == OBJECT_REPAIR || - type == OBJECT_DESTROYER || - type == OBJECT_ENERGY || - type == OBJECT_LABO || - type == OBJECT_PARA) // Buildings? - { - if ( dist > 15.0f ) continue; - dynamic_cast(pObj)->DamageObject(DamageType::Explosive, 0.2f); + m_engine->GetPyroManager()->Create(Gfx::PT_FRAGV, pObj); + } else // Other? { @@ -470,7 +455,7 @@ bool CTaskTerraform::Terraform() else { if ( !pObj->Implements(ObjectInterfaceType::Movable) ) continue; - motion = dynamic_cast(pObj)->GetMotion(); + motion = dynamic_cast(*pObj).GetMotion(); dist = Math::Distance(m_terraPos, pObj->GetPosition()); if ( dist > ACTION_RADIUS ) continue; @@ -478,13 +463,13 @@ bool CTaskTerraform::Terraform() if ( type == OBJECT_ANT || type == OBJECT_SPIDER ) { assert(pObj->Implements(ObjectInterfaceType::TaskExecutor)); - dynamic_cast(pObj)->StopForegroundTask(); + dynamic_cast(*pObj).StopForegroundTask(); int actionType = -1; if (type == OBJECT_ANT) actionType = MAS_BACK1; if (type == OBJECT_SPIDER) actionType = MSS_BACK1; motion->SetAction(actionType, 0.8f+Math::Rand()*0.3f); - dynamic_cast(pObj)->SetFixed(true); // not moving + dynamic_cast(*pObj).SetFixed(true); // not moving if ( dist > 5.0f ) continue; m_engine->GetPyroManager()->Create(Gfx::PT_EXPLOO, pObj); diff --git a/src/object/task/taskterraform.h b/src/object/task/taskterraform.h index 25b0d41b..5951c087 100644 --- a/src/object/task/taskterraform.h +++ b/src/object/task/taskterraform.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskturn.cpp b/src/object/task/taskturn.cpp index 1931a974..d116e82c 100644 --- a/src/object/task/taskturn.cpp +++ b/src/object/task/taskturn.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskturn.h b/src/object/task/taskturn.h index 0ae4bc0a..da194ac7 100644 --- a/src/object/task/taskturn.h +++ b/src/object/task/taskturn.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskwait.cpp b/src/object/task/taskwait.cpp index 7186316c..c15878ad 100644 --- a/src/object/task/taskwait.cpp +++ b/src/object/task/taskwait.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/task/taskwait.h b/src/object/task/taskwait.h index d32d925f..2dddaf14 100644 --- a/src/object/task/taskwait.h +++ b/src/object/task/taskwait.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/object/tool_type.cpp b/src/object/tool_type.cpp index 3a06e455..4cbb1511 100644 --- a/src/object/tool_type.cpp +++ b/src/object/tool_type.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -47,6 +47,12 @@ ToolType GetToolFromObject(ObjectType type) case OBJECT_MOBILEii: return ToolType::OrganicShooter; + case OBJECT_MOBILEwb: + case OBJECT_MOBILEtb: + case OBJECT_MOBILEfb: + case OBJECT_MOBILEib: + return ToolType::Builder; + default: return ToolType::Other; } diff --git a/src/object/tool_type.h b/src/object/tool_type.h index 627f8307..d8660b1f 100644 --- a/src/object/tool_type.h +++ b/src/object/tool_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ enum class ToolType : unsigned int Sniffer, Shooter, OrganicShooter, + Builder, }; ToolType GetToolFromObject(ObjectType type); diff --git a/src/physics/physics.cpp b/src/physics/physics.cpp index b97742c5..d3b69cd8 100644 --- a/src/physics/physics.cpp +++ b/src/physics/physics.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -804,7 +804,7 @@ void CPhysics::MotorUpdate(float aTime, float rTime) if (m_object->Implements(ObjectInterfaceType::Powered)) { - power = dynamic_cast(dynamic_cast(m_object)->GetPower()); // searches for the object battery uses + power = dynamic_cast(dynamic_cast(*m_object).GetPower()); // searches for the object battery uses if ( GetObjectEnergy(m_object) == 0.0f ) // no battery or flat? { motorSpeed.x = 0.0f; @@ -822,7 +822,7 @@ void CPhysics::MotorUpdate(float aTime, float rTime) } } - if ( m_object->GetType() == OBJECT_HUMAN && dynamic_cast(m_object)->GetDying() == DeathType::Dead ) // dead man? + if ( m_object->GetType() == OBJECT_HUMAN && dynamic_cast(*m_object).GetDying() == DeathType::Dead ) // dead man? { motorSpeed.x = 0.0f; motorSpeed.z = 0.0f; @@ -852,7 +852,7 @@ void CPhysics::MotorUpdate(float aTime, float rTime) } if ( m_object->Implements(ObjectInterfaceType::JetFlying) && - dynamic_cast(m_object)->GetRange() > 0.0f ) // limited flight range? + dynamic_cast(*m_object).GetRange() > 0.0f ) // limited flight range? { CJetFlyingObject* jetFlying = dynamic_cast(m_object); if ( m_bLand || m_bSwim || m_bObstacle ) // on the ground or in the water? @@ -960,7 +960,7 @@ void CPhysics::MotorUpdate(float aTime, float rTime) bool reactorCool = true; if ( m_object->Implements(ObjectInterfaceType::JetFlying) ) { - reactorCool = dynamic_cast(m_object)->GetReactorRange() > 0.1f; + reactorCool = dynamic_cast(*m_object).GetReactorRange() > 0.1f; } if ( motorSpeed.y > 0.0f && reactorCool && pos.y < h ) { @@ -988,9 +988,11 @@ void CPhysics::MotorUpdate(float aTime, float rTime) { factor = 1.0f; if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEis || type == OBJECT_MOBILEic || - type == OBJECT_MOBILEii ) factor = 0.5f; + type == OBJECT_MOBILEii || + type == OBJECT_MOBILEit ) factor = 0.5f; energy = power->GetEnergy(); energy -= fabs(motorSpeed.x)*rTime*factor*0.005f; @@ -1148,6 +1150,7 @@ void CPhysics::EffectUpdate(float aTime, float rTime) } if ( type == OBJECT_MOBILEwa || + type == OBJECT_MOBILEwb || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEwi || type == OBJECT_MOBILEws || @@ -1193,10 +1196,11 @@ void CPhysics::EffectUpdate(float aTime, float rTime) } if ( type == OBJECT_MOBILEfa || + type == OBJECT_MOBILEfb || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEfi || type == OBJECT_MOBILEfs || - type == OBJECT_MOBILEft ) // fliyng? + type == OBJECT_MOBILEft ) // flying? { if ( m_bLand ) // on the ground? { @@ -1459,7 +1463,7 @@ bool CPhysics::EventFrame(const Event &event) iAngle = angle = m_object->GetRotation(); // Accelerate is the descent, brake is the ascent. - if ( m_bFreeze || (m_object->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(m_object)->IsDying()) ) + if ( m_bFreeze || (m_object->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(*m_object).IsDying()) ) { m_linMotion.terrainSpeed.x = 0.0f; m_linMotion.terrainSpeed.z = 0.0f; @@ -1614,8 +1618,8 @@ void CPhysics::SoundMotor(float rTime) else if ( type == OBJECT_ANT ) { assert(m_object->Implements(ObjectInterfaceType::Destroyable)); - if ( dynamic_cast(m_object)->GetDying() == DeathType::Burning || - dynamic_cast(m_object)->GetFixed() ) + if ( dynamic_cast(*m_object).GetDying() == DeathType::Burning || + dynamic_cast(*m_object).GetFixed() ) { if ( m_lastSoundInsect <= 0.0f ) { @@ -1645,7 +1649,7 @@ void CPhysics::SoundMotor(float rTime) else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f; } } - else if ( dynamic_cast(m_object)->GetDying() == DeathType::Burning ) + else if ( dynamic_cast(*m_object).GetDying() == DeathType::Burning ) { if ( m_lastSoundInsect <= 0.0f ) { @@ -1666,7 +1670,7 @@ void CPhysics::SoundMotor(float rTime) else m_lastSoundInsect = 1.5f+Math::Rand()*4.0f; } } - else if ( dynamic_cast(m_object)->GetDying() == DeathType::Burning ) + else if ( dynamic_cast(*m_object).GetDying() == DeathType::Burning ) { if ( m_lastSoundInsect <= 0.0f ) { @@ -1678,8 +1682,8 @@ void CPhysics::SoundMotor(float rTime) else if ( type == OBJECT_SPIDER ) { assert(m_object->Implements(ObjectInterfaceType::Destroyable)); - if ( dynamic_cast(m_object)->GetDying() == DeathType::Burning || - dynamic_cast(m_object)->GetFixed() ) + if ( dynamic_cast(*m_object).GetDying() == DeathType::Burning || + dynamic_cast(*m_object).GetFixed() ) { if ( m_lastSoundInsect <= 0.0f ) { @@ -1800,6 +1804,10 @@ void CPhysics::WaterFrame(float aTime, float rTime) type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEwc || @@ -1820,6 +1828,8 @@ void CPhysics::WaterFrame(float aTime, float rTime) type == OBJECT_MOBILEtt || type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEtg || type == OBJECT_MOBILEdr || type == OBJECT_APOLLO2 ) { @@ -1838,9 +1848,11 @@ void CPhysics::SoundMotorFull(float rTime, ObjectType type) float amplitude, time, freq; if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEii || - type == OBJECT_MOBILEis ) + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEit ) { if ( m_soundChannel == -1 ) { @@ -1867,7 +1879,8 @@ void CPhysics::SoundMotorFull(float rTime, ObjectType type) return; } - if ( type == OBJECT_MOBILEsa ) + if ( type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst ) { sound = SOUND_MOTORs; amplitude = 0.6f; @@ -1876,7 +1889,8 @@ void CPhysics::SoundMotorFull(float rTime, ObjectType type) else if ( type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp ) { sound = SOUND_MOTORr; amplitude = 1.0f; @@ -1885,7 +1899,8 @@ void CPhysics::SoundMotorFull(float rTime, ObjectType type) else if ( type == OBJECT_MOBILEta || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || - type == OBJECT_MOBILEts ) + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEtt ) { sound = SOUND_MOTORt; amplitude = 1.0f; @@ -1953,9 +1968,11 @@ void CPhysics::SoundMotorSlow(float rTime, ObjectType type) int i, max; if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEii || - type == OBJECT_MOBILEis ) + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEit ) { if ( m_soundChannel != -1 ) // engine is running? { @@ -1966,7 +1983,8 @@ void CPhysics::SoundMotorSlow(float rTime, ObjectType type) return; } - if ( type == OBJECT_MOBILEsa ) + if ( type == OBJECT_MOBILEsa || + type == OBJECT_MOBILEst ) { sound = SOUND_MOTORs; amplitude = 0.4f; @@ -1974,15 +1992,18 @@ void CPhysics::SoundMotorSlow(float rTime, ObjectType type) else if ( type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp ) { sound = SOUND_MOTORr; amplitude = 0.9f; } else if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || - type == OBJECT_MOBILEts ) + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEtt ) { sound = SOUND_MOTORt; amplitude = 0.7f; @@ -2031,7 +2052,8 @@ void CPhysics::SoundMotorSlow(float rTime, ObjectType type) if ( type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp ) { m_soundTimePshhh -= rTime; @@ -2074,9 +2096,11 @@ void CPhysics::SoundMotorSlow(float rTime, ObjectType type) void CPhysics::SoundMotorStop(float rTime, ObjectType type) { if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEii || - type == OBJECT_MOBILEis ) + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEit ) { if ( m_soundChannel != -1 ) // engine is running? { @@ -2482,7 +2506,7 @@ int CPhysics::ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle) int colType; ObjectType iType, oType; - if ( m_object->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(m_object)->IsDying() ) return 0; // is burning or exploding? + if ( m_object->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(*m_object).IsDying() ) return 0; // is burning or exploding? if ( !m_object->GetCollisions() ) return 0; // iiPos = sphere center is the old position. @@ -2501,7 +2525,7 @@ int CPhysics::ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle) { if ( pObj == m_object ) continue; // yourself? if (IsObjectBeingTransported(pObj)) continue; - if ( pObj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(pObj)->IsDying() ) continue; // is burning or exploding? + if ( pObj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast(*pObj).GetDying() == DeathType::Exploding ) continue; // is exploding? oType = pObj->GetType(); if ( oType == OBJECT_TOTO ) continue; @@ -2603,7 +2627,7 @@ int CPhysics::ObjectAdapt(const Math::Vector &pos, const Math::Vector &angle) CPhysics* ph = nullptr; if (pObj->Implements(ObjectInterfaceType::Movable)) - ph = dynamic_cast(pObj)->GetPhysics(); + ph = dynamic_cast(*pObj).GetPhysics(); if ( ph != nullptr ) { oAngle = pObj->GetRotation(); @@ -2696,14 +2720,14 @@ bool CPhysics::ExploOther(ObjectType iType, if (pObj->GetType() == OBJECT_STONE ) { destructionForce = 25.0f; } // TitaniumOre if (pObj->GetType() == OBJECT_URANIUM ) { destructionForce = 25.0f; } // UraniumOre if (pObj->GetType() == OBJECT_MOBILEtg) { destructionForce = 10.0f; damageType = DamageType::Explosive; } // TargetBot (something running into it) - if (iType == OBJECT_MOBILEtg) { destructionForce = 10.0f; damageType = DamageType::Explosive; } // TargetBot (it running into something) + if (iType == OBJECT_MOBILEtg) { destructionForce = 0.0f; damageType = DamageType::Explosive; } // TargetBot (it running into something) if (pObj->GetType() == OBJECT_TNT ) { destructionForce = 10.0f; damageType = DamageType::Explosive; } // TNT if (pObj->GetType() == OBJECT_BOMB ) { destructionForce = 0.0f; damageType = DamageType::Explosive; } // Mine if ( force > destructionForce && destructionForce >= 0.0f ) { // TODO: implement "killer"? - dynamic_cast(pObj)->DamageObject(damageType); + dynamic_cast(*pObj).DamageObject(damageType); } } @@ -2729,13 +2753,17 @@ bool CPhysics::ExploOther(ObjectType iType, { assert(pObj->Implements(ObjectInterfaceType::Damageable)); // TODO: implement "killer"? - dynamic_cast(pObj)->DamageObject(DamageType::Collision, force/400.0f); + dynamic_cast(*pObj).DamageObject(DamageType::Collision, force/400.0f); } if (oType == OBJECT_MOBILEwa || oType == OBJECT_MOBILEta || oType == OBJECT_MOBILEfa || oType == OBJECT_MOBILEia || + oType == OBJECT_MOBILEwb || + oType == OBJECT_MOBILEtb || + oType == OBJECT_MOBILEfb || + oType == OBJECT_MOBILEib || oType == OBJECT_MOBILEwc || oType == OBJECT_MOBILEtc || oType == OBJECT_MOBILEfc || @@ -2756,14 +2784,30 @@ bool CPhysics::ExploOther(ObjectType iType, oType == OBJECT_MOBILEwt || oType == OBJECT_MOBILEtt || oType == OBJECT_MOBILEft || - oType == OBJECT_MOBILEit ) // vehicle? + oType == OBJECT_MOBILEit || + oType == OBJECT_MOBILErp || + oType == OBJECT_MOBILEst ) // vehicle? { assert(pObj->Implements(ObjectInterfaceType::Damageable)); // TODO: implement "killer"? - dynamic_cast(pObj)->DamageObject(DamageType::Collision, force/200.0f); + dynamic_cast(*pObj).DamageObject(DamageType::Collision, force/200.0f); } } + if((oType == OBJECT_PLANT0 || + oType == OBJECT_PLANT1 || + oType == OBJECT_PLANT2 || + oType == OBJECT_PLANT3 || + oType == OBJECT_PLANT4 || + oType == OBJECT_PLANT15 || + oType == OBJECT_PLANT16 || + oType == OBJECT_PLANT17 || + oType == OBJECT_PLANT18)&& + GetDriveFromObject(iType)==DriveType::Heavy) + { + dynamic_cast(pObj)->DestroyObject(DestructionType::Squash); + } + return false; } @@ -2780,13 +2824,13 @@ int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force) float destructionForce = -1.0f; // minimal force required to destroy an object using this explosive, default: not explosive if ( oType == OBJECT_TNT ) destructionForce = 10.0f; // TNT if ( oType == OBJECT_MOBILEtg ) destructionForce = 10.0f; // TargetBot (something running into it) - if ( iType == OBJECT_MOBILEtg ) destructionForce = 10.0f; // TargetBot (it running into something) + if ( iType == OBJECT_MOBILEtg ) destructionForce = 0.0f; // TargetBot (it running into something) if ( oType == OBJECT_BOMB ) destructionForce = 0.0f; // Mine if ( force > destructionForce && destructionForce >= 0.0f ) { // TODO: implement "killer"? - dynamic_cast(m_object)->DamageObject(DamageType::Explosive); + dynamic_cast(*m_object).DamageObject(DamageType::Explosive); return 2; } @@ -2797,6 +2841,10 @@ int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force) iType == OBJECT_MOBILEta || iType == OBJECT_MOBILEfa || iType == OBJECT_MOBILEia || + iType == OBJECT_MOBILEwb || + iType == OBJECT_MOBILEtb || + iType == OBJECT_MOBILEfb || + iType == OBJECT_MOBILEib || iType == OBJECT_MOBILEwc || iType == OBJECT_MOBILEtc || iType == OBJECT_MOBILEfc || @@ -2818,6 +2866,8 @@ int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force) iType == OBJECT_MOBILEtt || iType == OBJECT_MOBILEft || iType == OBJECT_MOBILEit || + iType == OBJECT_MOBILErp || + iType == OBJECT_MOBILEst || iType == OBJECT_MOBILEdr || iType == OBJECT_APOLLO2 ) // vehicle? { @@ -2867,7 +2917,7 @@ int CPhysics::ExploHimself(ObjectType iType, ObjectType oType, float force) } // TODO: implement "killer"? - if ( dynamic_cast(m_object)->DamageObject(DamageType::Collision, force) ) return 2; + if ( dynamic_cast(*m_object).DamageObject(DamageType::Collision, force) ) return 2; } } @@ -2919,9 +2969,9 @@ void CPhysics::PowerParticle(float factor, bool bBreak) bCarryPower = false; if (m_object->Implements(ObjectInterfaceType::Carrier)) { - CObject* cargo = dynamic_cast(m_object)->GetCargo(); + CObject* cargo = dynamic_cast(*m_object).GetCargo(); if ( cargo != nullptr && cargo->Implements(ObjectInterfaceType::PowerContainer) && - dynamic_cast(cargo)->IsRechargeable() && + dynamic_cast(*cargo).IsRechargeable() && m_object->GetPartRotationZ(1) == ARM_STOCK_ANGLE1 ) { bCarryPower = true; // carries a battery @@ -3019,9 +3069,11 @@ void CPhysics::MotorParticle(float aTime, float rTime) type = m_object->GetType(); if ( type == OBJECT_MOBILEia || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEic || type == OBJECT_MOBILEii || - type == OBJECT_MOBILEis || // legs? + type == OBJECT_MOBILEis || + type == OBJECT_MOBILEit || // legs? type == OBJECT_MOBILEdr || type == OBJECT_MOTHER || type == OBJECT_ANT || @@ -3124,9 +3176,11 @@ void CPhysics::MotorParticle(float aTime, float rTime) } if ( type == OBJECT_MOBILEta || + type == OBJECT_MOBILEtb || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEti || - type == OBJECT_MOBILEts ) // caterpillars? + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEtt ) // caterpillars? { if ( aTime-m_lastSlideParticle >= m_engine->ParticleAdapt(0.05f) ) { @@ -3153,7 +3207,8 @@ void CPhysics::MotorParticle(float aTime, float rTime) if ( type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) // large caterpillars? + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp ) // large caterpillars? { if ( aTime-m_lastSlideParticle >= m_engine->ParticleAdapt(0.05f) ) { @@ -3209,7 +3264,7 @@ void CPhysics::MotorParticle(float aTime, float rTime) } else // in flight? { - if ( !m_bMotor || (m_object->Implements(ObjectInterfaceType::JetFlying) && dynamic_cast(m_object)->GetReactorRange() == 0.0f) ) return; + if ( !m_bMotor || (m_object->Implements(ObjectInterfaceType::JetFlying) && dynamic_cast(*m_object).GetReactorRange() == 0.0f) ) return; if ( m_reactorTemperature < 1.0f ) // not too hot? { @@ -3339,7 +3394,7 @@ void CPhysics::MotorParticle(float aTime, float rTime) } else // in flight? { - if ( !m_bMotor || (m_object->Implements(ObjectInterfaceType::JetFlying) && dynamic_cast(m_object)->GetReactorRange() == 0.0f) ) return; + if ( !m_bMotor || (m_object->Implements(ObjectInterfaceType::JetFlying) && dynamic_cast(*m_object).GetReactorRange() == 0.0f) ) return; if ( aTime-m_lastMotorParticle < m_engine->ParticleAdapt(0.02f) ) return; m_lastMotorParticle = aTime; @@ -3400,7 +3455,7 @@ void CPhysics::MotorParticle(float aTime, float rTime) if ( (type == OBJECT_HUMAN || type == OBJECT_TECH) && m_bSwim ) { - if ( !m_object->Implements(ObjectInterfaceType::Destroyable) || dynamic_cast(m_object)->GetDying() != DeathType::Dead ) + if ( !m_object->Implements(ObjectInterfaceType::Destroyable) || dynamic_cast(*m_object).GetDying() != DeathType::Dead ) { h = Math::Mod(aTime, 5.0f); if ( h < 3.5f && ( h < 1.5f || h > 1.6f ) ) return; @@ -3427,7 +3482,7 @@ void CPhysics::MotorParticle(float aTime, float rTime) } } - if ( type == OBJECT_MOBILEsa && m_bSwim ) + if ( (type == OBJECT_MOBILEsa || type == OBJECT_MOBILEst) && m_bSwim ) { h = Math::Mod(aTime, 3.0f); if ( h < 1.5f && ( h < 0.5f || h > 0.9f ) ) return; @@ -3461,7 +3516,8 @@ void CPhysics::MotorParticle(float aTime, float rTime) if ( type == OBJECT_MOBILErt || type == OBJECT_MOBILErc || type == OBJECT_MOBILErr || - type == OBJECT_MOBILErs ) + type == OBJECT_MOBILErs || + type == OBJECT_MOBILErp ) { if ( !m_bMotor ) return; @@ -3722,7 +3778,7 @@ Error CPhysics::GetError() if (m_object->Implements(ObjectInterfaceType::ProgramStorage)) { - if ( dynamic_cast(m_object)->GetActiveVirus() ) + if ( dynamic_cast(*m_object).GetActiveVirus() ) { return ERR_VEH_VIRUS; } @@ -3730,14 +3786,14 @@ Error CPhysics::GetError() if (m_object->Implements(ObjectInterfaceType::Powered)) { - CObject* power = dynamic_cast(m_object)->GetPower(); // searches for the object battery used + CObject* power = dynamic_cast(*m_object).GetPower(); // searches for the object battery used if (power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer)) { return ERR_VEH_POWER; } else { - if ( dynamic_cast(power)->GetEnergy() == 0.0f ) return ERR_VEH_ENERGY; + if ( dynamic_cast(*power).GetEnergy() == 0.0f ) return ERR_VEH_ENERGY; } } diff --git a/src/physics/physics.h b/src/physics/physics.h index 36f10d96..709bd48f 100644 --- a/src/physics/physics.h +++ b/src/physics/physics.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/script/cbottoken.cpp b/src/script/cbottoken.cpp index 24b60a09..46e01eb4 100644 --- a/src/script/cbottoken.cpp +++ b/src/script/cbottoken.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -82,7 +82,12 @@ const char* GetObjectName(ObjectType type) if ( type == OBJECT_MARKKEYb ) return "KeyBSpot"; if ( type == OBJECT_MARKKEYc ) return "KeyCSpot"; if ( type == OBJECT_MARKKEYd ) return "KeyDSpot"; - if ( type == OBJECT_MOBILEwt ) return "PracticeBot"; + if ( type == OBJECT_MOBILEwt ) return "WheeledTrainer"; + if ( type == OBJECT_MOBILEtt ) return "TrackedTrainer"; + if ( type == OBJECT_MOBILEft ) return "WingedTrainer"; + if ( type == OBJECT_MOBILEit ) return "LeggedTrainer"; + if ( type == OBJECT_MOBILErp ) return "HeavyTrainer"; + if ( type == OBJECT_MOBILEst ) return "AmphibiousTrainer"; if ( type == OBJECT_MOBILEwa ) return "WheeledGrabber"; if ( type == OBJECT_MOBILEta ) return "TrackedGrabber"; if ( type == OBJECT_MOBILEfa ) return "WingedGrabber"; @@ -99,6 +104,10 @@ const char* GetObjectName(ObjectType type) if ( type == OBJECT_MOBILEts ) return "TrackedSniffer"; if ( type == OBJECT_MOBILEfs ) return "WingedSniffer"; if ( type == OBJECT_MOBILEis ) return "LeggedSniffer"; + if ( type == OBJECT_MOBILEwb ) return "WheeledBuilder"; + if ( type == OBJECT_MOBILEtb ) return "TrackedBuilder"; + if ( type == OBJECT_MOBILEfb ) return "WingedBuilder"; + if ( type == OBJECT_MOBILEib ) return "LeggedBuilder"; if ( type == OBJECT_MOBILErt ) return "Thumper"; if ( type == OBJECT_MOBILErc ) return "PhazerShooter"; if ( type == OBJECT_MOBILErr ) return "Recycler"; @@ -106,6 +115,7 @@ const char* GetObjectName(ObjectType type) if ( type == OBJECT_MOBILEsa ) return "Subber"; if ( type == OBJECT_MOBILEtg ) return "TargetBot"; if ( type == OBJECT_MOBILEdr ) return "Scribbler"; + if ( type == OBJECT_MOBILEpr ) return "PracticeBot"; if ( type == OBJECT_HUMAN ) return "Me"; if ( type == OBJECT_TECH ) return "Tech"; if ( type == OBJECT_MOTHER ) return "AlienQueen"; @@ -115,6 +125,12 @@ const char* GetObjectName(ObjectType type) if ( type == OBJECT_BEE ) return "AlienWasp"; if ( type == OBJECT_WORM ) return "AlienWorm"; if ( type == OBJECT_RUINmobilew1) return "Wreck"; + if ( type == OBJECT_RUINfactory ) return "Ruin"; + if ( type == OBJECT_PLANT0 ) return "Bush"; + if ( type == OBJECT_ROOT5 ) return "GraviPlant"; + if ( type == OBJECT_QUARTZ0 ) return "Crystal"; + if ( type == OBJECT_MUSHROOM1 ) return "BrownMushroom"; + if ( type == OBJECT_MUSHROOM2 ) return "GreenMushroom"; return ""; } @@ -196,14 +212,24 @@ std::string GetHelpFilename(ObjectType type) if ( type == OBJECT_MOBILEtc ) helpfile = "object/botfc"; if ( type == OBJECT_MOBILEfc ) helpfile = "object/botfj"; if ( type == OBJECT_MOBILEic ) helpfile = "object/botfs"; + if ( type == OBJECT_MOBILEwb ) helpfile = "object/botbr"; + if ( type == OBJECT_MOBILEtb ) helpfile = "object/botbc"; + if ( type == OBJECT_MOBILEfb ) helpfile = "object/botbj"; + if ( type == OBJECT_MOBILEib ) helpfile = "object/botbs"; if ( type == OBJECT_MOBILErt ) helpfile = "object/bottump"; if ( type == OBJECT_MOBILErc ) helpfile = "object/botphaz"; if ( type == OBJECT_MOBILErr ) helpfile = "object/botrecy"; if ( type == OBJECT_MOBILErs ) helpfile = "object/botshld"; if ( type == OBJECT_MOBILEsa ) helpfile = "object/botsub"; if ( type == OBJECT_MOBILEwt ) helpfile = "object/bottr"; + if ( type == OBJECT_MOBILEtt ) helpfile = "object/bottr"; + if ( type == OBJECT_MOBILEft ) helpfile = "object/bottr"; + if ( type == OBJECT_MOBILEit ) helpfile = "object/bottr"; + if ( type == OBJECT_MOBILErp ) helpfile = "object/bottr"; + if ( type == OBJECT_MOBILEst ) helpfile = "object/bottr"; if ( type == OBJECT_MOBILEtg ) helpfile = "object/bottarg"; if ( type == OBJECT_MOBILEdr ) helpfile = "object/botdraw"; + if ( type == OBJECT_MOBILEpr ) helpfile = "object/bottr"; if ( type == OBJECT_APOLLO2 ) helpfile = "object/lrv"; if ( type == OBJECT_HUMAN ) helpfile = "object/human"; if ( type == OBJECT_MOTHER ) helpfile = "object/mother"; @@ -213,6 +239,12 @@ std::string GetHelpFilename(ObjectType type) if ( type == OBJECT_BEE ) helpfile = "object/wasp"; if ( type == OBJECT_WORM ) helpfile = "object/worm"; if ( type == OBJECT_RUINmobilew1) helpfile = "object/wreck"; + if ( type == OBJECT_RUINfactory ) helpfile = "object/ruin"; + if ( type == OBJECT_PLANT0 ) helpfile = "object/bush"; + if ( type == OBJECT_ROOT5 ) helpfile = "object/gravi"; + if ( type == OBJECT_QUARTZ0 ) helpfile = "object/crystal"; + if ( type == OBJECT_MUSHROOM1 ) helpfile = "object/bromush"; + if ( type == OBJECT_MUSHROOM2 ) helpfile = "object/gremush"; if (helpfile.empty()) return ""; @@ -229,6 +261,7 @@ std::string GetHelpFilename(const char *token) if ( strcmp(token, "if" ) == 0 ) helpfile = "cbot/if"; if ( strcmp(token, "else" ) == 0 ) helpfile = "cbot/if"; + if ( strcmp(token, "repeat" ) == 0 ) helpfile = "cbot/repeat"; if ( strcmp(token, "for" ) == 0 ) helpfile = "cbot/for"; if ( strcmp(token, "while" ) == 0 ) helpfile = "cbot/while"; if ( strcmp(token, "do" ) == 0 ) helpfile = "cbot/do"; @@ -236,8 +269,13 @@ std::string GetHelpFilename(const char *token) if ( strcmp(token, "continue" ) == 0 ) helpfile = "cbot/continue"; if ( strcmp(token, "return" ) == 0 ) helpfile = "cbot/return"; if ( strcmp(token, "sizeof" ) == 0 ) helpfile = "cbot/sizeof"; + if ( strcmp(token, "byte" ) == 0 ) helpfile = "cbot/byte"; + if ( strcmp(token, "short" ) == 0 ) helpfile = "cbot/short"; + if ( strcmp(token, "char" ) == 0 ) helpfile = "cbot/char"; if ( strcmp(token, "int" ) == 0 ) helpfile = "cbot/int"; + if ( strcmp(token, "long" ) == 0 ) helpfile = "cbot/long"; if ( strcmp(token, "float" ) == 0 ) helpfile = "cbot/float"; + if ( strcmp(token, "double" ) == 0 ) helpfile = "cbot/double"; if ( strcmp(token, "bool" ) == 0 ) helpfile = "cbot/bool"; if ( strcmp(token, "string" ) == 0 ) helpfile = "cbot/string"; if ( strcmp(token, "point" ) == 0 ) helpfile = "cbot/point"; @@ -265,7 +303,7 @@ std::string GetHelpFilename(const char *token) if ( strcmp(token, "trunc" ) == 0 ) helpfile = "cbot/trunc"; if ( strcmp(token, "retobject" ) == 0 ) helpfile = "cbot/retobj"; if ( strcmp(token, "errmode" ) == 0 ) helpfile = "cbot/errmode"; - if ( strcmp(token, "busy" ) == 0 ) helpfile = "cbot/busy"; + if ( strcmp(token, "isbusy" ) == 0 ) helpfile = "cbot/isbusy"; if ( strcmp(token, "takeoff" ) == 0 ) helpfile = "cbot/takeoff"; if ( strcmp(token, "research" ) == 0 ) helpfile = "cbot/research"; if ( strcmp(token, "factory" ) == 0 ) helpfile = "cbot/factory"; @@ -285,6 +323,8 @@ std::string GetHelpFilename(const char *token) if ( strcmp(token, "researched" ) == 0 ) helpfile = "cbot/researched"; if ( strcmp(token, "buildingenabled") == 0 ) helpfile = "cbot/buildingenabled"; if ( strcmp(token, "build" ) == 0 ) helpfile = "cbot/build"; + if ( strcmp(token, "flag" ) == 0 ) helpfile = "cbot/flag"; + if ( strcmp(token, "deflag" ) == 0 ) helpfile = "cbot/deflag"; if ( strcmp(token, "wait" ) == 0 ) helpfile = "cbot/wait"; if ( strcmp(token, "move" ) == 0 ) helpfile = "cbot/move"; if ( strcmp(token, "turn" ) == 0 ) helpfile = "cbot/turn"; @@ -307,23 +347,24 @@ std::string GetHelpFilename(const char *token) if ( strcmp(token, "topo" ) == 0 ) helpfile = "cbot/topo"; if ( strcmp(token, "message" ) == 0 ) helpfile = "cbot/message"; if ( strcmp(token, "abstime" ) == 0 ) helpfile = "cbot/abstime"; + if ( strcmp(token, "Blue" ) == 0 ) helpfile = "cbot/flag"; + if ( strcmp(token, "Red" ) == 0 ) helpfile = "cbot/flag"; + if ( strcmp(token, "Green" ) == 0 ) helpfile = "cbot/flag"; + if ( strcmp(token, "Yellow" ) == 0 ) helpfile = "cbot/flag"; + if ( strcmp(token, "Violet" ) == 0 ) helpfile = "cbot/flag"; if ( strcmp(token, "BlackArrow" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "RedArrow" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "White" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Black" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Gray" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "LightGray" ) == 0 ) helpfile = "cbot/pendown"; - if ( strcmp(token, "Red" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Pink" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Purple" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Orange" ) == 0 ) helpfile = "cbot/pendown"; - if ( strcmp(token, "Yellow" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Beige" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Brown" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "Skin" ) == 0 ) helpfile = "cbot/pendown"; - if ( strcmp(token, "Green" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "LightGreen" ) == 0 ) helpfile = "cbot/pendown"; - if ( strcmp(token, "Blue" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "LightBlue" ) == 0 ) helpfile = "cbot/pendown"; if ( strcmp(token, "InFront" ) == 0 ) helpfile = "cbot/grab"; if ( strcmp(token, "Behind" ) == 0 ) helpfile = "cbot/grab"; @@ -388,8 +429,13 @@ std::string GetHelpFilename(const char *token) bool IsType(const char *token) { if ( strcmp(token, "void" ) == 0 ) return true; + if ( strcmp(token, "byte" ) == 0 ) return true; + if ( strcmp(token, "short" ) == 0 ) return true; + if ( strcmp(token, "char" ) == 0 ) return true; if ( strcmp(token, "int" ) == 0 ) return true; + if ( strcmp(token, "long" ) == 0 ) return true; if ( strcmp(token, "float" ) == 0 ) return true; + if ( strcmp(token, "double" ) == 0 ) return true; if ( strcmp(token, "bool" ) == 0 ) return true; if ( strcmp(token, "string" ) == 0 ) return true; if ( strcmp(token, "point" ) == 0 ) return true; @@ -419,7 +465,7 @@ bool IsFunction(const char *token) if ( strcmp(token, "trunc" ) == 0 ) return true; if ( strcmp(token, "retobjectbyid") == 0 ) return true; if ( strcmp(token, "retobject" ) == 0 ) return true; - if ( strcmp(token, "busy" ) == 0 ) return true; + if ( strcmp(token, "isbusy" ) == 0 ) return true; if ( strcmp(token, "factory" ) == 0 ) return true; if ( strcmp(token, "research" ) == 0 ) return true; if ( strcmp(token, "takeoff" ) == 0 ) return true; @@ -440,6 +486,8 @@ bool IsFunction(const char *token) if ( strcmp(token, "researched" ) == 0 ) return true; if ( strcmp(token, "buildingenabled") == 0 ) return true; if ( strcmp(token, "build" ) == 0 ) return true; + if ( strcmp(token, "flag" ) == 0 ) return true; + if ( strcmp(token, "deflag" ) == 0 ) return true; if ( strcmp(token, "wait" ) == 0 ) return true; if ( strcmp(token, "move" ) == 0 ) return true; if ( strcmp(token, "turn" ) == 0 ) return true; @@ -496,6 +544,7 @@ const char* GetHelpText(const char *token) { if ( strcmp(token, "if" ) == 0 ) return "if ( condition ) { code }"; if ( strcmp(token, "else" ) == 0 ) return "else { code }"; + if ( strcmp(token, "repeat" ) == 0 ) return "repeat ( number )"; if ( strcmp(token, "for" ) == 0 ) return "for ( before ; condition ; end )"; if ( strcmp(token, "while" ) == 0 ) return "while ( condition ) { code }"; if ( strcmp(token, "do" ) == 0 ) return "do { code } while ( condition );"; @@ -525,11 +574,11 @@ const char* GetHelpText(const char *token) if ( strcmp(token, "retobject" ) == 0 ) return "retobject ( rank );"; if ( strcmp(token, "retobjectbyid") == 0 ) return "retobjectbyid ( rank );"; if ( strcmp(token, "progfunc" ) == 0 ) return "progfunc ( funcname );"; - if ( strcmp(token, "busy" ) == 0 ) return "object.busy ( );"; - if ( strcmp(token, "factory" ) == 0 ) return "object.factory ( cat, program );"; - if ( strcmp(token, "research" ) == 0 ) return "object.research ( type );"; - if ( strcmp(token, "takeoff" ) == 0 ) return "object.takeoff ( );"; - if ( strcmp(token, "destroy" ) == 0 ) return "object.destroy ( );"; + if ( strcmp(token, "isbusy" ) == 0 ) return "isbusy ( object );"; + if ( strcmp(token, "factory" ) == 0 ) return "factory ( cat, program, object );"; + if ( strcmp(token, "research" ) == 0 ) return "research ( type, object );"; + if ( strcmp(token, "takeoff" ) == 0 ) return "takeoff ( object );"; + if ( strcmp(token, "destroy" ) == 0 ) return "destroy ( object );"; if ( strcmp(token, "search" ) == 0 ) return "search ( cat, pos, min, max, sens, filter );"; if ( strcmp(token, "searchall" ) == 0 ) return "searchall ( cat, pos, min, max, sens, filter );"; if ( strcmp(token, "radar" ) == 0 ) return "radar ( cat, angle, focus, min, max, sens, filter );"; @@ -546,6 +595,8 @@ const char* GetHelpText(const char *token) if ( strcmp(token, "researched" ) == 0 ) return "researched ( research );"; if ( strcmp(token, "buildingenabled") == 0 ) return "buildingenabled ( category );"; if ( strcmp(token, "build" ) == 0 ) return "build ( category );"; + if ( strcmp(token, "flag" ) == 0 ) return "flag ( color );"; + if ( strcmp(token, "deflag" ) == 0 ) return "deflag ( );"; if ( strcmp(token, "wait" ) == 0 ) return "wait ( time );"; if ( strcmp(token, "move" ) == 0 ) return "move ( distance );"; if ( strcmp(token, "turn" ) == 0 ) return "turn ( angle );"; diff --git a/src/script/cbottoken.h b/src/script/cbottoken.h index 01055fef..e175cba0 100644 --- a/src/script/cbottoken.h +++ b/src/script/cbottoken.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/script/script.cpp b/src/script/script.cpp index a94e850f..12be1ad9 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -589,16 +589,17 @@ void CScript::UpdateList(Ui::CList* list) list->SetState(Ui::STATE_ENABLE); } -// Colorize a string literal with escape sequences also colored +// Colorize a string or character literal with escape sequences also colored static void HighlightString(Ui::CEdit* edit, const std::string& s, int start) { edit->SetFormat(start, start + 1, Gfx::FONT_HIGHLIGHT_STRING); - auto it = s.cbegin() + 1; + auto it = s.cbegin(); + char endQuote = *(it++); ++start; - while (it != s.cend() && *it != '\"') + while (it != s.cend() && *it != endQuote) { if (*(it++) != '\\') // not escape sequence { @@ -697,7 +698,7 @@ void CScript::ColorizeScript(Ui::CEdit* edit, int rangeStart, int rangeEnd) { color = Gfx::FONT_HIGHLIGHT_STRING; } - else if (type == CBot::TokenTypString) // string literals + else if (type == CBot::TokenTypString || type == CBot::TokenTypChar) // string literals and character literals { HighlightString(edit, token, cursor1); bt = bt->GetNext(); @@ -1032,16 +1033,16 @@ bool CScript::WriteScript(const char* filename) // Reads a stack of script by execution as a file. -bool CScript::ReadStack(FILE *file) +bool CScript::ReadStack(std::istream &istr) { int nb; - CBot::fRead(&nb, sizeof(int), 1, file); - CBot::fRead(&m_ipf, sizeof(int), 1, file); - CBot::fRead(&m_errMode, sizeof(int), 1, file); + if (!CBot::ReadInt(istr, nb)) return false; + if (!CBot::ReadInt(istr, m_ipf)) return false; + if (!CBot::ReadInt(istr, m_errMode)) return false; if (m_botProg == nullptr) return false; - if ( !m_botProg->RestoreState(file) ) return false; + if (!m_botProg->RestoreState(istr)) return false; m_bRun = true; m_bContinue = false; @@ -1050,16 +1051,16 @@ bool CScript::ReadStack(FILE *file) // Writes a stack of script by execution as a file. -bool CScript::WriteStack(FILE *file) +bool CScript::WriteStack(std::ostream &ostr) { int nb; nb = 2; - CBot::fWrite(&nb, sizeof(int), 1, file); - CBot::fWrite(&m_ipf, sizeof(int), 1, file); - CBot::fWrite(&m_errMode, sizeof(int), 1, file); + if (!CBot::WriteInt(ostr, nb)) return false; + if (!CBot::WriteInt(ostr, m_ipf)) return false; + if (!CBot::WriteInt(ostr, m_errMode)) return false; - return m_botProg->SaveState(file); + return m_botProg->SaveState(ostr); } diff --git a/src/script/script.h b/src/script/script.h index f0f473fb..606cb302 100644 --- a/src/script/script.h +++ b/src/script/script.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ #include "CBot/CBot.h" #include +#include #include #include @@ -88,8 +89,8 @@ public: bool SendScript(const char* text); bool ReadScript(const char* filename); bool WriteScript(const char* filename); - bool ReadStack(FILE *file); - bool WriteStack(FILE *file); + bool ReadStack(std::istream &istr); + bool WriteStack(std::ostream &ostr); bool Compare(CScript* other); void SetFilename(const std::string &filename); diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index 0816cce8..f35c7a2f 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -344,22 +344,30 @@ bool CScriptFunctions::rGetObject(CBotVar* var, CBotVar* result, int& exception, return true; } -// Compilation of instruction "object.busy()" -CBotTypResult CScriptFunctions::cBusy(CBotVar* thisclass, CBotVar* &var) +// Compilation of instruction "isbusy( object )" + +CBotTypResult CScriptFunctions::cIsBusy(CBot::CBotVar* &var, void* user) { - if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); + if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); return CBotTypResult(CBotTypBoolean); } -// Instruction "object.busy()" +// Instruction "isbusy( object )" -bool CScriptFunctions::rBusy(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception, void* user) +bool CScriptFunctions::rIsBusy(CBotVar* var, CBotVar* result, int& exception, void* user) { CObject* pThis = static_cast(user)->m_object; exception = 0; - CObject* obj = static_cast(thisclass->GetUserPtr()); + CObject* obj = static_cast(var->GetUserPtr()); + if (obj == nullptr) + { + exception = ERR_WRONG_OBJ; + result->SetValInt(ERR_WRONG_OBJ); + return false; + } + CAuto* automat = obj->GetAuto(); if ( pThis->GetTeam() != obj->GetTeam() && obj->GetTeam() != 0 ) @@ -377,7 +385,7 @@ bool CScriptFunctions::rBusy(CBotVar* thisclass, CBotVar* var, CBotVar* result, return true; } -bool CScriptFunctions::rDestroy(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception, void* user) +bool CScriptFunctions::rDestroy(CBotVar* var, CBotVar* result, int& exception, void* user) { CScript* script = static_cast(user); CObject* pThis = script->m_object; @@ -385,7 +393,19 @@ bool CScriptFunctions::rDestroy(CBotVar* thisclass, CBotVar* var, CBotVar* resul exception = 0; Error err; - CObject* obj = static_cast(thisclass->GetUserPtr()); + CObject* obj; + if (var == nullptr) + obj = CObjectManager::GetInstancePointer()->FindNearest(pThis, OBJECT_DESTROYER); + else + obj = static_cast(var->GetUserPtr()); + + if (obj == nullptr) + { + exception = ERR_WRONG_OBJ; + result->SetValInt(ERR_WRONG_OBJ); + return false; + } + CAuto* automat = obj->GetAuto(); if ( pThis->GetTeam() != obj->GetTeam() && obj->GetTeam() != 0 ) @@ -414,26 +434,30 @@ bool CScriptFunctions::rDestroy(CBotVar* thisclass, CBotVar* var, CBotVar* resul return true; } +// Compilation of instruction "factory(cat[, program , object])" -// Compilation of instruction "object.factory(cat, program)" - -CBotTypResult CScriptFunctions::cFactory(CBotVar* thisclass, CBotVar* &var) +CBotTypResult CScriptFunctions::cFactory(CBotVar* &var, void* user) { if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); var = var->GetNext(); if ( var != nullptr ) { - if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadNum); + if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadParam); var = var->GetNext(); - if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); + if ( var != nullptr ) + { + if ( var->GetType() != CBotTypPointer ) return CBotTypResult(CBotErrBadParam); + var = var->GetNext(); + if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); + } } return CBotTypResult(CBotTypFloat); } -// Instruction "object.factory(cat, program)" +// Instruction "factory(cat[, program , object])" -bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception, void* user) +bool CScriptFunctions::rFactory(CBotVar* var, CBotVar* result, int& exception, void* user) { CScript* script = static_cast(user); CObject* pThis = script->m_object; @@ -444,18 +468,26 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul ObjectType type = static_cast(var->GetValInt()); var = var->GetNext(); + std::string program; if ( var != nullptr ) + { program = var->GetValString(); + var = var->GetNext(); + } else program = ""; - CObject* factory = static_cast(thisclass->GetUserPtr()); + CObject* factory; + if (var == nullptr) + factory = CObjectManager::GetInstancePointer()->FindNearest(pThis, OBJECT_FACTORY); + else + factory = static_cast(var->GetUserPtr()); + if (factory == nullptr) { - exception = ERR_UNKNOWN; - result->SetValInt(ERR_UNKNOWN); - GetLogger()->Error("in object.factory() - factory is nullptr"); + exception = ERR_WRONG_OBJ; + result->SetValInt(ERR_WRONG_OBJ); return false; } @@ -473,7 +505,7 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul { exception = ERR_UNKNOWN; result->SetValInt(ERR_UNKNOWN); - GetLogger()->Error("in object.factory() - automat is nullptr"); + GetLogger()->Error("in factory() - automat is nullptr"); return false; } @@ -507,9 +539,24 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul return true; } -// Instruction "object.research(type)" +// Compilation of instruction "research(type[, object])" -bool CScriptFunctions::rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception, void* user) +CBotTypResult CScriptFunctions::cResearch(CBotVar* &var, void* user) +{ + if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); + if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GetNext(); + if ( var != nullptr ) + { + if ( var->GetType() != CBotTypPointer ) return CBotTypResult(CBotErrBadParam); + var = var->GetNext(); + if ( var != nullptr ) return CBotTypResult(CBotErrOverParam); + } + return CBotTypResult(CBotTypFloat); +} +// Instruction "research(type[, object])" + +bool CScriptFunctions::rResearch(CBotVar* var, CBotVar* result, int& exception, void* user) { CScript* script = static_cast(user); CObject* pThis = script->m_object; @@ -519,8 +566,21 @@ bool CScriptFunctions::rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* resu exception = 0; ResearchType type = static_cast(var->GetValInt()); + var = var->GetNext(); + + CObject* center; + if (var == nullptr) + center = CObjectManager::GetInstancePointer()->FindNearest(pThis, OBJECT_RESEARCH); + else + center = static_cast(var->GetUserPtr()); + + if (center == nullptr) + { + exception = ERR_WRONG_OBJ; + result->SetValInt(ERR_WRONG_OBJ); + return false; + } - CObject* center = static_cast(thisclass->GetUserPtr()); CAuto* automat = center->GetAuto(); if ( pThis->GetTeam() != center->GetTeam() && center->GetTeam() != 0 ) @@ -535,7 +595,8 @@ bool CScriptFunctions::rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* resu { bool ok = false; if ( type == RESEARCH_iPAW || - type == RESEARCH_iGUN ) + type == RESEARCH_iGUN || + type == RESEARCH_TARGET ) { if ( center->GetType() != OBJECT_LABO ) err = ERR_WRONG_OBJ; @@ -582,9 +643,9 @@ bool CScriptFunctions::rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* resu return true; } -// Instruction "object.takeoff()" +// Instruction "takeoff(object)" -bool CScriptFunctions::rTakeOff(CBotVar* thisclass, CBotVar* var, CBotVar* result, int& exception, void* user) +bool CScriptFunctions::rTakeOff(CBotVar* var, CBotVar* result, int& exception, void* user) { CScript* script = static_cast(user); CObject* pThis = script->m_object; @@ -592,8 +653,19 @@ bool CScriptFunctions::rTakeOff(CBotVar* thisclass, CBotVar* var, CBotVar* resul Error err; exception = 0; + CObject* base; + if (var == nullptr) + base = CObjectManager::GetInstancePointer()->FindNearest(pThis, OBJECT_BASE); + else + base = static_cast(var->GetUserPtr()); + + if (base == nullptr) + { + exception = ERR_WRONG_OBJ; + result->SetValInt(ERR_WRONG_OBJ); + return false; + } - CObject* base = static_cast(thisclass->GetUserPtr()); CAuto* automat = base->GetAuto(); if ( pThis->GetTeam() != base->GetTeam() && base->GetTeam() != 0 ) @@ -657,15 +729,18 @@ bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, vo } CObject* obj = CObjectManager::GetInstancePointer()->GetObjectById(rank); - if ( obj == nullptr || (obj->Implements(ObjectInterfaceType::Old) && dynamic_cast(obj)->IsDying()) ) + if ( obj == nullptr || (obj->Implements(ObjectInterfaceType::Old) && dynamic_cast(*obj).IsDying()) ) { return true; } else { + CScript* script = static_cast(user); + bool deleteSelf = (obj == script->m_object); + if ( exploType != DestructionType::NoEffect && obj->Implements(ObjectInterfaceType::Destroyable) ) { - dynamic_cast(obj)->DestroyObject(static_cast(exploType)); + dynamic_cast(*obj).DestroyObject(static_cast(exploType)); } else { @@ -681,12 +756,13 @@ bool CScriptFunctions::rDelete(CBotVar* var, CBotVar* result, int& exception, vo } CObjectManager::GetInstancePointer()->DeleteObject(obj); } + // Returning "false" here makes sure the program doesn't try to keep executing + // if the robot just destroyed itself using delete(this.id) + // See issue #925 + return !deleteSelf; } - // Returning "false" here makes sure the program doesn't try to keep executing if the robot just destroyed itself - // using delete(this.id) - // See issue #925 - return false; + return true; } static CBotTypResult compileSearch(CBotVar* &var, void* user, CBotTypResult returnValue) @@ -796,16 +872,34 @@ static bool runSearch(CBotVar* var, Math::Vector pos, int& exception, std::funct { while ( array != nullptr ) { + if (array->GetValInt() == OBJECT_MOBILEpr) + { + type_v.push_back(OBJECT_MOBILEwt); + type_v.push_back(OBJECT_MOBILEtt); + type_v.push_back(OBJECT_MOBILEft); + type_v.push_back(OBJECT_MOBILEit); + type_v.push_back(OBJECT_MOBILErp); + type_v.push_back(OBJECT_MOBILEst); + } type_v.push_back(static_cast(array->GetValInt())); array = array->GetNext(); } } else { - if (type != OBJECT_NULL) + if (type != OBJECT_NULL && type != OBJECT_MOBILEpr) { type_v.push_back(static_cast(type)); } + else if (type == OBJECT_MOBILEpr) + { + type_v.push_back(OBJECT_MOBILEwt); + type_v.push_back(OBJECT_MOBILEtt); + type_v.push_back(OBJECT_MOBILEft); + type_v.push_back(OBJECT_MOBILEit); + type_v.push_back(OBJECT_MOBILErp); + type_v.push_back(OBJECT_MOBILEst); + } } return code(type_v, pos, minDist, maxDist, sens < 0, filter); @@ -854,16 +948,13 @@ bool CScriptFunctions::rSearchAll(CBotVar* var, CBotVar* result, int& exception, static CBotTypResult compileRadar(CBotVar* &var, void* user, CBotTypResult returnValue) { - CBotVar* array; - if ( var == nullptr ) return returnValue; if ( var->GetType() == CBotTypArrayPointer ) { - array = var->GetItemList(); - if ( array == nullptr ) return returnValue; - if ( array->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type + CBotTypResult type = var->GetTypResult().GetTypElem(); + if ( type.GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadParam); //type } - else if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type + else if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadParam); // type var = var->GetNext(); if ( var == nullptr ) return returnValue; if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle @@ -971,16 +1062,34 @@ static bool runRadar(CBotVar* var, std::function, f { while ( array != nullptr ) { + if (array->GetValInt() == OBJECT_MOBILEpr) + { + type_v.push_back(OBJECT_MOBILEwt); + type_v.push_back(OBJECT_MOBILEtt); + type_v.push_back(OBJECT_MOBILEft); + type_v.push_back(OBJECT_MOBILEit); + type_v.push_back(OBJECT_MOBILErp); + type_v.push_back(OBJECT_MOBILEst); + } type_v.push_back(static_cast(array->GetValInt())); array = array->GetNext(); } } else { - if (type != OBJECT_NULL) + if (type != OBJECT_NULL && type != OBJECT_MOBILEpr) { type_v.push_back(static_cast(type)); } + else if (type == OBJECT_MOBILEpr) + { + type_v.push_back(OBJECT_MOBILEwt); + type_v.push_back(OBJECT_MOBILEtt); + type_v.push_back(OBJECT_MOBILEft); + type_v.push_back(OBJECT_MOBILEit); + type_v.push_back(OBJECT_MOBILErp); + type_v.push_back(OBJECT_MOBILEst); + } } return code(type_v, angle, focus, minDist, maxDist, sens < 0, filter); @@ -1142,16 +1251,34 @@ bool CScriptFunctions::rDetect(CBotVar* var, CBotVar* result, int& exception, vo { while ( array != nullptr ) { + if (array->GetValInt() == OBJECT_MOBILEpr) + { + type_v.push_back(OBJECT_MOBILEwt); + type_v.push_back(OBJECT_MOBILEtt); + type_v.push_back(OBJECT_MOBILEft); + type_v.push_back(OBJECT_MOBILEit); + type_v.push_back(OBJECT_MOBILErp); + type_v.push_back(OBJECT_MOBILEst); + } type_v.push_back(static_cast(array->GetValInt())); array = array->GetNext(); } } else { - if (type != OBJECT_NULL) + if (type != OBJECT_NULL && type != OBJECT_MOBILEpr) { type_v.push_back(static_cast(type)); } + else if (type == OBJECT_MOBILEpr) + { + type_v.push_back(OBJECT_MOBILEwt); + type_v.push_back(OBJECT_MOBILEtt); + type_v.push_back(OBJECT_MOBILEft); + type_v.push_back(OBJECT_MOBILEit); + type_v.push_back(OBJECT_MOBILErp); + type_v.push_back(OBJECT_MOBILEst); + } } pBest = CObjectManager::GetInstancePointer()->Radar(pThis, type_v, 0.0f, 45.0f*Math::PI/180.0f, 0.0f, 20.0f, false, FILTER_NONE, true); @@ -1278,10 +1405,10 @@ bool CScriptFunctions::rBuild(CBotVar* var, CBotVar* result, int& exception, voi oType = pThis->GetType(); - if ( oType != OBJECT_MOBILEfa && // allowed only for grabber bots && humans - oType != OBJECT_MOBILEta && - oType != OBJECT_MOBILEwa && - oType != OBJECT_MOBILEia && + if ( oType != OBJECT_MOBILEfb && // allowed only for builder bots && humans + oType != OBJECT_MOBILEtb && + oType != OBJECT_MOBILEwb && + oType != OBJECT_MOBILEib && oType != OBJECT_HUMAN && oType != OBJECT_TECH ) { @@ -1317,6 +1444,102 @@ bool CScriptFunctions::rBuild(CBotVar* var, CBotVar* result, int& exception, voi } +// Instruction "flag(color)" + +bool CScriptFunctions::rFlag(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = static_cast(user); + CObject* pThis = script->m_object; + ObjectType oType; + int color; + Error err; + + exception = 0; + + if ( !script->m_taskExecutor->IsForegroundTask() ) + { + oType = pThis->GetType(); + if ( oType != OBJECT_MOBILEfs && // allowed only for sniffer bots && humans + oType != OBJECT_MOBILEts && + oType != OBJECT_MOBILEws && + oType != OBJECT_MOBILEis && + oType != OBJECT_HUMAN && + oType != OBJECT_TECH ) + { + err = ERR_WRONG_BOT; // Wrong object + } + else + { + if ( var == nullptr ) + { + color = 0; + } + else + { + color = var->GetValInt(); + if ( color < 0 || color > static_cast(TraceColor::Violet) ) color = 0; + } + err = script->m_taskExecutor->StartTaskFlag(TFL_CREATE, color); + } + + if ( err != ERR_OK ) + { + script->m_taskExecutor->StopForegroundTask(); + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return false; + } + return true; + } + } + return WaitForForegroundTask(script, result, exception); +} + +// Instruction "deflag()" + +bool CScriptFunctions::rDeflag(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = static_cast(user); + CObject* pThis = script->m_object; + ObjectType oType; + Error err; + + exception = 0; + + if ( !script->m_taskExecutor->IsForegroundTask() ) + { + oType = pThis->GetType(); + if ( oType != OBJECT_MOBILEfs && // allowed only for sniffer bots && humans + oType != OBJECT_MOBILEts && + oType != OBJECT_MOBILEws && + oType != OBJECT_MOBILEis && + oType != OBJECT_HUMAN && + oType != OBJECT_TECH ) + { + err = ERR_WRONG_BOT; // Wrong object + } + else + { + err = script->m_taskExecutor->StartTaskFlag(TFL_DELETE, 0); + } + + if ( err != ERR_OK ) + { + script->m_taskExecutor->StopForegroundTask(); + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return false; + } + return true; + } + } + return WaitForForegroundTask(script, result, exception); +} + // Compilation of the instruction "produce(pos, angle, type[, scriptName[, power]])" // or "produce(type[, power])". @@ -1434,7 +1657,7 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v CObjectManager::GetInstancePointer()->CreateObject(pos, angle, OBJECT_EGG); if (object->Implements(ObjectInterfaceType::Programmable)) { - dynamic_cast(object)->SetActivity(false); + dynamic_cast(*object).SetActivity(false); } } else @@ -1443,7 +1666,11 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v { power = 1.0f; } - object = CObjectManager::GetInstancePointer()->CreateObject(pos, angle, type, power); + bool exists = IsValidObjectTypeId(type) && type != OBJECT_NULL && type != OBJECT_MAX && type != OBJECT_MOBILEpr; + if (exists) + { + object = CObjectManager::GetInstancePointer()->CreateObject(pos, angle, type, power); + } if (object == nullptr) { result->SetValInt(1); // error @@ -1452,7 +1679,7 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v if (type == OBJECT_MOBILEdr) { assert(object->Implements(ObjectInterfaceType::Old)); // TODO: temporary hack - dynamic_cast(object)->SetManual(true); + dynamic_cast(*object).SetManual(true); } script->m_main->CreateShortcuts(); } @@ -1467,7 +1694,7 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v programStorage->ReadProgram(program, name2.c_str()); program->readOnly = true; program->filename = name; - dynamic_cast(object)->RunProgram(program); + dynamic_cast(*object).RunProgram(program); } } @@ -2073,7 +2300,7 @@ bool CScriptFunctions::rReceive(CBotVar* var, CBotVar* result, int& exception, v return true; } - CExchangePost* exchangePost = dynamic_cast(script->m_taskExecutor->GetForegroundTask())->FindExchangePost(power); + CExchangePost* exchangePost = dynamic_cast(*script->m_taskExecutor->GetForegroundTask()).FindExchangePost(power); script->m_returnValue = exchangePost->GetInfoValue(p); } if ( !WaitForForegroundTask(script, result, exception) ) return false; // not finished @@ -2358,7 +2585,7 @@ bool CScriptFunctions::rShield(CBotVar* var, CBotVar* result, int& exception, vo } else // up ? { - dynamic_cast(pThis)->SetShieldRadius(radius); + dynamic_cast(*pThis).SetShieldRadius(radius); err = script->m_taskExecutor->StartTaskShield(TSM_UP, 1000.0f); if ( err != ERR_OK ) { @@ -2376,7 +2603,7 @@ bool CScriptFunctions::rShield(CBotVar* var, CBotVar* result, int& exception, vo else // up? { //? result->SetValInt(1); // shows the error - dynamic_cast(pThis)->SetShieldRadius(radius); + dynamic_cast(*pThis).SetShieldRadius(radius); script->m_taskExecutor->StartTaskShield(TSM_UPDATE, 0.0f); } } @@ -2550,7 +2777,7 @@ bool CScriptFunctions::rMotor(CBotVar* var, CBotVar* result, int& exception, voi if ( turn < -1.0f ) turn = -1.0f; if ( turn > 1.0f ) turn = 1.0f; - if ( dynamic_cast(pThis) != nullptr && dynamic_cast(pThis)->GetFixed() ) // ant on the back? + if ( dynamic_cast(pThis) != nullptr && dynamic_cast(*pThis).GetFixed() ) // ant on the back? { speed = 0.0f; turn = 0.0f; @@ -2659,7 +2886,7 @@ bool CScriptFunctions::rCmdline(CBotVar* var, CBotVar* result, int& exception, v assert(pThis->Implements(ObjectInterfaceType::Programmable)); rank = var->GetValInt(); - value = dynamic_cast(pThis)->GetCmdLine(rank); + value = dynamic_cast(*pThis).GetCmdLine(rank); result->SetValFloat(value); return true; @@ -2941,20 +3168,29 @@ bool CScriptFunctions::rPenWidth(CBotVar* var, CBotVar* result, int& exception, CBotTypResult CScriptFunctions::cOneObject(CBotVar* &var, void* user) { - if ( var == nullptr ) return CBotTypResult(CBotErrLowParam); - var = var->GetNext(); - if ( var == nullptr ) return CBotTypResult(CBotTypFloat); + if ( var != nullptr ) + { + var = var->GetNext(); + if ( var == nullptr ) return CBotTypResult(CBotTypFloat); + } + else + return CBotTypResult(CBotTypFloat); return CBotTypResult(CBotErrOverParam); + } // Instruction "camerafocus(object)". bool CScriptFunctions::rCameraFocus(CBotVar* var, CBotVar* result, int& exception, void* user) { - CScript* script = static_cast(user); + CScript* script = static_cast(user); - CObject* object = static_cast(var->GetUserPtr()); + CObject* object; + if (var == nullptr) + object = script->m_object; + else + object = static_cast(var->GetUserPtr()); script->m_main->SelectObject(object, false); @@ -3175,7 +3411,6 @@ private: void CScriptFunctions::Init() { - CBotProgram::SetTimer(100); CBotProgram::Init(); for (int i = 0; i < OBJECT_MAX; i++) @@ -3238,6 +3473,7 @@ void CScriptFunctions::Init() CBotProgram::DefineNum("BuildAutoLab", BUILD_LABO); CBotProgram::DefineNum("BuildPowerCaptor", BUILD_PARA); CBotProgram::DefineNum("BuildExchangePost", BUILD_INFO); + CBotProgram::DefineNum("BuildVault", BUILD_SAFE); CBotProgram::DefineNum("BuildDestroyer", BUILD_DESTROYER); CBotProgram::DefineNum("FlatGround", BUILD_GFLAT); CBotProgram::DefineNum("UseFlags", BUILD_FLAG); @@ -3255,6 +3491,8 @@ void CScriptFunctions::Init() CBotProgram::DefineNum("ResearchRecycler", RESEARCH_RECYCLER); CBotProgram::DefineNum("ResearchSubber", RESEARCH_SUBM); CBotProgram::DefineNum("ResearchSniffer", RESEARCH_SNIFFER); + CBotProgram::DefineNum("ResearchBuilder", RESEARCH_BUILDER); + CBotProgram::DefineNum("ResearchTarget", RESEARCH_TARGET); CBotProgram::DefineNum("PolskiPortalColobota", 1337); @@ -3283,12 +3521,8 @@ void CScriptFunctions::Init() bc->AddItem("load", CBotTypResult(CBotTypPointer, "object"), CBotVar::ProtectionLevel::ReadOnly); bc->AddItem("id", CBotTypResult(CBotTypInt), CBotVar::ProtectionLevel::ReadOnly); bc->AddItem("team", CBotTypResult(CBotTypInt), CBotVar::ProtectionLevel::ReadOnly); + bc->AddItem("dead", CBotTypResult(CBotTypBoolean), CBotVar::ProtectionLevel::ReadOnly); bc->AddItem("velocity", CBotTypResult(CBotTypClass, "point"), CBotVar::ProtectionLevel::ReadOnly); - bc->AddFunction("busy", rBusy, cBusy); - bc->AddFunction("factory", rFactory, cFactory); - bc->AddFunction("research", rResearch, cClassOneFloat); - bc->AddFunction("takeoff", rTakeOff, cClassNull); - bc->AddFunction("destroy", rDestroy, cClassNull); CBotProgram::AddFunction("endmission",rEndMission,cEndMission); CBotProgram::AddFunction("playmusic", rPlayMusic ,cPlayMusic); @@ -3307,6 +3541,8 @@ void CScriptFunctions::Init() CBotProgram::AddFunction("buildingenabled", rBuildingEnabled, cOneIntReturnBool); CBotProgram::AddFunction("build", rBuild, cOneInt); + CBotProgram::AddFunction("flag", rFlag, cGrabDrop); + CBotProgram::AddFunction("deflag", rDeflag, cNull); CBotProgram::AddFunction("retobject", rGetObject, cGetObject); CBotProgram::AddFunction("retobjectbyid", rGetObjectById, cGetObject); @@ -3352,8 +3588,12 @@ void CScriptFunctions::Init() CBotProgram::AddFunction("penup", rPenUp, cNull); CBotProgram::AddFunction("pencolor", rPenColor, cOneFloat); CBotProgram::AddFunction("penwidth", rPenWidth, cOneFloat); - + CBotProgram::AddFunction("factory", rFactory, cFactory); CBotProgram::AddFunction("camerafocus", rCameraFocus, cOneObject); + CBotProgram::AddFunction("takeoff", rTakeOff, cOneObject); + CBotProgram::AddFunction("isbusy", rIsBusy, cIsBusy); + CBotProgram::AddFunction("research", rResearch, cResearch); + CBotProgram::AddFunction("destroy", rDestroy, cOneObject); SetFileAccessHandler(MakeUnique()); } @@ -3482,6 +3722,10 @@ void CScriptFunctions::uObject(CBotVar* botThis, void* user) value = object->GetTeam(); pVar->SetValInt(value); + pVar = pVar->GetNext(); // "dead" + value = object->IsDying(); + pVar->SetValInt(value); + // Updates the velocity of the object. pVar = pVar->GetNext(); // "velocity" if (IsObjectBeingTransported(object) || physics == nullptr) diff --git a/src/script/scriptfunc.h b/src/script/scriptfunc.h index 9121ef7c..2a2cd718 100644 --- a/src/script/scriptfunc.h +++ b/src/script/scriptfunc.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -80,6 +80,9 @@ private: static CBot::CBotTypResult cTopo(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cMessage(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cPenDown(CBot::CBotVar* &var, void* user); + static CBot::CBotTypResult cIsBusy(CBot::CBotVar* &var, void* user); + static CBot::CBotTypResult cFactory(CBot::CBotVar* &var, void* user); + static CBot::CBotTypResult cResearch(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cOnePoint(CBot::CBotVar* &var, void* user); static CBot::CBotTypResult cOneObject(CBot::CBotVar* &var, void* user); @@ -107,6 +110,8 @@ private: static bool rResearched(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rBuildingEnabled(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rBuild(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); + static bool rFlag(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); + static bool rDeflag(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rProduce(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rDistance(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rDistance2d(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); @@ -143,19 +148,15 @@ private: static bool rPenColor(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rPenWidth(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); static bool rCameraFocus(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); + static bool rIsBusy(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); + static bool rTakeOff(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); + static bool rFactory(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); + static bool rResearch(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); + static bool rDestroy(CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); - - static CBot::CBotTypResult cBusy(CBot::CBotVar* thisclass, CBot::CBotVar* &var); - static CBot::CBotTypResult cFactory(CBot::CBotVar* thisclass, CBot::CBotVar* &var); static CBot::CBotTypResult cClassNull(CBot::CBotVar* thisclass, CBot::CBotVar* &var); static CBot::CBotTypResult cClassOneFloat(CBot::CBotVar* thisclass, CBot::CBotVar* &var); - static bool rBusy(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); - static bool rFactory(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); - static bool rResearch(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); - static bool rTakeOff(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); - static bool rDestroy(CBot::CBotVar* thisclass, CBot::CBotVar* var, CBot::CBotVar* result, int& exception, void* user); - static CBot::CBotTypResult cPointConstructor(CBot::CBotVar* pThis, CBot::CBotVar* &var); static bool rPointConstructor(CBot::CBotVar* pThis, CBot::CBotVar* var, CBot::CBotVar* pResult, int& Exception, void* user); diff --git a/src/sound/oalsound/alsound.cpp b/src/sound/oalsound/alsound.cpp index bcea6979..26006198 100644 --- a/src/sound/oalsound/alsound.cpp +++ b/src/sound/oalsound/alsound.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -47,22 +47,7 @@ void CALSound::CleanUp() if (m_enabled) { GetLogger()->Info("Unloading files and closing device...\n"); - StopAll(); - StopMusic(); - - m_channels.clear(); - - m_currentMusic.reset(); - - m_oldMusic.clear(); - - m_previousMusic.music.reset(); - - m_sounds.clear(); - - m_music.clear(); - - m_enabled = false; + Reset(); alcDestroyContext(m_context); alcCloseDevice(m_device); @@ -99,6 +84,24 @@ bool CALSound::Create() return true; } +void CALSound::Reset() +{ + StopAll(); + StopMusic(); + + m_channels.clear(); + + m_currentMusic.reset(); + + m_oldMusic.clear(); + + m_previousMusic.music.reset(); + + m_sounds.clear(); + + m_music.clear(); +} + bool CALSound::GetEnable() { return m_enabled; diff --git a/src/sound/oalsound/alsound.h b/src/sound/oalsound/alsound.h index dc0e1ee8..75e3d7f6 100644 --- a/src/sound/oalsound/alsound.h +++ b/src/sound/oalsound/alsound.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -84,6 +84,7 @@ public: ~CALSound(); bool Create() override; + void Reset() override; bool Cache(SoundType, const std::string &) override; void CacheMusic(const std::string &) override; bool IsCached(SoundType) override; diff --git a/src/sound/oalsound/buffer.cpp b/src/sound/oalsound/buffer.cpp index 018d356d..26816b9d 100644 --- a/src/sound/oalsound/buffer.cpp +++ b/src/sound/oalsound/buffer.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/sound/oalsound/buffer.h b/src/sound/oalsound/buffer.h index be9d4c5e..ec838952 100644 --- a/src/sound/oalsound/buffer.h +++ b/src/sound/oalsound/buffer.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/sound/oalsound/channel.cpp b/src/sound/oalsound/channel.cpp index d2d3630e..4ec60b5c 100644 --- a/src/sound/oalsound/channel.cpp +++ b/src/sound/oalsound/channel.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/sound/oalsound/channel.h b/src/sound/oalsound/channel.h index 27b474af..640a9c40 100644 --- a/src/sound/oalsound/channel.h +++ b/src/sound/oalsound/channel.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/sound/oalsound/check.cpp b/src/sound/oalsound/check.cpp index 0d86fb95..3d399c25 100644 --- a/src/sound/oalsound/check.cpp +++ b/src/sound/oalsound/check.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/sound/oalsound/check.h b/src/sound/oalsound/check.h index c22dbd17..ac746cdb 100644 --- a/src/sound/oalsound/check.h +++ b/src/sound/oalsound/check.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/sound/sound.cpp b/src/sound/sound.cpp index b1cbc144..87d7266c 100644 --- a/src/sound/sound.cpp +++ b/src/sound/sound.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -52,6 +52,10 @@ void CSoundInterface::CacheAll() } } +void CSoundInterface::Reset() +{ +} + bool CSoundInterface::Cache(SoundType sound, const std::string &file) { return true; diff --git a/src/sound/sound.h b/src/sound/sound.h index c03fcf39..314eb856 100644 --- a/src/sound/sound.h +++ b/src/sound/sound.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -72,6 +72,10 @@ public: */ void CacheAll(); + /** Stop all sounds and music and clean cache. + */ + virtual void Reset(); + /** Function called to cache sound effect file. * This function is called by plugin interface for each file. * \param sound - id of a file, will be used to identify sound files diff --git a/src/sound/sound_type.cpp b/src/sound/sound_type.cpp index 22f629be..11908f64 100644 --- a/src/sound/sound_type.cpp +++ b/src/sound/sound_type.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/sound/sound_type.h b/src/sound/sound_type.h index a07870b1..f6e4f926 100644 --- a/src/sound/sound_type.h +++ b/src/sound/sound_type.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/tools/convert_model.cpp b/src/tools/convert_model.cpp index 4315c84f..192b2e79 100644 --- a/src/tools/convert_model.cpp +++ b/src/tools/convert_model.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/button.cpp b/src/ui/controls/button.cpp index 706946b7..86f0591b 100644 --- a/src/ui/controls/button.cpp +++ b/src/ui/controls/button.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/button.h b/src/ui/controls/button.h index 9abe3262..d388bbc8 100644 --- a/src/ui/controls/button.h +++ b/src/ui/controls/button.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/check.cpp b/src/ui/controls/check.cpp index af9f58aa..2fc7dafe 100644 --- a/src/ui/controls/check.cpp +++ b/src/ui/controls/check.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/check.h b/src/ui/controls/check.h index 445a6782..9add4f0e 100644 --- a/src/ui/controls/check.h +++ b/src/ui/controls/check.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/color.cpp b/src/ui/controls/color.cpp index faecb435..8c7f7929 100644 --- a/src/ui/controls/color.cpp +++ b/src/ui/controls/color.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -121,9 +121,7 @@ bool CColor::EventProcess(const Event &event) return true; } - -// Dessine le bouton. - +// Draw the button. void CColor::Draw() { Gfx::CDevice* device; diff --git a/src/ui/controls/color.h b/src/ui/controls/color.h index e694a7d5..490fd1f3 100644 --- a/src/ui/controls/color.h +++ b/src/ui/controls/color.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/control.cpp b/src/ui/controls/control.cpp index 588c136d..cb97d5db 100644 --- a/src/ui/controls/control.cpp +++ b/src/ui/controls/control.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/control.h b/src/ui/controls/control.h index a7166df8..0628c760 100644 --- a/src/ui/controls/control.h +++ b/src/ui/controls/control.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/edit.cpp b/src/ui/controls/edit.cpp index 2fa9e8ab..570bd518 100644 --- a/src/ui/controls/edit.cpp +++ b/src/ui/controls/edit.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -1299,7 +1299,9 @@ void CEdit::SetText(const std::string& text, bool bNew) if( m_len >= GetMaxChar() ) m_len = GetMaxChar(); m_text.resize( m_len + 1, '\0' ); + m_text[m_len] = '\0'; m_format.resize( m_len + 1, m_fontType ); + m_format[m_len] = m_fontType; font = m_fontType; j = 0; diff --git a/src/ui/controls/edit.h b/src/ui/controls/edit.h index 1fe83b1d..70ef1d4c 100644 --- a/src/ui/controls/edit.h +++ b/src/ui/controls/edit.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/editvalue.cpp b/src/ui/controls/editvalue.cpp index 330f9b32..fd99556b 100644 --- a/src/ui/controls/editvalue.cpp +++ b/src/ui/controls/editvalue.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/editvalue.h b/src/ui/controls/editvalue.h index 2094f7c4..85c38302 100644 --- a/src/ui/controls/editvalue.h +++ b/src/ui/controls/editvalue.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/enumslider.cpp b/src/ui/controls/enumslider.cpp index 6c791d2b..085e12be 100644 --- a/src/ui/controls/enumslider.cpp +++ b/src/ui/controls/enumslider.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/enumslider.h b/src/ui/controls/enumslider.h index 70643bf6..f52dcf64 100644 --- a/src/ui/controls/enumslider.h +++ b/src/ui/controls/enumslider.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/gauge.cpp b/src/ui/controls/gauge.cpp index 13bf7a5a..545fcfa7 100644 --- a/src/ui/controls/gauge.cpp +++ b/src/ui/controls/gauge.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/gauge.h b/src/ui/controls/gauge.h index c16452b8..b0c4cd3a 100644 --- a/src/ui/controls/gauge.h +++ b/src/ui/controls/gauge.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/group.cpp b/src/ui/controls/group.cpp index 8660ac0f..d303c118 100644 --- a/src/ui/controls/group.cpp +++ b/src/ui/controls/group.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/group.h b/src/ui/controls/group.h index cc65ac87..4f80aa7c 100644 --- a/src/ui/controls/group.h +++ b/src/ui/controls/group.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/image.cpp b/src/ui/controls/image.cpp index 5439f0d8..bb610042 100644 --- a/src/ui/controls/image.cpp +++ b/src/ui/controls/image.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/image.h b/src/ui/controls/image.h index 499b5785..556e4aa2 100644 --- a/src/ui/controls/image.h +++ b/src/ui/controls/image.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/interface.cpp b/src/ui/controls/interface.cpp index 050ce193..d394ddaa 100644 --- a/src/ui/controls/interface.cpp +++ b/src/ui/controls/interface.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -194,8 +194,7 @@ CEdit* CInterface::CreateEdit(Math::Point pos, Math::Point dim, int icon, EventT return CreateControl(pos, dim, icon, eventMsg); } -// Creates a new pave editable. - +// Creates a new editable area. CEditValue* CInterface::CreateEditValue(Math::Point pos, Math::Point dim, int icon, EventType eventMsg) { CEditValue* ev = CreateControl(pos, dim, icon, eventMsg); diff --git a/src/ui/controls/interface.h b/src/ui/controls/interface.h index 54737532..b2a5aad3 100644 --- a/src/ui/controls/interface.h +++ b/src/ui/controls/interface.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/key.cpp b/src/ui/controls/key.cpp index 846ce6e8..03dab6ac 100644 --- a/src/ui/controls/key.cpp +++ b/src/ui/controls/key.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/key.h b/src/ui/controls/key.h index 2f1702b4..e24f2559 100644 --- a/src/ui/controls/key.h +++ b/src/ui/controls/key.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/label.cpp b/src/ui/controls/label.cpp index 219e4d86..b307ce4b 100644 --- a/src/ui/controls/label.cpp +++ b/src/ui/controls/label.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/label.h b/src/ui/controls/label.h index 97a71e91..bc9f38aa 100644 --- a/src/ui/controls/label.h +++ b/src/ui/controls/label.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/list.cpp b/src/ui/controls/list.cpp index 4dd54045..59a02176 100644 --- a/src/ui/controls/list.cpp +++ b/src/ui/controls/list.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/list.h b/src/ui/controls/list.h index 02faa43b..14631e68 100644 --- a/src/ui/controls/list.h +++ b/src/ui/controls/list.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/map.cpp b/src/ui/controls/map.cpp index 03cee9a1..9d9ebb48 100644 --- a/src/ui/controls/map.cpp +++ b/src/ui/controls/map.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -830,63 +830,87 @@ void CMap::DrawObjectIcon(Math::Point pos, Math::Point dim, MapColor color, if ( bHilite ) { - icon = -1; - if ( type == OBJECT_FACTORY ) icon = 32; - if ( type == OBJECT_DERRICK ) icon = 33; - if ( type == OBJECT_CONVERT ) icon = 34; - if ( type == OBJECT_RESEARCH ) icon = 35; - if ( type == OBJECT_STATION ) icon = 36; - if ( type == OBJECT_TOWER ) icon = 37; - if ( type == OBJECT_LABO ) icon = 38; - if ( type == OBJECT_ENERGY ) icon = 39; - if ( type == OBJECT_RADAR ) icon = 40; - if ( type == OBJECT_INFO ) icon = 44; - if ( type == OBJECT_REPAIR ) icon = 41; - if ( type == OBJECT_DESTROYER) icon = 41; - if ( type == OBJECT_NUCLEAR ) icon = 42; - if ( type == OBJECT_PARA ) icon = 46; - if ( type == OBJECT_SAFE ) icon = 47; - if ( type == OBJECT_HUSTON ) icon = 48; - if ( type == OBJECT_TARGET1 ) icon = 45; - if ( type == OBJECT_BASE ) icon = 43; - if ( type == OBJECT_HUMAN ) icon = 8; - if ( type == OBJECT_MOBILEfa ) icon = 11; - if ( type == OBJECT_MOBILEta ) icon = 10; - if ( type == OBJECT_MOBILEwa ) icon = 9; - if ( type == OBJECT_MOBILEia ) icon = 22; - if ( type == OBJECT_MOBILEfc ) icon = 17; - if ( type == OBJECT_MOBILEtc ) icon = 16; - if ( type == OBJECT_MOBILEwc ) icon = 15; - if ( type == OBJECT_MOBILEic ) icon = 23; - if ( type == OBJECT_MOBILEfi ) icon = 27; - if ( type == OBJECT_MOBILEti ) icon = 26; - if ( type == OBJECT_MOBILEwi ) icon = 25; - if ( type == OBJECT_MOBILEii ) icon = 28; - if ( type == OBJECT_MOBILEfs ) icon = 14; - if ( type == OBJECT_MOBILEts ) icon = 13; - if ( type == OBJECT_MOBILEws ) icon = 12; - if ( type == OBJECT_MOBILEis ) icon = 24; - if ( type == OBJECT_MOBILErt ) icon = 18; - if ( type == OBJECT_MOBILErc ) icon = 19; - if ( type == OBJECT_MOBILErr ) icon = 20; - if ( type == OBJECT_MOBILErs ) icon = 29; - if ( type == OBJECT_MOBILEsa ) icon = 21; - if ( type == OBJECT_MOBILEft ) icon = 30; - if ( type == OBJECT_MOBILEtt ) icon = 30; - if ( type == OBJECT_MOBILEwt ) icon = 30; - if ( type == OBJECT_MOBILEit ) icon = 30; - if ( type == OBJECT_MOBILEtg ) icon = 45; - if ( type == OBJECT_MOBILEdr ) icon = 48; - if ( type == OBJECT_APOLLO2 ) icon = 49; - if ( type == OBJECT_MOTHER ) icon = 31; - if ( type == OBJECT_ANT ) icon = 31; - if ( type == OBJECT_SPIDER ) icon = 31; - if ( type == OBJECT_BEE ) icon = 31; - if ( type == OBJECT_WORM ) icon = 31; - if ( type == OBJECT_TEEN28 ) icon = 48; // bottle - if ( type == OBJECT_TEEN34 ) icon = 48; // stone + switch ( type ) + { + case OBJECT_FACTORY: icon = 32; break; + case OBJECT_DERRICK: icon = 33; break; + case OBJECT_CONVERT: icon = 34; break; + case OBJECT_RESEARCH: icon = 35; break; + case OBJECT_STATION: icon = 36; break; + case OBJECT_TOWER: icon = 37; break; + case OBJECT_LABO: icon = 38; break; + case OBJECT_ENERGY: icon = 39; break; + case OBJECT_RADAR: icon = 40; break; + case OBJECT_INFO: icon = 44; break; + case OBJECT_REPAIR: icon = 41; break; + case OBJECT_DESTROYER: icon = 41; break; + case OBJECT_NUCLEAR: icon = 42; break; + case OBJECT_PARA: icon = 46; break; + case OBJECT_SAFE: icon = 47; break; + case OBJECT_HUSTON: icon = 48; break; + case OBJECT_TARGET1: icon = 45; break; + case OBJECT_BASE: icon = 43; break; + case OBJECT_HUMAN: icon = 8; break; + case OBJECT_MOBILEfa: icon = 11; break; + case OBJECT_MOBILEta: icon = 10; break; + case OBJECT_MOBILEwa: icon = 9; break; + case OBJECT_MOBILEia: icon = 22; break; + case OBJECT_MOBILEfb: icon = 2; break; // button4 + case OBJECT_MOBILEtb: icon = 1; break; + case OBJECT_MOBILEwb: icon = 0; break; + case OBJECT_MOBILEib: icon = 3; break; + case OBJECT_MOBILEfc: icon = 17; break; + case OBJECT_MOBILEtc: icon = 16; break; + case OBJECT_MOBILEwc: icon = 15; break; + case OBJECT_MOBILEic: icon = 23; break; + case OBJECT_MOBILEfi: icon = 27; break; + case OBJECT_MOBILEti: icon = 26; break; + case OBJECT_MOBILEwi: icon = 25; break; + case OBJECT_MOBILEii: icon = 28; break; + case OBJECT_MOBILEfs: icon = 14; break; + case OBJECT_MOBILEts: icon = 13; break; + case OBJECT_MOBILEws: icon = 12; break; + case OBJECT_MOBILEis: icon = 24; break; + case OBJECT_MOBILErt: icon = 18; break; + case OBJECT_MOBILErc: icon = 19; break; + case OBJECT_MOBILErr: icon = 20; break; + case OBJECT_MOBILErs: icon = 29; break; + case OBJECT_MOBILEsa: icon = 21; break; + case OBJECT_MOBILEft: icon = 6; break; + case OBJECT_MOBILEtt: icon = 5; break; + case OBJECT_MOBILEwt: icon = 30; break; + case OBJECT_MOBILEit: icon = 7; break; + case OBJECT_MOBILErp: icon = 9; break; + case OBJECT_MOBILEst: icon = 10; break; + case OBJECT_MOBILEtg: icon = 45; break; + case OBJECT_MOBILEdr: icon = 48; break; + case OBJECT_APOLLO2: icon = 49; break; + case OBJECT_MOTHER: icon = 31; break; + case OBJECT_ANT: icon = 31; break; + case OBJECT_SPIDER: icon = 31; break; + case OBJECT_BEE: icon = 31; break; + case OBJECT_WORM: icon = 31; break; + case OBJECT_TEEN28: icon = 48; break; // bottle + case OBJECT_TEEN34: icon = 48; break; // stone + default: icon = -1; + } if ( icon == -1 ) return; + switch ( type ) + { + case OBJECT_MOBILEfb: + case OBJECT_MOBILEtb: + case OBJECT_MOBILEwb: + case OBJECT_MOBILEib: + case OBJECT_MOBILEft: + case OBJECT_MOBILEtt: + case OBJECT_MOBILEit: + case OBJECT_MOBILErp: + case OBJECT_MOBILEst: + m_engine->SetTexture("textures/interface/button4.png"); break; + default: ; // button3.png + } + m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE); uv1.x = (32.0f/256.0f)*(icon%8); uv1.y = (32.0f/256.0f)*(icon/8); @@ -1173,7 +1197,7 @@ void CMap::UpdateObject(CObject* pObj) type != OBJECT_WORM && type != OBJECT_MOBILEtg ) { - if (pObj->Implements(ObjectInterfaceType::Controllable) && !dynamic_cast(pObj)->GetSelectable()) return; + if (pObj->Implements(ObjectInterfaceType::Controllable) && !dynamic_cast(*pObj).GetSelectable()) return; } if ( pObj->GetProxyActivate() ) return; if (IsObjectBeingTransported(pObj)) return; @@ -1231,6 +1255,10 @@ void CMap::UpdateObject(CObject* pObj) type == OBJECT_MOBILEta || type == OBJECT_MOBILEfa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEwc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEfc || @@ -1253,6 +1281,8 @@ void CMap::UpdateObject(CObject* pObj) type == OBJECT_MOBILEtt || type == OBJECT_MOBILEft || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEst || type == OBJECT_MOBILEdr || type == OBJECT_APOLLO2 ) // moving vehicle? { @@ -1300,7 +1330,7 @@ void CMap::UpdateObject(CObject* pObj) color != MAPCOLOR_MOVE ) return; }*/ - if ( pObj->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(pObj)->GetSelect() ) + if ( pObj->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(*pObj).GetSelect() ) { m_map[MAPMAXOBJECT-1].type = type; m_map[MAPMAXOBJECT-1].object = pObj; diff --git a/src/ui/controls/map.h b/src/ui/controls/map.h index 75bf4c01..afff08d5 100644 --- a/src/ui/controls/map.h +++ b/src/ui/controls/map.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/scroll.cpp b/src/ui/controls/scroll.cpp index a9217686..2dbf39b1 100644 --- a/src/ui/controls/scroll.cpp +++ b/src/ui/controls/scroll.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/scroll.h b/src/ui/controls/scroll.h index 77d4b809..293dda8c 100644 --- a/src/ui/controls/scroll.h +++ b/src/ui/controls/scroll.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/shortcut.cpp b/src/ui/controls/shortcut.cpp index 7d3ddd6d..0864db1b 100644 --- a/src/ui/controls/shortcut.cpp +++ b/src/ui/controls/shortcut.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/shortcut.h b/src/ui/controls/shortcut.h index 9605d25b..51d01a5d 100644 --- a/src/ui/controls/shortcut.h +++ b/src/ui/controls/shortcut.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/slider.cpp b/src/ui/controls/slider.cpp index 32efeddc..3ae1109e 100644 --- a/src/ui/controls/slider.cpp +++ b/src/ui/controls/slider.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/slider.h b/src/ui/controls/slider.h index 3b9b3607..097f68dc 100644 --- a/src/ui/controls/slider.h +++ b/src/ui/controls/slider.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/target.cpp b/src/ui/controls/target.cpp index e7b899b6..24fa3c9a 100644 --- a/src/ui/controls/target.cpp +++ b/src/ui/controls/target.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -143,13 +143,13 @@ CObject* CTarget::DetectFriendObject(Math::Point pos) CObject* target = obj; if ( obj->Implements(ObjectInterfaceType::PowerContainer) && IsObjectBeingTransported(obj) ) { - target = dynamic_cast(obj)->GetTransporter(); + target = dynamic_cast(*obj).GetTransporter(); } if ( !target->GetDetectable() ) continue; if ( target->GetProxyActivate() ) continue; - if ( target->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(target)->GetSelect() ) continue; - if ( !target->Implements(ObjectInterfaceType::Controllable) || !dynamic_cast(target)->GetSelectable() ) continue; + if ( target->Implements(ObjectInterfaceType::Controllable) && dynamic_cast(*target).GetSelect() ) continue; + if ( !target->Implements(ObjectInterfaceType::Controllable) || !dynamic_cast(*target).GetSelectable() ) continue; if (!target->Implements(ObjectInterfaceType::Old)) continue; // TODO: To be removed after COldObjectInterface is gone diff --git a/src/ui/controls/target.h b/src/ui/controls/target.h index 807aae89..ceb1eb3a 100644 --- a/src/ui/controls/target.h +++ b/src/ui/controls/target.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/window.cpp b/src/ui/controls/window.cpp index 43086307..bcf76ce4 100644 --- a/src/ui/controls/window.cpp +++ b/src/ui/controls/window.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/controls/window.h b/src/ui/controls/window.h index 0c6b6792..4cadea7c 100644 --- a/src/ui/controls/window.h +++ b/src/ui/controls/window.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/debug_menu.cpp b/src/ui/debug_menu.cpp index 52f5efeb..e04704ff 100644 --- a/src/ui/debug_menu.cpp +++ b/src/ui/debug_menu.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/debug_menu.h b/src/ui/debug_menu.h index ecc6f81e..c49391a6 100644 --- a/src/ui/debug_menu.h +++ b/src/ui/debug_menu.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/displayinfo.cpp b/src/ui/displayinfo.cpp index b1e6220e..09f6d513 100644 --- a/src/ui/displayinfo.cpp +++ b/src/ui/displayinfo.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -109,7 +109,7 @@ bool CDisplayInfo::EventProcess(const Event &event) if ( m_toto != nullptr ) { assert(m_toto->Implements(ObjectInterfaceType::Movable)); - CMotionToto* toto = static_cast(dynamic_cast(m_toto)->GetMotion()); + CMotionToto* toto = static_cast(dynamic_cast(*m_toto).GetMotion()); assert(toto != nullptr); toto->SetMousePos(event.mousePos); } @@ -449,7 +449,7 @@ void CDisplayInfo::StartDisplayInfo(std::string filename, int index, bool bSoluc m_toto->SetDrawFront(true); assert(m_toto->Implements(ObjectInterfaceType::Movable)); - CMotionToto* toto = static_cast(dynamic_cast(m_toto)->GetMotion()); + CMotionToto* toto = static_cast(dynamic_cast(*m_toto).GetMotion()); assert(toto != nullptr); toto->StartDisplayInfo(); } @@ -840,7 +840,7 @@ void CDisplayInfo::StopDisplayInfo() if ( m_toto != nullptr ) { assert(m_toto->Implements(ObjectInterfaceType::Movable)); - CMotionToto* toto = static_cast(dynamic_cast(m_toto)->GetMotion()); + CMotionToto* toto = static_cast(dynamic_cast(*m_toto).GetMotion()); assert(toto != nullptr); toto->StopDisplayInfo(); } diff --git a/src/ui/displayinfo.h b/src/ui/displayinfo.h index 1f8fc9c1..5fcffedf 100644 --- a/src/ui/displayinfo.h +++ b/src/ui/displayinfo.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/displaytext.cpp b/src/ui/displaytext.cpp index 6bd8dcf7..b21263b4 100644 --- a/src/ui/displaytext.cpp +++ b/src/ui/displaytext.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -258,7 +258,7 @@ void CDisplayText::DisplayText(const char *text, Math::Vector goal, float height if ( toto != nullptr ) { assert(toto->Implements(ObjectInterfaceType::Movable)); - motion = dynamic_cast(toto)->GetMotion(); + motion = dynamic_cast(*toto).GetMotion(); if ( type == TT_ERROR ) { diff --git a/src/ui/displaytext.h b/src/ui/displaytext.h index 850e59ce..4c1d188b 100644 --- a/src/ui/displaytext.h +++ b/src/ui/displaytext.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/filedialog.cpp b/src/ui/filedialog.cpp new file mode 100644 index 00000000..b73c4fb1 --- /dev/null +++ b/src/ui/filedialog.cpp @@ -0,0 +1,1421 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + + +#include "ui/filedialog.h" + +#include "app/app.h" + +#include "common/logger.h" +#include "common/restext.h" + +#include "common/resources/resourcemanager.h" + +#include "level/robotmain.h" + +#include "ui/controls/check.h" +#include "ui/controls/control.h" +#include "ui/controls/edit.h" +#include "ui/controls/group.h" +#include "ui/controls/interface.h" +#include "ui/controls/label.h" +#include "ui/controls/list.h" +#include "ui/controls/window.h" + +#include +#include +#include + + +namespace Ui +{ + + +// time limit for double-click on directory +const float DELAY_DBCLICK_DIR = 0.75f; + + +// Object's constructor. + +CFileDialog::CFileDialog() +{ + m_eventQueue = CApplication::GetInstancePointer()->GetEventQueue(); + m_interface = CRobotMain::GetInstancePointer()->GetInterface(); + m_time = 0.0f; + m_lastTimeClickDir = 0.0f; +} + +// Object's destructor. + +CFileDialog::~CFileDialog() +{ +} + +// Beginning of the display of a dialogue. + +void CFileDialog::StartDialog() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW1)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW2)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW4)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW5)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + // the code battle interface, EVENT_WINDOW6, must be managed seperately + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW7)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW8)); + if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); + + if ( m_dialogtype != CFileDialog::Type::None ) + { + StartFileDialog(); + } + else + { + m_eventQueue->AddEvent(Event(EVENT_DIALOG_STOP)); + } +} + +void CFileDialog::StopDialog() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW1)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW2)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW4)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW5)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + // the code battle interface, EVENT_WINDOW6, must be managed seperately + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW7)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW8)); + if ( pw != nullptr ) pw->SetState(STATE_ENABLE); + + if ( m_windowEvent != EVENT_NULL ) // the window was created? + { + m_interface->DeleteControl(m_windowEvent); // delete it + } +} + +void CFileDialog::SetUsePublicPrivate(bool usePublic) +{ + m_usePublicPrivate = usePublic; +} + +void CFileDialog::SetPublic(bool bPublic) +{ + m_public = bPublic; +} + +bool CFileDialog::GetPublic() +{ + return m_public; +} + +void CFileDialog::SetPublicFolder(const std::string& dir) +{ + m_pathPublic = dir; +} + +void CFileDialog::SetPrivateFolder(const std::string& dir) +{ + m_pathPrivate = dir; +} + +void CFileDialog::SetBasePath(const std::string& dir) +{ + m_basePath = dir; +} + +std::string CFileDialog::GetBasePath() +{ + return m_basePath; +} + +void CFileDialog::SetSubFolderPath(const std::string& dir) +{ + m_subDirPath = dir; +} + +std::string CFileDialog::GetSubFolderPath() +{ + return m_subDirPath; +} + +void CFileDialog::SetFilename(const std::string& filename) +{ + m_filename = filename; +} + +std::string CFileDialog::GetFilename() +{ + return m_filename; +} + +// Start display of Open or Save dialogue + +void CFileDialog::StartFileDialog() +{ + m_captureClick = false; + Math::Point pos = m_windowPos; + Math::Point dim = m_windowDim; + int icon = (m_dialogtype == CFileDialog::Type::Open) ? 14 : 13 ; + + CWindow* pw = m_interface->CreateWindows(pos, dim, icon, m_windowEvent); + if ( pw == nullptr ) return; + + if ( m_windowEvent == EVENT_NULL ) // event type was not set? + { + m_windowEvent = pw->GetEventType(); // get the unique event id + } + + pw->SetState(STATE_SHADOW); + pw->SetMovable(true); + pw->SetClosable(true); + pw->SetMinDim(Math::Point(320.0f/640.0f, (121.0f+18.0f*4)/480.0f)); + + if ( m_title.empty() ) + { + if (m_dialogtype == CFileDialog::Type::Open) + GetResource(RES_TEXT, RT_IO_OPEN, m_title); + + if (m_dialogtype == CFileDialog::Type::Save) + GetResource(RES_TEXT, RT_IO_SAVE, m_title); + + if (m_dialogtype == CFileDialog::Type::Folder) + GetResource(RES_TEXT, RT_IO_SELECT_DIR, m_title); + } + pw->SetName(m_title); + + std::string name; + pos = Math::Point(0.0f, 0.0f); + dim = Math::Point(0.0f, 0.0f); + + GetResource(RES_TEXT, RT_IO_LIST, name); + CLabel* pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL1, name); // path label + pla->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + CButton* pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_NEWDIR); // New Folder button + pb->SetState(STATE_SHADOW); + + CList* pli = pw->CreateList(pos, dim, 0, EVENT_DIALOG_LIST); // file list + pli->SetState(STATE_SHADOW); + + CEdit* pe = pw->CreateEdit(pos, dim, 0, EVENT_DIALOG_EDIT2); // new folder edit box + pe->ClearState(STATE_VISIBLE | STATE_ENABLE); + + if ( m_usePublicPrivate ) + { + GetResource(RES_TEXT, RT_IO_DIR, name); + pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL3, name); // "Folder:" label + pla->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + CCheck* pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK1); // private check box + GetResource(RES_TEXT, RT_IO_PRIVATE, name); + pc->SetName(name); + pc->SetState(STATE_SHADOW); + + pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK2); // public check box + GetResource(RES_TEXT, RT_IO_PUBLIC, name); + pc->SetName(name); + pc->SetState(STATE_SHADOW); + } + + pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_CANCEL); // Cancel button + pb->SetState(STATE_SHADOW); + + pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_OK); // open/save button + pb->SetState(STATE_SHADOW); + + if (m_dialogtype == CFileDialog::Type::Folder) + { + m_selectFolderMode = true; + AdjustDialog(); + UpdatePublic(m_public); + PopulateList(); + UpdatePathLabel(); + UpdateSelectFolder(); + return; + } + + GetResource(RES_TEXT, RT_IO_OPEN, name); + if ( m_dialogtype == CFileDialog::Type::Save ) GetResource(RES_TEXT, RT_IO_SAVE, name); + pb->SetName(name); + + GetResource(RES_TEXT, RT_IO_NAME, name); + pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL2, name); // "Name:" label + pla->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pe = pw->CreateEdit(pos, dim, 0, EVENT_DIALOG_EDIT); // file name edit box + pe->SetState(STATE_SHADOW); + + // create "Overwrite existing file?" controls + CGroup* pg = pw->CreateGroup(pos, dim, 0, EVENT_DIALOG_GROUP1); // box "Overwrite ?" + pg->ClearState(STATE_VISIBLE | STATE_ENABLE); + pg->SetState(STATE_SHADOW); + + pla = pw->CreateLabel(pos, dim, 0, EVENT_LABEL0, name); // label "Overwrite ?" + pla->SetTextAlign(Gfx::TEXT_ALIGN_CENTER); + pla->ClearState(STATE_VISIBLE | STATE_ENABLE); + GetResource(RES_TEXT, RT_IO_REPLACE, name); + pla->SetName(name); + pla->SetState(STATE_SHADOW); + + pla = pw->CreateLabel(pos, dim, 0, EVENT_LABEL1, name); // filename label + pla->SetTextAlign(Gfx::TEXT_ALIGN_CENTER); + pla->ClearState(STATE_VISIBLE | STATE_ENABLE); + + pb = pw->CreateButton(pos, dim, -1, EVENT_BUTTON_CANCEL); // cancel + pb->ClearState(STATE_VISIBLE | STATE_ENABLE); + pb->SetState(STATE_SHADOW); + + pb = pw->CreateButton(pos, dim, -1, EVENT_BUTTON_OK); // ok + pb->ClearState(STATE_VISIBLE | STATE_ENABLE); + pb->SetState(STATE_SHADOW); + + AdjustDialog(); + + SetFilenameField(pe, m_filename); + SetFilename(""); + + UpdatePublic(m_public); + PopulateList(); + SearchList(pe->GetText(999)); + UpdateAction(); + UpdatePathLabel(); + + pe->SetCursor(999, 0); + m_interface->SetFocus(pe); +} + +void CFileDialog::SetFilenameField(CEdit* edit, const std::string& filename) +{ + std::string name = filename; + if (name.length() > static_cast(edit->GetMaxChar())) + { + if (name.substr(name.length()-5) == ".cbot") + name = name.substr(0, name.length()-5); + else if (name.substr(name.length()-4) == ".txt") + name = name.substr(0, name.length()-4); + if (name.length() > static_cast(edit->GetMaxChar())) + { + GetLogger()->Warn("Tried to load too long filename!\n"); + name = name.substr(0, edit->GetMaxChar()); // truncates according to max length + } + } + edit->SetText(name); +} + +void CFileDialog::AdjustDialog() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + + Math::Point wpos = m_windowPos = pw->GetPos(); + Math::Point wdim = m_windowDim = pw->GetDim(); + + pw->SetPos(wpos); // to move the buttons on the titlebar + pw->SetDim(wdim); + + Math::Point ppos(wpos.x+10.0f/640.0f, wpos.y+wdim.y-55.0f/480.0f); + Math::Point ddim(wdim.x-150.0f/640.0f, 20.0f/480.0f); + + CLabel* pla = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL1)); // path label + if ( pla != nullptr ) + { + pla->SetPos(ppos); + pla->SetDim(ddim); + UpdatePathLabel(); + } + + ddim.x = wdim.x-20.0f/640.0f; + int nli = static_cast((wdim.y-120.0f/480.0f)/(17.0f/480.0f)); + ddim.y = nli*17.0f/480.0f+9.0f/480.0f; + ppos.y = wpos.y+wdim.y-48.0f/480.0f-ddim.y; + if ( m_newFolderMode ) ddim.y -= 17.5f/480.0f; + + CList* pli = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); // file list + if ( pli != nullptr ) + { + pli->SetPos(ppos); + pli->SetDim(ddim); + pli->SetTabs(0, ddim.x-(50.0f+140.0f+16.0f)/640.0f); + pli->SetTabs(1, 50.0f/640.0f, Gfx::TEXT_ALIGN_RIGHT); + pli->SetTabs(2, 140.0f/640.0f); + if (pli->GetSelect() != -1) pli->ShowSelect(false); + } + + if ( m_newFolderMode ) + { + ppos.y += ddim.y-3.0f/480.0f; + ddim.y = 20.0f/480.0f; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT2)); // new folder edit box + if ( pe != nullptr ) + { + pe->SetPos(ppos); + pe->SetDim(ddim); + int nch = static_cast< int >((ddim.x*640.0f-22.0f)/5.75f); + std::string name = pe->GetText(nch); + pe->SetMaxChar(nch); + pe->SetText(name); + } + } + + if (!m_selectFolderMode) + { + ppos.y = wpos.y+30.0f/480.0f; + ddim.x = 50.0f/640.0f; + ddim.y = 20.0f/480.0f; + pla = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL2)); // "Name:" label + if ( pla != nullptr ) + { + pla->SetPos(ppos); + pla->SetDim(ddim); + } + + ppos.x += 50.0f/640.0f; + ppos.y = wpos.y+36.0f/480.0f; + ddim.x = wdim.x-170.0f/640.0f; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); // file name edit box + if ( pe != nullptr ) + { + pe->SetPos(ppos); + pe->SetDim(ddim); + + int nch = static_cast< int >((ddim.x*640.0f-22.0f)/5.75f); + std::string name = pe->GetText(nch); + pe->SetMaxChar(nch); + pe->SetText(name); + } + } + + if ( m_usePublicPrivate ) + { + ppos.x = wpos.x+10.0f/640.0f; + ppos.y = wpos.y+5.0f/480.0f; + ddim.x = 50.0f/640.0f; + ddim.y = 16.0f/480.0f; + pla = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL3)); // "Folder:" label + if ( pla != nullptr ) + { + pla->SetPos(ppos); + pla->SetDim(ddim); + } + + ppos.x += 50.0f/640.0f; + ppos.y = wpos.y+12.0f/480.0f; + ddim.x = 70.0f/640.0f; + CCheck* pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK1)); // private check box + if ( pc != nullptr ) + { + pc->SetPos(ppos); + pc->SetDim(ddim); + } + + ppos.x += 80.0f/640.0f; + pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK2)); // public check box + if ( pc != nullptr ) + { + pc->SetPos(ppos); + pc->SetDim(ddim); + } + } + + ppos.x = wpos.x+wdim.x-100.0f/640.0f; + ppos.y = wpos.y+34.0f/480.0f; + ddim.x = 90.0f/640.0f; + ddim.y = 23.0f/480.0f; + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); // open/save button + if ( pb != nullptr ) + { + pb->SetPos(ppos); + pb->SetDim(ddim); + } + + ppos.y -= 26.0f/480.0f; + pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_CANCEL)); // Cancel button + if ( pb != nullptr ) + { + pb->SetPos(ppos); + pb->SetDim(ddim); + } + + ppos.y = wpos.y+wdim.y-49.0f/480.0f; + pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_NEWDIR)); // New Folder button + if ( pb != nullptr ) + { + pb->SetPos(ppos); + pb->SetDim(ddim); + } + + if ( m_askOverwriteMode ) + { + ppos = wpos; + ppos.x += (wdim.x/2.0f) - (97.5f/640.0f); + ppos.y += (wdim.y/2.0f) - (50.0f/480.0f); + + ddim.x = 195.0f/640.0f; + ddim.y = 100.0f/480.0f; + CGroup* pg = static_cast< CGroup* >(pw->SearchControl(EVENT_DIALOG_GROUP1)); // "Overwrite ?" box + if ( pg != nullptr ) + { + pg->SetPos(ppos); + pg->SetDim(ddim); + } + + ddim.x = 82.5f/640.0f; + ddim.y = 23.0f/480.0f; + ppos.x += 10.0f/640.0f; + ppos.y += 10.0f/480.0f; + pb = static_cast< CButton* >(pw->SearchControl(EVENT_BUTTON_CANCEL)); // Cancel button + if ( pb != nullptr ) + { + pb->SetPos(ppos); + pb->SetDim(ddim); + } + + ppos.x += 92.5f/640.0f; + pb = static_cast< CButton* >(pw->SearchControl(EVENT_BUTTON_OK)); // Ok button + if ( pb != nullptr ) + { + pb->SetPos(ppos); + pb->SetDim(ddim); + } + + ddim.x = 185.0f/640.0f; + ppos.x -= 97.5f/640.0f; + ppos.y += 28.0f/480.0f; + pla = static_cast< CLabel* >(pw->SearchControl(EVENT_LABEL1)); // filename label + if ( pla != nullptr ) + { + pla->SetPos(ppos); + pla->SetDim(ddim); + } + + ppos.y += 28.0f/480.0f; + pla = static_cast< CLabel* >(pw->SearchControl(EVENT_LABEL0)); // "Overwrite ?" label + if ( pla != nullptr ) + { + pla->SetPos(ppos); + pla->SetDim(ddim); + } + } +} + +// Management of a dialogue event. + +bool CFileDialog::EventProcess(const Event &event) +{ + if ( event.type == m_windowEvent ) // window is moved ? + { + AdjustDialog(); + return true; + } + + if ( m_askOverwriteMode ) return EventAskOverwrite(event); + + m_time += event.rTime; + if ( event.type == EVENT_DIALOG_LIST ) // a list item was clicked ? + { + if ( ListItemIsFolder() ) + { + if ( m_captureClick ) + { + if (m_time - m_lastTimeClickDir <= DELAY_DBCLICK_DIR) // double click open folder + { + OpenFolder(); + } + m_captureClick = false; + } + else + { + m_captureClick = true; + m_lastTimeClickDir = m_time; + } + if (m_selectFolderMode) UpdateSelectFolder(); + return true; + } + + // a file name was clicked + m_captureClick = false; + if (m_selectFolderMode) + { + UpdateSelectFolder(); + return true; + } + + if (!m_newFolderMode) GetListChoice(); + return true; + } + + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return false; + + if ( event.type == EVENT_DIALOG_CANCEL || event.type == pw->GetEventTypeClose() ) + { + m_eventQueue->AddEvent(Event(EVENT_DIALOG_STOP)); + return true; + } + + EventType etype; + etype = ( m_newFolderMode ) ? EVENT_DIALOG_EDIT2 : EVENT_DIALOG_EDIT; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(etype)); + + if ( event.type == etype ) + { + if (pe != nullptr) SearchList(pe->GetText(999), m_newFolderMode); + return true; + } + + if ( m_usePublicPrivate ) + { + if ( event.type == EVENT_DIALOG_CHECK1 ) // private? + { + m_subDirPath.clear(); + UpdatePublic(false); + PopulateList(); + UpdatePathLabel(); + if (pe != nullptr) SearchList(pe->GetText(999), m_newFolderMode); + if (m_selectFolderMode) UpdateSelectFolder(); + } + else if ( event.type == EVENT_DIALOG_CHECK2 ) // public? + { + m_subDirPath.clear(); + UpdatePublic(true); + PopulateList(); + UpdatePathLabel(); + if (pe != nullptr) SearchList(pe->GetText(999), m_newFolderMode); + if (m_selectFolderMode) UpdateSelectFolder(); + } + } + + if (m_captureClick && m_time - m_lastTimeClickDir > DELAY_DBCLICK_DIR) + { + m_captureClick = false; + } + + if ( m_newFolderMode ) return EventNewFolder(event); // process 'new folder' events + + if ( event.type == EVENT_DIALOG_NEWDIR ) + { + if ( !StartNewFolderMode() ) StopNewFolderMode(true); + return true; + } + + if (m_selectFolderMode) return EventSelectFolder(event); + + if ( event.type == EVENT_DIALOG_OK || + (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(RETURN)) ) + { + if ( m_dialogtype == CFileDialog::Type::Open ) + { + if ( !ActionOpen() ) return true; + } + if ( m_dialogtype == CFileDialog::Type::Save ) + { + if ( !ActionSave(m_confirmOverwrite) ) return true; + } + + m_eventQueue->AddEvent(Event(EVENT_DIALOG_ACTION)); + } + + if ( event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE) ) + { + m_eventQueue->AddEvent(Event(EVENT_DIALOG_STOP)); + } + + return true; +} + +bool CFileDialog::StartNewFolderMode() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); // dialog window + if ( pw == nullptr ) return false; + + if (!m_selectFolderMode) + { + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); // filename edit box + if ( pe == nullptr ) return false; + pe->SetState(STATE_ENABLE, false); + } + + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_NEWDIR)); // new folder button + if ( pb == nullptr ) return false; + std::string name; + GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, name); + pb->SetName(name); + + + CList* pli = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); // file list + if ( pli == nullptr ) return false; + Math::Point dim = pli->GetDim(); + dim.y -= 17.5f/480.0f; + pli->SetDim(dim); + pli->SetSelect(-1); + pli->ShowSelect(false); + + Math::Point pos = pli->GetPos(); + + pos.y += dim.y-3.0f/480.0f; + dim.y = 20.0f/480.0f; + + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT2)); // new folder edit box + if ( pe == nullptr ) return false; + pe->SetState(STATE_VISIBLE, true); + pe->SetState(STATE_ENABLE, true); + pe->SetPos(pos); + pe->SetDim(dim); + pw->SetFocus(pe); + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); // open/save button + if ( pb == nullptr ) return false; + pb->SetState(STATE_ENABLE, false); + + m_newFolderMode = true; + + return true; +} + +bool CFileDialog::StopNewFolderMode(bool bCancel) +{ + m_newFolderMode = false; + + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); // dialog window + if ( pw == nullptr ) return false; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT2)); // new folder edit box + if ( pe != nullptr ) + { + pe->SetText(""); + pe->ClearState(STATE_VISIBLE | STATE_ENABLE); + } + + if (!m_selectFolderMode) + { + pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); // filename edit box + if ( pe != nullptr ) + { + pe->SetState(STATE_ENABLE, true); + pw->SetFocus(pe); + } + } + + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_NEWDIR)); // new folder button + if ( pb != nullptr ) + { + std::string name; + GetResource(RES_EVENT, EVENT_DIALOG_NEWDIR, name); + pb->SetName(name); + } + + AdjustDialog(); + + if (m_selectFolderMode) + { + UpdateSelectFolder(); + return true; + } + + if ( pe != nullptr ) + { + pe->SetCursor(999, 0); + if ( bCancel ) SearchList(pe->GetText(999)); + } + + return true; +} + +bool CFileDialog::EventNewFolder(const Event &event) +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return false; + + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_NEWDIR)); // new folder button + if ( pb == nullptr ) return false; + + if ( event.type == EVENT_DIALOG_NEWDIR ) + { + std::string text; + GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, text); + if (pb->GetName() == text) return StopNewFolderMode(true); // cancel + CreateNewFolder(); + return StopNewFolderMode(); + } + + if (event.type == EVENT_KEY_DOWN) + { + if (event.GetData()->key == KEY(ESCAPE)) + return StopNewFolderMode(true); + + if (event.GetData()->key == KEY(RETURN)) + { + std::string text; + GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, text); + if (pb->GetName() == text) return true; + CreateNewFolder(); + return StopNewFolderMode(); + } + } + + return true; +} + +bool CFileDialog::EventSelectFolder(const Event &event) +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return false; + + if ( event.type == EVENT_DIALOG_OK ) + { + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl == nullptr ) return false; + std::string name = pl->GetItemName(pl->GetSelect()); + name = name.substr(0, name.find_first_of("\t")); + m_subDirPath += m_subDirPath.empty() ? name : "/" + name; + m_eventQueue->AddEvent(Event(EVENT_DIALOG_ACTION)); + } + + if (event.type == EVENT_KEY_DOWN) + { + if (event.GetData()->key == KEY(ESCAPE)) + { + m_eventQueue->AddEvent(Event(EVENT_DIALOG_STOP)); + } + + if (event.GetData()->key == KEY(RETURN)) + { + if ( ListItemIsFolder() ) + { + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl == nullptr ) return false; + std::string name = pl->GetItemName(pl->GetSelect()); + name = name.substr(0, name.find_first_of("\t")); + if ( name != ".." ) + { + m_subDirPath += m_subDirPath.empty() ? name : "/" + name; + m_eventQueue->AddEvent(Event(EVENT_DIALOG_ACTION)); + } + } + } + } + + return true; +} + +// Updates the file name edit box after a click in the list. + +void CFileDialog::GetListChoice() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl == nullptr ) return; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); + if ( pe == nullptr ) return; + + std::string name = pl->GetItemName(pl->GetSelect()); + name = name.substr(0, name.find_first_of("\t")); + SetFilenameField(pe, name); + pe->SetCursor(999, 0); // select all + m_interface->SetFocus(pe); + + UpdateAction(); +} + +// Test if the selected list item is a directory that exists. + +bool CFileDialog::ListItemIsFolder() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return false; + + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl == nullptr ) return false; + + int n = pl->GetTotal(); + int i = pl->GetSelect(); + if (i < 0 || i >= n) return false; + + std::string name = pl->GetItemName(i); + name = name.substr(0, name.find_first_of("\t")); + + if (name == "..") return !m_subDirPath.empty(); + + if (name.find_first_of(".*?:<>\"|/\\") != std::string::npos) return false; + + return DirectoryExists(name); +} + +// Updates the list after a change in name. + +void CFileDialog::SearchList(const std::string &text, bool dirOnly) +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl == nullptr ) return; + + pl->SetSelect(-1); + + // highlight the list item matching what is typed in the edit box + if (!text.empty()) + { + for (int i = 0; i < pl->GetTotal(); i++) + { + std::string item = pl->GetItemName(i); + if (dirOnly && item.find("\t** DIR ** \t") == std::string::npos) break; + item = item.substr(0, item.find_first_of("\t")); + if (item.substr(0, text.length()) != text) continue; + pl->SetSelect(i); // select item + pl->ShowSelect(false); // scroll list + break; + } + } + + if ( m_newFolderMode ) UpdateNewFolder(); else UpdateAction(); +} + +// Updates the action button. + +void CFileDialog::UpdateAction() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); + if ( pe == nullptr ) return; + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); + if ( pb == nullptr ) return; + + bool bError = true; + std::string text = pe->GetText(999); + if ( !text.empty() ) + { + if (text.find_first_of("*?:<>\"|/\\") == std::string::npos) + bError = DirectoryExists(text); + + if (!bError && !CheckFilename(text)) + bError = !CheckFilename(text+m_extension); + } + + pb->SetState(STATE_ENABLE, !bError); +} + +void CFileDialog::UpdateSelectFolder() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); + if ( pb == nullptr ) return; + + bool bError = true; + if (!m_newFolderMode && ListItemIsFolder()) + { + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl != nullptr ) + { + std::string name = pl->GetItemName(pl->GetSelect()); + name = name.substr(0, name.find_first_of("\t")); + if (name != "..") bError = false; + } + } + + pb->SetState(STATE_ENABLE, !bError); +} + +// Updates the New Folder button. + +void CFileDialog::UpdateNewFolder() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT2)); + if ( pe == nullptr ) return; + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_NEWDIR)); + if ( pb == nullptr ) return; + + bool bError = true; + std::string text = pe->GetText(999); + if ( !text.empty() ) + { + if (text.find_first_of(".*?:<>\"|/\\") == std::string::npos) + bError = DirectoryExists(text); + } + + if (bError) GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, text); + else GetResource(RES_EVENT, EVENT_DIALOG_OK, text); + pb->SetName(text); +} + +// Updates the private/public buttons. + +void CFileDialog::UpdatePublic(bool bPublic) +{ + if ( !m_usePublicPrivate ) return; + + m_public = bPublic; + + SetBasePath(bPublic ? m_pathPublic : m_pathPrivate); + + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + + CCheck* pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK1)); + if ( pc != nullptr ) + { + pc->SetState(STATE_CHECK, !bPublic); + } + + pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK2)); + if ( pc != nullptr ) + { + pc->SetState(STATE_CHECK, bPublic); + } +} + +// Updates the path label + +void CFileDialog::UpdatePathLabel() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + + CLabel* pl = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL1)); + if ( pl != nullptr ) + { + Math::Point dim = pl->GetDim(); + size_t nch = static_cast< size_t >((dim.x*640.0f)/5.75f); + std::string text = SearchDirectory(false); + if (text.length() > nch) + { + text = "..." + text.substr(text.length()-nch, nch); + } + pl->SetName(text, false); + } +} + +// Fills the list with files and folders. + +void CFileDialog::PopulateList() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl == nullptr ) return; + pl->Flush(); + + if (!CResourceManager::DirectoryExists(SearchDirectory(false))) + return; + + int i = 0; + char timestr[100]; + + // list all folders + std::vector folders = CResourceManager::ListDirectories(SearchDirectory(false)); + if (!m_subDirPath.empty()) folders.insert(folders.begin(), std::string("..")); + for (auto& dir : folders) + { + std::ostringstream temp; + time_t now = CResourceManager::GetLastModificationTime(SearchDirectory(false) + dir); + strftime(timestr, 99, "%x %X", localtime(&now)); + temp << dir << '\t' << "** DIR **" << " \t" << timestr; + pl->SetItemName(i++, temp.str().c_str()); + } + + // list all files + std::vector files = CResourceManager::ListFiles(SearchDirectory(false), true); + auto it = std::remove_if(files.begin(), files.end(), [this](const std::string& name) + { + return !CheckFilename(name); + }); + files.erase(it, files.end()); // remove invalid file names + + for (auto& filename : files) + { + std::ostringstream temp; + time_t now = CResourceManager::GetLastModificationTime(SearchDirectory(false) + filename); + strftime(timestr, 99, "%x %X", localtime(&now)); + temp << filename << '\t' << CResourceManager::GetFileSize(SearchDirectory(false) + filename) << " \t" << timestr; + pl->SetItemName(i++, temp.str().c_str()); + } +} + +// Constructs the name of the folder for open/save. +// If the folder does not exist, it can be created. +std::string CFileDialog::SearchDirectory(bool bCreate) +{ + std::string dir = m_basePath; + + if (bCreate && !CResourceManager::DirectoryExists(dir)) + { + CResourceManager::CreateDirectory(dir); + } + + if (!m_subDirPath.empty()) + { + dir += "/" + m_subDirPath; + if (bCreate && !CResourceManager::DirectoryExists(dir)) + { + CResourceManager::CreateDirectory(dir); + } + } + + return dir + "/"; +} + +bool CFileDialog::DirectoryExists(const std::string &name) +{ + if ( name.empty() ) return false; + + if ( name == ".." ) return !m_subDirPath.empty(); + + return CResourceManager::DirectoryExists(SearchDirectory(false)+name); +} + +// Make folder + +void CFileDialog::CreateNewFolder() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT2)); + if ( pe == nullptr ) return; + std::string name = pe->GetText(999); + if ( name.empty() ) return; + + if ( !m_subDirPath.empty() ) m_subDirPath += "/"; + + m_subDirPath += name; // add to current path + + SearchDirectory(true); // make the new folder + + size_t pos = m_subDirPath.find_last_of("/"); + + // keep the current folder as current path + if (pos == std::string::npos) + m_subDirPath.clear(); + else + m_subDirPath.resize(pos); + + PopulateList(); // redraw the list + SearchList(name, true); // highlight the new folder in list box +} + +// Open folder + +void CFileDialog::OpenFolder() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return; + + CList* pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); + if ( pl == nullptr ) return; + + std::string name = pl->GetItemName(pl->GetSelect()); + name = name.substr(0, name.find_first_of("\t")); + + if ( name.empty() ) return; + + if ( name == ".." ) // parent folder + { + size_t pos = m_subDirPath.find_last_of("/"); + if (pos == std::string::npos) + m_subDirPath.clear(); + else + m_subDirPath.resize(pos); + } + else if ( DirectoryExists(name) ) + { + if (!m_subDirPath.empty()) m_subDirPath += "/"; + m_subDirPath += name; + } + + PopulateList(); + UpdatePathLabel(); + EventType type; + type = m_newFolderMode ? EVENT_DIALOG_EDIT2 : EVENT_DIALOG_EDIT; + + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(type)); + if ( pe != nullptr ) SearchList(pe->GetText(999), m_newFolderMode); +} + +bool CFileDialog::CheckFilename(const std::string& name) +{ + if ( name.empty() || name[0] == '.' ) return false; + + size_t namelen = name.length(); + if ( m_extension.empty() && m_extlist.empty() ) return true; // no required extension? + + for ( std::string ext : m_extlist ) // allowed extensions? + { + size_t extlen = ext.length(); + if ( namelen <= extlen ) continue; + if ( name == ext ) continue; + if ( ext == name.substr(namelen-extlen, extlen) ) return true; + } + + if ( !m_extension.empty() ) // default extension? + { + size_t extlen = m_extension.length(); + if ( namelen <= extlen ) return false; + if ( name == m_extension ) return false; + if ( m_extension == name.substr(namelen-extlen, extlen)) return true; + } + return false; +} + +bool CFileDialog::ActionOpen() +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return false; + + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); + if ( pe == nullptr ) return false; + std::string filename = pe->GetText(100); + if ( filename.empty() ) return false; + + if ( !CheckFilename(filename) ) // add default extension ? + { + if ( !m_extension.empty() ) filename += m_extension; + if ( !CheckFilename(filename) ) return false; // file name is ok ? + } + + SearchDirectory(true); + SetFilename(filename); + SetFilenameField(pe, filename); + pe->SetCursor(999, 0); // select all + pw->SetFocus(pe); + + return true; +} + +bool CFileDialog::ActionSave(bool checkFileExist) +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); + if ( pw == nullptr ) return false; + + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); + if ( pe == nullptr ) return false; + std::string filename = pe->GetText(100); + if ( filename.empty() ) return false; + + if ( !CheckFilename(filename) ) // add default extension ? + { + if ( !m_extension.empty() ) filename += m_extension; + if ( !CheckFilename(filename) ) return false; // file name is ok ? + } + + SearchDirectory(true); + + if ( checkFileExist ) + { + if (CResourceManager::Exists(SearchDirectory(false)+filename)) + { + if ( !StartAskOverwrite(filename) ) StopAskOverwrite(); + return false; + } + } + + SetFilename(filename); + SetFilenameField(pe, filename); + pe->SetCursor(999, 0); // select all + pw->SetFocus(pe); + + return true; +} + +bool CFileDialog::StartAskOverwrite(const std::string& name) +{ + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); // dialog window + if ( pw == nullptr ) return false; + + // disable controls + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); // filename edit box + if ( pe == nullptr ) return false; + pe->SetState(STATE_ENABLE, false); + + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_NEWDIR)); // new folder button + if ( pb == nullptr ) return false; + pb->SetState(STATE_ENABLE, false); + + CList* pli = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); // file list + if ( pli == nullptr ) return false; + pli->SetState(STATE_ENABLE, false); + + if ( m_usePublicPrivate ) + { + CCheck* pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK1)); // private check box + if ( pc == nullptr ) return false; + pc->SetState(STATE_ENABLE, false); + + pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK2)); // public check box + if ( pc == nullptr ) return false; + pc->SetState(STATE_ENABLE, false); + } + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); // open/save button + if ( pb == nullptr ) return false; + pb->SetState(STATE_ENABLE, false); + + // show overwrite controls + CGroup* pg = static_cast< CGroup* >(pw->SearchControl(EVENT_DIALOG_GROUP1)); // "Overwrite ?" box + if ( pg == nullptr ) return false; + pg->SetState(STATE_VISIBLE | STATE_ENABLE); + + CLabel* pla = static_cast< CLabel* >(pw->SearchControl(EVENT_LABEL0)); // "Overwrite ?" label + if ( pla == nullptr ) return false; + pla->SetState(STATE_VISIBLE | STATE_ENABLE); + + pla = static_cast< CLabel* >(pw->SearchControl(EVENT_LABEL1)); // filename label + if ( pla == nullptr ) return false; + pla->SetState(STATE_VISIBLE | STATE_ENABLE); + pla->SetName(name); + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_BUTTON_CANCEL)); // Cancel button + if ( pb == nullptr ) return false; + pb->SetState(STATE_VISIBLE | STATE_ENABLE); + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_BUTTON_OK)); // Ok button + if ( pb == nullptr ) return false; + pb->SetState(STATE_VISIBLE | STATE_ENABLE); + + m_askOverwriteMode = true; + + AdjustDialog(); + + return true; +} + +bool CFileDialog::StopAskOverwrite() +{ + m_askOverwriteMode = false; + + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); // dialog window + if ( pw == nullptr ) return false; + + // hide overwrite controls + CGroup* pg = static_cast< CGroup* >(pw->SearchControl(EVENT_DIALOG_GROUP1)); // "Overwrite ?" box + if ( pg != nullptr ) pg->ClearState(STATE_VISIBLE | STATE_ENABLE); + + CLabel* pla = static_cast< CLabel* >(pw->SearchControl(EVENT_LABEL0)); // "Overwrite ?" label + if ( pla != nullptr ) pla->ClearState(STATE_VISIBLE | STATE_ENABLE); + + pla = static_cast< CLabel* >(pw->SearchControl(EVENT_LABEL1)); // filename label + if ( pla != nullptr ) pla->ClearState(STATE_VISIBLE | STATE_ENABLE); + + CButton* pb = static_cast< CButton* >(pw->SearchControl(EVENT_BUTTON_CANCEL)); // Cancel button + if ( pb != nullptr ) pb->ClearState(STATE_VISIBLE | STATE_ENABLE); + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_BUTTON_OK)); // Ok button + if ( pb != nullptr ) pb->ClearState(STATE_VISIBLE | STATE_ENABLE); + + // enable other controls + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); // filename edit box + if ( pe != nullptr ) + { + pe->SetState(STATE_ENABLE, true); + pe->SetCursor(999, 0); + pw->SetFocus(pe); + } + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_NEWDIR)); // new folder button + if ( pb != nullptr ) pb->SetState(STATE_ENABLE, true); + + CList* pli = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); // file list + if ( pli != nullptr ) pli->SetState(STATE_ENABLE, true); + + if ( m_usePublicPrivate ) + { + CCheck* pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK1)); // private check box + if ( pc != nullptr ) pc->SetState(STATE_ENABLE, true); + + pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK2)); // public check box + if ( pc != nullptr ) pc->SetState(STATE_ENABLE, true); + } + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); // open/save button + if ( pb != nullptr ) pb->SetState(STATE_ENABLE, true); + + return true; +} + +bool CFileDialog::EventAskOverwrite(const Event &event) +{ + if ( event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE) ) + { + return StopAskOverwrite(); + } + + if ( event.type == EVENT_BUTTON_CANCEL ) + { + return StopAskOverwrite(); + } + + if ( event.type == EVENT_BUTTON_OK || + (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(RETURN)) ) + { + if ( ActionSave() ) + { + m_eventQueue->AddEvent(Event(EVENT_DIALOG_ACTION)); + } + + return StopAskOverwrite(); + } + + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(m_windowEvent)); // dialog window + if ( pw == nullptr ) return false; + + if ( event.type == EVENT_DIALOG_CANCEL || event.type == pw->GetEventTypeClose() ) + { + m_eventQueue->AddEvent(Event(EVENT_DIALOG_STOP)); + return true; + } + + return true; +} + + +} // namespace Ui diff --git a/src/ui/filedialog.h b/src/ui/filedialog.h new file mode 100644 index 00000000..1ad38bf3 --- /dev/null +++ b/src/ui/filedialog.h @@ -0,0 +1,364 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "common/event.h" + +#include "math/point.h" + +#include +#include + + +struct Event; + +namespace Ui +{ + +class CEdit; +class CInterface; + + +/** + * \brief File selector dialog + * + * \section Example Example usage + * Create the dialog and set the type of dialog. + * \code + * CFileDialog* fileDialog = new CFileDialog(); + * fileDialog->SetDialogType(CFileDialog::Type::Folder); + * \endcode + * + * Initial settings and start the dialog. + * \code + * fileDialog->SetWindowTitle("Select Player Folder"); + * fileDialog->SetBasePath("savegame"); + * fileDialog->StartDialog(); + * \endcode + * + * Handle events for the dialog. + * \code + * // first check for events sent from the dialog + * + * if (event.type == EVENT_DIALOG_STOP) // cancel or close + * { + * fileDialog->StopDialog(); + * delete fileDialog; + * return true; + * } + * + * if (event.type == EVENT_DIALOG_ACTION) // ok button was pressed + * { + * std::string folder = fileDialog->GetSubFolderPath(); + * fileDialog->StopDialog(); + * delete fileDialog; + * return true; + * } + * + * // send the event to the dialog + * return m_fileDialog->EventProcess(event); + * \endcode + * + * \nosubgrouping + */ +class CFileDialog +{ +public: + + /** + * \brief Constructor + */ + CFileDialog(); + + /** + * \brief Destructor + */ + ~CFileDialog(); + + //! \name Set dialog type, starting, event processing, and stopping + //@{ + /** + * \brief Disables other windows and creates the dialog window. + */ + void StartDialog(); + + /** + * \brief Enables other windows and deletes the dialog window. + */ + void StopDialog(); + + /** + * \brief Event processing. + */ + bool EventProcess(const Event &event); + + /** + * \brief Identifies the type of dialog to display. + */ + enum class Type + { + None, //!< Type was not set + Open, //!< Open dialog + Save, //!< Save dialog + Folder, //!< Select Folder dialog + }; + + /** + * \brief Set the type of dialog to use. + */ + void SetDialogType(CFileDialog::Type type) { m_dialogtype = type; } + + /** + * \brief Get the type of dialog. + */ + CFileDialog::Type GetDialogType() { return m_dialogtype; } + + //@} + + //! \name Dialog window properties + //@{ + /** + * \brief Set EventType for the dialog window. + * If not set, a unique EventType will be used. + */ + void SetWindowEvent(EventType type) { m_windowEvent = type; } + + /** + * \brief Get EventType for the dialog window. + */ + EventType GetWindowEvent() { return m_windowEvent; } + + /** + * \brief Set the initial position of the window. + */ + void SetWindowPos(Math::Point pos) { m_windowPos = pos; } + + /** + * \brief Get the position of the window. + */ + Math::Point GetWindowPos() { return m_windowPos; } + + /** + * \brief Set the initial size of the window. + */ + void SetWindowDim(Math::Point dim) { m_windowDim = dim; } + + /** + * \brief Get the size of the window. + */ + Math::Point GetWindowDim() { return m_windowDim; } + + /** + * \brief Set the text for the title bar of the dialog. + * This setting will override the default title text for the dialog. + */ + void SetWindowTitle(const std::string& name) { m_title = name; } + + //@} + + //! \name Settings for Public and Private check boxes + //@{ + /** + * \brief Set whether to create Public and Private check boxes. + * \param usePublic If true, Public and Private check boxes will be added to the dialog. + */ + void SetUsePublicPrivate(bool usePublic); + + /** + * \brief Set initial state for Public and Private check boxes. + * \param bPublic If true, the Public check box will be marked. + */ + void SetPublic(bool bPublic); + + /** + * \brief Get the state of Public and Private check boxes. + * \return true if Public check box is marked and false for Private. + */ + bool GetPublic(); + + /** + * \brief Set the path for the folder associated with the Public check box. + * \param dir Path to 'Public' folder. + */ + void SetPublicFolder(const std::string& dir); + + /** + * \brief Set the path for the folder associated with the Private check box. + * \param dir Path to 'Private' folder. + */ + void SetPrivateFolder(const std::string& dir); + + //@} + + //! \name Folder settings + //@{ + /** + * \brief Set the initial path for the folder whose contents are displayed. + * This setting is overridden by Public/Private settings. + */ + void SetBasePath(const std::string& dir); + + /** + * \brief Get the initial path or Public/Private folder path + */ + std::string GetBasePath(); + + /** + * \brief Set the initial subfolder whose contents are displayed. + * \param dir Name of a subfolder. Ex. "subfolder/anotherFolder/oneMoreFolder" + */ + void SetSubFolderPath(const std::string& dir); + + /** + * \brief Get the current subfolder shown by the dialog. + * \return A string with a folder name and subsequent folders separated by forward slash. + *

Returns empty string if the dialog is showing GetBasePath(). + */ + std::string GetSubFolderPath(); + + //@} + + //! \name File name settings + //@{ + /** + * \brief Set the extension that may be appended to a file name. + *

If any extensions are defined, the dialog will only show files + * with those extensions. + * \param ext A string with an extension. Ex. ".txt" + */ + void SetAutoExtension(const std::string& ext) { m_extension = ext; } + + /** + * \brief Define extensions that will be accepted as part of a valid file name. + * \param ext A string with an extension. Ex. ".txt" + */ + void AddOptionalExtension(const std::string& ext) { m_extlist.push_back(ext); } + + /** + * \brief Set the filename that appears in the edit box when the dialog opens. + */ + void SetFilename(const std::string& filename); + + /** + * \brief Get the filename that was selected or typed. + * \return The filename that was typed in the edit box. + */ + std::string GetFilename(); + + /** + * \brief Set whether to check if a file exists when the 'Save' button is pressed, + * and if the file exists, an "Overwrite existing file?" message is shown. + * \param doCheck true to check if a file exists when the 'Save' button is pressed. + */ + void SetConfirmOverwrite(bool doCheck) { m_confirmOverwrite = doCheck; } + + //@} + +private: + + void StartFileDialog(); + void AdjustDialog(); + + void PopulateList(); + void GetListChoice(); + void SearchList(const std::string &text, bool dirOnly = false); + + void UpdateAction(); + void UpdatePathLabel(); + void UpdatePublic(bool bPublic); + + void OpenFolder(); + + bool StartNewFolderMode(); + bool StopNewFolderMode(bool bCancel = false); + bool EventNewFolder(const Event &event); + void UpdateNewFolder(); + void CreateNewFolder(); + + bool EventSelectFolder(const Event &event); + void UpdateSelectFolder(); + + bool ListItemIsFolder(); + bool DirectoryExists(const std::string &name); + + bool CheckFilename(const std::string& name); + bool ActionOpen(); + bool ActionSave(bool checkFileExist = false); + + bool StartAskOverwrite(const std::string& name); + bool StopAskOverwrite(); + bool EventAskOverwrite(const Event &event); + + /*! + * \brief Set the text in the file name edit box. + * \param edit Pointer to the edit box. + * \param filename Text to put in the edit box. + */ + void SetFilenameField(CEdit* edit, const std::string& filename); + + /*! + * \brief Get the current directory with the current sub-directory appended. + * \param bCreate If true, the directories in question will be created. + * \return A string with the path of current directory, plus the + * current sub-directory if any. + */ + std::string SearchDirectory(bool bCreate); + +private: + + CEventQueue* m_eventQueue; + CInterface* m_interface; + + CFileDialog::Type m_dialogtype = Type::None; + + // EventType for this dialog. + // With EVENT_NULL, a unique EventType will be used. + EventType m_windowEvent = EVENT_NULL; + + Math::Point m_windowPos; + Math::Point m_windowDim; + std::string m_title = ""; + + float m_time; + float m_lastTimeClickDir; + bool m_captureClick = false; + + bool m_newFolderMode = false; + bool m_selectFolderMode = false; + bool m_askOverwriteMode = false; + bool m_confirmOverwrite = false; + + bool m_public = false; + std::string m_pathPublic = ""; + std::string m_pathPrivate = ""; + bool m_usePublicPrivate = false; + + std::string m_basePath = ""; + std::string m_subDirPath = ""; + + std::string m_filename = ""; + + //! The extension to add to a filename if needed + std::string m_extension = ""; + //! List of extensions accepted as part of a valid file name + std::vector m_extlist = {}; +}; + +} // namespace Ui diff --git a/src/ui/maindialog.cpp b/src/ui/maindialog.cpp index 01d87dc2..9321619f 100644 --- a/src/ui/maindialog.cpp +++ b/src/ui/maindialog.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -201,6 +201,7 @@ void CMainDialog::StartPauseMenu() if ( (m_main->GetLevelCategory() == LevelCategory::Missions || // missions ? m_main->GetLevelCategory() == LevelCategory::FreeGame || // free games? + m_main->GetLevelCategory() == LevelCategory::GamePlus || // new game plus? m_main->GetLevelCategory() == LevelCategory::CustomLevels ) && // user ? m_main->GetMissionType() != MISSION_CODE_BATTLE ) { diff --git a/src/ui/maindialog.h b/src/ui/maindialog.h index c17be255..ec3ef898 100644 --- a/src/ui/maindialog.h +++ b/src/ui/maindialog.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/mainmap.cpp b/src/ui/mainmap.cpp index 47214b8c..23c63360 100644 --- a/src/ui/mainmap.cpp +++ b/src/ui/mainmap.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/mainmap.h b/src/ui/mainmap.h index 26d068a9..fc334f84 100644 --- a/src/ui/mainmap.h +++ b/src/ui/mainmap.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/mainshort.cpp b/src/ui/mainshort.cpp index 9017ccd3..9e2a51a0 100644 --- a/src/ui/mainshort.cpp +++ b/src/ui/mainshort.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -150,7 +150,7 @@ bool CMainShort::CreateShortcuts() for (CObject* pObj : CObjectManager::GetInstancePointer()->GetAllObjects()) { if ( !pObj->GetDetectable() ) continue; - if ( pObj->Implements(ObjectInterfaceType::Controllable) && !dynamic_cast(pObj)->GetSelectable() ) continue; + if ( pObj->Implements(ObjectInterfaceType::Controllable) && !dynamic_cast(*pObj).GetSelectable() ) continue; if ( pObj->GetProxyActivate() ) continue; int icon = GetShortcutIcon(pObj->GetType()); @@ -182,57 +182,86 @@ int CMainShort::GetShortcutIcon(ObjectType type) int icon = -1; if ( m_bBuilding ) { - if ( type == OBJECT_FACTORY ) icon = 32; - if ( type == OBJECT_DERRICK ) icon = 33; - if ( type == OBJECT_CONVERT ) icon = 34; - if ( type == OBJECT_RESEARCH ) icon = 35; - if ( type == OBJECT_STATION ) icon = 36; - if ( type == OBJECT_TOWER ) icon = 37; - if ( type == OBJECT_LABO ) icon = 38; - if ( type == OBJECT_ENERGY ) icon = 39; - if ( type == OBJECT_RADAR ) icon = 40; - if ( type == OBJECT_INFO ) icon = 44; - if ( type == OBJECT_REPAIR ) icon = 41; - if ( type == OBJECT_DESTROYER) icon = 41; - if ( type == OBJECT_NUCLEAR ) icon = 42; - if ( type == OBJECT_PARA ) icon = 46; - if ( type == OBJECT_SAFE ) icon = 47; - if ( type == OBJECT_HUSTON ) icon = 48; - if ( type == OBJECT_BASE ) icon = 43; + switch ( type ) + { + case OBJECT_FACTORY: icon = 32; break; + case OBJECT_DERRICK: icon = 33; break; + case OBJECT_CONVERT: icon = 34; break; + case OBJECT_RESEARCH: icon = 35; break; + case OBJECT_STATION: icon = 36; break; + case OBJECT_TOWER: icon = 37; break; + case OBJECT_LABO: icon = 38; break; + case OBJECT_ENERGY: icon = 39; break; + case OBJECT_RADAR: icon = 40; break; + case OBJECT_INFO: icon = 44; break; + case OBJECT_REPAIR: icon = 41; break; + case OBJECT_DESTROYER: icon = 41; break; + case OBJECT_NUCLEAR: icon = 42; break; + case OBJECT_PARA: icon = 46; break; + case OBJECT_SAFE: icon = 47; break; + case OBJECT_HUSTON: icon = 48; break; + case OBJECT_BASE: icon = 43; break; + default: return -1; + } } else { - if ( type == OBJECT_HUMAN ) icon = 8; - if ( type == OBJECT_MOBILEfa ) icon = 11; - if ( type == OBJECT_MOBILEta ) icon = 10; - if ( type == OBJECT_MOBILEwa ) icon = 9; - if ( type == OBJECT_MOBILEia ) icon = 22; - if ( type == OBJECT_MOBILEfc ) icon = 17; - if ( type == OBJECT_MOBILEtc ) icon = 16; - if ( type == OBJECT_MOBILEwc ) icon = 15; - if ( type == OBJECT_MOBILEic ) icon = 23; - if ( type == OBJECT_MOBILEfi ) icon = 27; - if ( type == OBJECT_MOBILEti ) icon = 26; - if ( type == OBJECT_MOBILEwi ) icon = 25; - if ( type == OBJECT_MOBILEii ) icon = 28; - if ( type == OBJECT_MOBILEfs ) icon = 14; - if ( type == OBJECT_MOBILEts ) icon = 13; - if ( type == OBJECT_MOBILEws ) icon = 12; - if ( type == OBJECT_MOBILEis ) icon = 24; - if ( type == OBJECT_MOBILErt ) icon = 18; - if ( type == OBJECT_MOBILErc ) icon = 19; - if ( type == OBJECT_MOBILErr ) icon = 20; - if ( type == OBJECT_MOBILErs ) icon = 29; - if ( type == OBJECT_MOBILEsa ) icon = 21; - if ( type == OBJECT_MOBILEft ) icon = 30; - if ( type == OBJECT_MOBILEtt ) icon = 30; - if ( type == OBJECT_MOBILEwt ) icon = 30; - if ( type == OBJECT_MOBILEit ) icon = 30; - if ( type == OBJECT_MOBILEdr ) icon = 48; - if ( type == OBJECT_APOLLO2 ) icon = 49; + switch ( type ) + { + case OBJECT_HUMAN: icon = 8; break; + case OBJECT_MOBILEfa: icon = 11; break; + case OBJECT_MOBILEta: icon = 10; break; + case OBJECT_MOBILEwa: icon = 9; break; + case OBJECT_MOBILEia: icon = 22; break; + case OBJECT_MOBILEfb: icon = 2; break; // button4 + case OBJECT_MOBILEtb: icon = 1; break; + case OBJECT_MOBILEwb: icon = 0; break; + case OBJECT_MOBILEib: icon = 3; break; + case OBJECT_MOBILEfc: icon = 17; break; + case OBJECT_MOBILEtc: icon = 16; break; + case OBJECT_MOBILEwc: icon = 15; break; + case OBJECT_MOBILEic: icon = 23; break; + case OBJECT_MOBILEfi: icon = 27; break; + case OBJECT_MOBILEti: icon = 26; break; + case OBJECT_MOBILEwi: icon = 25; break; + case OBJECT_MOBILEii: icon = 28; break; + case OBJECT_MOBILEfs: icon = 14; break; + case OBJECT_MOBILEts: icon = 13; break; + case OBJECT_MOBILEws: icon = 12; break; + case OBJECT_MOBILEis: icon = 24; break; + case OBJECT_MOBILErt: icon = 18; break; + case OBJECT_MOBILErc: icon = 19; break; + case OBJECT_MOBILErr: icon = 20; break; + case OBJECT_MOBILErs: icon = 29; break; + case OBJECT_MOBILEsa: icon = 21; break; + case OBJECT_MOBILEft: icon = 6; break; + case OBJECT_MOBILEtt: icon = 5; break; + case OBJECT_MOBILEwt: icon = 30; break; + case OBJECT_MOBILEit: icon = 7; break; + case OBJECT_MOBILErp: icon = 9; break; + case OBJECT_MOBILEst: icon = 10; break; + case OBJECT_MOBILEtg: icon = 45; break; + case OBJECT_MOBILEdr: icon = 48; break; + case OBJECT_APOLLO2: icon = 49; break; + default: return -1; + } + } + + switch ( type ) + { + case OBJECT_MOBILEfb: + case OBJECT_MOBILEtb: + case OBJECT_MOBILEwb: + case OBJECT_MOBILEib: + case OBJECT_MOBILEft: + case OBJECT_MOBILEtt: + case OBJECT_MOBILEit: + case OBJECT_MOBILErp: + case OBJECT_MOBILEst: + return 192+icon; + default: + return 128+icon; } - if ( icon == -1 ) return -1; - return 128+icon; } // Updates the interface shortcuts to the units. @@ -245,9 +274,9 @@ bool CMainShort::UpdateShortcuts() if ( pc != nullptr ) { assert(m_shortcuts[i]->Implements(ObjectInterfaceType::Controllable)); - pc->SetState(STATE_CHECK, dynamic_cast(m_shortcuts[i])->GetSelect()); - pc->SetState(STATE_RUN, m_shortcuts[i]->Implements(ObjectInterfaceType::Programmable) && dynamic_cast(m_shortcuts[i])->IsProgram()); - pc->SetState(STATE_DAMAGE, dynamic_cast(m_shortcuts[i])->IsDamaging()); + pc->SetState(STATE_CHECK, dynamic_cast(*m_shortcuts[i]).GetSelect()); + pc->SetState(STATE_RUN, m_shortcuts[i]->Implements(ObjectInterfaceType::Programmable) && dynamic_cast(*m_shortcuts[i]).IsProgram()); + pc->SetState(STATE_DAMAGE, dynamic_cast(*m_shortcuts[i]).IsDamaging()); } } return true; diff --git a/src/ui/mainshort.h b/src/ui/mainshort.h index 52754c23..2613bf93 100644 --- a/src/ui/mainshort.h +++ b/src/ui/mainshort.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/mainui.cpp b/src/ui/mainui.cpp index 2ffb17fe..80fd5bc5 100644 --- a/src/ui/mainui.cpp +++ b/src/ui/mainui.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -35,6 +35,8 @@ #include "ui/maindialog.h" +#include "ui/particles_generator.h" + #include "ui/controls/group.h" #include "ui/controls/interface.h" #include "ui/controls/label.h" @@ -47,6 +49,7 @@ #include "ui/screen/screen_level_list.h" #include "ui/screen/screen_loading.h" #include "ui/screen/screen_main_menu.h" +#include "ui/screen/screen_mod_list.h" #include "ui/screen/screen_player_select.h" #include "ui/screen/screen_quit.h" #include "ui/screen/screen_setup_controls.h" @@ -66,7 +69,7 @@ CMainUserInterface::CMainUserInterface() m_app = CApplication::GetInstancePointer(); m_main = CRobotMain::GetInstancePointer(); m_engine = Gfx::CEngine::GetInstancePointer(); - m_particle = m_engine->GetParticle(); + m_particleManager = m_engine->GetParticle(); m_interface = m_main->GetInterface(); m_sound = m_app->GetSound(); m_settings = CSettings::GetInstancePointer(); @@ -78,6 +81,7 @@ CMainUserInterface::CMainUserInterface() m_screenIORead = MakeUnique(m_screenLevelList.get()); m_screenIOWrite = MakeUnique(m_screenLevelList.get()); m_screenLoading = MakeUnique(); + m_screenModList = MakeUnique(m_dialog.get(), m_app->GetModManager()); m_screenSetupControls = MakeUnique(); m_screenSetupDisplay = MakeUnique(); m_screenSetupGame = MakeUnique(); @@ -87,6 +91,7 @@ CMainUserInterface::CMainUserInterface() m_screenPlayerSelect = MakeUnique(m_dialog.get()); m_screenQuit = MakeUnique(); m_screenWelcome = MakeUnique(); + m_mouseParticlesGenerator = MakeUnique(); m_currentScreen = nullptr; @@ -132,7 +137,6 @@ CScreenLoading* CMainUserInterface::GetLoadingScreen() return m_screenLoading.get(); } - // Changes phase. CScreenSetup* CMainUserInterface::GetSetupScreen(Phase phase) @@ -182,6 +186,10 @@ void CMainUserInterface::ChangePhase(Phase phase) m_screenLevelList->SetLevelCategory(m_main->GetLevelCategory()); m_currentScreen = m_screenLevelList.get(); } + if (m_phase == PHASE_MOD_LIST) + { + m_currentScreen = m_screenModList.get(); + } if (m_phase >= PHASE_SETUPd && m_phase <= PHASE_SETUPs) { CScreenSetup* screenSetup = GetSetupScreen(m_phase); @@ -255,7 +263,7 @@ bool CMainUserInterface::EventProcess(const Event &event) if ( event.type == EVENT_MOUSE_MOVE ) { m_glintMouse = event.mousePos; - NiceParticle(event.mousePos, event.mouseButtonsState & MOUSE_BUTTON_LEFT); + CreateMouseParticles(event.mousePos, event.mouseButtonsState & MOUSE_BUTTON_LEFT); } if (!m_dialog->EventProcess(event)) return false; @@ -520,7 +528,7 @@ void CMainUserInterface::FrameParticle(float rTime) 279.0f, 18.0f, }; - if ( m_dialog->IsDialog() || !m_settings->GetInterfaceRain() ) return; + if (m_dialog->IsDialog() || !m_settings->GetMouseParticlesEnabled()) return; if ( m_phase == PHASE_MAIN_MENU ) { @@ -529,6 +537,7 @@ void CMainUserInterface::FrameParticle(float rTime) } else if ( m_phase == PHASE_PLAYER_SELECT || m_phase == PHASE_LEVEL_LIST || + m_phase == PHASE_MOD_LIST || m_phase == PHASE_SETUPd || m_phase == PHASE_SETUPg || m_phase == PHASE_SETUPp || @@ -584,7 +593,7 @@ void CMainUserInterface::FrameParticle(float rTime) speed.z = 0.0f; dim.x = 0.04f+Math::Rand()*0.04f; dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, + m_particleManager->CreateParticle(pos, speed, dim, rand()%2?Gfx::PARTIGLINT:Gfx::PARTICONTROL, Math::Rand()*0.4f+0.4f, 0.0f, 0.0f, Gfx::SH_INTERFACE); @@ -650,7 +659,7 @@ void CMainUserInterface::FrameParticle(float rTime) speed.z = 0.0f; dim.x = 0.005f+Math::Rand()*0.005f; dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIBLITZ, + m_particleManager->CreateParticle(pos, speed, dim, Gfx::PARTIBLITZ, Math::Rand()*0.2f+0.2f, 0.0f, 0.0f, Gfx::SH_INTERFACE); pos.x = m_particles[i].pos.x; @@ -661,7 +670,7 @@ void CMainUserInterface::FrameParticle(float rTime) speed.z = 0.0f; dim.x = 0.01f+Math::Rand()*0.01f; dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, + m_particleManager->CreateParticle(pos, speed, dim, static_cast(Gfx::PARTILENS1+rand()%3), Math::Rand()*0.5f+0.5f, 2.0f, 0.0f, Gfx::SH_INTERFACE); @@ -678,7 +687,7 @@ void CMainUserInterface::FrameParticle(float rTime) speed.z = 0.0f; dim.x = 0.005f+Math::Rand()*0.005f; dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, Gfx::PARTIBLITZ, + m_particleManager->CreateParticle(pos, speed, dim, Gfx::PARTIBLITZ, Math::Rand()*0.2f+0.2f, 0.0f, 0.0f, Gfx::SH_INTERFACE); pos.x = m_particles[i].pos.x; @@ -689,7 +698,7 @@ void CMainUserInterface::FrameParticle(float rTime) speed.z = 0.0f; dim.x = 0.005f+Math::Rand()*0.005f; dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISCRAPS, + m_particleManager->CreateParticle(pos, speed, dim, Gfx::PARTISCRAPS, Math::Rand()*0.5f+0.5f, 2.0f, 0.0f, Gfx::SH_INTERFACE); } @@ -705,7 +714,7 @@ void CMainUserInterface::FrameParticle(float rTime) speed.z = 0.0f; dim.x = 0.03f+Math::Rand()*0.07f; dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, Gfx::PARTICRASH, + m_particleManager->CreateParticle(pos, speed, dim, Gfx::PARTICRASH, Math::Rand()*0.4f+0.4f, 0.0f, 0.0f, Gfx::SH_INTERFACE); } @@ -719,50 +728,20 @@ void CMainUserInterface::FrameParticle(float rTime) } } -// Some nice particles following the mouse. - -void CMainUserInterface::NiceParticle(Math::Point mouse, bool bPress) +void CMainUserInterface::CreateMouseParticles(Math::Point mousePosition, bool buttonPressed) { - Math::Vector pos, speed; - Math::Point dim; - - if ( !m_settings->GetInterfaceRain() ) return; - if ( (m_phase == PHASE_SIMUL || - m_phase == PHASE_WIN || - m_phase == PHASE_LOST ) && - !m_dialog->IsDialog() ) return; - - if ( bPress ) + if (isAllowedToCreateMouseParticles()) { - pos.x = mouse.x; - pos.y = mouse.y; - pos.z = 0.0f; - speed.x = (Math::Rand()-0.5f)*0.5f; - speed.y = (0.3f+Math::Rand()*0.3f); - speed.z = 0.0f; - dim.x = 0.005f+Math::Rand()*0.005f; - dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISCRAPS, - Math::Rand()*0.5f+0.5f, 2.0f, 0.0f, - Gfx::SH_INTERFACE); - } - else - { - pos.x = mouse.x; - pos.y = mouse.y; - pos.z = 0.0f; - speed.x = (Math::Rand()-0.5f)*0.5f; - speed.y = (0.3f+Math::Rand()*0.3f); - speed.z = 0.0f; - dim.x = 0.01f+Math::Rand()*0.01f; - dim.y = dim.x/0.75f; - m_particle->CreateParticle(pos, speed, dim, - static_cast(Gfx::PARTILENS1+rand()%3), - Math::Rand()*0.5f+0.5f, 2.0f, 0.0f, - Gfx::SH_INTERFACE); + m_mouseParticlesGenerator->GenerateMouseParticles(Math::Point(mousePosition.x, mousePosition.y), buttonPressed); } } +bool CMainUserInterface::isAllowedToCreateMouseParticles() +{ + return m_settings->GetMouseParticlesEnabled() && + !((m_phase == PHASE_SIMUL || m_phase == PHASE_WIN || m_phase == PHASE_LOST) && !m_dialog->IsDialog()); +} + // Updates the lists according to the cheat code. void CMainUserInterface::AllMissionUpdate() @@ -790,6 +769,21 @@ bool CMainUserInterface::GetSceneSoluce() return m_screenLevelList->GetSceneSoluce(); } +bool CMainUserInterface::GetPlusTrainer() +{ + return m_screenLevelList->GetPlusTrainer(); +} + +bool CMainUserInterface::GetPlusResearch() +{ + return m_screenLevelList->GetPlusResearch(); +} + +bool CMainUserInterface::GetPlusExplorer() +{ + return m_screenLevelList->GetPlusExplorer(); +} + bool CMainUserInterface::GetGamerOnlyHead() { if (m_phase == PHASE_APPERANCE) diff --git a/src/ui/mainui.h b/src/ui/mainui.h index 77074492..1a33331e 100644 --- a/src/ui/mainui.h +++ b/src/ui/mainui.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,6 +21,8 @@ #include "level/robotmain.h" +#include "ui/particles_generator.h" + #include #include #include @@ -48,6 +50,7 @@ class CScreenIOWrite; class CScreenLevelList; class CScreenLoading; class CScreenMainMenu; +class CScreenModList; class CScreenPlayerSelect; class CScreenQuit; class CScreenSetup; @@ -74,6 +77,9 @@ public: void ChangePhase(Phase phase); bool GetSceneSoluce(); + bool GetPlusTrainer(); + bool GetPlusResearch(); + bool GetPlusExplorer(); void UpdateChapterPassed(); void NextMission(); @@ -91,15 +97,14 @@ public: protected: void GlintMove(); void FrameParticle(float rTime); - void NiceParticle(Math::Point mouse, bool bPress); - + void CreateMouseParticles(Math::Point mousePosition, bool buttonPressed); CScreenSetup* GetSetupScreen(Phase phase); protected: CApplication* m_app; CRobotMain* m_main; Gfx::CEngine* m_engine; - Gfx::CParticle* m_particle; + Gfx::CParticle* m_particleManager; CInterface* m_interface; CSoundInterface* m_sound; CSettings* m_settings; @@ -113,6 +118,7 @@ protected: std::unique_ptr m_screenLevelList; std::unique_ptr m_screenLoading; std::unique_ptr m_screenMainMenu; + std::unique_ptr m_screenModList; std::unique_ptr m_screenPlayerSelect; std::unique_ptr m_screenQuit; std::unique_ptr m_screenSetupControls; @@ -137,6 +143,10 @@ protected: Math::Point pos; }; std::array m_particles; + +private: + std::unique_ptr m_mouseParticlesGenerator; + bool isAllowedToCreateMouseParticles(); }; } // namespace Ui diff --git a/src/ui/object_interface.cpp b/src/ui/object_interface.cpp index ab1fb088..9ca2c8b1 100644 --- a/src/ui/object_interface.cpp +++ b/src/ui/object_interface.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -100,6 +100,8 @@ CObjectInterface::CObjectInterface(COldObject* object) m_manipStyle = EVENT_OBJECT_MFRONT; m_selScript = 0; + + m_buildInterface = false; } // Object's destructor. @@ -534,9 +536,9 @@ bool CObjectInterface::EventProcess(const Event &event) { err = m_taskExecutor->StartTaskBuild(OBJECT_INFO); } - if ( action == EVENT_OBJECT_BDESTROYER ) + if ( action == EVENT_OBJECT_BSAFE ) { - err = m_taskExecutor->StartTaskBuild(OBJECT_DESTROYER); + err = m_taskExecutor->StartTaskBuild(OBJECT_SAFE); } if ( action == EVENT_OBJECT_GFLAT ) @@ -593,7 +595,7 @@ bool CObjectInterface::EventProcess(const Event &event) ps = static_cast< CSlider* >(pw->SearchControl(EVENT_OBJECT_DIMSHIELD)); if ( ps != nullptr ) { - dynamic_cast(m_object)->SetShieldRadius((ps->GetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit)); + dynamic_cast(*m_object).SetShieldRadius((ps->GetVisibleValue()-(RADIUS_SHIELD_MIN/g_unit))/((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit)); } } } @@ -621,6 +623,12 @@ bool CObjectInterface::EventProcess(const Event &event) err = m_taskExecutor->StartTaskSpiderExplo(); } + if ( action == EVENT_OBJECT_BUILD ) + { + m_buildInterface = !m_buildInterface; + UpdateInterface(); + } + if ( action == EVENT_OBJECT_PEN0 ) // up { err = m_taskExecutor->StartTaskPen(false); @@ -841,6 +849,10 @@ bool CObjectInterface::CreateInterface(bool bSelect) type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEwc || @@ -863,6 +875,8 @@ bool CObjectInterface::CreateInterface(bool bSelect) type == OBJECT_MOBILEtt || type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEst || type == OBJECT_MOBILEdr || type == OBJECT_MOTHER || type == OBJECT_ANT || @@ -929,8 +943,9 @@ bool CObjectInterface::CreateInterface(bool bSelect) } } - if ( type == OBJECT_HUMAN || - type == OBJECT_TECH ) + if ( (type == OBJECT_HUMAN || + type == OBJECT_TECH ) && + !m_main->GetPlusExplorer() ) { pos.x = ox+sx*7.7f; pos.y = oy+sy*0.5f; @@ -972,7 +987,7 @@ bool CObjectInterface::CreateInterface(bool bSelect) DefaultEnter(pw, EVENT_OBJECT_MTAKE); } - if ( type == OBJECT_HUMAN ) // builder? + if ( type == OBJECT_HUMAN && !m_main->GetPlusExplorer()) // builder? { pos.x = 1.0f/640.0f; pos.y = 4.0f/480.0f; @@ -1050,8 +1065,8 @@ bool CObjectInterface::CreateInterface(bool bSelect) pos.x = ox+sx*5.4f; pos.y = oy+sy*0.1f; - pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BDESTROYER); - DeadInterface(pw, EVENT_OBJECT_BDESTROYER, m_main->CanBuild(OBJECT_DESTROYER, m_object->GetTeam())); + pw->CreateButton(pos, ddim, 128+47, EVENT_OBJECT_BSAFE); + DeadInterface(pw, EVENT_OBJECT_BSAFE, m_main->CanBuild(OBJECT_SAFE, m_object->GetTeam())); if ( m_main->IsBuildingEnabled(BUILD_GFLAT) ) { @@ -1102,16 +1117,39 @@ bool CObjectInterface::CreateInterface(bool bSelect) pw->CreateButton(pos, dim, 40, EVENT_OBJECT_SEARCH); DefaultEnter(pw, EVENT_OBJECT_SEARCH); - if ( m_main->IsBuildingEnabled(BUILD_GFLAT) ) - { - pos.x = ox+sx*9.0f; - pos.y = oy+sy*0.5f; - pw->CreateButton(pos, dim, 111, EVENT_OBJECT_GFLAT); - } - - pos.x = ox+sx*10.1f; + pos.x = ox+sx*9.0f; pos.y = oy+sy*0.5f; pw->CreateButton(pos, dim, 11, EVENT_OBJECT_DELSEARCH); + + if ( m_main->IsBuildingEnabled(BUILD_FLAG) ) + { + pos.x = ox+sx*10.1f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+54, EVENT_OBJECT_FCREATE); + + pos.x = ox+sx*11.1f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+55, EVENT_OBJECT_FDELETE); + + ddim.x = dim.x*0.4f; + ddim.y = dim.y*0.4f; + pos.x = ox+sx*10.1f; + pos.y = oy+sy*2.0f-ddim.y; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORb); + pc->SetColor(Gfx::Color(0.28f, 0.56f, 1.0f, 0.0f)); + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORr); + pc->SetColor(Gfx::Color(1.0f, 0.0f, 0.0f, 0.0f)); + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORg); + pc->SetColor(Gfx::Color(0.0f, 0.8f, 0.0f, 0.0f)); + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORy); + pc->SetColor(Gfx::Color(1.0f, 0.93f, 0.0f, 0.0f)); //0x00ffec00 + pos.x += ddim.x; + pc = pw->CreateColor(pos, ddim, -1, EVENT_OBJECT_FCOLORv); + pc->SetColor(Gfx::Color(0.82f, 0.004f, 0.99f, 0.0f)); //0x00d101fe + } } if ( type == OBJECT_MOBILErt && // Terraformer? @@ -1405,6 +1443,93 @@ bool CObjectInterface::CreateInterface(bool bSelect) pw->CreateGroup(pos, ddim, 16, EVENT_OBJECT_CORNERdr); } + if ( (type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib) && // builder? + !m_object->GetTrainer() ) + { + pos.x = ox+sx*7.7f; + pos.y = oy+sy*0.5f; + pb = pw->CreateButton(pos, dim, 192+4, EVENT_OBJECT_BUILD); + pb->SetImmediat(true); + DefaultEnter(pw, EVENT_OBJECT_BUILD); + + pos.x = 0.0f; + pos.y = oy+sy*2.6f; + ddim.x = 214.5f/640.0f; + ddim.y = 66.0f/480.0f; + pw->CreateGroup(pos, ddim, 6, EVENT_WINDOW3); + + ddim.x = dim.x*0.9f; + ddim.y = dim.y*0.9f; + pos.y = oy+sy*3.6f; + + pos.x = ox+sx*0.0f; + pw->CreateButton(pos, ddim, 128+35, EVENT_OBJECT_BRESEARCH); + DeadInterface(pw, EVENT_OBJECT_BRESEARCH, m_main->CanBuild(OBJECT_RESEARCH, m_object->GetTeam())); + + pos.x = ox+sx*0.9f; + pw->CreateButton(pos, ddim, 128+32, EVENT_OBJECT_BFACTORY); + DeadInterface(pw, EVENT_OBJECT_BFACTORY, m_main->CanBuild(OBJECT_FACTORY, m_object->GetTeam())); + + pos.x = ox+sx*1.8f; + pw->CreateButton(pos, ddim, 128+34, EVENT_OBJECT_BCONVERT); + DeadInterface(pw, EVENT_OBJECT_BCONVERT, m_main->CanBuild(OBJECT_CONVERT, m_object->GetTeam())); + + pos.x = ox+sx*2.7f; + pw->CreateButton(pos, ddim, 128+36, EVENT_OBJECT_BSTATION); + DeadInterface(pw, EVENT_OBJECT_BSTATION, m_main->CanBuild(OBJECT_STATION, m_object->GetTeam())); + + pos.x = ox+sx*3.6f; + pw->CreateButton(pos, ddim, 128+40, EVENT_OBJECT_BRADAR); + DeadInterface(pw, EVENT_OBJECT_BRADAR, m_main->CanBuild(OBJECT_RADAR, m_object->GetTeam())); + + pos.x = ox+sx*4.5f; + pw->CreateButton(pos, ddim, 128+41, EVENT_OBJECT_BREPAIR); + DeadInterface(pw, EVENT_OBJECT_BREPAIR, m_main->CanBuild(OBJECT_REPAIR, m_object->GetTeam())); + + pos.x = ox+sx*5.4f; + pw->CreateButton(pos, ddim, 128+44, EVENT_OBJECT_BINFO); + DeadInterface(pw, EVENT_OBJECT_BINFO, m_main->CanBuild(OBJECT_INFO, m_object->GetTeam())); + + pos.y = oy+sy*2.7f; + + pos.x = ox+sx*0.0f; + pw->CreateButton(pos, ddim, 128+37, EVENT_OBJECT_BTOWER); + DeadInterface(pw, EVENT_OBJECT_BTOWER, m_main->CanBuild(OBJECT_TOWER, m_object->GetTeam())); + + pos.x = ox+sx*0.9f; + pw->CreateButton(pos, ddim, 128+39, EVENT_OBJECT_BENERGY); + DeadInterface(pw, EVENT_OBJECT_BENERGY, m_main->CanBuild(OBJECT_ENERGY, m_object->GetTeam())); + + pos.x = ox+sx*1.8f; + pw->CreateButton(pos, ddim, 128+33, EVENT_OBJECT_BDERRICK); + DeadInterface(pw, EVENT_OBJECT_BDERRICK, m_main->CanBuild(OBJECT_DERRICK, m_object->GetTeam())); + + pos.x = ox+sx*2.7f; + pw->CreateButton(pos, ddim, 128+42, EVENT_OBJECT_BNUCLEAR); + DeadInterface(pw, EVENT_OBJECT_BNUCLEAR, m_main->CanBuild(OBJECT_NUCLEAR, m_object->GetTeam())); + + pos.x = ox+sx*3.6f; + pw->CreateButton(pos, ddim, 128+38, EVENT_OBJECT_BLABO); + DeadInterface(pw, EVENT_OBJECT_BLABO, m_main->CanBuild(OBJECT_LABO, m_object->GetTeam())); + + pos.x = ox+sx*4.5f; + pw->CreateButton(pos, ddim, 128+46, EVENT_OBJECT_BPARA); + DeadInterface(pw, EVENT_OBJECT_BPARA, m_main->CanBuild(OBJECT_PARA, m_object->GetTeam())); + + pos.x = ox+sx*5.4f; + pw->CreateButton(pos, ddim, 128+47, EVENT_OBJECT_BSAFE); + DeadInterface(pw, EVENT_OBJECT_BSAFE, m_main->CanBuild(OBJECT_SAFE, m_object->GetTeam())); + + if ( m_main->IsBuildingEnabled(BUILD_GFLAT) ) + { + pos.x = ox+sx*9.0f; + pos.y = oy+sy*0.5f; + pw->CreateButton(pos, dim, 64+47, EVENT_OBJECT_GFLAT); + } + } UpdateInterface(); m_lastUpdateTime = 0.0f; UpdateInterface(0.0f); @@ -1664,6 +1789,7 @@ void CObjectInterface::UpdateInterface() EnableInterface(pw, EVENT_OBJECT_TERRAFORM, bEnable); EnableInterface(pw, EVENT_OBJECT_RECOVER, bEnable); EnableInterface(pw, EVENT_OBJECT_FIRE, bEnable); + EnableInterface(pw, EVENT_OBJECT_BUILD, bEnable); EnableInterface(pw, EVENT_OBJECT_SPIDEREXPLO, bEnable); EnableInterface(pw, EVENT_OBJECT_RESET, bEnable); EnableInterface(pw, EVENT_OBJECT_PEN0, bEnable); @@ -1678,7 +1804,11 @@ void CObjectInterface::UpdateInterface() EnableInterface(pw, EVENT_OBJECT_REC, bEnable); EnableInterface(pw, EVENT_OBJECT_STOP, bEnable); - if ( type == OBJECT_HUMAN ) // builder? + if ( type == OBJECT_HUMAN || // builder? + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib ) { EnableInterface(pw, EVENT_OBJECT_BFACTORY, bEnable); EnableInterface(pw, EVENT_OBJECT_BDERRICK, bEnable); @@ -1693,11 +1823,15 @@ void CObjectInterface::UpdateInterface() EnableInterface(pw, EVENT_OBJECT_BNUCLEAR, bEnable); EnableInterface(pw, EVENT_OBJECT_BPARA, bEnable); EnableInterface(pw, EVENT_OBJECT_BINFO, bEnable); - EnableInterface(pw, EVENT_OBJECT_BDESTROYER,bEnable); + EnableInterface(pw, EVENT_OBJECT_BSAFE, bEnable); } - if ( type == OBJECT_HUMAN || // builder? - type == OBJECT_TECH ) + if ( type == OBJECT_HUMAN || // can create flags? + type == OBJECT_TECH || + type == OBJECT_MOBILEfs || + type == OBJECT_MOBILEts || + type == OBJECT_MOBILEws || + type == OBJECT_MOBILEis ) { CheckInterface(pw, EVENT_OBJECT_FCOLORb, m_flagColor==0); CheckInterface(pw, EVENT_OBJECT_FCOLORr, m_flagColor==1); @@ -1726,10 +1860,52 @@ void CObjectInterface::UpdateInterface() ps = static_cast< CSlider* >(pw->SearchControl(EVENT_OBJECT_DIMSHIELD)); if ( ps != nullptr ) { - ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+dynamic_cast(m_object)->GetShieldRadius()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit)); + ps->SetVisibleValue((RADIUS_SHIELD_MIN/g_unit)+dynamic_cast(*m_object).GetShieldRadius()*((RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)/g_unit)); } } + if ( (type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib) && // builder? + !m_object->GetTrainer() ) + { + if(!bEnable) m_buildInterface = false; + CheckInterface(pw, EVENT_OBJECT_BUILD, m_buildInterface); + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_WINDOW3)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BFACTORY)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BDERRICK)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BCONVERT)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BSTATION)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BREPAIR)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BTOWER)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BRESEARCH)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BRADAR)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BENERGY)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BLABO)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BNUCLEAR)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BPARA)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BSAFE)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_BINFO)); + pb->SetState(STATE_VISIBLE, m_buildInterface); + } + bFly = bEnable; if ( bFly && (type == OBJECT_HUMAN || type == OBJECT_TECH) ) { @@ -1755,6 +1931,10 @@ void CObjectInterface::UpdateInterface() type == OBJECT_MOBILEta || type == OBJECT_MOBILEwa || type == OBJECT_MOBILEia || + type == OBJECT_MOBILEfb || + type == OBJECT_MOBILEtb || + type == OBJECT_MOBILEwb || + type == OBJECT_MOBILEib || type == OBJECT_MOBILEfc || type == OBJECT_MOBILEtc || type == OBJECT_MOBILEwc || @@ -1777,6 +1957,8 @@ void CObjectInterface::UpdateInterface() type == OBJECT_MOBILEtt || type == OBJECT_MOBILEwt || type == OBJECT_MOBILEit || + type == OBJECT_MOBILErp || + type == OBJECT_MOBILEst || type == OBJECT_MOBILEdr || type == OBJECT_MOTHER || type == OBJECT_ANT || diff --git a/src/ui/object_interface.h b/src/ui/object_interface.h index adf44c0d..ca7578d2 100644 --- a/src/ui/object_interface.h +++ b/src/ui/object_interface.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -120,6 +120,8 @@ protected: float m_lastAlarmTime; int m_soundChannelAlarm; int m_flagColor; + + bool m_buildInterface; }; } // namespace Ui diff --git a/src/ui/particles_generator.cpp b/src/ui/particles_generator.cpp new file mode 100644 index 00000000..69b70a50 --- /dev/null +++ b/src/ui/particles_generator.cpp @@ -0,0 +1,55 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include "ui/particles_generator.h" + +#include "graphics/engine/particle.h" + +namespace UI +{ + CParticlesGenerator::CParticlesGenerator() + { + m_particleManager = Gfx::CEngine::GetInstancePointer()->GetParticle(); + } + + void CParticlesGenerator::GenerateMouseParticles(Math::Point mousePosition, bool buttonPressed) + { + Gfx::ParticleType particleType = buttonPressed ? Gfx::ParticleType::PARTISCRAPS : Gfx::ParticleType::PARTILENS1; + m_particleManager->CreateParticle(Math::Vector(mousePosition.x, mousePosition.y, 0), CreateRandomSpeedForMouseParticles(), + CreateRandomDimensionsForMouseParticles(buttonPressed), particleType, + CreateRandomDurationForMouseParticles(), 2.0f, 0.0f, Gfx::SH_INTERFACE); + } + + Math::Point CParticlesGenerator::CreateRandomDimensionsForMouseParticles(bool buttonPressed) + { + float dimensionX = buttonPressed ? (0.005f + Math::Rand() * 0.005f) : (0.01f + Math::Rand() * 0.01f); + return Math::Point(dimensionX, dimensionX / 0.75f); + } + + Math::Vector CParticlesGenerator::CreateRandomSpeedForMouseParticles() + { + return Math::Vector((Math::Rand() - 0.5f) * 0.5f, 0.3f + Math::Rand() * 0.3f, 0.0f); + } + + float CParticlesGenerator::CreateRandomDurationForMouseParticles() + { + return Math::Rand() * 0.5f + 0.5f; + } + +} diff --git a/src/ui/particles_generator.h b/src/ui/particles_generator.h new file mode 100644 index 00000000..e96b6c04 --- /dev/null +++ b/src/ui/particles_generator.h @@ -0,0 +1,47 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "graphics/engine/particle.h" + +#include "math/point.h" +#include "math/vector.h" + +namespace UI +{ + /** + * \brief class for generating particles in the menu + */ + class CParticlesGenerator + { + public: + CParticlesGenerator(); + /** + * \brief generates particles after mouse cursor movement + */ + void GenerateMouseParticles(Math::Point mousePosition, bool buttonPressed); + private: + Gfx::CParticle* m_particleManager; + Math::Point CreateRandomDimensionsForMouseParticles(bool buttonPressed); + Math::Vector CreateRandomSpeedForMouseParticles(); + float CreateRandomDurationForMouseParticles(); + }; + +} diff --git a/src/ui/screen/screen.cpp b/src/ui/screen/screen.cpp index a5d8fbb0..a10346a3 100644 --- a/src/ui/screen/screen.cpp +++ b/src/ui/screen/screen.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen.h b/src/ui/screen/screen.h index 3f5e1c7b..8ab58353 100644 --- a/src/ui/screen/screen.h +++ b/src/ui/screen/screen.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_apperance.cpp b/src/ui/screen/screen_apperance.cpp index a1d89a2a..729865e3 100644 --- a/src/ui/screen/screen_apperance.cpp +++ b/src/ui/screen/screen_apperance.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_apperance.h b/src/ui/screen/screen_apperance.h index 5278d671..c0156792 100644 --- a/src/ui/screen/screen_apperance.h +++ b/src/ui/screen/screen_apperance.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_io.cpp b/src/ui/screen/screen_io.cpp index d3df8fdb..66275490 100644 --- a/src/ui/screen/screen_io.cpp +++ b/src/ui/screen/screen_io.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -143,8 +143,24 @@ void CScreenIO::IOUpdateList(bool isWrite) sel = pl->GetSelect(); max = pl->GetTotal(); + // enable/disable buttons if we have selected a game + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_IODELETE)); + if ( pb != nullptr ) + { + pb->SetState(STATE_ENABLE, (!isWrite && sel < max) || (isWrite && sel < max - 1)); + } + + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_IOREAD)); + if ( pb != nullptr ) + { + pb->SetState(STATE_ENABLE, sel < max); + } + if (m_saveList.size() <= static_cast(sel)) + { + pi->SetFilenameImage(""); // clear screenshot, nothing selected or New save selected return; + } std::string filename = m_saveList.at(sel) + "/screen.png"; if ( isWrite ) @@ -153,16 +169,6 @@ void CScreenIO::IOUpdateList(bool isWrite) { pi->SetFilenameImage(filename.c_str()); } - else - { - pi->SetFilenameImage(""); - } - - pb = static_cast(pw->SearchControl(EVENT_INTERFACE_IODELETE)); - if ( pb != nullptr ) - { - pb->SetState(STATE_ENABLE, sel < max-1); - } } else { @@ -244,22 +250,24 @@ void CScreenIO::IOWriteScene() // Reads the scene. -void CScreenIO::IOReadScene() +bool CScreenIO::IOReadScene() { CWindow* pw; CList* pl; pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw == nullptr ) return; + if ( pw == nullptr ) return false; pl = static_cast(pw->SearchControl(EVENT_INTERFACE_IOLIST)); - if ( pl == nullptr ) return; + if ( pl == nullptr ) return false; int sel = pl->GetSelect(); - if (sel < 0 || sel >= static_cast(m_saveList.size())) return; + if (sel < 0 || sel >= static_cast(m_saveList.size())) return false; m_main->GetPlayerProfile()->LoadScene(m_saveList.at(sel)); m_screenLevelList->SetSelection(m_main->GetLevelCategory(), m_main->GetLevelChap()-1, m_main->GetLevelRank()-1); + + return true; } } // namespace Ui diff --git a/src/ui/screen/screen_io.h b/src/ui/screen/screen_io.h index dd5f35ec..ddea8b3e 100644 --- a/src/ui/screen/screen_io.h +++ b/src/ui/screen/screen_io.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -39,7 +39,7 @@ protected: void IOUpdateList(bool isWrite); void IODeleteScene(); void IOWriteScene(); - void IOReadScene(); + bool IOReadScene(); protected: CScreenLevelList* m_screenLevelList; diff --git a/src/ui/screen/screen_io_read.cpp b/src/ui/screen/screen_io_read.cpp index c80132bd..d682b019 100644 --- a/src/ui/screen/screen_io_read.cpp +++ b/src/ui/screen/screen_io_read.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -168,8 +168,7 @@ bool CScreenIORead::EventProcess(const Event &event) if ( event.type == EVENT_INTERFACE_IOREAD ) { - IOReadScene(); - if(m_inSimulation) + if(IOReadScene() && m_inSimulation) { m_main->StopSuspend(); m_main->ChangePhase(PHASE_SIMUL); diff --git a/src/ui/screen/screen_io_read.h b/src/ui/screen/screen_io_read.h index 2ab70854..a97104bf 100644 --- a/src/ui/screen/screen_io_read.h +++ b/src/ui/screen/screen_io_read.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_io_write.cpp b/src/ui/screen/screen_io_write.cpp index b39a2227..5bb213b9 100644 --- a/src/ui/screen/screen_io_write.cpp +++ b/src/ui/screen/screen_io_write.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_io_write.h b/src/ui/screen/screen_io_write.h index 57483222..d3291ed9 100644 --- a/src/ui/screen/screen_io_write.h +++ b/src/ui/screen/screen_io_write.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_level_list.cpp b/src/ui/screen/screen_level_list.cpp index 531fe6bf..b0ed6460 100644 --- a/src/ui/screen/screen_level_list.cpp +++ b/src/ui/screen/screen_level_list.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -48,6 +48,9 @@ CScreenLevelList::CScreenLevelList(CMainDialog* mainDialog) : m_dialog(mainDialog), m_category{}, m_sceneSoluce{false}, + m_plusTrainer{false}, + m_plusResearch{false}, + m_plusExplorer{false}, m_maxList{0}, m_accessChap{0} { @@ -86,6 +89,7 @@ void CScreenLevelList::CreateInterface() if ( m_category == LevelCategory::Missions ) res = RT_TITLE_MISSION; if ( m_category == LevelCategory::FreeGame ) res = RT_TITLE_FREE; if ( m_category == LevelCategory::CodeBattles ) res = RT_TITLE_CODE_BATTLES; + if ( m_category == LevelCategory::GamePlus ) res = RT_TITLE_PLUS; if ( m_category == LevelCategory::CustomLevels ) res = RT_TITLE_USER; GetResource(RES_TEXT, res, name); pw->SetName(name); @@ -109,6 +113,7 @@ void CScreenLevelList::CreateInterface() res = RT_PLAY_CHAP_CHAPTERS; if ( m_category == LevelCategory::Missions ) res = RT_PLAY_CHAP_PLANETS; if ( m_category == LevelCategory::FreeGame ) res = RT_PLAY_CHAP_PLANETS; + if ( m_category == LevelCategory::GamePlus ) res = RT_PLAY_CHAP_PLANETS; if ( m_category == LevelCategory::CustomLevels ) res = RT_PLAY_CHAP_USERLVL; GetResource(RES_TEXT, res, name); pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name); @@ -138,6 +143,7 @@ void CScreenLevelList::CreateInterface() if ( m_category == LevelCategory::Challenges ) res = RT_PLAY_LIST_CHALLENGES; if ( m_category == LevelCategory::Missions ) res = RT_PLAY_LIST_MISSIONS; if ( m_category == LevelCategory::FreeGame ) res = RT_PLAY_LIST_FREEGAME; + if ( m_category == LevelCategory::GamePlus ) res = RT_PLAY_LIST_MISSIONS; GetResource(RES_TEXT, res, name); pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name); pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); @@ -179,6 +185,7 @@ void CScreenLevelList::CreateInterface() // Button displays the "soluce": if ( m_category != LevelCategory::Exercises && + m_category != LevelCategory::GamePlus && m_category != LevelCategory::FreeGame ) { pos.x = ox+sx*9.5f; @@ -191,10 +198,36 @@ void CScreenLevelList::CreateInterface() } m_sceneSoluce = false; + if ( m_category == LevelCategory::GamePlus ) + { + pos.x = ox+sx*9.5f; + pos.y = oy+sy*6.1f; + ddim.x = dim.x*3.4f; + ddim.y = dim.y*0.5f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_PLUS_TRAINER); + pc->SetState(STATE_SHADOW); + pc->ClearState(STATE_CHECK); + + pos.y = oy+sy*5.5f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_PLUS_RESEARCH); + pc->SetState(STATE_SHADOW); + pc->ClearState(STATE_CHECK); + + pos.x = ox+sx*12.9f; + pos.y = oy+sy*6.1f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_PLUS_EXPLORER); + pc->SetState(STATE_SHADOW); + pc->ClearState(STATE_CHECK); + } + m_plusTrainer = false; + m_plusResearch = false; + m_plusExplorer = false; + UpdateSceneResume(m_chap[m_category]+1, m_sel[m_category]+1); if ( m_category == LevelCategory::Missions || m_category == LevelCategory::FreeGame || + m_category == LevelCategory::GamePlus || m_category == LevelCategory::CustomLevels ) { pos.x = ox+sx*9.5f; @@ -295,6 +328,27 @@ bool CScreenLevelList::EventProcess(const Event &event) pb->SetState(STATE_CHECK, m_sceneSoluce); break; + case EVENT_INTERFACE_PLUS_TRAINER: + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_PLUS_TRAINER)); + if ( pb == nullptr ) break; + m_plusTrainer = !m_plusTrainer; + pb->SetState(STATE_CHECK, m_plusTrainer); + break; + + case EVENT_INTERFACE_PLUS_RESEARCH: + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_PLUS_RESEARCH)); + if ( pb == nullptr ) break; + m_plusResearch = !m_plusResearch; + pb->SetState(STATE_CHECK, m_plusResearch); + break; + + case EVENT_INTERFACE_PLUS_EXPLORER: + pb = static_cast(pw->SearchControl(EVENT_INTERFACE_PLUS_EXPLORER)); + if ( pb == nullptr ) break; + m_plusExplorer = !m_plusExplorer; + pb->SetState(STATE_CHECK, m_plusExplorer); + break; + case EVENT_INTERFACE_PLAY: m_main->SetLevel(m_category, m_chap[m_category]+1, m_sel[m_category]+1); m_main->ChangePhase(PHASE_SIMUL); @@ -331,6 +385,21 @@ bool CScreenLevelList::GetSceneSoluce() return m_sceneSoluce; } +bool CScreenLevelList::GetPlusTrainer() +{ + return m_plusTrainer; +} + +bool CScreenLevelList::GetPlusResearch() +{ + return m_plusResearch; +} + +bool CScreenLevelList::GetPlusExplorer() +{ + return m_plusExplorer; +} + // Updates the chapters of exercises or missions. void CScreenLevelList::UpdateSceneChap(int &chap) @@ -392,7 +461,7 @@ void CScreenLevelList::UpdateSceneChap(int &chap) pl->SetCheck(j, bPassed); pl->SetEnable(j, true); - if ( m_category == LevelCategory::Missions && !m_main->GetShowAll() && !bPassed ) + if ( (m_category == LevelCategory::Missions || m_category == LevelCategory::GamePlus) && !m_main->GetShowAll() && !bPassed ) { j ++; break; @@ -459,7 +528,7 @@ void CScreenLevelList::UpdateSceneList(int chap, int &sel) pl->SetCheck(j, bPassed); pl->SetEnable(j, true); - if ( m_category == LevelCategory::Missions && !m_main->GetShowAll() && !bPassed ) + if ( (m_category == LevelCategory::Missions || m_category == LevelCategory::GamePlus) && !m_main->GetShowAll() && !bPassed ) { readAll = false; } diff --git a/src/ui/screen/screen_level_list.h b/src/ui/screen/screen_level_list.h index 6a95cb1b..089dc558 100644 --- a/src/ui/screen/screen_level_list.h +++ b/src/ui/screen/screen_level_list.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -43,6 +43,9 @@ public: void SetSelection(LevelCategory category, int chap, int rank); bool GetSceneSoluce(); + bool GetPlusTrainer(); + bool GetPlusResearch(); + bool GetPlusExplorer(); void AllMissionUpdate(); void ShowSoluceUpdate(); @@ -65,6 +68,9 @@ protected: LevelCategory m_category; bool m_sceneSoluce; + bool m_plusTrainer; + bool m_plusResearch; + bool m_plusExplorer; std::map m_chap; // selected chapter (0..8) std::map m_sel; // chosen mission (0..98) diff --git a/src/ui/screen/screen_loading.cpp b/src/ui/screen/screen_loading.cpp index e10a1754..a6455e58 100644 --- a/src/ui/screen/screen_loading.cpp +++ b/src/ui/screen/screen_loading.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_loading.h b/src/ui/screen/screen_loading.h index c4bedbc5..4e54c668 100644 --- a/src/ui/screen/screen_loading.h +++ b/src/ui/screen/screen_loading.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_main_menu.cpp b/src/ui/screen/screen_main_menu.cpp index 4ad270dc..c66e61a7 100644 --- a/src/ui/screen/screen_main_menu.cpp +++ b/src/ui/screen/screen_main_menu.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -91,14 +91,22 @@ void CScreenMainMenu::CreateInterface() pg = pw->CreateGroup(pos, ddim, 26, EVENT_LABEL1); // quit pg->SetState(STATE_SHADOW); - ddim.x = 0.18f; + ddim.x = 0.12f; ddim.y = dim.y*0.8f; pos.x = 0.41f; - pos.y = oy+sy*10.5f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MISSION); pb->SetState(STATE_SHADOW); + ddim.x = 0.06f; + pos.x = 0.53f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_PLUS); + pb->SetState(STATE_SHADOW); + + ddim.x = 0.18f; + pos.x = 0.41f; + pos.y = oy+sy*9.6f; pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_FREE); pb->SetState(STATE_SHADOW); @@ -170,6 +178,13 @@ void CScreenMainMenu::CreateInterface() pb = pw->CreateButton(pos, ddim, 128+60, EVENT_INTERFACE_SATCOM); pb->SetState(STATE_SHADOW); + // Mods button + pos.x = 447.0f/640.0f; + pos.y = 313.0f/480.0f; + ddim.x = 0.09f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MODS); + pb->SetState(STATE_SHADOW); + SetBackground("textures/interface/interface.png"); CreateVersionDisplay(); } @@ -218,6 +233,11 @@ bool CScreenMainMenu::EventProcess(const Event &event) m_main->ChangePhase(PHASE_LEVEL_LIST); break; + case EVENT_INTERFACE_PLUS: + m_main->SetLevel(LevelCategory::GamePlus, 0, 0); + m_main->ChangePhase(PHASE_LEVEL_LIST); + break; + case EVENT_INTERFACE_USER: m_main->SetLevel(LevelCategory::CustomLevels, 0, 0); m_main->ChangePhase(PHASE_LEVEL_LIST); @@ -235,6 +255,9 @@ bool CScreenMainMenu::EventProcess(const Event &event) m_main->ChangePhase(PHASE_SATCOM); break; + case EVENT_INTERFACE_MODS: + m_main->ChangePhase(PHASE_MOD_LIST); + default: return true; } diff --git a/src/ui/screen/screen_main_menu.h b/src/ui/screen/screen_main_menu.h index d797e71e..72acff7b 100644 --- a/src/ui/screen/screen_main_menu.h +++ b/src/ui/screen/screen_main_menu.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_mod_list.cpp b/src/ui/screen/screen_mod_list.cpp new file mode 100644 index 00000000..856f2a20 --- /dev/null +++ b/src/ui/screen/screen_mod_list.cpp @@ -0,0 +1,582 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#include "ui/screen/screen_mod_list.h" + +#include "common/config.h" + +#include "app/app.h" +#include "app/modman.h" + +#include "common/logger.h" +#include "common/restext.h" +#include "common/stringutils.h" + +#include "common/resources/resourcemanager.h" + +#include "common/system/system.h" + +#include "level/robotmain.h" + +#include "math/func.h" + +#include "sound/sound.h" + +#include "ui/controls/button.h" +#include "ui/controls/edit.h" +#include "ui/controls/interface.h" +#include "ui/controls/label.h" +#include "ui/controls/list.h" +#include "ui/controls/window.h" + +#include + +namespace Ui +{ + +CScreenModList::CScreenModList(CMainDialog* dialog, CModManager* modManager) + : m_dialog(dialog), + m_modManager(modManager) +{ +} + +void CScreenModList::CreateInterface() +{ + CWindow* pw; + CEdit* pe; + CLabel* pl; + CButton* pb; + CList* pli; + Math::Point pos, ddim; + std::string name; + + // Display the window + pos.x = 0.10f; + pos.y = 0.10f; + ddim.x = 0.80f; + ddim.y = 0.80f; + pw = m_interface->CreateWindows(pos, ddim, 12, EVENT_WINDOW5); + pw->SetClosable(true); + GetResource(RES_TEXT, RT_TITLE_MODS, name); + pw->SetName(name); + + pos.x = 0.10f; + pos.y = 0.40f; + ddim.x = 0.50f; + ddim.y = 0.50f; + pw->CreateGroup(pos, ddim, 5, EVENT_INTERFACE_GLINTl); // orange corner + pos.x = 0.40f; + pos.y = 0.10f; + ddim.x = 0.50f; + ddim.y = 0.50f; + pw->CreateGroup(pos, ddim, 4, EVENT_INTERFACE_GLINTr); // blue corner + + // Display the list of mods + pos.x = ox+sx*3; + pos.y = oy+sy*10.5f; + ddim.x = dim.x*7.5f; + ddim.y = dim.y*0.6f; + GetResource(RES_TEXT, RT_MOD_LIST, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL11, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.y = oy+sy*6.7f; + ddim.y = dim.y*4.6f; + ddim.x = dim.x*6.5f; + pli = pw->CreateList(pos, ddim, 0, EVENT_INTERFACE_MOD_LIST); + pli->SetState(STATE_SHADOW); + pli->SetState(STATE_EXTEND); + + // Displays the mod details + pos.x = ox+sx*9.5f; + pos.y = oy+sy*10.5f; + ddim.x = dim.x*7.5f; + ddim.y = dim.y*0.6f; + GetResource(RES_TEXT, RT_MOD_DETAILS, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL12, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.y = oy+sy*6.7f; + ddim.y = dim.y*4.3f; + ddim.x = dim.x*6.5f; + pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_MOD_DETAILS); + pe->SetState(STATE_SHADOW); + pe->SetMaxChar(500); + pe->SetEditCap(false); // just to see + pe->SetHighlightCap(true); + + pos = pli->GetPos(); + ddim = pli->GetDim(); + + // Displays the mod summary + pos.x = ox+sx*3; + pos.y = oy+sy*5.4f; + ddim.x = dim.x*6.5f; + ddim.y = dim.y*0.6f; + GetResource(RES_TEXT, RT_MOD_SUMMARY, name); + pl = pw->CreateLabel(pos, ddim, 0, EVENT_LABEL13, name); + pl->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); + + pos.x = ox+sx*3; + pos.y = oy+sy*3.6f; + ddim.x = dim.x*13.4f; + ddim.y = dim.y*1.9f; + pe = pw->CreateEdit(pos, ddim, 0, EVENT_INTERFACE_MOD_SUMMARY); + pe->SetState(STATE_SHADOW); + pe->SetMaxChar(500); + pe->SetEditCap(false); // just to see + pe->SetHighlightCap(true); + + // Apply button + pos.x = ox+sx*13.75f; + pos.y = oy+sy*2; + ddim.x = dim.x*2.0f; + ddim.y = dim.y*1; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MODS_APPLY); + pb->SetState(STATE_SHADOW); + + // Display the enable/disable button + pos.x -= dim.x*2.3f; + ddim.x = dim.x*2.0f; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE); + pb->SetState(STATE_SHADOW); + + // Display the move up button + pos.x -= dim.x*0.8f; + pos.y = oy+sy*2.48; + ddim.x = dim.x*0.5; + ddim.y = dim.y*0.5; + pb = pw->CreateButton(pos, ddim, 49, EVENT_INTERFACE_MOD_MOVE_UP); + pb->SetState(STATE_SHADOW); + + // Display the move down button + pos.y = oy+sy*2; + pb = pw->CreateButton(pos, ddim, 50, EVENT_INTERFACE_MOD_MOVE_DOWN); + pb->SetState(STATE_SHADOW); + + // Display the refresh button + pos.x -= dim.x*1.3f; + pos.y = oy+sy*2; + ddim.x = dim.x*1; + ddim.y = dim.y*1; + pb = pw->CreateButton(pos, ddim, 87, EVENT_INTERFACE_MODS_REFRESH); + pb->SetState(STATE_SHADOW); + + // Display the open website button + pos.x -= dim.x*1.3f; + pb = pw->CreateButton(pos, ddim, 40, EVENT_INTERFACE_WORKSHOP); + pb->SetState(STATE_SHADOW); + + // Display the open directory button + pos.x -= dim.x*1.3f; + pb = pw->CreateButton(pos, ddim, 57, EVENT_INTERFACE_MODS_DIR); + pb->SetState(STATE_SHADOW); + + // Back button + pos.x = ox+sx*3; + ddim.x = dim.x*4; + pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_BACK); + pb->SetState(STATE_SHADOW); + + FindMods(); + UpdateAll(); + + // Background + SetBackground("textures/interface/interface.png"); + CreateVersionDisplay(); +} + +bool CScreenModList::EventProcess(const Event &event) +{ + CWindow* pw; + CList* pl; + + const std::string workshopUrl = "https://www.moddb.com/games/colobot-gold-edition"; + const std::string modDir = CResourceManager::GetSaveLocation() + "/mods"; + + auto systemUtils = CSystemUtils::Create(); // platform-specific utils + + Mod const * mod; + + pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return false; + + if (event.type == pw->GetEventTypeClose() || + event.type == EVENT_INTERFACE_BACK || + (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE))) + { + if (m_modManager->Changes()) + { + m_dialog->StartQuestion(RT_DIALOG_CHANGES_QUESTION, true, true, false, + [this]() + { + ApplyChanges(); + CloseWindow(); + }, + [this]() + { + CloseWindow(); + }); + } + else + { + CloseWindow(); + } + return false; + } + + switch( event.type ) + { + case EVENT_INTERFACE_MOD_LIST: + pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_LIST)); + if (pl == nullptr) break; + m_modSelectedIndex = pl->GetSelect(); + UpdateModSummary(); + UpdateModDetails(); + UpdateEnableDisableButton(); + UpdateUpDownButtons(); + break; + + case EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE: + mod = &m_modManager->GetMod(m_modSelectedIndex); + if (mod->enabled) + { + m_modManager->DisableMod(m_modSelectedIndex); + } + else + { + m_modManager->EnableMod(m_modSelectedIndex); + } + UpdateModList(); + UpdateEnableDisableButton(); + UpdateApplyButton(); + break; + + case EVENT_INTERFACE_MOD_MOVE_UP: + m_modSelectedIndex = m_modManager->MoveUp(m_modSelectedIndex); + UpdateModList(); + UpdateUpDownButtons(); + UpdateApplyButton(); + break; + + case EVENT_INTERFACE_MOD_MOVE_DOWN: + m_modSelectedIndex = m_modManager->MoveDown(m_modSelectedIndex); + UpdateModList(); + UpdateUpDownButtons(); + UpdateApplyButton(); + break; + + case EVENT_INTERFACE_MODS_REFRESH: + // Apply any changes before refresh so that the config file + // is better synchronized with the state of the game + case EVENT_INTERFACE_MODS_APPLY: + ApplyChanges(); + UpdateAll(); + // Start playing the main menu music again + if (!m_app->GetSound()->IsPlayingMusic()) + { + m_app->GetSound()->PlayMusic("music/Intro1.ogg", false); + m_app->GetSound()->CacheMusic("music/Intro2.ogg"); + } + break; + + case EVENT_INTERFACE_MODS_DIR: + if (!systemUtils->OpenPath(modDir)) + { + std::string title, text; + GetResource(RES_TEXT, RT_DIALOG_OPEN_PATH_FAILED_TITLE, title); + GetResource(RES_TEXT, RT_DIALOG_OPEN_PATH_FAILED_TEXT, text); + + // Workaround for Windows: the label skips everything after the first \\ character + std::string modDirWithoutBackSlashes = modDir; + std::replace(modDirWithoutBackSlashes.begin(), modDirWithoutBackSlashes.end(), '\\', '/'); + + m_dialog->StartInformation(title, title, StrUtils::Format(text.c_str(), modDirWithoutBackSlashes.c_str())); + } + break; + + case EVENT_INTERFACE_WORKSHOP: + if (!systemUtils->OpenWebsite(workshopUrl)) + { + std::string title, text; + GetResource(RES_TEXT, RT_DIALOG_OPEN_WEBSITE_FAILED_TITLE, title); + GetResource(RES_TEXT, RT_DIALOG_OPEN_WEBSITE_FAILED_TEXT, text); + m_dialog->StartInformation(title, title, StrUtils::Format(text.c_str(), workshopUrl.c_str())); + } + break; + + default: + return true; + } + return false; +} + +void CScreenModList::FindMods() +{ + m_modManager->FindMods(); + if (m_modManager->CountMods() != 0) + { + m_modSelectedIndex = Math::Clamp(m_modSelectedIndex, static_cast(0), m_modManager->CountMods() - 1); + } +} + +void CScreenModList::ApplyChanges() +{ + m_modManager->SaveMods(); + m_modManager->ReloadMods(); +} + +void CScreenModList::CloseWindow() +{ + m_main->ChangePhase(PHASE_MAIN_MENU); +} + +void CScreenModList::UpdateAll() +{ + UpdateModList(); + UpdateModDetails(); + UpdateModSummary(); + UpdateEnableDisableButton(); + UpdateApplyButton(); + UpdateUpDownButtons(); +} + +void CScreenModList::UpdateModList() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CList* pl = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_LIST)); + if (pl == nullptr) return; + + pl->Flush(); + + if (m_modManager->CountMods() == 0) + { + return; + } + + const auto& mods = m_modManager->GetMods(); + for (size_t i = 0; i < mods.size(); ++i) + { + const auto& mod = mods[i]; + const auto& name = mod.data.displayName; + pl->SetItemName(i, name); + pl->SetCheck(i, mod.enabled); + pl->SetEnable(i, true); + } + + pl->SetSelect(m_modSelectedIndex); + pl->ShowSelect(false); +} + +void CScreenModList::UpdateModDetails() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CEdit* pe = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_DETAILS)); + if (pe == nullptr) return; + + if (m_modManager->CountMods() == 0) + { + pe->SetText("No information"); + return; + } + + std::string details{}; + + const auto& mod = m_modManager->GetMod(m_modSelectedIndex); + const auto data = mod.data; + + details += "\\b;" + data.displayName + '\n'; + + std::string authorFieldName; + GetResource(RES_TEXT, RT_MOD_AUTHOR_FIELD_NAME, authorFieldName); + details += "\\s;" + authorFieldName + " "; + if (!data.author.empty()) + { + details += data.author; + } + else + { + std::string unknownAuthor; + GetResource(RES_TEXT, RT_MOD_UNKNOWN_AUTHOR, unknownAuthor); + details += unknownAuthor; + } + details += '\n'; + + details += '\n'; + + if (!data.version.empty()) + { + std::string versionFieldName; + GetResource(RES_TEXT, RT_MOD_VERSION_FIELD_NAME, versionFieldName); + details += "\\t;" + versionFieldName + '\n' + data.version + '\n'; + } + + if (!data.website.empty()) + { + std::string websiteFieldName; + GetResource(RES_TEXT, RT_MOD_WEBSITE_FIELD_NAME, websiteFieldName); + details += "\\t;" + websiteFieldName + '\n' + data.website + '\n'; + } + + std::string changesFieldName; + GetResource(RES_TEXT, RT_MOD_CHANGES_FIELD_NAME, changesFieldName); + details += "\\t;" + changesFieldName + '\n'; + if (!data.changes.empty()) + { + for (const auto& change : data.changes) + { + details += change + '\n'; + } + } + else + { + std::string noChanges; + GetResource(RES_TEXT, RT_MOD_NO_CHANGES, noChanges); + details += noChanges; + } + + pe->SetText(details); + + pe->SetFirstLine(0); +} + +void CScreenModList::UpdateModSummary() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CEdit* pe = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_SUMMARY)); + if (pe == nullptr) return; + + std::string noSummary; + GetResource(RES_TEXT, RT_MOD_NO_SUMMARY, noSummary); + + if (m_modManager->CountMods() == 0) + { + pe->SetText(noSummary); + return; + } + + const auto& mod = m_modManager->GetMod(m_modSelectedIndex); + + if (!mod.data.summary.empty()) + { + pe->SetText(mod.data.summary); + } + else + { + pe->SetText(noSummary); + } +} + +void CScreenModList::UpdateEnableDisableButton() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_ENABLE_OR_DISABLE)); + if (pb == nullptr) return; + + std::string buttonName{}; + + if (m_modManager->CountMods() == 0) + { + pb->ClearState(STATE_ENABLE); + + // Set some default name + GetResource(RES_TEXT, RT_MOD_ENABLE, buttonName); + pb->SetName(buttonName); + + return; + } + + const auto& mod = m_modManager->GetMod(m_modSelectedIndex); + + if (mod.enabled) + { + GetResource(RES_TEXT, RT_MOD_DISABLE, buttonName); + pb->SetName(buttonName); + } + else + { + GetResource(RES_TEXT, RT_MOD_ENABLE, buttonName); + pb->SetName(buttonName); + } +} + +void CScreenModList::UpdateApplyButton() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CButton* pb = static_cast(pw->SearchControl(EVENT_INTERFACE_MODS_APPLY)); + if (pb == nullptr) return; + + if (m_modManager->Changes()) + { + pb->SetState(STATE_ENABLE); + } + else + { + pb->ClearState(STATE_ENABLE); + } +} + +void CScreenModList::UpdateUpDownButtons() +{ + CWindow* pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); + if (pw == nullptr) return; + + CButton* pb_up = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_MOVE_UP)); + if (pb_up == nullptr) return; + + CButton* pb_down = static_cast(pw->SearchControl(EVENT_INTERFACE_MOD_MOVE_DOWN)); + if (pb_down == nullptr) return; + + if (m_modManager->CountMods() == 0) + { + pb_up->ClearState(STATE_ENABLE); + pb_down->ClearState(STATE_ENABLE); + return; + } + + if (m_modSelectedIndex == 0) + { + pb_up->ClearState(STATE_ENABLE); + } + else + { + pb_up->SetState(STATE_ENABLE); + } + + if (m_modSelectedIndex >= m_modManager->CountMods() - 1) + { + pb_down->ClearState(STATE_ENABLE); + } + else + { + pb_down->SetState(STATE_ENABLE); + } +} + +} // namespace Ui diff --git a/src/ui/screen/screen_mod_list.h b/src/ui/screen/screen_mod_list.h new file mode 100644 index 00000000..ca2c130b --- /dev/null +++ b/src/ui/screen/screen_mod_list.h @@ -0,0 +1,66 @@ +/* + * This file is part of the Colobot: Gold Edition source code + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam + * http://epsitec.ch; http://colobot.info; http://github.com/colobot + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://gnu.org/licenses + */ + +#pragma once + +#include "app/modman.h" + +#include "ui/maindialog.h" + +#include "ui/screen/screen.h" + +#include + +namespace Ui +{ + +/** + * \class CScreenModList + * \brief This class is the front-end for the \ref CModManager. + */ +class CScreenModList : public CScreen +{ +public: + CScreenModList(CMainDialog* dialog, CModManager* modManager); + + void CreateInterface() override; + bool EventProcess(const Event &event) override; + +protected: + void FindMods(); + void ApplyChanges(); + void CloseWindow(); + + void UpdateAll(); + void UpdateModList(); + void UpdateModDetails(); + void UpdateModSummary(); + void UpdateEnableDisableButton(); + void UpdateApplyButton(); + void UpdateUpDownButtons(); + +protected: + Ui::CMainDialog* m_dialog; + + CModManager* m_modManager; + + size_t m_modSelectedIndex = 0; +}; + +} // namespace Ui diff --git a/src/ui/screen/screen_player_select.cpp b/src/ui/screen/screen_player_select.cpp index a9dc98fd..da28ad28 100644 --- a/src/ui/screen/screen_player_select.cpp +++ b/src/ui/screen/screen_player_select.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_player_select.h b/src/ui/screen/screen_player_select.h index 5413c45e..0a4f9035 100644 --- a/src/ui/screen/screen_player_select.h +++ b/src/ui/screen/screen_player_select.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_quit.cpp b/src/ui/screen/screen_quit.cpp index 0928c6bc..92895ee2 100644 --- a/src/ui/screen/screen_quit.cpp +++ b/src/ui/screen/screen_quit.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_quit.h b/src/ui/screen/screen_quit.h index f8c0d592..99ee337e 100644 --- a/src/ui/screen/screen_quit.h +++ b/src/ui/screen/screen_quit.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup.cpp b/src/ui/screen/screen_setup.cpp index 823207af..67848640 100644 --- a/src/ui/screen/screen_setup.cpp +++ b/src/ui/screen/screen_setup.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup.h b/src/ui/screen/screen_setup.h index 6bbea815..0c85a281 100644 --- a/src/ui/screen/screen_setup.h +++ b/src/ui/screen/screen_setup.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup_controls.cpp b/src/ui/screen/screen_setup_controls.cpp index 8890da8f..7dcbd296 100644 --- a/src/ui/screen/screen_setup_controls.cpp +++ b/src/ui/screen/screen_setup_controls.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup_controls.h b/src/ui/screen/screen_setup_controls.h index 2ce2bd0a..1dbe6e6a 100644 --- a/src/ui/screen/screen_setup_controls.h +++ b/src/ui/screen/screen_setup_controls.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup_display.cpp b/src/ui/screen/screen_setup_display.cpp index d015a58c..f465a488 100644 --- a/src/ui/screen/screen_setup_display.cpp +++ b/src/ui/screen/screen_setup_display.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -293,6 +293,7 @@ void CScreenSetupDisplay::UpdateApply() CWindow* pw; CButton* pb; CList* pl; + CList* pvl; CCheck* pc; int sel2; bool bFull; @@ -309,6 +310,22 @@ void CScreenSetupDisplay::UpdateApply() pc = static_cast(pw->SearchControl(EVENT_INTERFACE_FULL)); bFull = pc->TestState(STATE_CHECK); + pvl = static_cast(pw->SearchControl(EVENT_INTERFACE_VSYNC)); + if (pvl == nullptr) return; + + switch (m_engine->GetVSync()) + { + case -1: //Adaptive? + pvl->SetSelect(1); + break; + case 0: //Off? + pvl->SetSelect(0); + break; + case 1: //On? + pvl->SetSelect(2); + break; + } + if ( sel2 == m_setupSelMode && bFull == m_setupFull ) { diff --git a/src/ui/screen/screen_setup_display.h b/src/ui/screen/screen_setup_display.h index 690771b1..84928011 100644 --- a/src/ui/screen/screen_setup_display.h +++ b/src/ui/screen/screen_setup_display.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup_game.cpp b/src/ui/screen/screen_setup_game.cpp index a076ab59..5a519b54 100644 --- a/src/ui/screen/screen_setup_game.cpp +++ b/src/ui/screen/screen_setup_game.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -173,7 +173,7 @@ bool CScreenSetupGame::EventProcess(const Event &event) break; case EVENT_INTERFACE_RAIN: - m_settings->SetInterfaceRain(!m_settings->GetInterfaceRain()); + m_settings->SetMouseParticlesEnabled(!m_settings->GetMouseParticlesEnabled()); ChangeSetupButtons(); UpdateSetupButtons(); break; @@ -291,7 +291,7 @@ void CScreenSetupGame::UpdateSetupButtons() pc = static_cast(pw->SearchControl(EVENT_INTERFACE_RAIN)); if ( pc != nullptr ) { - pc->SetState(STATE_CHECK, m_settings->GetInterfaceRain()); + pc->SetState(STATE_CHECK, m_settings->GetMouseParticlesEnabled()); } pc = static_cast(pw->SearchControl(EVENT_INTERFACE_BGPAUSE)); diff --git a/src/ui/screen/screen_setup_game.h b/src/ui/screen/screen_setup_game.h index f549c490..c2ccda32 100644 --- a/src/ui/screen/screen_setup_game.h +++ b/src/ui/screen/screen_setup_game.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup_graphics.cpp b/src/ui/screen/screen_setup_graphics.cpp index bcbecdeb..9086b126 100644 --- a/src/ui/screen/screen_setup_graphics.cpp +++ b/src/ui/screen/screen_setup_graphics.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup_graphics.h b/src/ui/screen/screen_setup_graphics.h index cbec45e9..f5269dc3 100644 --- a/src/ui/screen/screen_setup_graphics.h +++ b/src/ui/screen/screen_setup_graphics.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_setup_sound.cpp b/src/ui/screen/screen_setup_sound.cpp index 28ad0b31..4f72b7bf 100644 --- a/src/ui/screen/screen_setup_sound.cpp +++ b/src/ui/screen/screen_setup_sound.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -30,6 +30,7 @@ #include "sound/sound.h" #include "ui/controls/button.h" +#include "ui/controls/check.h" #include "ui/controls/interface.h" #include "ui/controls/label.h" #include "ui/controls/slider.h" @@ -53,6 +54,7 @@ void CScreenSetupSound::CreateInterface() CLabel* pl; CSlider* psl; CButton* pb; + CCheck* pc; Math::Point pos, ddim; std::string name; @@ -96,6 +98,13 @@ void CScreenSetupSound::CreateInterface() pb = pw->CreateButton(pos, ddim, -1, EVENT_INTERFACE_NOISY); pb->SetState(STATE_SHADOW); + ddim.x = dim.x*6; + ddim.y = dim.y*0.5f; + pos.x = ox+sx*10; + pos.y = 0.55f; + pc = pw->CreateCheck(pos, ddim, -1, EVENT_INTERFACE_BGMUTE); + pc->SetState(STATE_SHADOW); + UpdateSetupButtons(); } @@ -121,6 +130,12 @@ bool CScreenSetupSound::EventProcess(const Event &event) UpdateSetupButtons(); break; + case EVENT_INTERFACE_BGMUTE: + m_settings->SetFocusLostMute(!m_settings->GetFocusLostMute()); + ChangeSetupButtons(); + UpdateSetupButtons(); + break; + default: return true; } @@ -133,6 +148,7 @@ void CScreenSetupSound::UpdateSetupButtons() { CWindow* pw; CSlider* ps; + CCheck* pc; float value; pw = static_cast(m_interface->SearchControl(EVENT_WINDOW5)); @@ -151,6 +167,14 @@ void CScreenSetupSound::UpdateSetupButtons() value = static_cast(m_sound->GetMusicVolume()); ps->SetVisibleValue(value); } + + pc = static_cast(pw->SearchControl(EVENT_INTERFACE_BGMUTE)); + if ( pc != nullptr ) + { + pc->SetState(STATE_CHECK, m_settings->GetFocusLostMute()); + } + + m_settings->SaveAudioSettings(); } // Updates the engine function of the buttons after the setup phase. @@ -177,6 +201,8 @@ void CScreenSetupSound::ChangeSetupButtons() value = ps->GetVisibleValue(); m_sound->SetMusicVolume(static_cast(value)); } + + m_settings->SaveAudioSettings(); } } // namespace Ui diff --git a/src/ui/screen/screen_setup_sound.h b/src/ui/screen/screen_setup_sound.h index d9d2148c..6c765ac9 100644 --- a/src/ui/screen/screen_setup_sound.h +++ b/src/ui/screen/screen_setup_sound.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_welcome.cpp b/src/ui/screen/screen_welcome.cpp index 16e48d89..2638111e 100644 --- a/src/ui/screen/screen_welcome.cpp +++ b/src/ui/screen/screen_welcome.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/screen/screen_welcome.h b/src/ui/screen/screen_welcome.h index cc70deaa..631d709b 100644 --- a/src/ui/screen/screen_welcome.h +++ b/src/ui/screen/screen_welcome.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/src/ui/studio.cpp b/src/ui/studio.cpp index 3602aeac..22c21a7f 100644 --- a/src/ui/studio.cpp +++ b/src/ui/studio.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -45,6 +45,8 @@ #include "sound/sound.h" +#include "ui/filedialog.h" + #include "ui/controls/check.h" #include "ui/controls/color.h" #include "ui/controls/control.h" @@ -93,7 +95,7 @@ CStudio::CStudio() m_bRealTime = true; m_bRunning = false; m_fixInfoTextTime = 0.0f; - m_dialog = SD_NULL; + m_fileDialog = nullptr; m_editCamera = Gfx::CAM_TYPE_NULL; } @@ -112,7 +114,7 @@ bool CStudio::EventProcess(const Event &event) CEdit* edit; CSlider* slider; - if ( m_dialog != SD_NULL ) // dialogue exists? + if (m_fileDialog != nullptr) // dialogue exists? { return EventDialog(event); } @@ -133,7 +135,7 @@ bool CStudio::EventProcess(const Event &event) m_event->AddEvent(Event(EVENT_STUDIO_OK)); } - if ( event.type == EVENT_STUDIO_EDIT ) // text modifief? + if ( event.type == EVENT_STUDIO_EDIT ) // text modified? { ColorizeScript(edit); } @@ -150,11 +152,13 @@ bool CStudio::EventProcess(const Event &event) if ( event.type == EVENT_STUDIO_OPEN ) // open? { - StartDialog(SD_OPEN); + StartDialog(event); + return true; } if ( event.type == EVENT_STUDIO_SAVE ) // save? { - StartDialog(SD_SAVE); + StartDialog(event); + return true; } if ( event.type == EVENT_STUDIO_UNDO ) // undo? @@ -182,13 +186,11 @@ bool CStudio::EventProcess(const Event &event) ViewEditScript(); } - if ( event.type == EVENT_STUDIO_TOOL && // instructions? - m_dialog == SD_NULL ) + if ( event.type == EVENT_STUDIO_TOOL ) // instructions? { m_main->StartDisplayInfo(SATCOM_HUSTON, false); } - if ( event.type == EVENT_STUDIO_HELP && // help? - m_dialog == SD_NULL ) + if ( event.type == EVENT_STUDIO_HELP ) // help? { m_main->StartDisplayInfo(SATCOM_PROG, false); } @@ -976,6 +978,132 @@ void CStudio::SetInfoText(std::string text, bool bClickable) } } +// Beginning of the display of a dialogue. + +void CStudio::StartDialog(const Event &event) +{ + if ( event.type == EVENT_STUDIO_OPEN ) + { + m_fileDialog = MakeUnique(); + m_fileDialog->SetDialogType(CFileDialog::Type::Open); + } + if ( event.type == EVENT_STUDIO_SAVE ) + { + m_fileDialog = MakeUnique(); + m_fileDialog->SetDialogType(CFileDialog::Type::Save); + } + + if (m_fileDialog != nullptr) // a dialog was created? + { + m_main->SetSatComLock(true); // impossible to use the SatCom + + m_fileDialog->SetWindowEvent(EVENT_WINDOW9); + m_fileDialog->SetWindowPos(m_dialogPos); + m_fileDialog->SetWindowDim(m_dialogDim); + + m_fileDialog->SetAutoExtension(".cbot"); + m_fileDialog->AddOptionalExtension(".txt"); + + m_fileDialog->SetUsePublicPrivate(true); + m_fileDialog->SetPublic(m_settings->GetIOPublic()); + m_fileDialog->SetPublicFolder("program"); + m_fileDialog->SetPrivateFolder(m_main->GetPlayerProfile()->GetSaveFile("program")); + + if ( event.type == EVENT_STUDIO_SAVE ) + { + m_fileDialog->SetConfirmOverwrite(true); + + // filename in CScript may include sub-folder + std::string filename = m_script->GetFilename(); + if (!filename.empty()) + { + size_t pos = filename.find_last_of("/"); + if (pos != std::string::npos) // split subfolder from filename + { + m_fileDialog->SetSubFolderPath(filename.substr(0, pos)); + filename = filename.substr(pos+1, filename.length()-pos-1); + } + } + m_fileDialog->SetFilename(filename); + } + + m_fileDialog->StartDialog(); + } +} + +// End of the display of a dialogue. + +void CStudio::StopDialog() +{ + if (m_fileDialog != nullptr) // a dialog exists? + { + m_settings->SetIOPublic(m_fileDialog->GetPublic()); + m_dialogPos = m_fileDialog->GetWindowPos(); + m_dialogDim = m_fileDialog->GetWindowDim(); + m_fileDialog->StopDialog(); + m_fileDialog.reset(); + } + + m_main->SetSatComLock(false); // possible to use the SatCom +} + +// Management of events for a dialogue. + +bool CStudio::EventDialog(const Event &event) +{ + if (m_fileDialog != nullptr) // a dialog exists? + { + if ( event.type == EVENT_DIALOG_STOP ) + { + StopDialog(); + return true; + } + + if (event.type == EVENT_DIALOG_ACTION) // operation complete ? + { + CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); + if ( pw == nullptr ) return false; + CEdit* pe = static_cast< CEdit* >(pw->SearchControl(EVENT_STUDIO_EDIT)); + if ( pe == nullptr ) return false; + + std::string path = m_fileDialog->GetBasePath() + "/"; // public/private folder + std::string subpath = m_fileDialog->GetSubFolderPath();// sub-folder + + // filename in CScript may include sub-folder + std::string filename = subpath.empty() ? "" : subpath + "/"; + filename += m_fileDialog->GetFilename(); + CFileDialog::Type type = m_fileDialog->GetDialogType(); + + if ( type == CFileDialog::Type::Save ) + { + if (!pe->WriteText(path + filename)) + { + m_sound->Play(SOUND_TZOING); + return true; + } + if ( !m_program->readOnly ) + m_script->SetFilename(filename); + } + else if ( type == CFileDialog::Type::Open ) + { + if (!pe->ReadText(path + filename)) + { + m_sound->Play(SOUND_TZOING); + return true; + } + m_script->SetFilename(filename); + ColorizeScript(pe); + } + + StopDialog(); + return true; + } + + return m_fileDialog->EventProcess(event); + } + + return true; +} // Changing the size of a editing program. @@ -1097,614 +1225,4 @@ void CStudio::UpdateButtons() button->SetState(STATE_ENABLE, !m_program->readOnly); } - -// Beginning of the display of a dialogue. - -void CStudio::StartDialog(StudioDialog type) -{ - CWindow* pw; - CButton* pb; - CCheck* pc; - CLabel* pla; - CList* pli; - CEdit* pe; - Math::Point pos, dim; - std::string name; - - m_dialog = type; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW1)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW4)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - //pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW6)); - //if ( pw != nullptr ) pw->ClearState(STATE_VISIBLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW7)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW8)); - if ( pw != nullptr ) pw->ClearState(STATE_ENABLE); - - if ( m_dialog == SD_OPEN || - m_dialog == SD_SAVE ) - { - pos = m_settings->GetIOPos(); - dim = m_settings->GetIODim(); - } -//? pw = m_interface->CreateWindows(pos, dim, 8, EVENT_WINDOW9); - pw = m_interface->CreateWindows(pos, dim, m_dialog==SD_OPEN?14:13, EVENT_WINDOW9); - pw->SetState(STATE_SHADOW); - pw->SetMovable(true); - pw->SetClosable(true); - pw->SetMinDim(Math::Point(320.0f/640.0f, (121.0f+18.0f*4)/480.0f)); - if ( m_dialog == SD_OPEN ) GetResource(RES_TEXT, RT_IO_OPEN, name); - if ( m_dialog == SD_SAVE ) GetResource(RES_TEXT, RT_IO_SAVE, name); - pw->SetName(name); - - pos = Math::Point(0.0f, 0.0f); - dim = Math::Point(0.0f, 0.0f); - - if ( m_dialog == SD_OPEN || - m_dialog == SD_SAVE ) - { - GetResource(RES_TEXT, RT_IO_LIST, name); - pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL1, name); - pla->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); - - pli = pw->CreateList(pos, dim, 0, EVENT_DIALOG_LIST); - pli->SetState(STATE_SHADOW); - - GetResource(RES_TEXT, RT_IO_NAME, name); - pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL2, name); - pla->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); - - pe = pw->CreateEdit(pos, dim, 0, EVENT_DIALOG_EDIT); - pe->SetState(STATE_SHADOW); - - GetResource(RES_TEXT, RT_IO_DIR, name); - pla = pw->CreateLabel(pos, dim, 0, EVENT_DIALOG_LABEL3, name); - pla->SetTextAlign(Gfx::TEXT_ALIGN_LEFT); - - pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK1); - GetResource(RES_TEXT, RT_IO_PRIVATE, name); - pc->SetName(name); - pc->SetState(STATE_SHADOW); - - pc = pw->CreateCheck(pos, dim, 0, EVENT_DIALOG_CHECK2); - GetResource(RES_TEXT, RT_IO_PUBLIC, name); - pc->SetName(name); - pc->SetState(STATE_SHADOW); - - pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_OK); - pb->SetState(STATE_SHADOW); - if ( m_dialog == SD_OPEN ) GetResource(RES_TEXT, RT_IO_OPEN, name); - if ( m_dialog == SD_SAVE ) GetResource(RES_TEXT, RT_IO_SAVE, name); - pb->SetName(name); - - pb = pw->CreateButton(pos, dim, -1, EVENT_DIALOG_CANCEL); - pb->SetState(STATE_SHADOW); - GetResource(RES_EVENT, EVENT_DIALOG_CANCEL, name); - pb->SetName(name); - - AdjustDialog(); - UpdateDialogList(); - UpdateDialogPublic(); - UpdateDialogAction(); - - if ( m_dialog == SD_SAVE ) - { - SetFilenameField(pe, m_script->GetFilename()); - UpdateChangeEdit(); - } - - pe->SetCursor(999, 0); // selects all - m_interface->SetFocus(pe); - } - - m_main->SetSatComLock(true); // impossible to use the SatCom -} - -// End of the display of a dialogue. - -void CStudio::StopDialog() -{ - CWindow* pw; - - if ( m_dialog == SD_NULL ) return; - m_dialog = SD_NULL; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW1)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW2)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW4)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW5)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - //pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW6)); - //if ( pw != nullptr ) pw->SetState(STATE_VISIBLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW7)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW8)); - if ( pw != nullptr ) pw->SetState(STATE_ENABLE); - - m_interface->DeleteControl(EVENT_WINDOW9); - m_main->SetSatComLock(false); // possible to use the SatCom -} - -// Adjust all controls of dialogue after a change in geometry. - -void CStudio::AdjustDialog() -{ - CWindow* pw; - CButton* pb; - CCheck* pc; - CLabel* pla; - CList* pli; - CEdit* pe; - Math::Point wpos, wdim, ppos, ddim; - int nli, nch; - std::string name; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return; - - m_dialogPos = wpos = pw->GetPos(); - m_dialogDim = wdim = pw->GetDim(); - pw->SetPos(wpos); // to move the buttons on the titlebar - - if ( m_dialog == SD_OPEN || - m_dialog == SD_SAVE ) - { - ppos.x = wpos.x+10.0f/640.0f; - ppos.y = wpos.y+wdim.y-55.0f/480.0f; - ddim.x = wdim.x-20.0f/640.0f; - ddim.y = 20.0f/480.0f; - pla = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL1)); - if ( pla != nullptr ) - { - pla->SetPos(ppos); - pla->SetDim(ddim); - } - - nli = static_cast((wdim.y-120.0f/480.0f)/(18.0f/480.0f)); - ddim.y = nli*18.0f/480.0f+9.0f/480.0f; - ppos.y = wpos.y+wdim.y-48.0f/480.0f-ddim.y; - pli = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); - if ( pli != nullptr ) - { - pli->SetPos(ppos); - pli->SetDim(ddim); - pli->SetTabs(0, ddim.x-(50.0f+140.0f+16.0f)/640.0f); - pli->SetTabs(1, 50.0f/640.0f, Gfx::TEXT_ALIGN_RIGHT); - pli->SetTabs(2, 140.0f/640.0f); -//? pli->ShowSelect(); - } - - ppos.y = wpos.y+30.0f/480.0f; - ddim.x = 50.0f/640.0f; - ddim.y = 20.0f/480.0f; - pla = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL2)); - if ( pla != nullptr ) - { - pla->SetPos(ppos); - pla->SetDim(ddim); - } - - ppos.x += 50.0f/640.0f; - ppos.y = wpos.y+36.0f/480.0f; - ddim.x = wdim.x-170.0f/640.0f; - pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); - if ( pe != nullptr ) - { - pe->SetPos(ppos); - pe->SetDim(ddim); - - nch = static_cast< int >((ddim.x*640.0f-22.0f)/5.75f); - name = pe->GetText(nch); // truncates the text according to max - pe->SetMaxChar(nch); - pe->SetText(name); - } - - ppos.x = wpos.x+10.0f/640.0f; - ppos.y = wpos.y+5.0f/480.0f; - ddim.x = 50.0f/640.0f; - ddim.y = 16.0f/480.0f; - pla = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL3)); - if ( pla != nullptr ) - { - pla->SetPos(ppos); - pla->SetDim(ddim); - } - - ppos.x += 50.0f/640.0f; - ppos.y = wpos.y+12.0f/480.0f; - ddim.x = 70.0f/640.0f; - pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK1)); - if ( pc != nullptr ) - { - pc->SetPos(ppos); - pc->SetDim(ddim); - } - - ppos.x += 80.0f/640.0f; - pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK2)); - if ( pc != nullptr ) - { - pc->SetPos(ppos); - pc->SetDim(ddim); - } - - ppos.x = wpos.x+wdim.x-100.0f/640.0f; - ppos.y = wpos.y+34.0f/480.0f; - ddim.x = 90.0f/640.0f; - ddim.y = 23.0f/480.0f; - pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); - if ( pb != nullptr ) - { - pb->SetPos(ppos); - pb->SetDim(ddim); - } - - ppos.y -= 26.0f/480.0f; - pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_CANCEL)); - if ( pb != nullptr ) - { - pb->SetPos(ppos); - pb->SetDim(ddim); - } - } -} - -// Management of the event of a dialogue. - -bool CStudio::EventDialog(const Event &event) -{ - if ( event.type == EVENT_WINDOW9 ) // window is moved? - { - AdjustDialog(); - return true; - } - - if ( m_dialog == SD_OPEN || - m_dialog == SD_SAVE ) - { - if ( event.type == EVENT_DIALOG_LIST ) - { - UpdateChangeList(); - } - if ( event.type == EVENT_DIALOG_EDIT ) - { - UpdateChangeEdit(); - } - - if ( event.type == EVENT_DIALOG_CHECK1 ) // private? - { - m_settings->SetIOPublic(false); - UpdateDialogPublic(); - UpdateDialogList(); - } - if ( event.type == EVENT_DIALOG_CHECK2 ) // public? - { - m_settings->SetIOPublic(true); - UpdateDialogPublic(); - UpdateDialogList(); - } - } - - if ( event.type == EVENT_DIALOG_OK || - (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(RETURN)) ) - { - if ( m_dialog == SD_OPEN ) - { - if ( !ReadProgram() ) return true; - } - if ( m_dialog == SD_SAVE ) - { - if ( !WriteProgram() ) return true; - } - - StopDialog(); - return true; - } - - CWindow* pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return false; - - if ( event.type == EVENT_DIALOG_CANCEL || - (event.type == EVENT_KEY_DOWN && event.GetData()->key == KEY(ESCAPE)) || - event.type == pw->GetEventTypeClose() ) - { - StopDialog(); - return true; - } - - return true; -} - -// Updates the name after a click in the list. - -void CStudio::UpdateChangeList() -{ - CWindow* pw; - CList* pl; - CEdit* pe; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return; - pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); - if ( pl == nullptr ) return; - pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); - if ( pe == nullptr ) return; - - std::string name = pl->GetItemName(pl->GetSelect()); - name = name.substr(0, name.find_first_of("\t")); - SetFilenameField(pe, name); - pe->SetCursor(999, 0); // selects all - m_interface->SetFocus(pe); - - UpdateDialogAction(); -} - -void CStudio::SetFilenameField(CEdit* edit, const std::string& filename) -{ - std::string name = filename; - if (name.length() > static_cast(edit->GetMaxChar())) - { - if (name.substr(name.length()-4) == ".txt") - name = name.substr(0, name.length()-4); - if (name.length() > static_cast(edit->GetMaxChar())) - { - GetLogger()->Warn("Tried to load too long filename!\n"); - name = name.substr(0, edit->GetMaxChar()); // truncates according to max length - } - } - edit->SetText(name); -} - -// Updates the list after a change in name. - -void CStudio::UpdateChangeEdit() -{ - CWindow* pw; - CList* pl; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return; - pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); - if ( pl == nullptr ) return; - - pl->SetSelect(-1); - - UpdateDialogAction(); -} - -// Updates the action button. - -void CStudio::UpdateDialogAction() -{ - CWindow* pw; - CEdit* pe; - CButton* pb; - std::string name; - int len, i; - bool bError; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return; - pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); - if ( pe == nullptr ) return; - pb = static_cast< CButton* >(pw->SearchControl(EVENT_DIALOG_OK)); - if ( pb == nullptr ) return; - - name = pe->GetText(100); - len = name.size(); - if ( len == 0 ) - { - bError = true; - } - else - { - bError = false; - for ( i=0 ; i' || - name[i] == '"' || - name[i] == '|' || - name[i] == '/' || - name[i] == '\\' ) bError = true; - } - } - - pb->SetState(STATE_ENABLE, !bError); -} - -// Updates the buttons private/public. - -void CStudio::UpdateDialogPublic() -{ - CWindow* pw; - CCheck* pc; - CLabel* pl; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return; - - pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK1)); - if ( pc != nullptr ) - { - pc->SetState(STATE_CHECK, !m_settings->GetIOPublic()); - } - - pc = static_cast< CCheck* >(pw->SearchControl(EVENT_DIALOG_CHECK2)); - if ( pc != nullptr ) - { - pc->SetState(STATE_CHECK, m_settings->GetIOPublic()); - } - - pl = static_cast< CLabel* >(pw->SearchControl(EVENT_DIALOG_LABEL1)); - if ( pl != nullptr ) - { - // GetResource(RES_TEXT, RT_IO_LIST, name); // TODO: unused? - pl->SetName(SearchDirectory(false), false); - } -} - -// Fills the list with all programs saved. - -void CStudio::UpdateDialogList() -{ - CWindow* pw; - CList* pl; - int i = 0; - char timestr[100]; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return; - pl = static_cast< CList* >(pw->SearchControl(EVENT_DIALOG_LIST)); - if ( pl == nullptr ) return; - pl->Flush(); - - if (!CResourceManager::DirectoryExists(SearchDirectory(false))) - return; - - std::vector programs = CResourceManager::ListFiles(SearchDirectory(false)); - for (auto& prog : programs) - { - std::ostringstream temp; - time_t now = CResourceManager::GetLastModificationTime(SearchDirectory(false) + prog); - strftime(timestr, 99, "%x %X", localtime(&now)); - temp << prog << '\t' << CResourceManager::GetFileSize(SearchDirectory(false) + prog) << " \t" << timestr; - pl->SetItemName(i++, temp.str().c_str()); - } -} - -// Constructs the name of the folder or open/save. -// If the folder does not exist, it will be created. -std::string CStudio::SearchDirectory(bool bCreate) -{ - std::string dir; - if ( m_settings->GetIOPublic() ) - { - dir = "program"; - } - else - { - dir = m_main->GetPlayerProfile()->GetSaveFile("program"); - } - - if ( bCreate ) - { - if (!CResourceManager::DirectoryExists(dir)) - CResourceManager::CreateDirectory(dir); - } - return dir+"/"; -} - -// Reads a new program. - -bool CStudio::ReadProgram() -{ - CWindow* pw; - CEdit* pe; - std::string filename; - std::string dir; - size_t p; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return false; - - pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); - if ( pe == nullptr ) return false; - filename = pe->GetText(100); - if ( filename.empty() ) return false; - - p = filename.find(".txt"); - if ( p == std::string::npos ) - { - filename += ".txt"; - } - dir = SearchDirectory(true); - dir += filename; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); - if ( pw == nullptr ) return false; - pe = static_cast< CEdit* >(pw->SearchControl(EVENT_STUDIO_EDIT)); - if ( pe == nullptr ) return false; - - if ( !pe->ReadText(dir) ) return false; - - m_script->SetFilename(filename); - ColorizeScript(pe); - return true; -} - -// Writes the current program. - -bool CStudio::WriteProgram() -{ - CWindow* pw; - CEdit* pe; - std::string filename; - std::string dir; - size_t p; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW9)); - if ( pw == nullptr ) return false; - - pe = static_cast< CEdit* >(pw->SearchControl(EVENT_DIALOG_EDIT)); - if ( pe == nullptr ) return false; - filename = pe->GetText(100); - if ( filename.empty() ) return false; - - p = filename.find(".txt"); - if ( p == std::string::npos ) - { - filename += ".txt"; - } - dir = SearchDirectory(true); - dir += filename; - - pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW3)); - if ( pw == nullptr ) return false; - pe = static_cast< CEdit* >(pw->SearchControl(EVENT_STUDIO_EDIT)); - if ( pe == nullptr ) return false; - - if ( !pe->WriteText(dir) ) return false; - - m_script->SetFilename(filename); - return true; -} - -} +} // namespace Ui diff --git a/src/ui/studio.h b/src/ui/studio.h index be898d4e..5e7ad0c5 100644 --- a/src/ui/studio.h +++ b/src/ui/studio.h @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -37,16 +37,7 @@ namespace Ui class CEdit; class CInterface; - -enum StudioDialog -{ - SD_NULL, - SD_OPEN, - SD_SAVE, - SD_FIND, - SD_REPLACE, -}; - +class CFileDialog; class CStudio @@ -71,20 +62,9 @@ protected: void UpdateFlux(); void UpdateButtons(); - void StartDialog(StudioDialog type); + void StartDialog(const Event &event); void StopDialog(); - void AdjustDialog(); bool EventDialog(const Event &event); - void UpdateChangeList(); - void UpdateChangeEdit(); - void UpdateDialogAction(); - void UpdateDialogPublic(); - void UpdateDialogList(); - std::string SearchDirectory(bool bCreate); - bool ReadProgram(); - bool WriteProgram(); - - void SetFilenameField(CEdit* edit, const std::string& filename); protected: Gfx::CEngine* m_engine; @@ -121,7 +101,7 @@ protected: ActivePause* m_runningPause = nullptr; std::string m_helpFilename; - StudioDialog m_dialog; + std::unique_ptr m_fileDialog; }; diff --git a/test/cbot/compile_graph.cpp b/test/cbot/compile_graph.cpp index 0232ad2c..a99526e9 100644 --- a/test/cbot/compile_graph.cpp +++ b/test/cbot/compile_graph.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/cbot/console.cpp b/test/cbot/console.cpp index f00bdbf8..40a28d88 100644 --- a/test/cbot/console.cpp +++ b/test/cbot/console.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/CBot/CBotToken_test.cpp b/test/unit/CBot/CBotToken_test.cpp index 613d7b84..5afe026a 100644 --- a/test/unit/CBot/CBotToken_test.cpp +++ b/test/unit/CBot/CBotToken_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/CBot/CBot_test.cpp b/test/unit/CBot/CBot_test.cpp index cc3261b8..1e4aac06 100644 --- a/test/unit/CBot/CBot_test.cpp +++ b/test/unit/CBot/CBot_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -22,6 +22,9 @@ #include #include +extern bool g_cbotTestSaveState; +bool g_cbotTestSaveState = false; + using namespace CBot; class CBotUT : public testing::Test @@ -197,6 +200,23 @@ private: return ss.str(); } + static void TestSaveAndRestore(CBotProgram* program) + { + std::stringstream sstr(""); + // save + if (!program->SaveState(sstr)) + throw CBotTestFail("CBotProgram::SaveState Failed"); + + if (!CBotClass::SaveStaticState(sstr)) + throw CBotTestFail("CBotClass::SaveStaticState Failed"); + // restore + if (!program->RestoreState(sstr)) + throw CBotTestFail("CBotProgram::RestoreState Failed"); + + if (!CBotClass::RestoreStaticState(sstr)) + throw CBotTestFail("CBotClass::RestoreStaticState Failed"); + } + protected: std::unique_ptr ExecuteTest(const std::string& code, CBotError expectedError = CBotNoErr) { @@ -231,7 +251,17 @@ protected: try { program->Start(test); - while (!program->Run()); + if (g_cbotTestSaveState) + { + while (!program->Run(nullptr, 0)) // save/restore at each step + { + TestSaveAndRestore(program.get()); + } + } + else + { + while (!program->Run(nullptr, 0)); // execute in step mode + } program->GetError(error, cursor1, cursor2); if (error != expectedRuntimeError) { @@ -575,6 +605,192 @@ TEST_F(CBotUT, VarImplicitCast) ); } +TEST_F(CBotUT, IntegerMathNearLimits_Issue993) +{ + ExecuteTest( + "extern void Test_Issue993() {\n" + " ASSERT(-2147483600 * 1 == -2147483600);\n" + " ASSERT( 2147483600 * 1 == 2147483600);\n" + " ASSERT( 2147483646 * 1 == 2147483646);\n" + " ASSERT( 2147483646 * -1 == -2147483646);\n" + " ASSERT( 2147483000 * -1 == -2147483000);\n" + " ASSERT( 2147483000 * 1 == 2147483000);\n" + "}\n" + ); +} + +TEST_F(CBotUT, BinaryLiterals) +{ + ExecuteTest( + "extern void TestBinaryLiterals() {\n" + " ASSERT( 8 == 0b00001000);\n" + " ASSERT( 12 == 0b00001100);\n" + " ASSERT( 16 == 0b00010000);\n" + " ASSERT( 24 == 0b00011000);\n" + " ASSERT( 32 == 0b00100000);\n" + " ASSERT( 48 == 0b00110000);\n" + " ASSERT( 64 == 0b01000000);\n" + " ASSERT( 96 == 0b01100000);\n" + " ASSERT(128 == 0b10000000);\n" + " ASSERT(192 == 0b11000000);\n" + " ASSERT(256 == 0b100000000);\n" + " ASSERT(384 == 0b110000000);\n" + " ASSERT(512 == 0b1000000000);\n" + "}\n" + ); +} + +TEST_F(CBotUT, TestSwitchCase) +{ + ExecuteTest( + "extern void Test_Switch_Case() {\n" + " int n = 0, c = 0;\n" + " for (int i = -9; i < 11; ++i) {\n" + " switch (i) {\n" + " case -9: n = -9; ++c; break;\n" + " case -8: n = -8; ++c; break;\n" + " case -7: n = -7; ++c; break;\n" + " case -6: n = -6; ++c; break;\n" + " case -5: n = -5; ++c; break;\n" + " case -4: n = -4; ++c; break;\n" + " case -3: n = -3; ++c; break;\n" + " case -2: n = -2; ++c; break;\n" + " case -1: n = -1; ++c; break;\n" + " case 0: n = 0; ++c; break;\n" + " case 1: n = 1; ++c; break;\n" + " case 2: n = 2; ++c; break;\n" + " case 3: n = 3; ++c; break;\n" + " case 4: n = 4; ++c; break;\n" + " case 5: n = 5; ++c; break;\n" + " case 6: n = 6; ++c; break;\n" + " case 7: n = 7; ++c; break;\n" + " case 8: n = 8; ++c; break;\n" + " case 9: n = 9; ++c; break;\n" + " default: n = 10; ++c; break;\n" + " }\n" + " ASSERT(n == i);\n" + " }\n" + " ASSERT(n == 10);\n" + " ASSERT(c == 20);\n" + "}\n" + "extern void Test_Case_With_Math() {\n" + " int n = 0, c = 0;\n" + " for (int i = -9; i < 11; ++i) {\n" + " switch (i * 10) {\n" + " case -9*10: n = -90; ++c; break;\n" + " case -8*10: n = -80; ++c; break;\n" + " case -7*10: n = -70; ++c; break;\n" + " case -6*10: n = -60; ++c; break;\n" + " case -5*10: n = -50; ++c; break;\n" + " case -4*10: n = -40; ++c; break;\n" + " case -3*10: n = -30; ++c; break;\n" + " case -2*10: n = -20; ++c; break;\n" + " case -1*10: n = -10; ++c; break;\n" + " case 0*10: n = 0; ++c; break;\n" + " case 1*10: n = 10; ++c; break;\n" + " case 2*10: n = 20; ++c; break;\n" + " case 3*10: n = 30; ++c; break;\n" + " case 4*10: n = 40; ++c; break;\n" + " case 5*10: n = 50; ++c; break;\n" + " case 6*10: n = 60; ++c; break;\n" + " case 7*10: n = 70; ++c; break;\n" + " case 8*10: n = 80; ++c; break;\n" + " case 9*10: n = 90; ++c; break;\n" + " default: n = 100; ++c; break;\n" + " }\n" + " ASSERT(n == i * 10);\n" + " }\n" + " ASSERT(n == 100);\n" + " ASSERT(c == 20);\n" + "}\n" + ); + + ExecuteTest( + "extern void Duplicate_Case() {\n" + " switch(0) {\n" + " case 1000:\n" + " case 10*100:\n" + " }\n" + "}\n", + CBotErrRedefCase + ); + + ExecuteTest( + "extern void Duplicate_Default() {\n" + " switch(0) {\n" + " default:\n" + " default:\n" + " }\n" + "}\n", + CBotErrRedefCase + ); +} + +TEST_F(CBotUT, TestRepeatInstruction) +{ + ExecuteTest( + "extern void TestRepeat() {\n" + " int c = 0;\n" + " for (int i = 1; i < 11; ++i)\n" + " {\n" + " repeat (i) ++c;\n" + " }\n" + " ASSERT(c == 55);\n" + "}\n" + "extern void TestRepeatBreakAndContinue() {\n" + " int c = 0;\n" + " repeat (10)\n" + " {\n" + " if (++c == 5) break;\n" + " continue;\n" + " FAIL();\n" + " }\n" + " ASSERT(c == 5);\n" + " label:repeat (10)\n" + " {\n" + " if (++c == 10) break label;\n" + " continue label;\n" + " FAIL();\n" + " }\n" + " ASSERT(c == 10);\n" + "}\n" + "extern void NoRepeatNumberLessThanOne() {\n" + " repeat (0) FAIL();\n" + " repeat (-1) FAIL();\n" + " repeat (-2) FAIL();\n" + "}\n" + "extern void EvaluateExpressionOnlyOnce() {\n" + " int c = 0;\n" + " repeat (c + 5) ASSERT(++c < 6);\n" + " ASSERT(c == 5);\n" + "}\n" + ); + ExecuteTest( + "extern void MissingOpenParen() {\n" + " repeat ;\n" + "}\n", + CBotErrOpenPar + ); + ExecuteTest( + "extern void MissingNumber() {\n" + " repeat (;\n" + "}\n", + CBotErrBadNum + ); + ExecuteTest( + "extern void WrongType() {\n" + " repeat (\"not number\");\n" + "}\n", + CBotErrBadType1 + ); + ExecuteTest( + "extern void MissingCloseParen() {\n" + " repeat (2;\n" + "}\n", + CBotErrClosePar + ); +} + TEST_F(CBotUT, ToString) { ExecuteTest( @@ -596,6 +812,48 @@ TEST_F(CBotUT, ToString) "}\n" ); + ExecuteTest( + "extern void ClassToString_2()\n" + "{\n" + " string s = new TestClass;\n" + " ASSERT(s == \"Pointer to TestClass( )\");\n" + "}\n" + "public class TestClass { /* no fields */ }\n" + ); + + ExecuteTest( + "extern void ClassInheritanceToString()\n" + "{\n" + " string s = new SubClass;\n" + " ASSERT(s == \"Pointer to SubClass( c=7, d=8, e=9 ) extends MidClass( b=4, c=5, d=6 ) extends BaseClass( a=1, b=2, c=3 )\");\n" + "}\n" + "public class BaseClass { int a = 1, b = 2, c = 3; }\n" + "public class MidClass extends BaseClass { int b = 4, c = 5, d = 6; }\n" + "public class SubClass extends MidClass { int c = 7, d = 8, e = 9; }\n" + ); + + ExecuteTest( + "extern void ClassInheritanceToString_2()\n" + "{\n" + " string s = new SubClass;\n" + " ASSERT(s == \"Pointer to SubClass( c=7, d=8, e=9 ) extends MidClass( ) extends BaseClass( a=1, b=2, c=3 )\");\n" + "}\n" + "public class BaseClass { int a = 1, b = 2, c = 3; }\n" + "public class MidClass extends BaseClass { /* no fields */ }\n" + "public class SubClass extends MidClass { int c = 7, d = 8, e = 9; }\n" + ); + + ExecuteTest( + "extern void ClassInheritanceToString_3()\n" + "{\n" + " string s = new SubClass;\n" + " ASSERT(s == \"Pointer to SubClass( c=7, d=8, e=9 ) extends MidClass( ) extends BaseClass( )\");\n" + "}\n" + "public class BaseClass { /* no fields */ }\n" + "public class MidClass extends BaseClass { /* no fields */ }\n" + "public class SubClass extends MidClass { int c = 7, d = 8, e = 9; }\n" + ); + // TODO: IntrinsicClassToString ? (e.g. point) } @@ -1708,6 +1966,107 @@ TEST_F(CBotUT, StringFunctions) ); } +TEST_F(CBotUT, LiteralCharacters) +{ + ExecuteTest( + "extern void TestCharValue()\n" + "{\n" + " ASSERT('A' == 65);\n" + " ASSERT('B' == 66);\n" + " ASSERT('C' == 67);\n" + " ASSERT('\\a' == 0x07);\n" + " ASSERT('\\b' == 0x08);\n" + " ASSERT('\\t' == 0x09);\n" + " ASSERT('\\n' == 0x0A);\n" + " ASSERT('\\v' == 0x0B);\n" + " ASSERT('\\f' == 0x0C);\n" + " ASSERT('\\r' == 0x0D);\n" + " ASSERT('\\\"' == 0x22);\n" + " ASSERT('\\\'' == 0x27);\n" + " ASSERT('\\\\' == 0x5C);\n" + "}\n" + "extern void TestCharUnicodeEscape()\n" + "{\n" + " ASSERT('\\u0007' == '\\a');\n" + " ASSERT('\\u0008' == '\\b');\n" + " ASSERT('\\u0009' == '\\t');\n" + " ASSERT('\\u000A' == '\\n');\n" + " ASSERT('\\u000B' == '\\v');\n" + " ASSERT('\\u000C' == '\\f');\n" + " ASSERT('\\u000D' == '\\r');\n" + " ASSERT('\\u0022' == '\\\"');\n" + " ASSERT('\\u0027' == '\\\'');\n" + " ASSERT('\\u005C' == '\\\\');\n" + "}\n" + "extern void AssignCharToString_ToUTF_8()\n" + "{\n" + " string test = '\\u00A9';\n" + " test += '\\u00AE';\n" + " ASSERT(test == \"\\xC2\\xA9\\xC2\\xAE\");\n" + "}\n" + "extern void AddCharToString_ToUTF_8()\n" + "{\n" + " ASSERT(\"\" + 'A' + 'B' + 'C' == \"ABC\");\n" + " ASSERT(\"\" + '\\u00A9' == \"\\xC2\\xA9\");\n" + " ASSERT(\"\" + '\\u00AE' == \"\\xC2\\xAE\");\n" + " ASSERT(\"\" + '\\u262E' == \"\\xE2\\x98\\xAE\");\n" + " ASSERT(\"\" + '\\u262F' == \"\\xE2\\x98\\xAF\");\n" + " ASSERT(\"\" + '\\U0001F60E' == \"\\xF0\\x9F\\x98\\x8E\");\n" + " ASSERT(\"\" + '\\U0001F61C' == \"\\xF0\\x9F\\x98\\x9C\");\n" + " ASSERT(\"\" + '\\U0001F6E0' == \"\\xF0\\x9F\\x9B\\xA0\");\n" + " ASSERT(\"\" + '\\U0010FFFF' == \"\\xF4\\x8F\\xBF\\xBF\");\n" + "}\n" + ); + + ExecuteTest( + "extern void MissingEndQuote()\n" + "{\n" + " '\n" + "}\n", + CBotErrEndQuote + ); + + ExecuteTest( + "extern void MissingEndQuote()\n" + "{\n" + " 'a\n" + "}\n", + CBotErrEndQuote + ); + + ExecuteTest( + "extern void EmptyQuotes()\n" + "{\n" + " '';\n" + "}\n", + CBotErrCharEmpty + ); + + ExecuteTest( + "extern void UnknownEscapeSequence()\n" + "{\n" + " '\\p';\n" + "}\n", + CBotErrBadEscape + ); + + ExecuteTest( + "extern void MissingHexDigits()\n" + "{\n" + " '\\u';\n" + "}\n", + CBotErrHexDigits + ); + + ExecuteTest( + "extern void BadUnicodeCharacterName()\n" + "{\n" + " '\\U00110000';\n" + "}\n", + CBotErrUnicodeName + ); +} + TEST_F(CBotUT, TestNANParam_Issue642) { ExecuteTest( @@ -2516,3 +2875,454 @@ TEST_F(CBotUT, ParametersWithDefaultValues) "}\n" ); } + +TEST_F(CBotUT, ClassMethodsOutOfClass_Issue207) +{ + auto publicProgram = ExecuteTest( + "public class OtherClass {}\n" + "public class TestClass {}\n" + ); + + ExecuteTest( + "extern void TestCallWithoutObject()\n" + "{\n" + " TestMethod();\n" + "}\n" + "public void TestClass::TestMethod() {}\n", + CBotErrUndefCall + ); + + ExecuteTest( + "extern void TestCallWithWrongObject()\n" + "{\n" + " OtherClass oc();\n" + " oc.TestMethod();\n" + "}\n" + "public void TestClass::TestMethod() {}\n", + CBotErrUndefCall + ); + + ExecuteTest( + "extern void OtherClass::TestCallWithWrongThis()\n" + "{\n" + " this.TestMethod();\n" + "}\n" + "public void TestClass::TestMethod() {}\n", + CBotErrUndefCall + ); +} + +TEST_F(CBotUT, ClassMethodsOutOfClass) +{ + auto publicProgram = ExecuteTest( + "public class TestClass\n" + "{\n" + " int i = 123, j = 456, k = 789;\n" + " int InsideClass()\n" + " {\n" + " ASSERT(456 == PublicMethod());\n" + " ASSERT(789 == NotPublicMethod());\n" + " return this.i;\n" + " }\n" + "}\n" + "extern void TestMethodsOutOfClass()\n" + "{\n" + " TestClass tc();\n" + " ASSERT(123 == tc.InsideClass());\n" + " ASSERT(456 == tc.PublicMethod());\n" + " ASSERT(789 == tc.NotPublicMethod());\n" + "}\n" + "public int TestClass::PublicMethod()\n" + "{\n" + " return this.j;\n" + "}\n" + "int TestClass::NotPublicMethod()\n" + "{\n" + " return k;\n" + "}\n" + ); + + ExecuteTest( + "extern void TestFromOtherProgram()\n" + "{\n" + " TestClass tc();\n" + " ASSERT(123 == tc.InsideClass());\n" + " ASSERT(456 == tc.PublicMethod());\n" + " ASSERT(789 == tc.MethodInThisProgram());\n" + "}\n" + "int TestClass::MethodInThisProgram()\n" + "{\n" + " ASSERT(123 == InsideClass());\n" + " ASSERT(456 == PublicMethod());\n" + " ASSERT(123 == this.InsideClass());\n" + " ASSERT(456 == this.PublicMethod());\n" + " ASSERT(i == 123 && this.j == 456);\n" + " return this.k;\n" + "}\n" + ); +} + +TEST_F(CBotUT, ClassInheritanceMethodsOutOfClass) +{ + ExecuteTest( + "public class BaseClass {\n" + " int a = 123;\n" + " int b = 456;\n" + " int c = 789;\n" + "}\n" + "int BaseClass::testOverride() { return 123; }\n" + "int BaseClass::testNoOverride() { return 456; }\n" + "int BaseClass::testInsideBaseClass() {\n" + " ASSERT(a == 123);\n" + " ASSERT(b == 456);\n" + " ASSERT(c == 789);\n" + " ASSERT(456 == testNoOverride());\n" + " return c;\n" + "}\n" + "int BaseClass::testInsideBaseOverride() { return testOverride(); }\n" + "\n" + "public class MidClass extends BaseClass {\n" + " int b = 1011;\n" + " int c = 1213;\n" + " int d = 1415;\n" + "}\n" + "int MidClass::testOverride() { return 1011; }\n" + "int MidClass::testInsideMidClass() {\n" + " ASSERT(a == 123);\n" + " ASSERT(b == 1011);\n" + " ASSERT(c == 1213);\n" + " ASSERT(d == 1415);\n" + " ASSERT(456 == testNoOverride());\n" + " ASSERT(789 == testInsideBaseClass());\n" + " return c;\n" + "}\n" + "int MidClass::testSuper() {\n" + " ASSERT(super.a == 123);\n" + " ASSERT(super.b == 456);\n" + " ASSERT(super.c == 789);\n" + " ASSERT(123 == super.testOverride());\n" + " ASSERT(789 == super.testInsideBaseClass());\n" + " return super.testInsideBaseOverride();\n" + "}\n" + "int MidClass::testInsideMidOverride() { return testOverride(); }\n" + "\n" + "public class SubClass extends MidClass {\n" + " int c = 1617;\n" + " int d = 1819;\n" + " int e = 2021;\n" + "}\n" + "int SubClass::testOverride() { return 1617; }\n" + "int SubClass::testInsideSubClass() {\n" + " ASSERT(a == 123);\n" + " ASSERT(b == 1011);\n" + " ASSERT(c == 1617);\n" + " ASSERT(d == 1819);\n" + " ASSERT(e == 2021);\n" + " ASSERT(456 == testNoOverride());\n" + " ASSERT(789 == testInsideBaseClass());\n" + " ASSERT(1213 == testInsideMidClass());\n" + " return c;\n" + "}\n" + "int SubClass::testSuper() {\n" + " ASSERT(super.a == 123);\n" + " ASSERT(super.b == 1011);\n" + " ASSERT(super.c == 1213);\n" + " ASSERT(super.d == 1415);\n" + " ASSERT(1011 == super.testOverride());\n" + " ASSERT(789 == super.testInsideBaseClass());\n" + " ASSERT(1213 == super.testInsideMidClass());\n" + " return super.testSuper();\n" + "}\n" + "int SubClass::testInsideSubOverride() { return testOverride(); }\n" + "\n" + "extern void InheritanceMethodsOutOfClass()\n" + "{\n" + " BaseClass bc();\n" + " ASSERT(123 == bc.testOverride());\n" + " ASSERT(456 == bc.testNoOverride());\n" + " ASSERT(789 == bc.testInsideBaseClass());\n" + " ASSERT(123 == bc.testInsideBaseOverride());\n" + " MidClass mc();\n" + " ASSERT(1011 == mc.testSuper());\n" + " ASSERT(1011 == mc.testOverride());\n" + " ASSERT(456 == mc.testNoOverride());\n" + " ASSERT(789 == mc.testInsideBaseClass());\n" + " ASSERT(1213 == mc.testInsideMidClass());\n" + " ASSERT(1011 == mc.testInsideBaseOverride());\n" + " ASSERT(1011 == mc.testInsideMidOverride());\n" + " SubClass sc();\n" + " ASSERT(1617 == sc.testSuper());\n" + " ASSERT(1617 == sc.testOverride());\n" + " ASSERT(456 == sc.testNoOverride());\n" + " ASSERT(789 == sc.testInsideBaseClass());\n" + " ASSERT(1213 == sc.testInsideMidClass());\n" + " ASSERT(1617 == sc.testInsideSubClass());\n" + " ASSERT(1617 == sc.testInsideBaseOverride());\n" + " ASSERT(1617 == sc.testInsideMidOverride());\n" + " ASSERT(1617 == sc.testInsideSubOverride());\n" + // Test polymorphism + " bc = mc;\n" + " ASSERT(1011 == bc.testOverride());\n" + " ASSERT(789 == bc.testInsideBaseClass());\n" + " ASSERT(1011 == bc.testInsideBaseOverride());\n" + " bc = sc;\n" + " ASSERT(1617 == bc.testOverride());\n" + " ASSERT(789 == bc.testInsideBaseClass());\n" + " ASSERT(1617 == bc.testInsideBaseOverride());\n" + " mc = sc;\n" + " ASSERT(1617 == mc.testSuper());\n" + " ASSERT(1617 == mc.testOverride());\n" + " ASSERT(789 == mc.testInsideBaseClass());\n" + " ASSERT(1213 == mc.testInsideMidClass());\n" + " ASSERT(1617 == mc.testInsideBaseOverride());\n" + " ASSERT(1617 == mc.testInsideMidOverride());\n" + "}\n" + ); +} + +TEST_F(CBotUT, ClassInheritanceTestThisOutOfClass) +{ + ExecuteTest( + "public class BaseClass {\n" + " int a = 123;\n" + " int b = 456;\n" + " int c = 789;\n" + "}\n" + "void BaseClass::testBaseMembersAndParams(int a, int b, int c) {\n" + " ASSERT(a != 123);\n" + " ASSERT(b != 456);\n" + " ASSERT(c != 789);\n" + " ASSERT(this.a == 123);\n" + " ASSERT(this.b == 456);\n" + " ASSERT(this.c == 789);\n" + "}\n" + "BaseClass BaseClass::testSuperReturnThis(){ return this; }\n" + "BaseClass BaseClass::testReturnThisFromBaseClass() { return this; }\n" + "\n" + "public class MidClass extends BaseClass {\n" + " int b = 1011;\n" + " int c = 1213;\n" + " int d = 1415;\n" + "}\n" + "void MidClass::testMidMembersAndParams(int a, int b, int c, int d) {\n" + " ASSERT(a != 123);\n" + " ASSERT(b != 1011);\n" + " ASSERT(c != 1213);\n" + " ASSERT(d != 1415);\n" + " ASSERT(this.a == 123);\n" + " ASSERT(this.b == 1011);\n" + " ASSERT(this.c == 1213);\n" + " ASSERT(this.d == 1415);\n" + "}\n" + "MidClass MidClass::testSuperReturnThis(){ return super.testSuperReturnThis(); }\n" + "MidClass MidClass::testReturnThisFromMidClass() { return this; }\n" + "\n" + "public class SubClass extends MidClass {\n" + " int c = 1617;\n" + " int d = 1819;\n" + " int e = 2021;\n" + "}\n" + "void SubClass::testSubMembersAndParams(int a, int b, int c, int d, int e) {\n" + " ASSERT(a != 123);\n" + " ASSERT(b != 1011);\n" + " ASSERT(c != 1617);\n" + " ASSERT(d != 1819);\n" + " ASSERT(e != 2021);\n" + " ASSERT(this.a == 123);\n" + " ASSERT(this.b == 1011);\n" + " ASSERT(this.c == 1617);\n" + " ASSERT(this.d == 1819);\n" + " ASSERT(this.e == 2021);\n" + "}\n" + "SubClass SubClass::testSuperReturnThis(){ return super.testSuperReturnThis(); }\n" + "SubClass SubClass::testReturnThisFromSubClass() { return this; }\n" + "\n" + "extern void ClassInheritanceTestThisOutOfClass()\n" + "{\n" + " BaseClass bc();\n" + " MidClass mc();\n" + " SubClass sc();\n" + " ASSERT(bc == bc.testSuperReturnThis());\n" + " ASSERT(bc == bc.testReturnThisFromBaseClass());\n" + " bc.testBaseMembersAndParams(-1, -2, -3);\n" + " ASSERT(mc == mc.testSuperReturnThis());\n" + " ASSERT(mc == mc.testReturnThisFromBaseClass());\n" + " ASSERT(mc == mc.testReturnThisFromMidClass());\n" + " mc.testBaseMembersAndParams(-1, -2, -3);\n" + " mc.testMidMembersAndParams(-1, -2, -3, -4);\n" + " ASSERT(sc == sc.testSuperReturnThis());\n" + " ASSERT(sc == sc.testReturnThisFromBaseClass());\n" + " ASSERT(sc == sc.testReturnThisFromMidClass());\n" + " ASSERT(sc == sc.testReturnThisFromSubClass());\n" + " sc.testBaseMembersAndParams(-1, -2, -3);\n" + " sc.testMidMembersAndParams(-1, -2, -3, -4);\n" + " sc.testSubMembersAndParams(-1, -2, -3, -4, -5);\n" + // Test polymorphism + " bc = mc;\n" + " ASSERT(mc == bc.testSuperReturnThis());\n" + " ASSERT(mc == bc.testReturnThisFromBaseClass());\n" + " bc.testBaseMembersAndParams(-1, -2, -3);\n" + " bc = sc;\n" + " ASSERT(sc == bc.testSuperReturnThis());\n" + " ASSERT(sc == bc.testReturnThisFromBaseClass());\n" + " bc.testBaseMembersAndParams(-1, -2, -3);\n" + " mc = sc;\n" + " ASSERT(sc == mc.testSuperReturnThis());\n" + " ASSERT(sc == mc.testReturnThisFromBaseClass());\n" + " ASSERT(sc == mc.testReturnThisFromMidClass());\n" + " mc.testBaseMembersAndParams(-1, -2, -3);\n" + " mc.testMidMembersAndParams(-1, -2, -3, -4);\n" + "}\n" + ); +} + +TEST_F(CBotUT, ClassTestProtectedMethod) +{ + auto publicProgram = ExecuteTest( + "public class BaseClass {\n" + " protected bool BaseClassProtected() {\n" + " return true;\n" + " }\n" + " bool NoErrorProtectedSameClass() {\n" + " BaseClass b();\n" + " ASSERT(true == b.BaseClassProtected());\n" + " return BaseClassProtected();\n" + " }\n" + "}\n" + "extern void Test() {\n" + " BaseClass b();\n" + " ASSERT(true == b.NoErrorProtectedSameClass());\n" + "}\n" + ); + + ExecuteTest( + "public class SubClass extends BaseClass {\n" + " bool NoErrorProtectedSubClass() {\n" + " ASSERT(true == BaseClassProtected());\n" + " ASSERT(true == this.BaseClassProtected());\n" + " ASSERT(true == super.BaseClassProtected());\n" + " return true;\n" + " }\n" + "}\n" + "extern void TestNoErrorProtected() {\n" + " SubClass s();\n" + " ASSERT(true == s.NoErrorProtectedSubClass());\n" + "}\n" + ); + + ExecuteTest( + "extern void TestErrorProtected_1() {\n" + " BaseClass b();\n" + " b.BaseClassProtected();\n" + "}\n", + CBotErrPrivate + ); + + ExecuteTest( + "public class SubClass extends BaseClass {}\n" + "\n" + "extern void TestErrorProtected_2() {\n" + " SubClass s();\n" + " s.BaseClassProtected();\n" + "}\n", + CBotErrPrivate + ); + + ExecuteTest( + "public class SomeOtherClass {\n" + " void testErrorProtected() {\n" + " BaseClass b();\n" + " b.BaseClassProtected();\n" + " }\n" + "}\n", + CBotErrPrivate + ); +} + +TEST_F(CBotUT, ClassTestPrivateMethod) +{ + auto publicProgram = ExecuteTest( + "public class BaseClass {\n" + " private bool BaseClassPrivate() {\n" + " return true;\n" + " }\n" + " bool NoErrorPrivateSameClass() {\n" + " BaseClass b();\n" + " ASSERT(true == b.BaseClassPrivate());\n" + " return BaseClassPrivate();\n" + " }\n" + "}\n" + "extern void Test() {\n" + " BaseClass b();\n" + " ASSERT(true == b.NoErrorPrivateSameClass());\n" + "}\n" + ); + + ExecuteTest( + "public class SubClass extends BaseClass {\n" + " void ErrorPrivateThis() {\n" + " this.BaseClassPrivate();\n" + " }\n" + "}\n", + CBotErrPrivate + ); + + ExecuteTest( + "public class SubClass extends BaseClass {\n" + " void ErrorPrivateSuper() {\n" + " super.BaseClassPrivate();\n" + " }\n" + "}\n", + CBotErrPrivate + ); + + ExecuteTest( + "extern void TestErrorPrivate_1() {\n" + " BaseClass b();\n" + " b.BaseClassPrivate();\n" + "}\n", + CBotErrPrivate + ); + + ExecuteTest( + "public class SubClass extends BaseClass {}\n" + "\n" + "extern void TestErrorPrivate_2() {\n" + " SubClass s();\n" + " s.BaseClassPrivate();\n" + "}\n", + CBotErrPrivate + ); + + ExecuteTest( + "public class SomeOtherClass {\n" + " void ErrorPrivate() {\n" + " BaseClass b();\n" + " b.BaseClassPrivate();\n" + " }\n" + "}\n", + CBotErrPrivate + ); +} + +TEST_F(CBotUT, ClassTestSaveInheritedMembers) +{ + auto publicProgram = ExecuteTest( + "public class TestClass { int a = 123; }\n" + "public class TestClass2 extends TestClass { int b = 456; }\n" + ); + // Note: Use --CBotUT_TestSaveState command line arg. + ExecuteTest( + "extern void TestSaveInheritedMembers()\n" + "{\n" + " TestClass2 t();\n" + " ASSERT(t.a == 123);\n" + " ASSERT(t.b == 456);\n" + " t.a = 789; t.b = 1011;\n" + " ASSERT(t.a == 789);\n" + " ASSERT(t.b == 1011);\n" + " ASSERT(789 == t.a);\n" + " ASSERT(1011 == t.b);\n" + "}\n" + ); +} diff --git a/test/unit/app/app_test.cpp b/test/unit/app/app_test.cpp index 3ae5334d..aad94e39 100644 --- a/test/unit/app/app_test.cpp +++ b/test/unit/app/app_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -55,9 +55,9 @@ public: SDL_Quit(); } - Event CreateUpdateEvent() override + Event CreateUpdateEvent(SystemTimeStamp *timestamp) override { - return CApplication::CreateUpdateEvent(); + return CApplication::CreateUpdateEvent(timestamp); } }; @@ -157,7 +157,9 @@ void CApplicationUT::TestCreateUpdateEvent(long long relTimeExact, long long abs float relTime, float absTime, long long relTimeReal, long long absTimeReal) { - Event event = m_app->CreateUpdateEvent(); + SystemTimeStamp *now = CreateTimeStamp(); + GetCurrentTimeStamp(now); + Event event = m_app->CreateUpdateEvent(now); EXPECT_EQ(EVENT_FRAME, event.type); EXPECT_FLOAT_EQ(relTime, event.rTime); EXPECT_FLOAT_EQ(relTime, m_app->GetRelTime()); @@ -172,7 +174,11 @@ void CApplicationUT::TestCreateUpdateEvent(long long relTimeExact, long long abs TEST_F(CApplicationUT, UpdateEventTimeCalculation_SimulationSuspended) { m_app->SuspendSimulation(); - Event event = m_app->CreateUpdateEvent(); + + SystemTimeStamp *now = CreateTimeStamp(); + GetCurrentTimeStamp(now); + Event event = m_app->CreateUpdateEvent(now); + EXPECT_EQ(EVENT_NULL, event.type); } @@ -224,7 +230,9 @@ TEST_F(CApplicationUT, UpdateEventTimeCalculation_NegativeTimeOperation) NextInstant(-1111); - Event event = m_app->CreateUpdateEvent(); + SystemTimeStamp *now = CreateTimeStamp(); + GetCurrentTimeStamp(now); + Event event = m_app->CreateUpdateEvent(now); EXPECT_EQ(EVENT_NULL, event.type); } diff --git a/test/unit/common/colobot.ini b/test/unit/common/colobot.ini index c4d21623..7cc649b5 100644 --- a/test/unit/common/colobot.ini +++ b/test/unit/common/colobot.ini @@ -6,3 +6,8 @@ string_value=Hello world [test_int] int_value=42 + +[test_array] +string_array=AAA,Hello world,Gold Edition +int_array=2,3,1 +bool_array=1,0,1 diff --git a/test/unit/common/config_file_test.cpp b/test/unit/common/config_file_test.cpp index 05c26820..762c3307 100644 --- a/test/unit/common/config_file_test.cpp +++ b/test/unit/common/config_file_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -52,3 +52,25 @@ TEST_F(CConfigFileTest, ReadTest) ASSERT_TRUE(m_configFile.GetFloatProperty("test_float", "float_value", float_value)); ASSERT_FLOAT_EQ(1.5, float_value); } + +TEST_F(CConfigFileTest, ReadArrayTest) +{ + m_configFile.SetUseCurrentDirectory(true); + + ASSERT_TRUE(m_configFile.Init()); // load colobot.ini file + + std::vector expected_string_values = { "AAA", "Hello world", "Gold Edition" }; + std::vector string_values; + ASSERT_TRUE(m_configFile.GetArrayProperty("test_array", "string_array", string_values)); + ASSERT_EQ(expected_string_values, string_values); + + std::vector expected_int_values = { 2, 3, 1 }; + std::vector int_values; + ASSERT_TRUE(m_configFile.GetArrayProperty("test_array", "int_array", int_values)); + ASSERT_EQ(expected_int_values, int_values); + + std::vector expected_bool_values = { true, false, true }; + std::vector bool_values; + ASSERT_TRUE(m_configFile.GetArrayProperty("test_array", "bool_array", bool_values)); + ASSERT_EQ(expected_bool_values, bool_values); +} diff --git a/test/unit/common/system/system_linux_test.cpp b/test/unit/common/system/system_linux_test.cpp index a882f016..6a503c18 100644 --- a/test/unit/common/system/system_linux_test.cpp +++ b/test/unit/common/system/system_linux_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/common/system/system_windows_test.cpp b/test/unit/common/system/system_windows_test.cpp index f36e878c..eb959ff0 100644 --- a/test/unit/common/system/system_windows_test.cpp +++ b/test/unit/common/system/system_windows_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/graphics/engine/lightman_test.cpp b/test/unit/graphics/engine/lightman_test.cpp index 6fd160fe..3480ab3f 100644 --- a/test/unit/graphics/engine/lightman_test.cpp +++ b/test/unit/graphics/engine/lightman_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/main.cpp b/test/unit/main.cpp index 91d640de..090cbe33 100644 --- a/test/unit/main.cpp +++ b/test/unit/main.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify @@ -21,11 +21,21 @@ #include +extern bool g_cbotTestSaveState; + int main(int argc, char* argv[]) { CLogger logger; ::testing::InitGoogleTest(&argc, argv); + // parse arguments not removed by InitGoogleTest + for (int i = 1; i < argc; ++i) + { + std::string arg(argv[i]); + if (arg == "--CBotUT_TestSaveState") + g_cbotTestSaveState = true; + } + return RUN_ALL_TESTS(); } diff --git a/test/unit/math/func_test.cpp b/test/unit/math/func_test.cpp index 11ebd7b1..430ebbec 100644 --- a/test/unit/math/func_test.cpp +++ b/test/unit/math/func_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/math/geometry_test.cpp b/test/unit/math/geometry_test.cpp index b811a757..33ec8143 100644 --- a/test/unit/math/geometry_test.cpp +++ b/test/unit/math/geometry_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/math/matrix_test.cpp b/test/unit/math/matrix_test.cpp index b7196b84..929e4de2 100644 --- a/test/unit/math/matrix_test.cpp +++ b/test/unit/math/matrix_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/test/unit/math/vector_test.cpp b/test/unit/math/vector_test.cpp index d9d07604..c18caf6a 100644 --- a/test/unit/math/vector_test.cpp +++ b/test/unit/math/vector_test.cpp @@ -1,6 +1,6 @@ /* * This file is part of the Colobot: Gold Edition source code - * Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam + * Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam * http://epsitec.ch; http://colobot.info; http://github.com/colobot * * This program is free software: you can redistribute it and/or modify diff --git a/tools/blender-scripts.py b/tools/blender-scripts.py index d2273d67..b4104793 100644 --- a/tools/blender-scripts.py +++ b/tools/blender-scripts.py @@ -8,7 +8,7 @@ bl_info = { "name": "Colobot Model Format (.txt)", "author": "TerranovaTeam", - "version": (0, 0, 2), + "version": (0, 0, 3), "blender": (2, 6, 4), "location": "File > Export > Colobot (.txt)", "description": "Export Colobot Model Format (.txt)", @@ -35,7 +35,7 @@ FUZZY_TOLERANCE = 1e-5 class ColobotError(Exception): """Exception in I/O operations""" - def __init__(self, value): + def __init__(self, value, errcode=None): self.value = value def __str__(self): return repr(self.value) @@ -199,7 +199,8 @@ def write_colobot_model(filename, model): file.write('tex1 ' + t.mat.tex1 + '\n') file.write('tex2 ' + t.mat.tex2 + '\n') file.write('var_tex2 ' + ( 'Y' if t.mat.var_tex2 else 'N' + '\n' ) ) - file.write('lod_level ' + str(t.lod_level) + '\n') + if model.version == 1: + file.write('lod_level ' + str(t.lod_level) + '\n') file.write('state ' + str(t.mat.state) + '\n') file.write('\n') @@ -281,8 +282,8 @@ def read_colobot_model(filename): if (tokens[0] != 'version'): raise ColobotError("Invalid header", "version") model.version = int(tokens[1]) - if (model.version != 1): - raise ColobotError("Unknown model file version") + if (model.version != 1 and model.version != 2): + raise ColobotError("Unknown model file version "+str(model.version)) tokens, index = token_next_line(lines, index) if (tokens[0] != 'total_triangles'): @@ -329,10 +330,13 @@ def read_colobot_model(filename): raise ColobotError("Invalid triangle", "var_tex2") t.mat.var_tex2 = tokens[1] == 'Y' - tokens, index = token_next_line(lines, index) - if (tokens[0] != 'lod_level'): - raise ColobotError("Invalid triangle", "lod_level") - t.lod_level = int(tokens[1]) + if (model.version == 1): + tokens, index = token_next_line(lines, index) + if (tokens[0] != 'lod_level'): + raise ColobotError("Invalid triangle", "lod_level") + t.lod_level = int(tokens[1]) + else: + t.lod_level = 0 # constant tokens, index = token_next_line(lines, index) if (tokens[0] != 'state'): @@ -384,9 +388,9 @@ def append_obj_to_colobot_model(obj, model, scene, defaults): t.mat.specular[3] = mat.specular_alpha if (mat.texture_slots[0] != None): - t.tex1 = bpy.path.basename(mat.texture_slots[0].texture.image.filepath) + t.mat.tex1 = bpy.path.basename(mat.texture_slots[0].texture.image.filepath) if (mat.texture_slots[1] != None): - t.tex2 = bpy.path.basename(mat.texture_slots[1].texture.image.filepath) + t.mat.tex2 = bpy.path.basename(mat.texture_slots[1].texture.image.filepath) t.var_tex2 = mat.get('var_tex2', defaults['var_tex2']) t.state = mat.get('state', defaults['state']) @@ -589,7 +593,7 @@ class ExportColobotDialog(bpy.types.Operator): write_colobot_model(EXPORT_FILEPATH, model) except ColobotError as e: - self.report({'ERROR'}, e.args.join(": ")) + self.report({'ERROR'}, ": ".join(e.args)) return {'FINISHED'} self.report({'INFO'}, 'Export OK') @@ -665,7 +669,7 @@ class ImportColobotDialog(bpy.types.Operator): obj.layers = layers except ColobotError as e: - self.report({'ERROR'}, e.args.join(": ")) + self.report({'ERROR'}, ": ".join(e.args)) return {'FINISHED'} self.report({'INFO'}, 'Import OK')