Merge branch 'dev' into dev-modern
commit
5e37f84bc7
|
@ -9,7 +9,7 @@ jobs:
|
|||
strategy:
|
||||
matrix:
|
||||
target_os: [linux]
|
||||
host_os: [ubuntu-16.04, ubuntu-18.04, ubuntu-20.04]
|
||||
host_os: [ubuntu-18.04, ubuntu-20.04]
|
||||
container: ['']
|
||||
include:
|
||||
- target_os: windows
|
||||
|
|
|
@ -1,207 +0,0 @@
|
|||
name: Linter
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
# it's easiest if it matches the version that was used to build colobot-lint, newer versions don't have llvm-3.6-dev in repo...
|
||||
runs-on: ubuntu-16.04
|
||||
env:
|
||||
CC: /usr/lib/llvm-3.6/bin/clang
|
||||
CXX: /usr/lib/llvm-3.6/bin/clang++
|
||||
CLANG_PREFIX: /usr/lib/llvm-3.6
|
||||
steps:
|
||||
- name: Download 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
|
||||
# TODO: migrate colobot-lint to GitHub Actions
|
||||
- name: Download colobot-lint
|
||||
run: |
|
||||
sudo apt-get install -y --no-install-recommends clang-3.6 libtinyxml2.6.2v5
|
||||
mkdir -p /tmp/colobot-lint
|
||||
cd /tmp/colobot-lint
|
||||
wget -O colobot-lint.zip "https://compiled.colobot.info/job/colobot/job/colobot-lint/job/dev/lastSuccessfulBuild/artifact/*zip*/archive.zip"
|
||||
|
||||
# Unzip the archive
|
||||
unzip ./colobot-lint.zip
|
||||
# Workaround for Clang not finding system headers
|
||||
mkdir ./bin
|
||||
mv ./archive/build/colobot-lint ./bin/
|
||||
chmod +x ./bin/colobot-lint
|
||||
ln -s ${CLANG_PREFIX}/lib ./lib
|
||||
# Unpack HtmlReport
|
||||
tar -zxf ./archive/build/html_report.tar.gz
|
||||
# Clean up
|
||||
rm -r ./archive
|
||||
- uses: actions/checkout@v2
|
||||
- name: Checkout the Google Test submodule
|
||||
run: git submodule update --init -- lib/googletest
|
||||
- name: Create build directory
|
||||
run: cmake -E make_directory build
|
||||
- name: Run CMake
|
||||
working-directory: build
|
||||
run: cmake -DCOLOBOT_LINT_BUILD=1 -DTESTS=1 -DTOOLS=1 -DCMAKE_EXPORT_COMPILE_COMMANDS=1 ..
|
||||
- name: Run linter
|
||||
shell: bash
|
||||
run: |
|
||||
set -e +x
|
||||
WORKSPACE="$GITHUB_WORKSPACE"
|
||||
COLOBOT_DIR="$WORKSPACE"
|
||||
COLOBOT_BUILD_DIR="$WORKSPACE/build"
|
||||
COLOBOT_LINT_REPORT_FILE="$WORKSPACE/build/colobot_lint_report.xml"
|
||||
|
||||
cd "/tmp/colobot-lint"
|
||||
find "$WORKSPACE" \( -wholename "$COLOBOT_DIR/src/*.cpp" \
|
||||
-or -wholename "$COLOBOT_DIR/test/unit/*.cpp" \
|
||||
-or -wholename "$COLOBOT_BUILD_DIR/fake_header_sources/src/*.cpp" \
|
||||
-or -wholename "$COLOBOT_BUILD_DIR/fake_header_sources/test/unit/*.cpp" \) \
|
||||
-exec ./bin/colobot-lint \
|
||||
-verbose \
|
||||
-output-format xml \
|
||||
-output-file "$COLOBOT_LINT_REPORT_FILE" \
|
||||
-p "$COLOBOT_BUILD_DIR" \
|
||||
-project-local-include-path "$COLOBOT_DIR/src" -project-local-include-path "$COLOBOT_BUILD_DIR/src" \
|
||||
-license-template-file "$COLOBOT_DIR/LICENSE-HEADER.txt" \
|
||||
{} +
|
||||
- name: Upload results (XML)
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: XML results
|
||||
path: build/colobot_lint_report.xml
|
||||
- name: Generate HTML report
|
||||
shell: bash
|
||||
run: /tmp/colobot-lint/HtmlReport/generate.py --xml-report "build/colobot_lint_report.xml" --output-dir "build/html_report"
|
||||
- name: Upload results (HTML)
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: HTML results
|
||||
path: build/html_report
|
||||
- run: pip install requests
|
||||
- name: Send linter results to GitHub
|
||||
shell: python
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
import os
|
||||
import sys
|
||||
import requests
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
OVERALL_STABLE_RULES=[
|
||||
"class naming",
|
||||
"code block placement",
|
||||
"compile error",
|
||||
# "compile warning",
|
||||
# "enum naming",
|
||||
# "function naming",
|
||||
"header file not self-contained",
|
||||
# "implicit bool cast",
|
||||
# "include style",
|
||||
# "inconsistent declaration parameter name",
|
||||
"license header",
|
||||
# "naked delete",
|
||||
# "naked new",
|
||||
# "old style function",
|
||||
"old-style null pointer",
|
||||
# "possible forward declaration",
|
||||
"undefined function",
|
||||
# "uninitialized field",
|
||||
# "uninitialized local variable",
|
||||
# "unused forward declaration",
|
||||
# "variable naming",
|
||||
"whitespace",
|
||||
]
|
||||
|
||||
STABLE_RULES_WITHOUT_CBOT=[
|
||||
"class naming",
|
||||
"code block placement",
|
||||
"compile error",
|
||||
"compile warning",
|
||||
# "enum naming",
|
||||
# "function naming",
|
||||
"header file not self-contained",
|
||||
# "implicit bool cast",
|
||||
"include style",
|
||||
"inconsistent declaration parameter name",
|
||||
"license header",
|
||||
"naked delete",
|
||||
"naked new",
|
||||
# "old style function",
|
||||
"old-style null pointer",
|
||||
# "possible forward declaration",
|
||||
"undefined function",
|
||||
"uninitialized field",
|
||||
# "uninitialized local variable",
|
||||
"unused forward declaration",
|
||||
# "variable naming",
|
||||
"whitespace",
|
||||
]
|
||||
|
||||
# None of the available actions seem to do what I want, they all do stupid things like adding another check... let's just do it manually
|
||||
# GitHub also doesn't seem to provide you with the check suite or check run ID, so we have to get it from the action ID via the API
|
||||
s = requests.Session()
|
||||
s.headers.update({
|
||||
'Authorization': 'token ' + os.environ['GITHUB_TOKEN'],
|
||||
'Accept': 'application/vnd.github.antiope-preview+json' # Annotations are still technically a preview feature of the API
|
||||
})
|
||||
action_run = s.get(os.environ['GITHUB_API_URL'] + "/repos/" + os.environ['GITHUB_REPOSITORY'] + "/actions/runs/" + os.environ['GITHUB_RUN_ID']).json()
|
||||
check_suite = s.get(action_run['check_suite_url']).json()
|
||||
check_suite_runs = s.get(check_suite['check_runs_url']).json()
|
||||
check_run = check_suite_runs['check_runs'][0] # NOTE: This assumes that the 'lint' job is the first one in the workflow. You could find it by name if you really wanted.
|
||||
|
||||
def we_care_about(file_name, type):
|
||||
if 'CBot' in file_name:
|
||||
return type in OVERALL_STABLE_RULES
|
||||
else:
|
||||
return type in STABLE_RULES_WITHOUT_CBOT
|
||||
|
||||
results = ET.parse('build/colobot_lint_report.xml')
|
||||
annotations = []
|
||||
for error in results.find('errors').findall('error'):
|
||||
location = error.find('location')
|
||||
file_name = os.path.relpath(location.get('file'), os.environ['GITHUB_WORKSPACE'])
|
||||
line_num = int(location.get('line'))
|
||||
type = error.get('id')
|
||||
severity = error.get('severity')
|
||||
msg = error.get('msg')
|
||||
|
||||
gh_severity = 'warning'
|
||||
if severity == 'error':
|
||||
gh_severity = 'failure'
|
||||
elif severity == 'information':
|
||||
gh_severity = 'notice'
|
||||
|
||||
if not we_care_about(file_name, type):
|
||||
# don't send the unstable rules to github at all as there are way too many of them and it would overload the API rate limit
|
||||
continue
|
||||
|
||||
print('{}:{}: [{}] {}'.format(file_name, line_num, type, msg))
|
||||
|
||||
annotations.append({
|
||||
'path': file_name,
|
||||
'start_line': line_num,
|
||||
'end_line': line_num,
|
||||
'annotation_level': gh_severity,
|
||||
'title': type,
|
||||
'message': msg
|
||||
})
|
||||
|
||||
summary = 'colobot-lint found {} issues'.format(len(annotations))
|
||||
all_ok = len(annotations) == 0
|
||||
|
||||
# Annotations have to be sent in batches of 50
|
||||
first = True
|
||||
while first or len(annotations) > 0:
|
||||
first = False
|
||||
to_send = annotations[:50]
|
||||
annotations = annotations[50:]
|
||||
data = {
|
||||
'output': {
|
||||
'title': summary,
|
||||
'summary': summary,
|
||||
'annotations': to_send
|
||||
}
|
||||
}
|
||||
r = s.patch(check_run['url'], json=data)
|
||||
r.raise_for_status()
|
||||
|
||||
sys.exit(0 if all_ok else 1)
|
|
@ -1,14 +1,21 @@
|
|||
name: Verify pull request target
|
||||
|
||||
on: [pull_request]
|
||||
on: [pull_request_target]
|
||||
|
||||
jobs:
|
||||
check_pr_target:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Wrong pull request target
|
||||
run: echo "This pull request targets the master branch. Please edit the pull request to target dev." && exit 1
|
||||
- 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
|
||||
run: echo "This pull request targets the correct branch." && exit 0
|
||||
if: github.base_ref != 'master'
|
||||
run: echo "This pull request targets the correct branch." && exit 0
|
||||
|
|
|
@ -16,8 +16,8 @@ set(CMAKE_CXX_EXTENSIONS NO)
|
|||
##
|
||||
set(COLOBOT_VERSION_CODENAME "Gold")
|
||||
set(COLOBOT_VERSION_MAJOR 0)
|
||||
set(COLOBOT_VERSION_MINOR 1)
|
||||
set(COLOBOT_VERSION_REVISION 12)
|
||||
set(COLOBOT_VERSION_MINOR 2)
|
||||
set(COLOBOT_VERSION_REVISION 0)
|
||||
|
||||
# Used on official releases
|
||||
#set(COLOBOT_VERSION_RELEASE_CODENAME "-alpha")
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -31,6 +31,7 @@ On some Linux distributions there are also distribution packages available:
|
|||
* 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
|
||||
|
@ -43,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).
|
||||
|
|
2
data
2
data
|
@ -1 +1 @@
|
|||
Subproject commit 611cbfdd079e97a71f97810636f2ab2358cb4eeb
|
||||
Subproject commit 0ac8197b7a8a005c714b7696d36c642cf0e81474
|
|
@ -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}"
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
@ -280,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 ""
|
||||
|
||||
|
@ -316,6 +375,9 @@ msgstr ""
|
|||
msgid "SatCom"
|
||||
msgstr ""
|
||||
|
||||
msgid "Mods\\Mod manager"
|
||||
msgstr ""
|
||||
|
||||
msgid "Change player\\Change player"
|
||||
msgstr ""
|
||||
|
||||
|
@ -340,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 ""
|
||||
|
||||
|
@ -415,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 ""
|
||||
|
||||
|
@ -580,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 ""
|
||||
|
||||
|
@ -751,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"
|
||||
|
|
113
po/cs.po
113
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"
|
||||
|
||||
|
@ -125,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"
|
||||
|
||||
|
@ -197,9 +203,6 @@ 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"
|
||||
|
||||
|
@ -272,6 +275,9 @@ 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 ""
|
||||
|
||||
|
@ -371,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:"
|
||||
|
||||
|
@ -440,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"
|
||||
|
||||
|
@ -473,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"
|
||||
|
||||
|
@ -485,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"
|
||||
|
||||
|
@ -501,6 +522,9 @@ 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"
|
||||
|
||||
|
@ -528,6 +552,9 @@ msgstr "Vejce"
|
|||
msgid "Empty character constant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable\\Enable the selected mod"
|
||||
msgstr ""
|
||||
|
||||
msgid "End of block missing"
|
||||
msgstr "Chybí konec bloku"
|
||||
|
||||
|
@ -754,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"
|
||||
|
||||
|
@ -901,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"
|
||||
|
||||
|
@ -916,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"
|
||||
|
||||
|
@ -934,6 +979,9 @@ msgstr "Nový"
|
|||
msgid "New ..."
|
||||
msgstr "Nový..."
|
||||
|
||||
msgid "New Folder"
|
||||
msgstr ""
|
||||
|
||||
msgid "New bot available"
|
||||
msgstr "Robot vyroben"
|
||||
|
||||
|
@ -946,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"
|
||||
|
||||
|
@ -1066,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"
|
||||
|
||||
|
@ -1090,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é"
|
||||
|
||||
|
@ -1273,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"
|
||||
|
||||
|
@ -1387,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"
|
||||
|
||||
|
@ -1453,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"
|
||||
|
||||
|
@ -1531,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"
|
||||
|
||||
|
@ -1543,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"
|
||||
|
||||
|
@ -1670,6 +1756,9 @@ msgstr "Jednotka"
|
|||
msgid "Unknown Object"
|
||||
msgstr "Neznámý objekt"
|
||||
|
||||
msgid "Unknown author"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown command"
|
||||
msgstr "Neznámý příkaz"
|
||||
|
||||
|
@ -1682,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ěž)"
|
||||
|
||||
|
@ -1703,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 ""
|
||||
|
||||
|
@ -1721,6 +1816,9 @@ msgstr "Vosa byla smrtelně raněna"
|
|||
msgid "Waste"
|
||||
msgstr "Odpad"
|
||||
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wheeled builder"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1754,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"
|
||||
|
||||
|
@ -1904,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č"
|
||||
|
|
104
po/de.po
104
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"
|
||||
|
||||
|
@ -126,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"
|
||||
|
||||
|
@ -198,9 +204,6 @@ 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"
|
||||
|
||||
|
@ -273,6 +276,9 @@ 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 ""
|
||||
|
||||
|
@ -372,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:"
|
||||
|
||||
|
@ -441,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"
|
||||
|
||||
|
@ -474,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"
|
||||
|
||||
|
@ -486,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"
|
||||
|
||||
|
@ -502,6 +523,9 @@ 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"
|
||||
|
||||
|
@ -529,6 +553,9 @@ 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)"
|
||||
|
||||
|
@ -756,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"
|
||||
|
||||
|
@ -917,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"
|
||||
|
||||
|
@ -932,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"
|
||||
|
||||
|
@ -965,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"
|
||||
|
||||
|
@ -1085,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\"{\""
|
||||
|
||||
|
@ -1296,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"
|
||||
|
||||
|
@ -1479,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"
|
||||
|
||||
|
@ -1557,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 ""
|
||||
|
||||
|
@ -1569,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"
|
||||
|
||||
|
@ -1696,6 +1773,9 @@ msgstr "Einheit"
|
|||
msgid "Unknown Object"
|
||||
msgstr "Das Objekt existiert nicht"
|
||||
|
||||
msgid "Unknown author"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown command"
|
||||
msgstr "Befehl unbekannt"
|
||||
|
||||
|
@ -1708,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"
|
||||
|
||||
|
@ -1729,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 ""
|
||||
|
||||
|
@ -1747,6 +1833,9 @@ msgstr "Wespe tödlich verwundet"
|
|||
msgid "Waste"
|
||||
msgstr "Abfall"
|
||||
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wheeled builder"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1780,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"
|
||||
|
||||
|
@ -1928,6 +2020,9 @@ msgstr "\\Violette Fahne"
|
|||
msgid "\\Yellow flags"
|
||||
msgstr "\\Gelbe Fahne"
|
||||
|
||||
msgid "by"
|
||||
msgstr ""
|
||||
|
||||
msgid "colobot.info"
|
||||
msgstr "colobot.info"
|
||||
|
||||
|
@ -1949,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"
|
||||
|
||||
|
|
104
po/fr.po
104
po/fr.po
|
@ -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"
|
||||
|
||||
|
@ -125,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"
|
||||
|
||||
|
@ -200,9 +206,6 @@ 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 station relais"
|
||||
|
||||
|
@ -275,6 +278,9 @@ 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 ""
|
||||
|
||||
|
@ -374,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 :"
|
||||
|
||||
|
@ -443,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é"
|
||||
|
||||
|
@ -476,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"
|
||||
|
||||
|
@ -488,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"
|
||||
|
||||
|
@ -504,6 +525,9 @@ 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"
|
||||
|
||||
|
@ -531,6 +555,9 @@ 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"
|
||||
|
||||
|
@ -758,6 +785,9 @@ msgstr "Infecté par un virus; ne fonctionne plus temporairement"
|
|||
msgid "Information exchange post"
|
||||
msgstr "Station relais"
|
||||
|
||||
msgid "Information:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Instruction \"break\" outside a loop"
|
||||
msgstr "Instruction \"break\" en dehors d'une boucle"
|
||||
|
||||
|
@ -919,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"
|
||||
|
||||
|
@ -934,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"
|
||||
|
||||
|
@ -967,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"
|
||||
|
||||
|
@ -1087,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"
|
||||
|
||||
|
@ -1298,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"
|
||||
|
||||
|
@ -1481,6 +1538,15 @@ 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"
|
||||
|
||||
|
@ -1559,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"
|
||||
|
||||
|
@ -1571,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à"
|
||||
|
||||
|
@ -1698,6 +1775,9 @@ msgstr "Unité"
|
|||
msgid "Unknown Object"
|
||||
msgstr "Objet inconnu"
|
||||
|
||||
msgid "Unknown author"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown command"
|
||||
msgstr "Commande inconnue"
|
||||
|
||||
|
@ -1710,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)"
|
||||
|
||||
|
@ -1731,6 +1814,9 @@ msgstr "Variable non initialisée"
|
|||
msgid "Vault"
|
||||
msgstr "Coffre-fort"
|
||||
|
||||
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."
|
||||
|
||||
|
@ -1749,6 +1835,9 @@ msgstr "Guêpe mortellement touchée"
|
|||
msgid "Waste"
|
||||
msgstr "Déchet"
|
||||
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wheeled builder"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1782,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"
|
||||
|
||||
|
@ -1930,6 +2022,9 @@ msgstr "\\Drapeaux violets"
|
|||
msgid "\\Yellow flags"
|
||||
msgstr "\\Drapeaux jaunes"
|
||||
|
||||
msgid "by"
|
||||
msgstr ""
|
||||
|
||||
msgid "colobot.info"
|
||||
msgstr "colobot.info"
|
||||
|
||||
|
@ -1948,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"
|
||||
|
||||
|
|
146
po/pl.po
146
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"
|
||||
|
||||
|
@ -124,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"
|
||||
|
||||
|
@ -182,7 +188,7 @@ msgid "Bot factory"
|
|||
msgstr "Fabryka robotów"
|
||||
|
||||
msgid "Build (\\key action;)"
|
||||
msgstr ""
|
||||
msgstr "Buduj (\\key action;)"
|
||||
|
||||
msgid "Build a bot factory"
|
||||
msgstr "Zbuduj fabrykę robotów"
|
||||
|
@ -196,14 +202,11 @@ 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 ""
|
||||
msgstr "Zbuduj budowniczego na nogach"
|
||||
|
||||
msgid "Build a legged grabber"
|
||||
msgstr "Zbuduj transporter na nogach"
|
||||
|
@ -251,13 +254,13 @@ msgid "Build a subber"
|
|||
msgstr "Zbuduj robota nurka"
|
||||
|
||||
msgid "Build a target bot"
|
||||
msgstr ""
|
||||
msgstr "Zbuduj robota-cel"
|
||||
|
||||
msgid "Build a thumper"
|
||||
msgstr "Zbuduj robota uderzacza"
|
||||
|
||||
msgid "Build a tracked builder"
|
||||
msgstr ""
|
||||
msgstr "Zbuduj budowniczego na gąsienicach"
|
||||
|
||||
msgid "Build a tracked grabber"
|
||||
msgstr "Zbuduj transporter na gąsienicach"
|
||||
|
@ -271,8 +274,11 @@ 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 ""
|
||||
msgstr "Zbuduj budowniczego na kołach"
|
||||
|
||||
msgid "Build a wheeled grabber"
|
||||
msgstr "Zbuduj transporter na kołach"
|
||||
|
@ -287,7 +293,7 @@ msgid "Build a wheeled sniffer"
|
|||
msgstr "Zbuduj szperacz na kołach"
|
||||
|
||||
msgid "Build a winged builder"
|
||||
msgstr ""
|
||||
msgstr "Zbuduj latającego budowniczego"
|
||||
|
||||
msgid "Build a winged grabber"
|
||||
msgstr "Zbuduj transporter latający"
|
||||
|
@ -370,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:"
|
||||
|
||||
|
@ -439,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"
|
||||
|
||||
|
@ -472,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"
|
||||
|
||||
|
@ -484,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"
|
||||
|
||||
|
@ -500,11 +521,14 @@ 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 ""
|
||||
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"
|
||||
|
@ -525,7 +549,10 @@ msgid "Egg"
|
|||
msgstr "Jajo"
|
||||
|
||||
msgid "Empty character constant"
|
||||
msgstr ""
|
||||
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"
|
||||
|
@ -742,7 +769,7 @@ msgid "Inappropriate object"
|
|||
msgstr "Nieodpowiedni obiekt"
|
||||
|
||||
msgid "Inappropriate sample"
|
||||
msgstr ""
|
||||
msgstr "Nieprawidłowa próbka"
|
||||
|
||||
msgid "Incorrect index type"
|
||||
msgstr "Nieprawidłowy typ indeksu"
|
||||
|
@ -753,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"
|
||||
|
||||
|
@ -784,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"
|
||||
|
@ -814,7 +844,7 @@ msgid "LOADING"
|
|||
msgstr "WCZYTYWANIE"
|
||||
|
||||
msgid "Legged builder"
|
||||
msgstr ""
|
||||
msgstr "Budowniczy na nogach"
|
||||
|
||||
msgid "Legged grabber"
|
||||
msgstr "Transporter na nogach"
|
||||
|
@ -900,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"
|
||||
|
||||
|
@ -915,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"
|
||||
|
||||
|
@ -934,7 +979,7 @@ msgid "New ..."
|
|||
msgstr "Nowy ..."
|
||||
|
||||
msgid "New Folder"
|
||||
msgstr ""
|
||||
msgstr "Nowy folder"
|
||||
|
||||
msgid "New bot available"
|
||||
msgstr "Dostępny nowy robot"
|
||||
|
@ -948,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"
|
||||
|
||||
|
@ -1068,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"
|
||||
|
||||
|
@ -1093,7 +1147,7 @@ msgid "Original game developed by:"
|
|||
msgstr "Twórcy oryginalnej gry:"
|
||||
|
||||
msgid "Overwrite existing file?"
|
||||
msgstr ""
|
||||
msgstr "Nadpisać istniejący plik?"
|
||||
|
||||
msgid "Parameters missing"
|
||||
msgstr "Brak wymaganego parametru"
|
||||
|
@ -1129,7 +1183,7 @@ msgid "Planets:"
|
|||
msgstr "Planety:"
|
||||
|
||||
msgid "Plans for builder available"
|
||||
msgstr ""
|
||||
msgstr "Dostępne plany robota budowniczego"
|
||||
|
||||
msgid "Plans for defense tower available"
|
||||
msgstr "Dostępne plany wieży obronnej"
|
||||
|
@ -1278,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"
|
||||
|
||||
|
@ -1336,7 +1393,7 @@ msgid "Ruin"
|
|||
msgstr "Ruiny"
|
||||
|
||||
msgid "Run research program for builder"
|
||||
msgstr ""
|
||||
msgstr "Rozpocznij prace badawcze nad robotem budowniczym"
|
||||
|
||||
msgid "Run research program for defense tower"
|
||||
msgstr "Rozpocznij prace badawcze nad wieżą obronną"
|
||||
|
@ -1360,7 +1417,7 @@ msgid "Run research program for shooter"
|
|||
msgstr "Rozpocznij prace badawcze nad działem"
|
||||
|
||||
msgid "Run research program for target bot"
|
||||
msgstr ""
|
||||
msgstr "Rozpocznij prace badawcze nad robotem-celem"
|
||||
|
||||
msgid "Run research program for thumper"
|
||||
msgstr "Rozpocznij prace badawcze nad robotem uderzaczem"
|
||||
|
@ -1393,7 +1450,7 @@ msgid "Save\\Saves the current mission"
|
|||
msgstr "Zapisz\\Zapisuje bieżącą misję"
|
||||
|
||||
msgid "Select Folder"
|
||||
msgstr ""
|
||||
msgstr "Wybierz folder"
|
||||
|
||||
msgid "Select the astronaut\\Selects the astronaut"
|
||||
msgstr "Zaznacz astronautę\\Zaznacza astronautę"
|
||||
|
@ -1461,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"
|
||||
|
||||
|
@ -1539,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ę"
|
||||
|
||||
|
@ -1551,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"
|
||||
|
||||
|
@ -1628,7 +1705,7 @@ msgid "Too many parameters"
|
|||
msgstr "Za dużo parametrów"
|
||||
|
||||
msgid "Tracked builder"
|
||||
msgstr ""
|
||||
msgstr "Budowniczy na gąsienicach"
|
||||
|
||||
msgid "Tracked grabber"
|
||||
msgstr "Transporter na gąsienicach"
|
||||
|
@ -1678,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"
|
||||
|
@ -1690,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ę)"
|
||||
|
||||
|
@ -1711,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"
|
||||
|
||||
|
@ -1729,8 +1815,11 @@ msgstr "Osa śmiertelnie raniona"
|
|||
msgid "Waste"
|
||||
msgstr "Odpady"
|
||||
|
||||
msgid "Website"
|
||||
msgstr "Strona internetowa"
|
||||
|
||||
msgid "Wheeled builder"
|
||||
msgstr ""
|
||||
msgstr "Budowniczy na kołach"
|
||||
|
||||
msgid "Wheeled grabber"
|
||||
msgstr "Transporter na kołach"
|
||||
|
@ -1745,7 +1834,7 @@ msgid "Wheeled sniffer"
|
|||
msgstr "Szperacz na kołach"
|
||||
|
||||
msgid "Winged builder"
|
||||
msgstr ""
|
||||
msgstr "Budowniczy latający"
|
||||
|
||||
msgid "Winged grabber"
|
||||
msgstr "Transporter latający"
|
||||
|
@ -1762,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"
|
||||
|
||||
|
@ -1912,6 +2004,9 @@ msgstr "\\Fioletowe flagi"
|
|||
msgid "\\Yellow flags"
|
||||
msgstr "\\Żółte flagi"
|
||||
|
||||
msgid "by"
|
||||
msgstr "autorstwa"
|
||||
|
||||
msgid "colobot.info"
|
||||
msgstr "colobot.info"
|
||||
|
||||
|
@ -1927,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"
|
||||
|
||||
|
|
113
po/pt.po
113
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"
|
||||
|
||||
|
@ -122,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"
|
||||
|
||||
|
@ -194,9 +200,6 @@ 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"
|
||||
|
||||
|
@ -269,6 +272,9 @@ 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 ""
|
||||
|
||||
|
@ -368,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:"
|
||||
|
||||
|
@ -438,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"
|
||||
|
||||
|
@ -471,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"
|
||||
|
||||
|
@ -483,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"
|
||||
|
||||
|
@ -499,6 +520,9 @@ 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"
|
||||
|
||||
|
@ -526,6 +550,9 @@ msgstr "Ovo"
|
|||
msgid "Empty character constant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable\\Enable the selected mod"
|
||||
msgstr ""
|
||||
|
||||
msgid "End of block missing"
|
||||
msgstr "Fim do bloco ausente"
|
||||
|
||||
|
@ -753,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"
|
||||
|
||||
|
@ -914,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"
|
||||
|
||||
|
@ -929,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"
|
||||
|
||||
|
@ -947,6 +992,9 @@ msgstr "Novo"
|
|||
msgid "New ..."
|
||||
msgstr "Novo ..."
|
||||
|
||||
msgid "New Folder"
|
||||
msgstr ""
|
||||
|
||||
msgid "New bot available"
|
||||
msgstr "Novo robô disponível"
|
||||
|
||||
|
@ -959,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"
|
||||
|
||||
|
@ -1079,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"
|
||||
|
||||
|
@ -1103,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"
|
||||
|
||||
|
@ -1287,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"
|
||||
|
||||
|
@ -1401,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"
|
||||
|
||||
|
@ -1467,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"
|
||||
|
||||
|
@ -1545,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"
|
||||
|
||||
|
@ -1557,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"
|
||||
|
||||
|
@ -1684,6 +1770,9 @@ msgstr "Unidade"
|
|||
msgid "Unknown Object"
|
||||
msgstr "Objeto desconhecido"
|
||||
|
||||
msgid "Unknown author"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown command"
|
||||
msgstr "Comando desconhecido"
|
||||
|
||||
|
@ -1696,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)"
|
||||
|
||||
|
@ -1717,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 ""
|
||||
|
||||
|
@ -1735,6 +1830,9 @@ msgstr "Vespa fatalmente ferida"
|
|||
msgid "Waste"
|
||||
msgstr "Desperdício"
|
||||
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wheeled builder"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1768,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"
|
||||
|
||||
|
@ -1916,6 +2017,9 @@ msgstr "\\Bandeiras violetas"
|
|||
msgid "\\Yellow flags"
|
||||
msgstr "\\Bandeiras amarelas"
|
||||
|
||||
msgid "by"
|
||||
msgstr ""
|
||||
|
||||
msgid "colobot.info"
|
||||
msgstr "colobot.info"
|
||||
|
||||
|
@ -1937,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"
|
||||
|
||||
|
|
104
po/ru.po
104
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 "Сзади"
|
||||
|
||||
|
@ -124,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 "Соответствующий конструктор отсутствует"
|
||||
|
||||
|
@ -197,9 +203,6 @@ msgstr "Построить защитную башню"
|
|||
msgid "Build a derrick"
|
||||
msgstr "Построить буровую вышку"
|
||||
|
||||
msgid "Build a destroyer"
|
||||
msgstr "Построить уничтожитель"
|
||||
|
||||
msgid "Build a exchange post"
|
||||
msgstr "Построить пост по обмену сообщениями"
|
||||
|
||||
|
@ -272,6 +275,9 @@ msgstr "Собрать гусеничного стрелка"
|
|||
msgid "Build a tracked sniffer"
|
||||
msgstr "Собрать гусеничного искателя"
|
||||
|
||||
msgid "Build a vault"
|
||||
msgstr ""
|
||||
|
||||
msgid "Build a wheeled builder"
|
||||
msgstr ""
|
||||
|
||||
|
@ -375,6 +381,9 @@ msgstr "Изменить вид\\Переключение между борто
|
|||
msgid "Change player\\Change player"
|
||||
msgstr "Новый игрок\\Выберите имя для игрока"
|
||||
|
||||
msgid "Changes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Chapters:"
|
||||
msgstr "Разделы:"
|
||||
|
||||
|
@ -446,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 "Текущая миссия сохранена"
|
||||
|
||||
|
@ -480,6 +495,9 @@ msgstr "Космический корабль"
|
|||
msgid "Descend\\Reduces the power of the jet"
|
||||
msgstr "Снижение и посадка\\Понижение мощности реактивного двигателя"
|
||||
|
||||
msgid "Description:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Destroy"
|
||||
msgstr "Уничтожить"
|
||||
|
||||
|
@ -492,6 +510,9 @@ msgstr "Уничтожитель"
|
|||
msgid "Device\\Driver and resolution settings"
|
||||
msgstr "Устройство\\Драйвер и настройки разрешения"
|
||||
|
||||
msgid "Disable\\Disable the selected mod"
|
||||
msgstr ""
|
||||
|
||||
msgid "Dividing by zero"
|
||||
msgstr "Деление на ноль (запрещено!)"
|
||||
|
||||
|
@ -508,6 +529,9 @@ 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 "Рисовальщик"
|
||||
|
||||
|
@ -535,6 +559,9 @@ msgstr "Яйцо"
|
|||
msgid "Empty character constant"
|
||||
msgstr ""
|
||||
|
||||
msgid "Enable\\Enable the selected mod"
|
||||
msgstr ""
|
||||
|
||||
msgid "End of block missing"
|
||||
msgstr "Отсутствует конец блока"
|
||||
|
||||
|
@ -762,6 +789,9 @@ msgstr "Заражено вирусом. Временно вышел из стр
|
|||
msgid "Information exchange post"
|
||||
msgstr "Пост обмена информацией"
|
||||
|
||||
msgid "Information:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Instruction \"break\" outside a loop"
|
||||
msgstr "Инструкция \"break\" вне цикла"
|
||||
|
||||
|
@ -923,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\\Инверсия прокрутки по оси Х"
|
||||
|
||||
|
@ -940,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 "Без звука\\Без звука"
|
||||
|
||||
|
@ -973,6 +1018,12 @@ msgstr "Следующий объект\\Выбор следующего объ
|
|||
msgid "No"
|
||||
msgstr "Нет"
|
||||
|
||||
msgid "No changes."
|
||||
msgstr ""
|
||||
|
||||
msgid "No description."
|
||||
msgstr ""
|
||||
|
||||
msgid "No energy in the subsoil"
|
||||
msgstr "Под землей нет запасов энергии"
|
||||
|
||||
|
@ -1093,6 +1144,9 @@ msgstr "Открыть"
|
|||
msgid "Open (Ctrl+O)"
|
||||
msgstr "Открыть (Ctrl+O)"
|
||||
|
||||
msgid "Open Directory\\Open the mods directory"
|
||||
msgstr ""
|
||||
|
||||
msgid "Opening brace missing"
|
||||
msgstr "Открывающая скобка отсутствует"
|
||||
|
||||
|
@ -1305,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 "Остатки миссии Аполлон"
|
||||
|
||||
|
@ -1491,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 "Космический корабль"
|
||||
|
||||
|
@ -1570,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 ""
|
||||
|
||||
|
@ -1582,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 "Этот класс уже существует"
|
||||
|
||||
|
@ -1709,6 +1786,9 @@ msgstr "Юнит"
|
|||
msgid "Unknown Object"
|
||||
msgstr "Неизвестный объект"
|
||||
|
||||
msgid "Unknown author"
|
||||
msgstr ""
|
||||
|
||||
msgid "Unknown command"
|
||||
msgstr "Неизвестная команда"
|
||||
|
||||
|
@ -1721,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 "Запасы урана (место для буровой вышки)"
|
||||
|
||||
|
@ -1742,6 +1825,9 @@ msgstr "Переменная не инициализирована"
|
|||
msgid "Vault"
|
||||
msgstr "Хранилище"
|
||||
|
||||
msgid "Version"
|
||||
msgstr ""
|
||||
|
||||
msgid "Vertical Synchronization\\Limits the number of frames per second to display frequency"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1760,6 +1846,9 @@ msgstr "Оса смертельно ранена"
|
|||
msgid "Waste"
|
||||
msgstr "Мусор"
|
||||
|
||||
msgid "Website"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wheeled builder"
|
||||
msgstr ""
|
||||
|
||||
|
@ -1793,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 "Червь"
|
||||
|
||||
|
@ -1941,6 +2033,9 @@ msgstr "\\Фиолетовый флаг"
|
|||
msgid "\\Yellow flags"
|
||||
msgstr "\\Желтый флаг"
|
||||
|
||||
msgid "by"
|
||||
msgstr ""
|
||||
|
||||
msgid "colobot.info"
|
||||
msgstr "colobot.info"
|
||||
|
||||
|
@ -1962,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 "Здание слишком близко"
|
||||
|
||||
|
|
|
@ -31,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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -171,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;
|
||||
}
|
||||
|
@ -211,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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -261,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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -310,15 +297,12 @@ 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;
|
||||
|
||||
*pp = pVar; // added after
|
||||
p->m_listVar.emplace_back(pVar);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -369,19 +353,14 @@ void CBotCStack::CreateMemberVars(CBotClass* pClass, bool setDefined)
|
|||
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;
|
||||
}
|
||||
|
@ -392,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(p->GetString(), ppVars, nIdent, m_prog);
|
||||
val = CBotFunction::CompileCall(p->GetString(), ppVars, nIdent, GetProgram());
|
||||
if ( val.GetType() < 0 )
|
||||
{
|
||||
// pVar = nullptr; // the error is not on a particular parameter
|
||||
|
@ -410,13 +389,13 @@ CBotTypResult CBotCStack::CompileCall(CBotToken* &p, CBotVar** ppVars, long& nId
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
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() )
|
||||
|
@ -429,7 +408,7 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::
|
|||
|
||||
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() )
|
||||
|
@ -443,4 +422,4 @@ bool CBotCStack::CheckCall(CBotToken* &pToken, CBotDefParam* pParam, const std::
|
|||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace CBot
|
||||
|
|
|
@ -22,6 +22,9 @@
|
|||
#include "CBot/CBotVar/CBotVar.h"
|
||||
#include "CBot/CBotProgram.h"
|
||||
|
||||
#include <list>
|
||||
#include <memory>
|
||||
|
||||
namespace CBot
|
||||
{
|
||||
|
||||
|
@ -157,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
|
||||
|
@ -269,21 +277,20 @@ public:
|
|||
bool NextToken(CBotToken* &p);
|
||||
|
||||
private:
|
||||
CBotCStack* m_next;
|
||||
std::unique_ptr<CBotCStack> 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<CBotVar> 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<std::unique_ptr<CBotVar>> m_listVar;
|
||||
};
|
||||
|
||||
} // namespace CBot
|
||||
|
|
|
@ -605,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<CBotFunction*>::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 );
|
||||
});
|
||||
|
@ -626,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();
|
||||
|
|
|
@ -94,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());
|
||||
|
@ -137,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;
|
||||
|
|
|
@ -100,6 +100,7 @@ enum TokenId
|
|||
ID_STATIC,
|
||||
ID_PROTECTED,
|
||||
ID_PRIVATE,
|
||||
ID_REPEAT,
|
||||
ID_INT,
|
||||
ID_FLOAT,
|
||||
ID_BOOLEAN,
|
||||
|
|
|
@ -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)
|
||||
// if this is a method call we need to use AddStack()
|
||||
CBotStack* pile = (thisVar != nullptr) ? pStack->AddStack() : pStack->AddStackExternalCall(pt);
|
||||
|
||||
if (pile->GetState() == 0) // the first time?
|
||||
{
|
||||
// lists the parameters depending on the contents of the stack
|
||||
CBotVar* pVar = MakeListVars(ppVar, true);
|
||||
|
||||
// creates a variable to the result
|
||||
CBotVar* pResult = rettype.Eq(CBotTypVoid) ? nullptr : CBotVar::Create("", rettype);
|
||||
|
||||
pile->SetVar(pVar);
|
||||
|
||||
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
|
||||
|
|
|
@ -135,7 +135,7 @@ 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)
|
||||
|
@ -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?
|
||||
|
|
|
@ -445,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 );
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -78,12 +78,12 @@ CBotInstr* CBotInstrCall::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
{
|
||||
// if (pVar2!=nullptr) pp = pVar2->RetToken();
|
||||
pStack->SetError( static_cast<CBotError>(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?
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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<std::string, CBotInstr*> CBotRepeat::GetDebugLinks()
|
||||
{
|
||||
auto links = CBotInstr::GetDebugLinks();
|
||||
links["m_expr"] = m_expr;
|
||||
links["m_block"] = m_block;
|
||||
return links;
|
||||
}
|
||||
|
||||
} // namespace CBot
|
|
@ -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<std::string, CBotInstr*> 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
|
|
@ -71,7 +71,7 @@ CBotInstr* CBotSwitch::Compile(CBotToken* &p, CBotCStack* pStack)
|
|||
{
|
||||
if ( p->GetType() == ID_CASE || p->GetType() == ID_DEFAULT)
|
||||
{
|
||||
delete pStk2;
|
||||
pStk->DeleteNext();
|
||||
pStk2 = pStk->TokenStack(p, true); // some space for a stack, plz
|
||||
|
||||
caseInst = static_cast<CBotCase*>(CBotCase::Compile(p, pStk2, inst->m_labels));
|
||||
|
|
|
@ -357,6 +357,7 @@ 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);
|
||||
|
||||
// 2nd state, evalute right operand
|
||||
if ( pStk2->GetState() == 0 )
|
||||
|
@ -514,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
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
namespace CBot
|
||||
{
|
||||
|
||||
CBotExternalCallList* CBotProgram::m_externalCalls = new CBotExternalCallList();
|
||||
std::unique_ptr<CBotExternalCallList> CBotProgram::m_externalCalls;
|
||||
|
||||
CBotProgram::CBotProgram()
|
||||
{
|
||||
|
@ -243,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;
|
||||
|
@ -395,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
|
||||
|
@ -420,9 +415,10 @@ void CBotProgram::Free()
|
|||
CBotToken::ClearDefineNum();
|
||||
m_externalCalls->Clear();
|
||||
CBotClass::ClearPublic();
|
||||
m_externalCalls.reset();
|
||||
}
|
||||
|
||||
CBotExternalCallList* CBotProgram::GetExternalCalls()
|
||||
const std::unique_ptr<CBotExternalCallList>& CBotProgram::GetExternalCalls()
|
||||
{
|
||||
return m_externalCalls;
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "CBot/CBotTypResult.h"
|
||||
#include "CBot/CBotEnums.h"
|
||||
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
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
|
||||
*
|
||||
|
@ -335,11 +329,11 @@ public:
|
|||
/**
|
||||
* \brief Returns static list of all registered external calls
|
||||
*/
|
||||
static CBotExternalCallList* GetExternalCalls();
|
||||
static const std::unique_ptr<CBotExternalCallList>& GetExternalCalls();
|
||||
|
||||
private:
|
||||
//! All external calls
|
||||
static CBotExternalCallList* m_externalCalls;
|
||||
static std::unique_ptr<CBotExternalCallList> m_externalCalls;
|
||||
//! All user-defined functions
|
||||
std::list<CBotFunction*> m_functions{};
|
||||
//! The entry point function
|
||||
|
|
|
@ -39,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<CBotVar> retvar;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CBotStack* CBotStack::AllocateStack()
|
||||
{
|
||||
CBotStack* p;
|
||||
|
@ -73,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;
|
||||
}
|
||||
|
||||
|
@ -97,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));
|
||||
|
@ -123,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;
|
||||
|
@ -166,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;
|
||||
|
@ -220,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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -258,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;
|
||||
}
|
||||
|
@ -294,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<CBotError>(-val); // reacts as an Exception
|
||||
m_labelBreak = name;
|
||||
m_data->error = static_cast<CBotError>(-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;
|
||||
}
|
||||
}
|
||||
|
@ -307,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
|
||||
|
@ -322,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)
|
||||
{
|
||||
|
@ -332,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;
|
||||
}
|
||||
|
@ -375,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;
|
||||
}
|
||||
|
@ -410,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
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -419,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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -542,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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -908,13 +932,18 @@ bool CBotVar::RestoreState(std::istream &istr, CBotVar* &pVar)
|
|||
|
||||
if (isClass && p == nullptr) // set id for each item in this instance
|
||||
{
|
||||
CBotVar* pVars = pNew->GetItemList();
|
||||
CBotVar* pv = pNew->GetClass()->GetVar();
|
||||
CBotClass* pClass = pNew->GetClass();
|
||||
CBotVar* pVars = (static_cast<CBotVarClass*>(pNew))->m_pVar;
|
||||
while (pClass != nullptr && pVars != nullptr)
|
||||
{
|
||||
CBotVar* pv = pClass->GetVar();
|
||||
while (pVars != nullptr && pv != nullptr)
|
||||
{
|
||||
pVars->m_ident = pv->m_ident;
|
||||
pv = pv->GetNext();
|
||||
pVars = pVars->GetNext();
|
||||
pVars = pVars->m_next;
|
||||
pv = pv->m_next;
|
||||
}
|
||||
pClass = pClass->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -65,6 +65,7 @@ static const boost::bimap<TokenId, std::string> KEYWORDS = makeBimap<TokenId, st
|
|||
{ID_STATIC, "static"},
|
||||
{ID_PROTECTED, "protected"},
|
||||
{ID_PRIVATE, "private"},
|
||||
{ID_REPEAT, "repeat"},
|
||||
{ID_INT, "int"},
|
||||
{ID_FLOAT, "float"},
|
||||
{ID_BOOLEAN, "boolean"},
|
||||
|
|
|
@ -54,7 +54,6 @@ CBotVarClass::CBotVarClass(const CBotToken& name, const CBotTypResult& type) : C
|
|||
// official type for this object
|
||||
|
||||
m_pClass = nullptr;
|
||||
m_pParent = nullptr;
|
||||
m_binit = InitType::UNDEF;
|
||||
m_bStatic = false;
|
||||
m_mPrivate = ProtectionLevel::Public;
|
||||
|
@ -63,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 );
|
||||
|
||||
|
@ -82,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;
|
||||
}
|
||||
|
@ -113,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;
|
||||
|
@ -162,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 )
|
||||
|
@ -214,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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +236,6 @@ CBotVar* CBotVarClass::GetItem(const std::string& name)
|
|||
p = p->GetNext();
|
||||
}
|
||||
|
||||
if ( m_pParent != nullptr ) return m_pParent->GetItem(name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -261,7 +250,6 @@ CBotVar* CBotVarClass::GetItemRef(int nIdent)
|
|||
p = p->GetNext();
|
||||
}
|
||||
|
||||
if ( m_pParent != nullptr ) return m_pParent->GetItemRef(nIdent);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -311,31 +299,45 @@ 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)
|
||||
{
|
||||
pClass = pClass->GetParent();
|
||||
if (pClass == nullptr) break;
|
||||
res += " ) extends ";
|
||||
res += my->m_pClass->GetName();
|
||||
res += pClass->GetName();
|
||||
res += "( ";
|
||||
}
|
||||
}
|
||||
|
@ -378,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;
|
||||
|
||||
|
@ -399,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--;
|
||||
|
|
|
@ -99,8 +99,6 @@ private:
|
|||
static std::set<CBotVarClass*> m_instances;
|
||||
//! Class definition
|
||||
CBotClass* m_pClass;
|
||||
//! Parent class instance
|
||||
CBotVarClass* m_pParent;
|
||||
//! Class members
|
||||
CBotVar* m_pVar;
|
||||
//! Reference counter
|
||||
|
|
|
@ -110,6 +110,8 @@ target_sources(CBot PRIVATE
|
|||
CBotInstr/CBotPostIncExpr.h
|
||||
CBotInstr/CBotPreIncExpr.cpp
|
||||
CBotInstr/CBotPreIncExpr.h
|
||||
CBotInstr/CBotRepeat.cpp
|
||||
CBotInstr/CBotRepeat.h
|
||||
CBotInstr/CBotReturn.cpp
|
||||
CBotInstr/CBotReturn.h
|
||||
CBotInstr/CBotSwitch.cpp
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -24,6 +24,8 @@ add_library(colobotbase STATIC
|
|||
app/controller.h
|
||||
app/input.cpp
|
||||
app/input.h
|
||||
app/modman.cpp
|
||||
app/modman.h
|
||||
app/pathman.cpp
|
||||
app/pathman.h
|
||||
app/pausemanager.cpp
|
||||
|
@ -297,6 +299,7 @@ add_library(colobotbase STATIC
|
|||
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
|
||||
|
@ -446,6 +449,8 @@ add_library(colobotbase STATIC
|
|||
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
|
||||
|
|
157
src/app/app.cpp
157
src/app/app.cpp
|
@ -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<ApplicationPrivate>()),
|
||||
m_configFile(MakeUnique<CConfigFile>()),
|
||||
m_input(MakeUnique<CInput>()),
|
||||
m_pathManager(MakeUnique<CPathManager>(systemUtils))
|
||||
m_pathManager(MakeUnique<CPathManager>(systemUtils)),
|
||||
m_modManager(MakeUnique<CModManager>(this, m_pathManager.get()))
|
||||
{
|
||||
m_exitCode = 0;
|
||||
m_active = false;
|
||||
|
@ -220,6 +222,11 @@ 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");
|
||||
|
@ -513,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)
|
||||
|
@ -538,6 +549,8 @@ bool CApplication::Create()
|
|||
|
||||
/* SDL initialization sequence */
|
||||
|
||||
// Creating the m_engine now because it holds the vsync flag
|
||||
m_engine = MakeUnique<Gfx::CEngine>(this, m_systemUtils);
|
||||
|
||||
Uint32 initFlags = SDL_INIT_VIDEO | SDL_INIT_TIMER;
|
||||
|
||||
|
@ -682,8 +695,6 @@ bool CApplication::Create()
|
|||
}
|
||||
|
||||
// Create the 3D engine
|
||||
m_engine = MakeUnique<Gfx::CEngine>(this, m_systemUtils);
|
||||
|
||||
m_engine->SetDevice(m_device.get());
|
||||
|
||||
if (! m_engine->Create() )
|
||||
|
@ -698,21 +709,7 @@ bool CApplication::Create()
|
|||
// Create the robot application.
|
||||
m_controller = MakeUnique<CController>();
|
||||
|
||||
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();
|
||||
|
@ -726,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;
|
||||
|
@ -844,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")));
|
||||
|
@ -870,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;
|
||||
|
@ -878,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);
|
||||
|
||||
|
@ -1060,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)
|
||||
|
@ -1158,8 +1160,16 @@ int CApplication::Run()
|
|||
|
||||
CProfiler::StartPerformanceCounter(PCNT_UPDATE_ALL);
|
||||
|
||||
// Prepare and process step simulation event
|
||||
Event event = CreateUpdateEvent();
|
||||
// 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<int>(GetSimulationSpeed());
|
||||
if(numTickSlices < 1) numTickSlices = 1;
|
||||
m_systemUtils->CopyTimeStamp(previousTimeStamp, m_curTimeStamp);
|
||||
m_systemUtils->GetCurrentTimeStamp(currentTimeStamp);
|
||||
for(int tickSlice = 0; tickSlice < numTickSlices; tickSlice++)
|
||||
{
|
||||
m_systemUtils->InterpolateTimeStamp(interpolatedTimeStamp, previousTimeStamp, currentTimeStamp, (tickSlice+1)/static_cast<float>(numTickSlices));
|
||||
Event event = CreateUpdateEvent(interpolatedTimeStamp);
|
||||
if (event.type != EVENT_NULL && m_controller != nullptr)
|
||||
{
|
||||
LogEvent(event);
|
||||
|
@ -1174,6 +1184,7 @@ int CApplication::Run()
|
|||
m_engine->FrameUpdate();
|
||||
CProfiler::StopPerformanceCounter(PCNT_UPDATE_ENGINE);
|
||||
}
|
||||
}
|
||||
|
||||
CProfiler::StopPerformanceCounter(PCNT_UPDATE_ALL);
|
||||
|
||||
|
@ -1188,6 +1199,10 @@ int CApplication::Run()
|
|||
}
|
||||
|
||||
end:
|
||||
m_systemUtils->DestroyTimeStamp(previousTimeStamp);
|
||||
m_systemUtils->DestroyTimeStamp(currentTimeStamp);
|
||||
m_systemUtils->DestroyTimeStamp(interpolatedTimeStamp);
|
||||
|
||||
return m_exitCode;
|
||||
}
|
||||
|
||||
|
@ -1520,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;
|
||||
|
@ -1529,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;
|
||||
|
|
|
@ -42,6 +42,7 @@ class CEventQueue;
|
|||
class CController;
|
||||
class CSoundInterface;
|
||||
class CInput;
|
||||
class CModManager;
|
||||
class CPathManager;
|
||||
class CConfigFile;
|
||||
class CSystemUtils;
|
||||
|
@ -162,6 +163,8 @@ public:
|
|||
CEventQueue* GetEventQueue();
|
||||
//! Returns the sound subsystem
|
||||
CSoundInterface* GetSound();
|
||||
//! Returns the mod manager
|
||||
CModManager* GetModManager();
|
||||
|
||||
public:
|
||||
//! Loads some data from environment variables
|
||||
|
@ -170,6 +173,8 @@ public:
|
|||
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
|
||||
|
@ -283,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);
|
||||
|
||||
|
@ -301,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;
|
||||
|
@ -322,6 +333,8 @@ protected:
|
|||
std::unique_ptr<CInput> m_input;
|
||||
//! Path manager
|
||||
std::unique_ptr<CPathManager> m_pathManager;
|
||||
//! Mod manager
|
||||
std::unique_ptr<CModManager> m_modManager;
|
||||
|
||||
//! Code to return at exit
|
||||
int m_exitCode;
|
||||
|
|
|
@ -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 <algorithm>
|
||||
#include <map>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
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<std::string> savedModNames;
|
||||
GetConfigFile().GetArrayProperty("Mods", "Names", savedModNames);
|
||||
std::vector<bool> 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<std::string, std::string> 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<std::string> 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<std::string> 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<bool> 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<Mod>& 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<std::string>(line->GetParam("major")->AsInt());
|
||||
auto minor = boost::lexical_cast<std::string>(line->GetParam("minor")->AsInt());
|
||||
auto patch = boost::lexical_cast<std::string>(line->GetParam("patch")->AsInt());
|
||||
data.version = boost::algorithm::join(std::vector<std::string>{ 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();
|
||||
}
|
|
@ -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 <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class CApplication;
|
||||
class CPathManager;
|
||||
|
||||
struct ModData
|
||||
{
|
||||
std::string displayName{};
|
||||
std::string author{};
|
||||
std::string version{};
|
||||
std::string website{};
|
||||
std::string summary{};
|
||||
std::vector<std::string> 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<Mod>& 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<std::string> m_mountedModPaths;
|
||||
|
||||
//! List of mods
|
||||
std::vector<Mod> m_mods;
|
||||
|
||||
bool m_userChanges = false;
|
||||
};
|
|
@ -41,8 +41,7 @@ CPathManager::CPathManager(CSystemUtils* systemUtils)
|
|||
: m_dataPath(systemUtils->GetDataPath())
|
||||
, m_langPath(systemUtils->GetLangPath())
|
||||
, m_savePath(systemUtils->GetSaveDir())
|
||||
, m_modAutoloadDir{}
|
||||
, 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;
|
||||
|
@ -131,40 +120,18 @@ void CPathManager::InitPaths()
|
|||
GetLogger()->Info("Data path: %s\n", m_dataPath.c_str());
|
||||
GetLogger()->Info("Save path: %s\n", m_savePath.c_str());
|
||||
|
||||
m_modAutoloadDir.push_back(m_dataPath + "/mods");
|
||||
m_modAutoloadDir.push_back(m_savePath + "/mods");
|
||||
m_modSearchDirs.push_back(m_dataPath + "/mods");
|
||||
m_modSearchDirs.push_back(m_savePath + "/mods");
|
||||
|
||||
if (!m_modAutoloadDir.empty())
|
||||
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);
|
||||
|
||||
|
@ -174,7 +141,45 @@ void CPathManager::InitPaths()
|
|||
GetLogger()->Debug(" * %s\n", path.c_str());
|
||||
}
|
||||
|
||||
std::vector<std::string> CPathManager::FindModsInDir(const std::string &dir)
|
||||
void CPathManager::AddMod(const std::string &path)
|
||||
{
|
||||
m_mods.push_back(path);
|
||||
}
|
||||
|
||||
std::vector<std::string> CPathManager::FindMods() const
|
||||
{
|
||||
std::vector<std::string> 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<std::string> CPathManager::FindModsInDir(const std::string &dir) const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
try
|
||||
|
|
|
@ -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<std::string> FindMods() const;
|
||||
//! Adds a mod search directory
|
||||
void AddModSearchDir(const std::string &modSearchDirPath);
|
||||
|
||||
private:
|
||||
//! Loads all mods from given directory
|
||||
std::vector<std::string> FindModsInDir(const std::string &dir);
|
||||
std::vector<std::string> 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<std::string> m_modAutoloadDir;
|
||||
//! Mod paths
|
||||
//! Mod search paths
|
||||
std::vector<std::string> m_modSearchDirs;
|
||||
//! Additional mod paths
|
||||
std::vector<std::string> m_mods;
|
||||
};
|
||||
|
|
|
@ -26,9 +26,15 @@
|
|||
|
||||
#include "common/singleton.h"
|
||||
|
||||
#include "common/logger.h"
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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<typename T>
|
||||
bool SetArrayProperty(std::string section, std::string key, const std::vector<T>& 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<typename T>
|
||||
bool GetArrayProperty(std::string section, std::string key, std::vector<T>& array)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string readValue = m_propertyTree.get<std::string>(section + "." + key);
|
||||
std::vector<T> convertedValue = StringToArray<T>(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<typename T>
|
||||
std::vector<T> StringToArray(const std::string& s)
|
||||
{
|
||||
std::vector<T> result;
|
||||
std::stringstream ss(s);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, ','))
|
||||
{
|
||||
result.push_back(boost::lexical_cast<T>(item));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string ArrayToString(const std::vector<T> &array)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
if (!array.empty())
|
||||
{
|
||||
std::copy(array.begin(), array.end() - 1, std::ostream_iterator<T>(oss, ","));
|
||||
oss << array.back();
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
private:
|
||||
boost::property_tree::ptree m_propertyTree;
|
||||
bool m_needsSave;
|
||||
|
|
|
@ -190,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";
|
||||
|
@ -272,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";
|
||||
|
@ -405,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";
|
||||
|
|
|
@ -225,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,
|
||||
|
@ -311,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,
|
||||
|
@ -469,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,
|
||||
|
|
|
@ -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<std::string> 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)
|
||||
{
|
||||
|
|
|
@ -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<std::string> 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();
|
||||
|
|
|
@ -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 <path_to_build_folder> --target update-pot`
|
||||
* after changing this file in order to update translation files. Thank you.
|
||||
*/
|
||||
|
||||
void InitializeRestext()
|
||||
|
@ -77,6 +77,8 @@ void InitializeRestext()
|
|||
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)");
|
||||
|
@ -153,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");
|
||||
|
||||
|
@ -173,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");
|
||||
|
@ -181,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");
|
||||
|
@ -275,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");
|
||||
|
@ -341,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");
|
||||
|
|
|
@ -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,
|
||||
|
@ -147,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
|
||||
};
|
||||
|
|
|
@ -72,7 +72,6 @@ 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);
|
||||
|
@ -80,7 +79,6 @@ void CSettings::SaveSettings()
|
|||
GetConfigFile().SetBoolProperty("Setup", "Soluce4", m_soluce4);
|
||||
GetConfigFile().SetBoolProperty("Setup", "Movies", m_movies);
|
||||
GetConfigFile().SetBoolProperty("Setup", "FocusLostPause", m_focusLostPause);
|
||||
GetConfigFile().SetBoolProperty("Setup", "FocusLostMute", m_focusLostMute);
|
||||
GetConfigFile().SetBoolProperty("Setup", "OldCameraScroll", camera->GetOldCameraScroll());
|
||||
GetConfigFile().SetBoolProperty("Setup", "CameraInvertX", camera->GetCameraInvertX());
|
||||
GetConfigFile().SetBoolProperty("Setup", "CameraInvertY", camera->GetCameraInvertY());
|
||||
|
@ -95,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());
|
||||
|
@ -112,6 +108,9 @@ void CSettings::SaveSettings()
|
|||
GetConfigFile().SetIntProperty("Setup", "ShadowMappingResolution",
|
||||
engine->GetShadowMappingOffscreen() ? engine->GetShadowMappingOffscreenResolution() : 0);
|
||||
|
||||
// Save Audio settings
|
||||
SaveAudioSettings();
|
||||
|
||||
// Experimental settings
|
||||
GetConfigFile().SetBoolProperty("Experimental", "TerrainShadows", engine->GetTerrainShadows());
|
||||
GetConfigFile().SetIntProperty("Setup", "VSync", engine->GetVSync());
|
||||
|
@ -140,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();
|
||||
|
|
|
@ -37,6 +37,7 @@ public:
|
|||
void SaveSettings();
|
||||
void LoadSettings();
|
||||
|
||||
void SaveAudioSettings();
|
||||
|
||||
void SetTooltips(bool tooltips);
|
||||
bool GetTooltips();
|
||||
|
|
|
@ -215,3 +215,13 @@ 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -142,6 +145,14 @@ public:
|
|||
//! 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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -137,6 +150,28 @@ std::string CSystemUtilsLinux::GetEnvVar(const std::string& name)
|
|||
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);
|
||||
|
|
|
@ -40,6 +40,7 @@ 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;
|
||||
|
||||
|
@ -47,6 +48,9 @@ public:
|
|||
|
||||
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:
|
||||
|
|
|
@ -119,6 +119,28 @@ std::string CSystemUtilsMacOSX::GetEnvVar(const std::string& str)
|
|||
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);
|
||||
|
|
|
@ -38,6 +38,9 @@ public:
|
|||
|
||||
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:
|
||||
|
|
|
@ -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<Uint32>((b->sdlTicks - a->sdlTicks) * i);
|
||||
}
|
||||
|
||||
long long int CSystemUtilsOther::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after)
|
||||
{
|
||||
return (after->sdlTicks - before->sdlTicks) * 1000000ll;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "common/logger.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <windows.h>
|
||||
|
||||
|
||||
|
@ -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<long long>((b->counterValue - a->counterValue) * static_cast<double>(i));
|
||||
}
|
||||
|
||||
long long int CSystemUtilsWindows::TimeStampExactDiff(SystemTimeStamp* before, SystemTimeStamp* after)
|
||||
{
|
||||
float floatValue = static_cast<double>(after->counterValue - before->counterValue) * (1e9 / static_cast<double>(m_counterFrequency));
|
||||
|
@ -147,6 +153,28 @@ std::string CSystemUtilsWindows::GetEnvVar(const std::string& name)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -38,6 +38,7 @@ 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;
|
||||
|
||||
|
@ -45,6 +46,9 @@ public:
|
|||
|
||||
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:
|
||||
|
|
|
@ -59,14 +59,14 @@ static void SetTransparency(CObject* obj, float value)
|
|||
|
||||
if (obj->Implements(ObjectInterfaceType::Carrier))
|
||||
{
|
||||
CObject* cargo = dynamic_cast<CCarrierObject*>(obj)->GetCargo();
|
||||
CObject* cargo = dynamic_cast<CCarrierObject&>(*obj).GetCargo();
|
||||
if (cargo != nullptr)
|
||||
cargo->SetTransparency(value);
|
||||
}
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Powered))
|
||||
{
|
||||
CObject* power = dynamic_cast<CPoweredObject*>(obj)->GetPower();
|
||||
CObject* power = dynamic_cast<CPoweredObject&>(*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<CMovableObject*>(m_cameraObj)->GetPhysics()->GetLand();
|
||||
ground = dynamic_cast<CMovableObject&>(*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<CControllableObject*>(m_cameraObj)->AdjustCamera(m_eyePt, m_directionH, m_directionV, lookatPt, upVec, m_type);
|
||||
dynamic_cast<CControllableObject&>(*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;
|
||||
|
||||
|
|
|
@ -408,6 +408,7 @@ void CEngine::ReloadAllTextures()
|
|||
{
|
||||
FlushTextureCache();
|
||||
m_text->FlushCache();
|
||||
m_text->ReloadFonts();
|
||||
|
||||
m_app->GetEventQueue()->AddEvent(Event(EVENT_RELOAD_TEXTURES));
|
||||
UpdateGroundSpotTextures();
|
||||
|
|
|
@ -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<WriteScreenShotData> 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;
|
||||
|
|
|
@ -323,7 +323,7 @@ CObject* CLightning::SearchObject(Math::Vector pos)
|
|||
|
||||
if (!obj->Implements(ObjectInterfaceType::Destroyable)) continue;
|
||||
|
||||
float detect = m_magnetic * dynamic_cast<CDestroyableObject*>(obj)->GetLightningHitProbability();
|
||||
float detect = m_magnetic * dynamic_cast<CDestroyableObject&>(*obj).GetLightningHitProbability();
|
||||
if (detect == 0.0f) continue;
|
||||
|
||||
Math::Vector oPos = obj->GetPosition();
|
||||
|
|
|
@ -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 + "'");
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -953,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<CDamageableObject*>(object)->DamageObject(DamageType::Phazer, 0.002f, m_particle[i].objFather);
|
||||
dynamic_cast<CDamageableObject&>(*object).DamageObject(DamageType::Phazer, 0.002f, m_particle[i].objFather);
|
||||
}
|
||||
|
||||
m_particle[i].zoom = 1.0f-(m_particle[i].time-m_particle[i].duration);
|
||||
|
@ -1156,7 +1156,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
{
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire, 0.001f, m_particle[i].objFather);
|
||||
dynamic_cast<CDamageableObject&>(*object).DamageObject(DamageType::Fire, 0.001f, m_particle[i].objFather);
|
||||
}
|
||||
|
||||
m_exploGunCounter++;
|
||||
|
@ -1222,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<CShielder*>(object)->GetActiveShieldRadius() > 0.0f) // protected by shield?
|
||||
if (object->GetType() == OBJECT_MOBILErs && dynamic_cast<CShielder&>(*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)
|
||||
|
@ -1240,7 +1240,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.1f, m_particle[i].objFather); // starts explosion
|
||||
dynamic_cast<CDamageableObject&>(*object).DamageObject(DamageType::Organic, 0.1f, m_particle[i].objFather); // starts explosion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1270,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<CShielder*>(object)->GetActiveShieldRadius() > 0.0f)
|
||||
if (object->GetType() == OBJECT_MOBILErs && dynamic_cast<CShielder&>(*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)
|
||||
|
@ -1285,7 +1285,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
{
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Fire, std::numeric_limits<float>::infinity(), m_particle[i].objFather); // starts explosion
|
||||
dynamic_cast<CDamageableObject&>(*object).DamageObject(DamageType::Fire, std::numeric_limits<float>::infinity(), m_particle[i].objFather); // starts explosion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1344,7 +1344,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
{
|
||||
if (object->Implements(ObjectInterfaceType::Damageable))
|
||||
{
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Organic, 0.001f, m_particle[i].objFather);
|
||||
dynamic_cast<CDamageableObject&>(*object).DamageObject(DamageType::Organic, 0.001f, m_particle[i].objFather);
|
||||
}
|
||||
|
||||
m_exploGunCounter ++;
|
||||
|
@ -2422,7 +2422,7 @@ void CParticle::FrameParticle(float rTime)
|
|||
if (object != nullptr)
|
||||
{
|
||||
assert(object->Implements(ObjectInterfaceType::Damageable));
|
||||
dynamic_cast<CDamageableObject*>(object)->DamageObject(DamageType::Tower, std::numeric_limits<float>::infinity(), m_particle[i].objFather);
|
||||
dynamic_cast<CDamageableObject&>(*object).DamageObject(DamageType::Tower, std::numeric_limits<float>::infinity(), m_particle[i].objFather);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3543,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();
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ bool CPyro::Create(PyroType type, CObject* obj, float force)
|
|||
|
||||
CObject* power = nullptr;
|
||||
if (obj->Implements(ObjectInterfaceType::Powered))
|
||||
power = dynamic_cast<CPoweredObject*>(obj)->GetPower();
|
||||
power = dynamic_cast<CPoweredObject&>(*obj).GetPower();
|
||||
|
||||
if (power == nullptr)
|
||||
{
|
||||
|
@ -260,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<CControllableObject*>(m_object)->GetSelect() )
|
||||
if ( type == PT_SHOTH && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
|
||||
{
|
||||
m_sound->Play(SOUND_AIE, m_pos);
|
||||
m_sound->Play(SOUND_AIE, m_engine->GetEyePt());
|
||||
|
@ -278,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<CDestroyableObject*>(m_object)->SetDying(DeathType::Dead);
|
||||
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Dead);
|
||||
|
||||
assert(obj->Implements(ObjectInterfaceType::Movable));
|
||||
dynamic_cast<CMovableObject*>(obj)->GetMotion()->SetAction(MHS_DEADg, 1.0f);
|
||||
dynamic_cast<CMovableObject&>(*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);
|
||||
|
@ -291,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<CDestroyableObject*>(m_object)->SetDying(DeathType::Dead);
|
||||
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Dead);
|
||||
|
||||
assert(obj->Implements(ObjectInterfaceType::Movable));
|
||||
dynamic_cast<CMovableObject*>(obj)->GetMotion()->SetAction(MHS_DEADw, 1.0f);
|
||||
dynamic_cast<CMovableObject&>(*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);
|
||||
|
@ -312,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<CControllableObject*>(m_object)->GetSelect() )
|
||||
if ( m_camera->GetBlood() && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
|
||||
{
|
||||
m_camera->StartOver(CAM_OVER_EFFECT_BLOOD, m_pos, force);
|
||||
}
|
||||
|
@ -356,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 ||
|
||||
|
@ -399,7 +405,8 @@ bool CPyro::Create(PyroType type, CObject* obj, float force)
|
|||
if ( m_type != PT_FRAGV &&
|
||||
m_type != PT_EGG &&
|
||||
m_type != PT_WIN &&
|
||||
m_type != PT_LOST )
|
||||
m_type != PT_LOST &&
|
||||
m_type != PT_SQUASH)
|
||||
{
|
||||
float h = 40.0f;
|
||||
if ( m_type == PT_FRAGO ||
|
||||
|
@ -454,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);
|
||||
}
|
||||
|
@ -1049,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 )
|
||||
{
|
||||
|
@ -1229,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);
|
||||
|
@ -1395,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<CTransportableObject*>(m_object)->GetTransporter();
|
||||
CObject* transporter = dynamic_cast<CTransportableObject&>(*m_object).GetTransporter();
|
||||
if (transporter != nullptr)
|
||||
{
|
||||
if (transporter->Implements(ObjectInterfaceType::Powered))
|
||||
|
@ -1564,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<CDestroyableObject*>(m_object)->SetDying(DeathType::Exploding); // being destroyed
|
||||
dynamic_cast<CDestroyableObject&>(*m_object).SetDying(DeathType::Exploding); // being destroyed
|
||||
m_object->FlatParent();
|
||||
|
||||
if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject*>(m_object)->GetSelect() )
|
||||
if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
|
||||
{
|
||||
dynamic_cast<CControllableObject*>(m_object)->SetSelect(false); // deselects the object
|
||||
dynamic_cast<CControllableObject&>(*m_object).SetSelect(false); // deselects the object
|
||||
m_camera->SetType(CAM_TYPE_EXPLO);
|
||||
m_main->DeselectAll();
|
||||
}
|
||||
|
@ -1593,7 +1611,7 @@ void CPyro::ExploStart()
|
|||
|
||||
// TODO: temporary hack (hopefully)
|
||||
assert(m_object->Implements(ObjectInterfaceType::Old));
|
||||
Math::Vector pos = dynamic_cast<COldObject*>(m_object)->GetPartPosition(i);
|
||||
Math::Vector pos = dynamic_cast<COldObject&>(*m_object).GetPartPosition(i);
|
||||
|
||||
Math::Vector speed;
|
||||
float weight;
|
||||
|
@ -1640,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<CControllableObject*>(m_object)->GetSelect() )
|
||||
if ( m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject&>(*m_object).GetSelect() )
|
||||
{
|
||||
dynamic_cast<CControllableObject*>(m_object)->SetSelect(false); // deselects the object
|
||||
dynamic_cast<CControllableObject&>(*m_object).SetSelect(false); // deselects the object
|
||||
m_camera->SetType(CAM_TYPE_EXPLO);
|
||||
m_main->DeselectAll();
|
||||
}
|
||||
|
@ -2180,7 +2198,7 @@ void CPyro::BurnProgress()
|
|||
|
||||
if (m_object->Implements(ObjectInterfaceType::Powered))
|
||||
{
|
||||
CObject* sub = dynamic_cast<CPoweredObject*>(m_object)->GetPower();
|
||||
CObject* sub = dynamic_cast<CPoweredObject&>(*m_object).GetPower();
|
||||
if (sub != nullptr) // is there a battery?
|
||||
sub->SetScaleY(1.0f - m_progress); // complete flattening
|
||||
}
|
||||
|
@ -2274,7 +2292,7 @@ CObject* CPyro::FallSearchBeeExplo()
|
|||
|
||||
if (obj->GetType() == OBJECT_MOBILErs)
|
||||
{
|
||||
float shieldRadius = dynamic_cast<CShielder*>(obj)->GetActiveShieldRadius();
|
||||
float shieldRadius = dynamic_cast<CShielder&>(*obj).GetActiveShieldRadius();
|
||||
if ( shieldRadius > 0.0f )
|
||||
{
|
||||
float distance = Math::Distance(oPos, bulletCrashSphere.sphere.pos);
|
||||
|
@ -2342,12 +2360,12 @@ void CPyro::FallProgress(float rTime)
|
|||
{
|
||||
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
|
||||
// TODO: implement "killer"?
|
||||
dynamic_cast<CDestroyableObject*>(m_object)->DestroyObject(DestructionType::Explosion);
|
||||
dynamic_cast<CDestroyableObject&>(*m_object).DestroyObject(DestructionType::Explosion);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (obj->GetType() == OBJECT_MOBILErs && dynamic_cast<CShielder*>(obj)->GetActiveShieldRadius() > 0.0f) // protected by shield?
|
||||
if (obj->GetType() == OBJECT_MOBILErs && dynamic_cast<CShielder&>(*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);
|
||||
|
@ -2358,7 +2376,7 @@ void CPyro::FallProgress(float rTime)
|
|||
else
|
||||
{
|
||||
assert(obj->Implements(ObjectInterfaceType::Damageable));
|
||||
if (dynamic_cast<CDamageableObject*>(obj)->DamageObject(DamageType::FallingObject))
|
||||
if (dynamic_cast<CDamageableObject&>(*obj).DamageObject(DamageType::FallingObject))
|
||||
{
|
||||
DeleteObject(true, true); // removes the ball
|
||||
}
|
||||
|
@ -2366,7 +2384,7 @@ void CPyro::FallProgress(float rTime)
|
|||
{
|
||||
assert(m_object->Implements(ObjectInterfaceType::Destroyable));
|
||||
// TODO: implement "killer"?
|
||||
dynamic_cast<CDestroyableObject*>(m_object)->DestroyObject(DestructionType::Explosion);
|
||||
dynamic_cast<CDestroyableObject&>(*m_object).DestroyObject(DestructionType::Explosion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ enum PyroType
|
|||
PT_DEADW = 25, //! < drowning death
|
||||
PT_FINDING = 26, //! < object discovered
|
||||
PT_FRAGV = 27, //! < fragmentation of plant object
|
||||
PT_SQUASH = 28, //! < flattening plants
|
||||
};
|
||||
|
||||
} // namespace Gfx
|
||||
|
|
|
@ -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<Gfx::FontType>(type)] = MakeUnique<MultisizeFont>(fontLoader.GetFont(type));
|
||||
|
@ -214,8 +229,11 @@ 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<FontMetaChar>::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<FontMetaChar>::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<FontMetaChar>::iterator f
|
|||
if (format + fmtIndex != end)
|
||||
font = static_cast<FontType>(*(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<FontMetaChar>::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<UTF8Char> &
|
|||
if (format + index != end)
|
||||
font = static_cast<FontType>(*(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<UTF8Char> &
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -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<UTF8Char> &chars);
|
||||
void StringToUTFCharList(const std::string &text, std::vector<UTF8Char> &chars, std::vector<FontMetaChar>::iterator format, std::vector<FontMetaChar>::iterator end);
|
||||
|
||||
int GetCharSizeAt(Gfx::FontType font, const std::string& text, unsigned int index) const;
|
||||
|
||||
protected:
|
||||
CEngine* m_engine;
|
||||
CDevice* m_device;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -25,10 +25,11 @@
|
|||
// TODO: I'm not sure about "challenges" + "custom". It may be messing things up already right now.
|
||||
const std::map<LevelCategory, std::string> 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" },
|
||||
};
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ enum class LevelCategory
|
|||
Missions,
|
||||
FreeGame,
|
||||
CodeBattles,
|
||||
GamePlus,
|
||||
CustomLevels,
|
||||
Max,
|
||||
};
|
||||
|
|
|
@ -90,7 +90,7 @@ bool CMainMovie::Start(MainMovieType type, float time)
|
|||
}
|
||||
|
||||
assert(pObj->Implements(ObjectInterfaceType::Movable));
|
||||
dynamic_cast<CMovableObject*>(pObj)->GetMotion()->SetAction(MHS_SATCOM, 0.5f); // reads the SatCom
|
||||
dynamic_cast<CMovableObject&>(*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<CMovableObject*>(pObj)->GetMotion()->SetAction(-1); // finishes reading SatCom
|
||||
dynamic_cast<CMovableObject&>(*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<CMovableObject*>(pObj)->GetMotion()->SetAction(-1); // finishes reading SatCom
|
||||
dynamic_cast<CMovableObject&>(*pObj).GetMotion()->SetAction(-1); // finishes reading SatCom
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include <boost/algorithm/string/trim.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -885,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;
|
||||
|
|
|
@ -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";
|
||||
|
@ -742,7 +743,7 @@ bool CRobotMain::ProcessEvent(Event &event)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_sound->SetMusicVolume(100);
|
||||
m_sound->SetMusicVolume(MAXVOLUME*3/4);
|
||||
}
|
||||
// Set audio volume
|
||||
if (GetConfigFile().GetIntProperty("Setup", "AudioVolume", volume))
|
||||
|
@ -751,7 +752,7 @@ bool CRobotMain::ProcessEvent(Event &event)
|
|||
}
|
||||
else
|
||||
{
|
||||
m_sound->SetAudioVolume(100);
|
||||
m_sound->SetAudioVolume(MAXVOLUME);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1360,7 +1361,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
{
|
||||
CObject* object = GetSelect();
|
||||
if (object != nullptr && object->Implements(ObjectInterfaceType::Shielded))
|
||||
dynamic_cast<CShieldedObject*>(object)->SetMagnifyDamage(dynamic_cast<CShieldedObject*>(object)->GetMagnifyDamage()*0.1f);
|
||||
dynamic_cast<CShieldedObject&>(*object).SetMagnifyDamage(dynamic_cast<CShieldedObject&>(*object).GetMagnifyDamage()*0.1f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1368,7 +1369,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
{
|
||||
CObject* object = GetSelect();
|
||||
if (object != nullptr && object->Implements(ObjectInterfaceType::JetFlying))
|
||||
dynamic_cast<CJetFlyingObject*>(object)->SetRange(dynamic_cast<CJetFlyingObject*>(object)->GetRange()*10.0f);
|
||||
dynamic_cast<CJetFlyingObject&>(*object).SetRange(dynamic_cast<CJetFlyingObject&>(*object).GetRange()*10.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1393,16 +1394,16 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
{
|
||||
if (object->Implements(ObjectInterfaceType::Powered))
|
||||
{
|
||||
CObject* power = dynamic_cast<CPoweredObject*>(object)->GetPower();
|
||||
CObject* power = dynamic_cast<CPoweredObject&>(*object).GetPower();
|
||||
if (power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer))
|
||||
dynamic_cast<CPowerContainerObject*>(power)->SetEnergyLevel(1.0f);
|
||||
dynamic_cast<CPowerContainerObject&>(*power).SetEnergyLevel(1.0f);
|
||||
}
|
||||
|
||||
if (object->Implements(ObjectInterfaceType::Shielded))
|
||||
dynamic_cast<CShieldedObject*>(object)->SetShield(1.0f);
|
||||
dynamic_cast<CShieldedObject&>(*object).SetShield(1.0f);
|
||||
|
||||
if (object->Implements(ObjectInterfaceType::JetFlying))
|
||||
dynamic_cast<CJetFlyingObject*>(object)->SetReactorRange(1.0f);
|
||||
dynamic_cast<CJetFlyingObject&>(*object).SetReactorRange(1.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1415,9 +1416,9 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
{
|
||||
if (object->Implements(ObjectInterfaceType::Powered))
|
||||
{
|
||||
CObject* power = dynamic_cast<CPoweredObject*>(object)->GetPower();
|
||||
CObject* power = dynamic_cast<CPoweredObject&>(*object).GetPower();
|
||||
if (power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer))
|
||||
dynamic_cast<CPowerContainerObject*>(power)->SetEnergyLevel(1.0f);
|
||||
dynamic_cast<CPowerContainerObject&>(*power).SetEnergyLevel(1.0f);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -1427,7 +1428,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
{
|
||||
CObject* object = GetSelect();
|
||||
if (object != nullptr && object->Implements(ObjectInterfaceType::Shielded))
|
||||
dynamic_cast<CShieldedObject*>(object)->SetShield(1.0f);
|
||||
dynamic_cast<CShieldedObject&>(*object).SetShield(1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1437,7 +1438,7 @@ void CRobotMain::ExecuteCmd(const std::string& cmd)
|
|||
if (object != nullptr)
|
||||
{
|
||||
if (object->Implements(ObjectInterfaceType::JetFlying))
|
||||
dynamic_cast<CJetFlyingObject*>(object)->SetReactorRange(1.0f);
|
||||
dynamic_cast<CJetFlyingObject&>(*object).SetReactorRange(1.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1537,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<CMovableObject*>(obj)->GetMotion()->GetAction() == -1)
|
||||
if (dynamic_cast<CMovableObject&>(*obj).GetMotion()->GetAction() == -1)
|
||||
{
|
||||
m_movieInfoIndex = index;
|
||||
m_movie->Start(MM_SATCOMopen, 2.5f);
|
||||
|
@ -1851,7 +1852,7 @@ CObject* CRobotMain::DeselectAll()
|
|||
void CRobotMain::SelectOneObject(CObject* obj, bool displayError)
|
||||
{
|
||||
assert(obj->Implements(ObjectInterfaceType::Controllable));
|
||||
dynamic_cast<CControllableObject*>(obj)->SetSelect(true, displayError);
|
||||
dynamic_cast<CControllableObject&>(*obj).SetSelect(true, displayError);
|
||||
m_camera->SetControllingObject(obj);
|
||||
|
||||
ObjectType type = obj->GetType();
|
||||
|
@ -1890,7 +1891,7 @@ void CRobotMain::SelectOneObject(CObject* obj, bool displayError)
|
|||
type == OBJECT_MOBILEdr ||
|
||||
type == OBJECT_APOLLO2 )
|
||||
{
|
||||
m_camera->SetType(dynamic_cast<CControllableObject*>(obj)->GetCameraType());
|
||||
m_camera->SetType(dynamic_cast<CControllableObject&>(*obj).GetCameraType());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1906,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<CControllableObject*>(obj)->GetSelectable() || m_cheatSelectInsect))) return false;
|
||||
(!obj->Implements(ObjectInterfaceType::Controllable) || !(dynamic_cast<CControllableObject&>(*obj).GetSelectable() || m_cheatSelectInsect))) return false;
|
||||
|
||||
if (m_missionType == MISSION_CODE_BATTLE && m_codeBattleStarted && m_codeBattleSpectator)
|
||||
{
|
||||
|
@ -1982,7 +1983,7 @@ CObject* CRobotMain::GetSelect()
|
|||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (!obj->Implements(ObjectInterfaceType::Controllable)) continue;
|
||||
if (dynamic_cast<CControllableObject*>(obj)->GetSelect())
|
||||
if (dynamic_cast<CControllableObject&>(*obj).GetSelect())
|
||||
return obj;
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -2000,7 +2001,7 @@ CObject* CRobotMain::DetectObject(Math::Point pos)
|
|||
|
||||
CObject* transporter = nullptr;
|
||||
if (obj->Implements(ObjectInterfaceType::Transportable))
|
||||
transporter = dynamic_cast<CTransportableObject*>(obj)->GetTransporter();
|
||||
transporter = dynamic_cast<CTransportableObject&>(*obj).GetTransporter();
|
||||
|
||||
if (transporter != nullptr && !transporter->GetDetectable()) continue;
|
||||
if (obj->GetProxyActivate()) continue;
|
||||
|
@ -2008,14 +2009,14 @@ CObject* CRobotMain::DetectObject(Math::Point pos)
|
|||
CObject* target = obj;
|
||||
if (obj->Implements(ObjectInterfaceType::PowerContainer) && obj->Implements(ObjectInterfaceType::Transportable))
|
||||
{
|
||||
target = dynamic_cast<CTransportableObject*>(obj)->GetTransporter(); // battery connected
|
||||
target = dynamic_cast<CTransportableObject&>(*obj).GetTransporter(); // battery connected
|
||||
if (target == nullptr)
|
||||
{
|
||||
target = obj; // standalone battery
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!target->Implements(ObjectInterfaceType::Powered) || dynamic_cast<CPoweredObject*>(target)->GetPower() != obj)
|
||||
if (!target->Implements(ObjectInterfaceType::Powered) || dynamic_cast<CPoweredObject&>(*target).GetPower() != obj)
|
||||
{
|
||||
// transported, but not in the power slot
|
||||
target = obj;
|
||||
|
@ -2045,7 +2046,7 @@ bool CRobotMain::DestroySelectedObject()
|
|||
|
||||
m_engine->GetPyroManager()->Create(Gfx::PT_FRAGT, obj);
|
||||
|
||||
dynamic_cast<CControllableObject*>(obj)->SetSelect(false); // deselects the object
|
||||
dynamic_cast<CControllableObject&>(*obj).SetSelect(false); // deselects the object
|
||||
m_camera->SetType(Gfx::CAM_TYPE_EXPLO);
|
||||
DeselectAll();
|
||||
RemoveFromSelectionHistory(obj);
|
||||
|
@ -2068,7 +2069,7 @@ void CRobotMain::HiliteClear()
|
|||
for (CObject* obj : m_objMan->GetAllObjects())
|
||||
{
|
||||
if (!obj->Implements(ObjectInterfaceType::Controllable)) continue;
|
||||
dynamic_cast<CControllableObject*>(obj)->SetHighlight(false);
|
||||
dynamic_cast<CControllableObject&>(*obj).SetHighlight(false);
|
||||
}
|
||||
m_map->SetHighlight(nullptr);
|
||||
m_short->SetHighlight(nullptr);
|
||||
|
@ -2128,12 +2129,12 @@ void CRobotMain::HiliteObject(Math::Point pos)
|
|||
}
|
||||
}
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Controllable) && (dynamic_cast<CControllableObject*>(obj)->GetSelectable() || m_cheatSelectInsect))
|
||||
if (obj->Implements(ObjectInterfaceType::Controllable) && (dynamic_cast<CControllableObject&>(*obj).GetSelectable() || m_cheatSelectInsect))
|
||||
{
|
||||
if (dynamic_cast<CControllableObject*>(obj)->GetSelectable())
|
||||
if (dynamic_cast<CControllableObject&>(*obj).GetSelectable())
|
||||
{
|
||||
// Don't highlight objects that would not be selectable without selectinsect
|
||||
dynamic_cast<CControllableObject*>(obj)->SetHighlight(true);
|
||||
dynamic_cast<CControllableObject&>(*obj).SetHighlight(true);
|
||||
}
|
||||
m_map->SetHighlight(obj);
|
||||
m_short->SetHighlight(obj);
|
||||
|
@ -2390,7 +2391,7 @@ bool CRobotMain::EventFrame(const Event &event)
|
|||
if (obj->GetType() == OBJECT_TOTO)
|
||||
toto = obj;
|
||||
else if (obj->Implements(ObjectInterfaceType::Interactive))
|
||||
dynamic_cast<CInteractiveObject*>(obj)->EventProcess(event);
|
||||
dynamic_cast<CInteractiveObject&>(*obj).EventProcess(event);
|
||||
|
||||
if ( obj->GetProxyActivate() ) // active if it is near?
|
||||
{
|
||||
|
@ -2413,7 +2414,7 @@ bool CRobotMain::EventFrame(const Event &event)
|
|||
continue;
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Interactive))
|
||||
dynamic_cast<CInteractiveObject*>(obj)->EventProcess(event);
|
||||
dynamic_cast<CInteractiveObject&>(*obj).EventProcess(event);
|
||||
}
|
||||
|
||||
m_engine->GetPyroManager()->EventProcess(event);
|
||||
|
@ -2437,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<CInteractiveObject*>(toto)->EventProcess(event);
|
||||
dynamic_cast<CInteractiveObject&>(*toto).EventProcess(event);
|
||||
|
||||
// NOTE: m_movieLock is set only after the first update of CAutoBase finishes
|
||||
|
||||
|
@ -2461,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)
|
||||
|
@ -2670,7 +2672,7 @@ bool CRobotMain::EventObject(const Event &event)
|
|||
{
|
||||
if (obj->Implements(ObjectInterfaceType::Interactive))
|
||||
{
|
||||
dynamic_cast<CInteractiveObject*>(obj)->EventProcess(event);
|
||||
dynamic_cast<CInteractiveObject&>(*obj).EventProcess(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2711,7 +2713,7 @@ void CRobotMain::ScenePerso()
|
|||
obj->SetDrawFront(true); // draws the interface
|
||||
|
||||
assert(obj->Implements(ObjectInterfaceType::Movable));
|
||||
CMotionHuman* mh = static_cast<CMotionHuman*>(dynamic_cast<CMovableObject*>(obj)->GetMotion());
|
||||
CMotionHuman* mh = static_cast<CMotionHuman*>(dynamic_cast<CMovableObject&>(*obj).GetMotion());
|
||||
mh->StartDisplayPerso();
|
||||
}
|
||||
}
|
||||
|
@ -3149,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;
|
||||
}
|
||||
|
@ -3379,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<COldObject*>(m_controller)->SetCheckToken(false);
|
||||
dynamic_cast<COldObject&>(*m_controller).SetCheckToken(false);
|
||||
|
||||
if (line->GetParam("script")->IsDefined())
|
||||
{
|
||||
|
@ -3387,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<CProgrammableObject*>(m_controller)->RunProgram(program);
|
||||
dynamic_cast<CProgrammableObject&>(*m_controller).RunProgram(program);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -3412,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<CMovableObject*>(obj)->GetMotion();
|
||||
CMotion* motion = dynamic_cast<CMovableObject&>(*obj).GetMotion();
|
||||
if (m_phase == PHASE_WIN ) motion->SetAction(MHS_WIN, 0.4f);
|
||||
if (m_phase == PHASE_LOST) motion->SetAction(MHS_LOST, 0.5f);
|
||||
}
|
||||
|
@ -3427,7 +3431,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
|
|||
{
|
||||
CProgramStorageObject* programStorage = dynamic_cast<CProgramStorageObject*>(obj);
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject*>(obj)->GetSelectable() && obj->GetType() != OBJECT_HUMAN)
|
||||
if (obj->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject&>(*obj).GetSelectable() && obj->GetType() != OBJECT_HUMAN)
|
||||
{
|
||||
programStorage->SetProgramStorageIndex(rankObj);
|
||||
}
|
||||
|
@ -3781,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?
|
||||
|
@ -3810,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<CControllableObject*>(obj)->GetCameraType());
|
||||
m_camera->SetType(dynamic_cast<CControllableObject&>(*obj).GetCameraType());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3911,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;
|
||||
|
@ -4406,7 +4417,7 @@ void CRobotMain::StartShowLimit()
|
|||
CObject* obj = GetSelect();
|
||||
if (obj == nullptr) return;
|
||||
if (!obj->Implements(ObjectInterfaceType::Ranged)) return;
|
||||
float range = dynamic_cast<CRangedObject*>(obj)->GetShowLimitRadius();
|
||||
float range = dynamic_cast<CRangedObject&>(*obj).GetShowLimitRadius();
|
||||
if (range == 0.0f) return;
|
||||
SetShowLimit(0, Gfx::PARTILIMIT1, obj, obj->GetPosition(), range);
|
||||
}
|
||||
|
@ -4576,8 +4587,8 @@ bool CRobotMain::IOIsBusy()
|
|||
{
|
||||
if (! obj->Implements(ObjectInterfaceType::TaskExecutor)) continue;
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable) && dynamic_cast<CProgrammableObject*>(obj)->IsProgram()) continue; // TODO: I'm not sure if this is correct but this is how it worked earlier
|
||||
if (dynamic_cast<CTaskExecutorObject*>(obj)->IsForegroundTask()) return true;
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable) && dynamic_cast<CProgrammableObject&>(*obj).IsProgram()) continue; // TODO: I'm not sure if this is correct but this is how it worked earlier
|
||||
if (dynamic_cast<CTaskExecutorObject&>(*obj).IsForegroundTask()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -4628,7 +4639,7 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj, const std::
|
|||
|
||||
if (obj->Implements(ObjectInterfaceType::Programmable))
|
||||
{
|
||||
int run = dynamic_cast<CProgramStorageObject*>(obj)->GetProgramIndex(dynamic_cast<CProgrammableObject*>(obj)->GetCurrentProgram());
|
||||
int run = dynamic_cast<CProgramStorageObject&>(*obj).GetProgramIndex(dynamic_cast<CProgrammableObject&>(*obj).GetCurrentProgram());
|
||||
if (run != -1)
|
||||
{
|
||||
line->AddParam("run", MakeUnique<CLevelParserParam>(run+1));
|
||||
|
@ -4703,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<CDestroyableObject*>(obj)->IsDying()) continue;
|
||||
if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast<CDestroyableObject&>(*obj).IsDying()) continue;
|
||||
|
||||
if (obj->Implements(ObjectInterfaceType::Carrier))
|
||||
{
|
||||
CObject* cargo = dynamic_cast<CCarrierObject*>(obj)->GetCargo();
|
||||
CObject* cargo = dynamic_cast<CCarrierObject&>(*obj).GetCargo();
|
||||
if (cargo != nullptr) // object transported?
|
||||
{
|
||||
line = MakeUnique<CLevelParserLine>("CreateFret");
|
||||
|
@ -4718,7 +4729,7 @@ bool CRobotMain::IOWriteScene(std::string filename, std::string filecbot, std::s
|
|||
|
||||
if (obj->Implements(ObjectInterfaceType::Powered))
|
||||
{
|
||||
CObject* power = dynamic_cast<CPoweredObject*>(obj)->GetPower();
|
||||
CObject* power = dynamic_cast<CPoweredObject&>(*obj).GetPower();
|
||||
if (power != nullptr) // battery transported?
|
||||
{
|
||||
line = MakeUnique<CLevelParserLine>("CreatePower");
|
||||
|
@ -4757,7 +4768,7 @@ 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<CDestroyableObject*>(obj)->IsDying()) continue;
|
||||
if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast<CDestroyableObject&>(*obj).IsDying()) continue;
|
||||
|
||||
if (!SaveFileStack(obj, ostr))
|
||||
{
|
||||
|
@ -4908,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<CCarrierObject*>(obj)->SetCargo(cargo);
|
||||
dynamic_cast<CCarrierObject&>(*obj).SetCargo(cargo);
|
||||
auto task = MakeUnique<CTaskManip>(dynamic_cast<COldObject*>(obj));
|
||||
task->Start(TMO_AUTO, TMA_GRAB); // holds the object!
|
||||
}
|
||||
|
@ -4916,9 +4927,9 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
|||
if (power != nullptr)
|
||||
{
|
||||
assert(obj->Implements(ObjectInterfaceType::Powered));
|
||||
dynamic_cast<CPoweredObject*>(obj)->SetPower(power);
|
||||
dynamic_cast<CPoweredObject&>(*obj).SetPower(power);
|
||||
assert(power->Implements(ObjectInterfaceType::Transportable));
|
||||
dynamic_cast<CTransportableObject*>(power)->SetTransporter(obj);
|
||||
dynamic_cast<CTransportableObject&>(*power).SetTransporter(obj);
|
||||
}
|
||||
cargo = nullptr;
|
||||
power = nullptr;
|
||||
|
@ -4950,7 +4961,7 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
|
|||
{
|
||||
if (obj->GetType() == OBJECT_TOTO) continue;
|
||||
if (IsObjectBeingTransported(obj)) continue;
|
||||
if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast<CDestroyableObject*>(obj)->IsDying()) continue;
|
||||
if (obj->Implements(ObjectInterfaceType::Destroyable) && dynamic_cast<CDestroyableObject&>(*obj).IsDying()) continue;
|
||||
|
||||
if (!ReadFileStack(obj, istr))
|
||||
{
|
||||
|
@ -5307,7 +5318,7 @@ Error CRobotMain::CheckEndMission(bool frame)
|
|||
if (m_base != nullptr && !m_endTakeImmediat)
|
||||
{
|
||||
assert(m_base->Implements(ObjectInterfaceType::Controllable));
|
||||
if(dynamic_cast<CControllableObject*>(m_base)->GetSelectable())
|
||||
if(dynamic_cast<CControllableObject&>(*m_base).GetSelectable())
|
||||
return ERR_MISSION_NOTERM;
|
||||
}
|
||||
}
|
||||
|
@ -5347,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()
|
||||
{
|
||||
|
@ -5870,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;
|
||||
|
@ -5940,6 +5962,8 @@ Error CRobotMain::CanFactoryError(ObjectType type, int team)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -5976,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)
|
||||
|
|
|
@ -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();
|
||||
|
@ -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;
|
||||
|
|
|
@ -82,7 +82,7 @@ bool CObjectCondition::CheckForObject(CObject* obj)
|
|||
}
|
||||
else if (obj->Implements(ObjectInterfaceType::Powered))
|
||||
{
|
||||
CObject* powerObj = dynamic_cast<CPoweredObject*>(obj)->GetPower();
|
||||
CObject* powerObj = dynamic_cast<CPoweredObject&>(*obj).GetPower();
|
||||
if(powerObj != nullptr && powerObj->Implements(ObjectInterfaceType::PowerContainer))
|
||||
{
|
||||
power = dynamic_cast<CPowerContainerObject*>(powerObj);
|
||||
|
@ -98,7 +98,7 @@ bool CObjectCondition::CheckForObject(CObject* obj)
|
|||
|
||||
Math::Vector oPos;
|
||||
if (IsObjectBeingTransported(obj))
|
||||
oPos = dynamic_cast<CTransportableObject*>(obj)->GetTransporter()->GetPosition();
|
||||
oPos = dynamic_cast<CTransportableObject&>(*obj).GetTransporter()->GetPosition();
|
||||
else
|
||||
oPos = obj->GetPosition();
|
||||
oPos.y = 0.0f;
|
||||
|
|
|
@ -169,7 +169,7 @@ begin:
|
|||
else
|
||||
{
|
||||
assert(pObj->Implements(ObjectInterfaceType::Controllable));
|
||||
m_camera->SetType(dynamic_cast<CControllableObject*>(pObj)->GetCameraType());
|
||||
m_camera->SetType(dynamic_cast<CControllableObject&>(*pObj).GetCameraType());
|
||||
}
|
||||
|
||||
m_main->StartMusic();
|
||||
|
@ -594,7 +594,7 @@ begin:
|
|||
else
|
||||
{
|
||||
assert(pObj->Implements(ObjectInterfaceType::Controllable));
|
||||
m_camera->SetType(dynamic_cast<CControllableObject*>(pObj)->GetCameraType());
|
||||
m_camera->SetType(dynamic_cast<CControllableObject&>(*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<CControllableObject*>(pObj)->GetCameraType());
|
||||
m_camera->SetType(dynamic_cast<CControllableObject&>(*pObj).GetCameraType());
|
||||
}
|
||||
|
||||
m_engine->SetFogStart(m_fogStart);
|
||||
|
@ -1248,7 +1248,7 @@ void CAutoBase::FreezeCargo(bool freeze)
|
|||
m_cargoObjects.insert(obj);
|
||||
if ( obj->Implements(ObjectInterfaceType::Movable) )
|
||||
{
|
||||
CPhysics* physics = dynamic_cast<CMovableObject*>(obj)->GetPhysics();
|
||||
CPhysics* physics = dynamic_cast<CMovableObject&>(*obj).GetPhysics();
|
||||
physics->SetFreeze(freeze);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ bool CAutoDestroyer::EventProcess(const Event &event)
|
|||
if ( scrap != nullptr )
|
||||
{
|
||||
assert(scrap->Implements(ObjectInterfaceType::Destroyable));
|
||||
dynamic_cast<CDestroyableObject*>(scrap)->DestroyObject(DestructionType::Explosion);
|
||||
dynamic_cast<CDestroyableObject&>(*scrap).DestroyObject(DestructionType::Explosion);
|
||||
}
|
||||
m_bExplo = true;
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ void CAutoEgg::DeleteObject(bool all)
|
|||
alien->SetLock(false);
|
||||
if (alien->Implements(ObjectInterfaceType::Programmable))
|
||||
{
|
||||
dynamic_cast<CProgrammableObject*>(alien)->SetActivity(true); // the insect is active
|
||||
dynamic_cast<CProgrammableObject&>(*alien).SetActivity(true); // the insect is active
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -123,7 +123,7 @@ void CAutoEgg::Init()
|
|||
|
||||
if (alien->Implements(ObjectInterfaceType::Programmable))
|
||||
{
|
||||
dynamic_cast<CProgrammableObject*>(alien)->SetActivity(false);
|
||||
dynamic_cast<CProgrammableObject&>(*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<CProgrammableObject*>(alien)->SetActivity(false);
|
||||
dynamic_cast<CProgrammableObject&>(*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<CProgrammableObject*>(alien)->SetActivity(true); // the insect is active
|
||||
dynamic_cast<CProgrammableObject&>(*alien).SetActivity(true); // the insect is active
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -397,7 +397,7 @@ bool CAutoFactory::EventProcess(const Event &event)
|
|||
if ( vehicle != nullptr )
|
||||
{
|
||||
assert(vehicle->Implements(ObjectInterfaceType::Movable));
|
||||
physics = dynamic_cast<CMovableObject*>(vehicle)->GetPhysics();
|
||||
physics = dynamic_cast<CMovableObject&>(*vehicle).GetPhysics();
|
||||
physics->SetFreeze(false); // can move
|
||||
|
||||
vehicle->SetLock(false); // vehicle useable
|
||||
|
@ -408,7 +408,7 @@ bool CAutoFactory::EventProcess(const Event &event)
|
|||
{
|
||||
if (vehicle->Implements(ObjectInterfaceType::Programmable) && vehicle->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
{
|
||||
Program* program = dynamic_cast<CProgramStorageObject*>(vehicle)->AddProgram();
|
||||
Program* program = dynamic_cast<CProgramStorageObject&>(*vehicle).AddProgram();
|
||||
|
||||
if (boost::regex_match(m_program, boost::regex("[A-Za-z0-9_]+"))) // Public function name?
|
||||
{
|
||||
|
@ -424,7 +424,7 @@ bool CAutoFactory::EventProcess(const Event &event)
|
|||
program->script->SendScript(m_program.c_str());
|
||||
}
|
||||
|
||||
dynamic_cast<CProgrammableObject*>(vehicle)->RunProgram(program);
|
||||
dynamic_cast<CProgrammableObject&>(*vehicle).RunProgram(program);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -670,7 +670,7 @@ bool CAutoFactory::CreateVehicle()
|
|||
vehicle->SetLock(true); // not usable
|
||||
|
||||
assert(vehicle->Implements(ObjectInterfaceType::Movable));
|
||||
CPhysics* physics = dynamic_cast<CMovableObject*>(vehicle)->GetPhysics();
|
||||
CPhysics* physics = dynamic_cast<CMovableObject&>(*vehicle).GetPhysics();
|
||||
physics->SetFreeze(true); // it doesn't move
|
||||
|
||||
if (vehicle->Implements(ObjectInterfaceType::ProgramStorage))
|
||||
|
|
|
@ -400,7 +400,7 @@ void CAutoNuclearPlant::CreatePower()
|
|||
float powerLevel = 1.0f;
|
||||
CObject* power = CObjectManager::GetInstancePointer()->CreateObject(pos, angle, OBJECT_ATOMIC, powerLevel);
|
||||
|
||||
dynamic_cast<CTransportableObject*>(power)->SetTransporter(m_object);
|
||||
dynamic_cast<CTransportableObject&>(*power).SetTransporter(m_object);
|
||||
power->SetPosition(Math::Vector(22.0f, 3.0f, 0.0f));
|
||||
m_object->SetPower(power);
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ void CAutoPowerCaptor::ChargeObject(float rTime)
|
|||
|
||||
if (obj->Implements(ObjectInterfaceType::Powered))
|
||||
{
|
||||
CObject* power = dynamic_cast<CPoweredObject*>(obj)->GetPower();
|
||||
CObject* power = dynamic_cast<CPoweredObject&>(*obj).GetPower();
|
||||
if ( power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer) )
|
||||
{
|
||||
CPowerContainerObject* powerContainer = dynamic_cast<CPowerContainerObject*>(power);
|
||||
|
@ -285,7 +285,7 @@ void CAutoPowerCaptor::ChargeObject(float rTime)
|
|||
|
||||
if (obj->Implements(ObjectInterfaceType::Carrier))
|
||||
{
|
||||
CObject* power = dynamic_cast<CCarrierObject*>(obj)->GetCargo();
|
||||
CObject* power = dynamic_cast<CCarrierObject&>(*obj).GetCargo();
|
||||
if ( power != nullptr && power->Implements(ObjectInterfaceType::PowerContainer) )
|
||||
{
|
||||
CPowerContainerObject* powerContainer = dynamic_cast<CPowerContainerObject*>(power);
|
||||
|
|
|
@ -331,7 +331,7 @@ bool CAutoPowerPlant::EventProcess(const Event &event)
|
|||
|
||||
cargo->SetScale(1.0f);
|
||||
cargo->SetLock(false); // usable battery
|
||||
dynamic_cast<CTransportableObject*>(cargo)->SetTransporter(m_object);
|
||||
dynamic_cast<CTransportableObject&>(*cargo).SetTransporter(m_object);
|
||||
cargo->SetPosition(Math::Vector(0.0f, 3.0f, 0.0f));
|
||||
m_object->SetPower(cargo);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue