diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index ec328113d..cd8498c2e 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -90,14 +90,14 @@ jobs: - platform: android-32 os: macos-14 extension: apk - preset: android-daily-release + preset: android-conan-ninja-release conan_profile: android-32 conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT artifact_platform: armeabi-v7a - platform: android-64 os: macos-14 extension: apk - preset: android-daily-release + preset: android-conan-ninja-release conan_profile: android-64 conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT artifact_platform: arm64-v8a @@ -111,22 +111,6 @@ jobs: with: submodules: recursive - - name: Ensure LF line endings - if: ${{ startsWith(matrix.preset, 'linux-clang-test') }} - run: | - find . -path ./.git -prune -o -path ./AI/FuzzyLite -prune -o -path ./test/googletest \ - -o -path ./osx -prune -o -type f \ - -not -name '*.png' -and -not -name '*.vcxproj*' -and -not -name '*.props' -and -not -name '*.wav' -and -not -name '*.webm' -and -not -name '*.ico' -and -not -name '*.bat' -print0 | \ - { ! xargs -0 grep -l -z -P '\r\n'; } - - - name: Validate JSON - # the Python yaml module doesn't seem to work on mac-arm - # also, running it on multiple presets is redundant and slightly increases already long CI built times - if: ${{ startsWith(matrix.preset, 'linux-clang-test') }} - run: | - sudo apt install python3-jstyleson - python3 CI/linux-qt6/validate_json.py - - name: Dependencies run: source '${{github.workspace}}/CI/${{matrix.platform}}/before_install.sh' env: @@ -210,6 +194,9 @@ jobs: if [[ ${{matrix.preset}} == linux-gcc-test ]] then cmake -DENABLE_CCACHE:BOOL=ON -DCMAKE_C_COMPILER=gcc-14 -DCMAKE_CXX_COMPILER=g++-14 --preset ${{ matrix.preset }} + elif [[ (${{matrix.preset}} == android-conan-ninja-release) && (${{github.ref}} != 'refs/heads/master') ]] + then + cmake -DENABLE_CCACHE:BOOL=ON -DANDROID_GRADLE_PROPERTIES="applicationIdSuffix=.daily;signingConfig=dailySigning;applicationLabel=VCMI daily" --preset ${{ matrix.preset }} elif [[ ${{matrix.platform}} != msvc ]] then cmake -DENABLE_CCACHE:BOOL=ON --preset ${{ matrix.preset }} @@ -220,6 +207,9 @@ jobs: - name: Build run: | cmake --build --preset ${{matrix.preset}} + env: + ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }} + ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} - name: Test env: @@ -247,12 +237,6 @@ jobs: && '${{github.workspace}}/CI/${{matrix.platform}}/post_pack.sh' '${{github.workspace}}' "$(ls '${{ env.VCMI_PACKAGE_FILE_NAME }}'.*)" rm -rf _CPack_Packages - - name: Additional logs - if: ${{ failure() && steps.cpack.outcome == 'failure' && matrix.platform == 'msvc' }} - run: | - cat '${{github.workspace}}/out/build/${{matrix.preset}}/_CPack_Packages/win32/NSIS/project.nsi' - cat '${{github.workspace}}/out/build/${{matrix.preset}}/_CPack_Packages/win32/NSIS/NSISOutput.log' - - name: Artifacts if: ${{ matrix.pack == 1 }} uses: actions/upload-artifact@v4 @@ -265,10 +249,15 @@ jobs: if: ${{ startsWith(matrix.platform, 'android') }} run: | builtApkPath="$(ls ${{ github.workspace }}/out/build/${{ matrix.preset }}/android-build/vcmi-app/build/outputs/apk/release/*.${{ matrix.extension }})" + builtAabPath="$(ls ${{ github.workspace }}/out/build/${{ matrix.preset }}/android-build/vcmi-app/build/outputs/bundle/release/*.aab)" ANDROID_APK_PATH="${{ github.workspace }}/$VCMI_PACKAGE_FILE_NAME.${{ matrix.extension }}" + ANDROID_AAB_PATH="${{ github.workspace }}/$VCMI_PACKAGE_FILE_NAME.aab" mv "$builtApkPath" "$ANDROID_APK_PATH" + mv "$builtAabPath" "$ANDROID_AAB_PATH" echo "ANDROID_APK_PATH=$ANDROID_APK_PATH" >> $GITHUB_ENV - - name: Android artifacts + echo "ANDROID_AAB_PATH=$ANDROID_AAB_PATH" >> $GITHUB_ENV + + - name: Android apk artifacts if: ${{ startsWith(matrix.platform, 'android') }} uses: actions/upload-artifact@v4 with: @@ -276,6 +265,14 @@ jobs: path: | ${{ env.ANDROID_APK_PATH }} + - name: Android aab artifacts + if: ${{ startsWith(matrix.platform, 'android') }} + uses: actions/upload-artifact@v4 + with: + name: ${{ env.VCMI_PACKAGE_FILE_NAME }} - ${{ matrix.platform }} - aab + path: | + ${{ env.ANDROID_AAB_PATH }} + - name: Symbols if: ${{ matrix.platform == 'msvc' }} uses: actions/upload-artifact@v4 @@ -284,14 +281,6 @@ jobs: path: | ${{github.workspace}}/**/*.pdb - - name: Android JNI ${{matrix.platform}} - if: ${{ startsWith(matrix.platform, 'android') && github.ref == 'refs/heads/master' }} - uses: actions/upload-artifact@v4 - with: - name: Android JNI ${{matrix.platform}} - path: | - ${{github.workspace}}/out/build/${{matrix.preset}}/android-build/libs - - name: Upload build if: ${{ (matrix.pack == 1 || startsWith(matrix.platform, 'android')) && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/features/')) && matrix.platform != 'msvc' && matrix.platform != 'mingw-32' }} continue-on-error: true @@ -304,107 +293,6 @@ jobs: DEPLOY_RSA: ${{ secrets.DEPLOY_RSA }} PACKAGE_EXTENSION: ${{ matrix.extension }} - # copy-pasted mostly - bundle_release: - - needs: build - if: always() && github.ref == 'refs/heads/master' - strategy: - matrix: - include: - - platform: android-32 - os: macos-14 - preset: android-conan-ninja-release - conan_profile: android-32 - conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT - artifact_platform: aab - runs-on: ${{ matrix.os }} - defaults: - run: - shell: bash - - steps: - - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Dependencies - run: source '${{github.workspace}}/CI/${{matrix.platform}}/before_install.sh' - env: - VCMI_BUILD_PLATFORM: x64 - - - uses: actions/setup-python@v5 - if: "${{ matrix.conan_profile != '' }}" - with: - python-version: '3.10' - - - name: Conan setup - if: "${{ matrix.conan_profile != '' }}" - run: | - pip3 install 'conan<2.0' - conan profile new default --detect - conan install . \ - --install-folder=conan-generated \ - --no-imports \ - --build=never \ - --profile:build=default \ - --profile:host=CI/conan/${{ matrix.conan_profile }} \ - ${{ matrix.conan_options }} - env: - GENERATE_ONLY_BUILT_CONFIG: 1 - - - uses: actions/setup-java@v4 - if: ${{ startsWith(matrix.platform, 'android') }} - with: - distribution: 'temurin' - java-version: '11' - - - name: Build Number - run: | - source '${{github.workspace}}/CI/get_package_name.sh' - if [ '${{ matrix.artifact_platform }}' ]; then - VCMI_PACKAGE_FILE_NAME+="-${{ matrix.artifact_platform }}" - fi - echo VCMI_PACKAGE_FILE_NAME="$VCMI_PACKAGE_FILE_NAME" >> $GITHUB_ENV - echo VCMI_PACKAGE_NAME_SUFFIX="$VCMI_PACKAGE_NAME_SUFFIX" >> $GITHUB_ENV - echo VCMI_PACKAGE_GOLDMASTER="$VCMI_PACKAGE_GOLDMASTER" >> $GITHUB_ENV - env: - PULL_REQUEST: ${{ github.event.pull_request.number }} - - - name: CMake Preset - run: | - cmake --preset ${{ matrix.preset }} - - - name: Build Preset - run: | - cmake --build --preset ${{matrix.preset}} - env: - ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }} - ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} - - - name: Download libs x64 - uses: actions/download-artifact@v4 - with: - name: Android JNI android-64 - path: ${{ github.workspace }}/out/build/${{ matrix.preset }}/android-build/libs - - - name: Create Android package - run: | - cd out/build/${{ matrix.preset }}/android-build - ./gradlew bundleRelease --info - echo ANDROID_APK_PATH="$(ls ${{ github.workspace }}/out/build/${{ matrix.preset }}/android-build/vcmi-app/build/outputs/bundle/release/*.aab)" >> $GITHUB_ENV - env: - ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }} - ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }} - - - name: Android artifacts - uses: actions/upload-artifact@v4 - with: - name: ${{ env.VCMI_PACKAGE_FILE_NAME }} - path: | - ${{ env.ANDROID_APK_PATH }} - - deploy-src: if: always() && github.ref == 'refs/heads/master' runs-on: ubuntu-latest @@ -434,3 +322,29 @@ jobs: name: ${{ env.VCMI_PACKAGE_FILE_NAME }} path: | ./release.tar.gz + + validate-code: + if: always() + runs-on: ubuntu-24.04 + defaults: + run: + shell: bash + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + if: "${{ matrix.conan_profile != '' }}" + with: + python-version: '3.10' + + - name: Ensure LF line endings + run: | + find . -path ./.git -prune -o -path ./AI/FuzzyLite -prune -o -path ./test/googletest \ + -o -path ./osx -prune -o -type f \ + -not -name '*.png' -and -not -name '*.vcxproj*' -and -not -name '*.props' -and -not -name '*.wav' -and -not -name '*.webm' -and -not -name '*.ico' -and -not -name '*.bat' -print0 | \ + { ! xargs -0 grep -l -z -P '\r\n'; } + + - name: Validate JSON + run: | + sudo apt install python3-jstyleson + python3 CI/linux-qt6/validate_json.py diff --git a/.travis.yml b/.travis.yml index 492820a41..9de209a7b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,8 +51,6 @@ notifications: - noreply@vcmi.eu on_success: change on_failure: always - slack: - secure: KHXFe14FFKtw5mErWbj730+utqy7i/3AUobWfAMAGvWI5sJYlhbBU+KvvCoD2SlRQg3mQqgwVw8NBJF1Mffs7WcRmrFFFmuMqZxFLAfKBd3T0CxWpAGfnfNgDmlfV4OfEgQWk1pakEPOymhxbbmLUuCjykZDuTcioxAk0UAHDwY= before_install: - test $TRAVIS_BRANCH != coverity_scan -o ${TRAVIS_JOB_NUMBER##*.} = 1 || exit 0 diff --git a/AI/BattleAI/BattleEvaluator.cpp b/AI/BattleAI/BattleEvaluator.cpp index 3c4b2d52a..2824b39e1 100644 --- a/AI/BattleAI/BattleEvaluator.cpp +++ b/AI/BattleAI/BattleEvaluator.cpp @@ -674,6 +674,9 @@ bool BattleEvaluator::attemptCastingSpell(const CStack * activeStack) } for(const auto & unit : allUnits) { + if (!unit->isValidTarget()) + continue; + auto newHealth = unit->getAvailableHealth(); auto oldHealth = vstd::find_or(healthOfStack, unit->unitId(), 0); // old health value may not exist for newly summoned units diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index 330183de1..f3feeda6b 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -649,7 +649,7 @@ void AIGateway::showBlockingDialog(const std::string & text, const std::vector(danger) / hero->getTotalStrength(); answer = topObj->id == goalObjectID; // no if we do not aim to visit this object - logAi->trace("Query hook: %s(%s) by %s danger ratio %f", target.toString(), topObj->getObjectName(), hero.name, ratio); + logAi->trace("Query hook: %s(%s) by %s danger ratio %f", target.toString(), topObj->getObjectName(), hero.name(), ratio); if(cb->getObj(goalObjectID, false)) { @@ -1553,7 +1553,7 @@ void AIGateway::requestActionASAP(std::function whatToDo) void AIGateway::lostHero(HeroPtr h) { - logAi->debug("I lost my hero %s. It's best to forget and move on.", h.name); + logAi->debug("I lost my hero %s. It's best to forget and move on.", h.name()); } void AIGateway::answerQuery(QueryID queryID, int selection) diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 7d2f57710..e55330fbd 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -67,7 +67,6 @@ HeroPtr::HeroPtr(const CGHeroInstance * H) } h = H; - name = h->getNameTranslated(); hid = H->id; // infosCount[ai->playerID][hid]++; } @@ -89,6 +88,14 @@ bool HeroPtr::operator<(const HeroPtr & rhs) const return hid < rhs.hid; } +std::string HeroPtr::name() const +{ + if (h) + return h->getNameTextID(); + else + return ""; +} + const CGHeroInstance * HeroPtr::get(bool doWeExpectNull) const { return get(cb, doWeExpectNull); diff --git a/AI/Nullkiller/AIUtility.h b/AI/Nullkiller/AIUtility.h index c5a8ca1c2..b851d0527 100644 --- a/AI/Nullkiller/AIUtility.h +++ b/AI/Nullkiller/AIUtility.h @@ -87,8 +87,7 @@ struct DLL_EXPORT HeroPtr ObjectInstanceID hid; public: - std::string name; - + std::string name() const; HeroPtr(); HeroPtr(const CGHeroInstance * H); diff --git a/AI/Nullkiller/Analyzers/HeroManager.cpp b/AI/Nullkiller/Analyzers/HeroManager.cpp index 674463341..44b66b46b 100644 --- a/AI/Nullkiller/Analyzers/HeroManager.cpp +++ b/AI/Nullkiller/Analyzers/HeroManager.cpp @@ -176,7 +176,7 @@ int HeroManager::selectBestSkill(const HeroPtr & hero, const std::vectortrace( "Hero %s is proposed to learn %d with score %f", - hero.name, + hero.name(), skills[i].toEnum(), score); } @@ -204,6 +204,7 @@ float HeroManager::getFightingStrengthCached(const CGHeroInstance * hero) const { auto cached = knownFightingStrength.find(hero->id); + //FIXME: fallback to hero->getFightingStrength() is VERY slow on higher difficulties (no object graph? map reveal?) return cached != knownFightingStrength.end() ? cached->second : hero->getFightingStrength(); } diff --git a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp index 1b5891a7c..4a3d379cf 100644 --- a/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp +++ b/AI/Nullkiller/Behaviors/CaptureObjectsBehavior.cpp @@ -204,7 +204,7 @@ void CaptureObjectsBehavior::decomposeObjects( vstd::concatenate(tasksLocal, getVisitGoals(paths, nullkiller, objToVisit, specificObjects)); } - std::lock_guard lock(sync); + std::lock_guard lock(sync); // FIXME: consider using tbb::parallel_reduce instead to avoid mutex overhead vstd::concatenate(result, tasksLocal); }); } diff --git a/AI/Nullkiller/Goals/CaptureObject.h b/AI/Nullkiller/Goals/CaptureObject.h index bda5669af..e219e37ec 100644 --- a/AI/Nullkiller/Goals/CaptureObject.h +++ b/AI/Nullkiller/Goals/CaptureObject.h @@ -31,7 +31,7 @@ namespace Goals { objid = obj->id.getNum(); tile = obj->visitablePos(); - name = obj->getObjectName(); + name = obj->typeName; } bool operator==(const CaptureObject & other) const override; diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp index 68a7375c6..d69b529c7 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp +++ b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp @@ -26,7 +26,7 @@ ExecuteHeroChain::ExecuteHeroChain(const AIPath & path, const CGObjectInstance * if(obj) { objid = obj->id.getNum(); - targetName = obj->getObjectName() + tile.toString(); + targetName = obj->typeName + tile.toString(); } else { @@ -106,7 +106,7 @@ void ExecuteHeroChain::accept(AIGateway * ai) if(!heroPtr.validAndSet()) { - logAi->error("Hero %s was lost. Exit hero chain.", heroPtr.name); + logAi->error("Hero %s was lost. Exit hero chain.", heroPtr.name()); return; } @@ -143,7 +143,7 @@ void ExecuteHeroChain::accept(AIGateway * ai) if(!heroPtr.validAndSet()) { - logAi->error("Hero %s was lost trying to execute special action. Exit hero chain.", heroPtr.name); + logAi->error("Hero %s was lost trying to execute special action. Exit hero chain.", heroPtr.name()); return; } @@ -204,7 +204,7 @@ void ExecuteHeroChain::accept(AIGateway * ai) { if(!heroPtr.validAndSet()) { - logAi->error("Hero %s was lost. Exit hero chain.", heroPtr.name); + logAi->error("Hero %s was lost. Exit hero chain.", heroPtr.name()); return; } @@ -250,7 +250,7 @@ void ExecuteHeroChain::accept(AIGateway * ai) { if(!heroPtr.validAndSet()) { - logAi->debug("Hero %s was killed while attempting to reach %s", heroPtr.name, node->coord.toString()); + logAi->debug("Hero %s was killed while attempting to reach %s", heroPtr.name(), node->coord.toString()); return; } diff --git a/AI/Nullkiller/Helpers/ExplorationHelper.cpp b/AI/Nullkiller/Helpers/ExplorationHelper.cpp index 6abec91ac..75f40e9cb 100644 --- a/AI/Nullkiller/Helpers/ExplorationHelper.cpp +++ b/AI/Nullkiller/Helpers/ExplorationHelper.cpp @@ -70,11 +70,8 @@ bool ExplorationHelper::scanMap() int3 mapSize = cbp->getMapSize(); int perimeter = 2 * sightRadius * (mapSize.x + mapSize.y); - std::vector from; - std::vector to; - - from.reserve(perimeter); - to.reserve(perimeter); + std::vector edgeTiles; + edgeTiles.reserve(perimeter); foreach_tile_pos([&](const int3 & pos) { @@ -91,13 +88,13 @@ bool ExplorationHelper::scanMap() }); if(hasInvisibleNeighbor) - from.push_back(pos); + edgeTiles.push_back(pos); } }); logAi->debug("Exploration scan visible area perimeter for hero %s", hero->getNameTranslated()); - for(const int3 & tile : from) + for(const int3 & tile : edgeTiles) { scanTile(tile); } @@ -108,19 +105,36 @@ bool ExplorationHelper::scanMap() } allowDeadEndCancellation = false; - - for(int i = 0; i < sightRadius; i++) - { - getVisibleNeighbours(from, to); - vstd::concatenate(from, to); - vstd::removeDuplicates(from); - } - logAi->debug("Exploration scan all possible tiles for hero %s", hero->getNameTranslated()); - for(const int3 & tile : from) + boost::multi_array potentialTiles = ts->fogOfWarMap; + std::vector tilesToExploreFrom = edgeTiles; + + // WARNING: POTENTIAL BUG + // AI attempts to move to any tile within sight radius to reveal some new tiles + // however sight radius is circular, while this method assumes square radius + // standing on the edge of a square will NOT reveal tile in opposite corner + for(int i = 0; i < sightRadius; i++) { - scanTile(tile); + std::vector newTilesToExploreFrom; + + for(const int3 & tile : tilesToExploreFrom) + { + foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour) + { + if(potentialTiles[neighbour.z][neighbour.x][neighbour.y]) + { + newTilesToExploreFrom.push_back(neighbour); + potentialTiles[neighbour.z][neighbour.x][neighbour.y] = false; + } + }); + } + for(const int3 & tile : newTilesToExploreFrom) + { + scanTile(tile); + } + + std::swap(tilesToExploreFrom, newTilesToExploreFrom); } return !bestGoal->invalid(); @@ -172,20 +186,6 @@ void ExplorationHelper::scanTile(const int3 & tile) } } -void ExplorationHelper::getVisibleNeighbours(const std::vector & tiles, std::vector & out) const -{ - for(const int3 & tile : tiles) - { - foreach_neighbour(cbp, tile, [&](CCallback * cbp, int3 neighbour) - { - if(ts->fogOfWarMap[neighbour.z][neighbour.x][neighbour.y]) - { - out.push_back(neighbour); - } - }); - } -} - int ExplorationHelper::howManyTilesWillBeDiscovered(const int3 & pos) const { int ret = 0; diff --git a/AI/Nullkiller/Helpers/ExplorationHelper.h b/AI/Nullkiller/Helpers/ExplorationHelper.h index 8c4ec58f4..994d2809a 100644 --- a/AI/Nullkiller/Helpers/ExplorationHelper.h +++ b/AI/Nullkiller/Helpers/ExplorationHelper.h @@ -46,7 +46,6 @@ public: private: void scanTile(const int3 & tile); bool hasReachableNeighbor(const int3 & pos) const; - void getVisibleNeighbours(const std::vector & tiles, std::vector & out) const; }; } diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp index c6c9fee8b..b113e27ae 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.cpp +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.cpp @@ -320,11 +320,9 @@ void AINodeStorage::calculateNeighbours( const PathfinderConfig * pathfinderConfig, const CPathfinderHelper * pathfinderHelper) { - std::vector accessibleNeighbourTiles; + NeighbourTilesVector accessibleNeighbourTiles; result.clear(); - accessibleNeighbourTiles.reserve(8); - pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source); const AIPathNode * srcNode = getAINode(source.node); diff --git a/AI/Nullkiller/Pathfinding/AINodeStorage.h b/AI/Nullkiller/Pathfinding/AINodeStorage.h index 9f51cd531..12cf787d0 100644 --- a/AI/Nullkiller/Pathfinding/AINodeStorage.h +++ b/AI/Nullkiller/Pathfinding/AINodeStorage.h @@ -23,6 +23,8 @@ constexpr int NKAI_GRAPH_TRACE_LEVEL = 0; #include "Actions/SpecialAction.h" #include "Actors.h" +#include + namespace NKAI { namespace AIPathfinding @@ -85,7 +87,9 @@ struct AIPathNodeInfo struct AIPath { - std::vector nodes; + using NodesVector = boost::container::small_vector; + + NodesVector nodes; uint64_t targetObjectDanger; uint64_t armyLoss; uint64_t targetObjectArmyLoss; diff --git a/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp index d255dcb1e..548792412 100644 --- a/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp +++ b/AI/Nullkiller/Pathfinding/Actions/BoatActions.cpp @@ -141,7 +141,8 @@ namespace AIPathfinding { SpellID summonBoat = SpellID::SUMMON_BOAT; - return hero->getSpellCost(summonBoat.toSpell()); + // FIXME: this should be hero->getSpellCost, however currently queries to bonus system are too slow + return summonBoat.toSpell()->getCost(0); } } diff --git a/AI/Nullkiller/Pathfinding/GraphPaths.cpp b/AI/Nullkiller/Pathfinding/GraphPaths.cpp index 9c27c738c..150d37c1a 100644 --- a/AI/Nullkiller/Pathfinding/GraphPaths.cpp +++ b/AI/Nullkiller/Pathfinding/GraphPaths.cpp @@ -118,7 +118,7 @@ void GraphPaths::calculatePaths(const CGHeroInstance * targetHero, const Nullkil targetNode.specialAction = compositeAction; - auto targetGraphNode = graph.getNode(target); + const auto & targetGraphNode = graph.getNode(target); if(targetGraphNode.objID.hasValue()) { diff --git a/AI/StupidAI/StupidAI.cpp b/AI/StupidAI/StupidAI.cpp index d2486507c..3c152de13 100644 --- a/AI/StupidAI/StupidAI.cpp +++ b/AI/StupidAI/StupidAI.cpp @@ -77,6 +77,15 @@ public: // FIXME: provide distance info for Jousting bonus DamageEstimation retal; DamageEstimation dmg = cb->getBattle(battleID)->battleEstimateDamage(ourStack, s, 0, &retal); + // Clip damage dealt to total stack health + auto totalHealth = s->getTotalHealth(); + vstd::amin(dmg.damage.min, totalHealth); + vstd::amin(dmg.damage.max, totalHealth); + + auto ourHealth = s->getTotalHealth(); + vstd::amin(retal.damage.min, ourHealth); + vstd::amin(retal.damage.max, ourHealth); + adi = static_cast((dmg.damage.min + dmg.damage.max) / 2); adr = static_cast((retal.damage.min + retal.damage.max) / 2); } diff --git a/AI/VCAI/Pathfinding/AINodeStorage.cpp b/AI/VCAI/Pathfinding/AINodeStorage.cpp index 80d476fa7..63bd2bd4e 100644 --- a/AI/VCAI/Pathfinding/AINodeStorage.cpp +++ b/AI/VCAI/Pathfinding/AINodeStorage.cpp @@ -162,10 +162,9 @@ void AINodeStorage::calculateNeighbours( const PathfinderConfig * pathfinderConfig, const CPathfinderHelper * pathfinderHelper) { - std::vector accessibleNeighbourTiles; + NeighbourTilesVector accessibleNeighbourTiles; result.clear(); - accessibleNeighbourTiles.reserve(8); pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source); diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f6eda5ae..dcbe5d562 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ option(ENABLE_CCACHE "Speed up recompilation by caching previous compilations" O # Platform-specific options if(ANDROID) - set(ANDROID_TARGET_SDK_VERSION "33" CACHE STRING "Android target SDK version") + set(ANDROID_TARGET_SDK_VERSION "34" CACHE STRING "Android target SDK version") set(ANDROIDDEPLOYQT_OPTIONS "" CACHE STRING "Additional androiddeployqt options separated by semi-colon") set(ANDROID_GRADLE_PROPERTIES "" CACHE STRING "Additional Gradle properties separated by semi-colon") @@ -519,7 +519,7 @@ if(ENABLE_LAUNCHER OR ENABLE_EDITOR) endif() endif() -if(ENABLE_NULLKILLER_AI AND ENABLE_CLIENT) +if(ENABLE_CLIENT) find_package(TBB REQUIRED) endif() diff --git a/CMakePresets.json b/CMakePresets.json index 9a045ff6e..3746ce676 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -292,7 +292,8 @@ "default-release" ], "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo" + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "ANDROIDDEPLOYQT_OPTIONS" : "--aab" } }, { diff --git a/ChangeLog.md b/ChangeLog.md index 9ed76c11e..bf895d923 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,50 @@ +# 1.5.3 -> 1.5.4 + +### Stability +* Fixed a possible crash when clicking on an adventure map when another player is taking a turn in multiplayer mode. +* Failure to extract a mod will now display an error message instead of a silent crash. +* Fixed crash on opening town hall screen of a town from a mod with invalid building identifier +* Fixed crash when faerie dragons die after casting Ice Ring on themselves. + +### Mechanics +* The scholar will now correctly upgrade a skill if the visiting hero has offered a skill at either the basic or advanced level. +* Hero now reveals Fog of War when receiving new or upgraded secondary skills (such as scouting). +* AI will now always act after all human players during simturns instead of acting after host player + +### Interface +* Pressing the up and down keys on the town screen will now move to the next or previous town instead of scrolling through the list of towns. +* Long text in scenario name and highscore screen now shortened to fit the interface +* Game now moves cursor to tap event position when using software cursor with touch screen input +* Right-click popup on spell scroll campaign bonus now shows spell name instead of artefact name +* Damage estimation tooltip will no longer show damage greater than the targeted unit's health. + +### Random Maps Generator +* Generator will try to place roads even further away from zone borders +* Fixed rare crash when placing two quest artefacts in the same location at the same time + +### AI +* Improved performance of Nullkiller AI +* Stupid AI no longer overestimates damage when killing entire unit +* Fixed a bug leading to Battle AI not using spells when sieging town with Citadel or Castle built +* Fixed an unsigned integer overflow that caused the Nullkiller AI to overestimate the total army strength after merging two armies. + +### Launcher +* Added button to reset touchscreen tutorial on mobile systems +* Launcher will now warn if player selects Gog Galaxy installer instead of offline installer +* Launcher will now ask for the .bin file first as it is usually listed first in the file system view +* Extraction failure now displays error message instead of crashing +* Launcher will now use the header signature to check the file type instead of the extension when using the gog.com installer. +* Fixed broken controller sensitivity configuration options +* Fixed manual file installation on Android + +### Map Editor +* Icons and translations now embedded in executable file + +### Modding +* Improved bonus format validation +* Validator now reports valid values for enumeration fields +* Fixed missing addInfo field for bonuses that use the BONUS_OWNER_UPDATER propagation updater. + # 1.5.2 -> 1.5.3 ### Stability @@ -46,6 +93,7 @@ * Added the configuration files directory to the Help tab as it is located separately on Linux systems * Removed H3 data language selection during setup in favor of auto-detection * Replaced checkboxes with toggle buttons for easier of access on touchscreens. +* Icons and translations now embedded in executable file * Added interface for configuring several previously existing but inaccessible options in Launcher: * Selection of input tolerance precision for all input types * Relative cursor mode for mobile systems (was only available on Android) diff --git a/Mods/vcmi/config/vcmi/czech.json b/Mods/vcmi/config/vcmi/czech.json index 7495a13b6..3851bfb5c 100644 --- a/Mods/vcmi/config/vcmi/czech.json +++ b/Mods/vcmi/config/vcmi/czech.json @@ -49,10 +49,10 @@ "vcmi.radialWheel.heroSwapArtifacts" : "Vyměnit artefakty s jiným hrdinou", "vcmi.radialWheel.heroDismiss" : "Propustit hrdinu", - "vcmi.radialWheel.moveTop" : "Move to top", - "vcmi.radialWheel.moveUp" : "Move up", - "vcmi.radialWheel.moveDown" : "Move down", - "vcmi.radialWheel.moveBottom" : "Move to bottom", + "vcmi.radialWheel.moveTop" : "Přesunout nahoru", + "vcmi.radialWheel.moveUp" : "Posunout výše", + "vcmi.radialWheel.moveDown" : "Posunout níže", + "vcmi.radialWheel.moveBottom" : "Přesunout dolů", "vcmi.spellBook.search" : "hledat...", @@ -62,24 +62,88 @@ "vcmi.mainMenu.serverClosing" : "Zavírání...", "vcmi.mainMenu.hostTCP" : "Pořádat hru TCP/IP", "vcmi.mainMenu.joinTCP" : "Připojit se do hry TCP/IP", - "vcmi.mainMenu.playerName" : "Hráč", - + "vcmi.lobby.filepath" : "Název souboru", "vcmi.lobby.creationDate" : "Datum vytvoření", "vcmi.lobby.scenarioName" : "Název scénáře", "vcmi.lobby.mapPreview" : "Náhled mapy", "vcmi.lobby.noPreview" : "bez náhledu", "vcmi.lobby.noUnderground" : "bez podzemí", + "vcmi.lobby.sortDate" : "Řadit mapy dle data změny", + "vcmi.lobby.backToLobby" : "Vrátit se do předsíně", + + "vcmi.lobby.login.title" : "Online předsíň VCMI", + "vcmi.lobby.login.username" : "Uživatelské jméno:", + "vcmi.lobby.login.connecting" : "Připojování...", + "vcmi.lobby.login.error" : "Chyba při připojování: %s", + "vcmi.lobby.login.create" : "Nový účet", + "vcmi.lobby.login.login" : "Přihlásit se", + "vcmi.lobby.login.as" : "Přilásit se jako %s", + "vcmi.lobby.header.rooms" : "Herní místnosti - %d", + "vcmi.lobby.header.channels" : "Kanály konverzace", + "vcmi.lobby.header.chat.global" : "Globální konverzace hry - %s", // %s -> language name + "vcmi.lobby.header.chat.match" : "Konverzace předchozí hry %s", // %s -> game start date & time + "vcmi.lobby.header.chat.player" : "Soukromá konverzace s %s", // %s -> nickname of another player + "vcmi.lobby.header.history" : "Vaše předchozí hry", + "vcmi.lobby.header.players" : "Online hráči - %d", + "vcmi.lobby.match.solo" : "Hra jednoho hráče", + "vcmi.lobby.match.duel" : "Hra s %s", // %s -> nickname of another player + "vcmi.lobby.match.multi" : "%d hráčů", + "vcmi.lobby.room.create" : "Vytvořit novou místnost", + "vcmi.lobby.room.players.limit" : "Omezení počtu hráčů", + "vcmi.lobby.room.description.public" : "Jakýkoliv hráč se může připojit do veřejné místnosti.", + "vcmi.lobby.room.description.private" : "Pouze pozvaní hráči se mohou připojit do soukromé místnosti.", + "vcmi.lobby.room.description.new" : "Pro start hry vyberte scénář, nebo nastavte náhodnou mapu.", + "vcmi.lobby.room.description.load" : "Pro start hry načtěte uloženou hru.", + "vcmi.lobby.room.description.limit" : "Až %d hráčů se může připojit do vaší místnosti (včetně vás).", + "vcmi.lobby.invite.header" : "Pozvat hráče", + "vcmi.lobby.invite.notification" : "Pozval vás hráč do jejich soukromé místnosti. Nyní se do ní můžete připojit.", + "vcmi.lobby.preview.title" : "Připojit se do herní místnosti", + "vcmi.lobby.preview.subtitle" : "Hra na %s, pořádána %s", //TL Note: 1) name of map or RMG template 2) nickname of game host + "vcmi.lobby.preview.version" : "Verze hry:", + "vcmi.lobby.preview.players" : "Hráči:", + "vcmi.lobby.preview.mods" : "Použité modifikace:", + "vcmi.lobby.preview.allowed" : "Připojit se do herní místnosti?", + "vcmi.lobby.preview.error.header" : "Nelze se připojit do této herní místnosti.", + "vcmi.lobby.preview.error.playing" : "Nejdříve musíte opustit vaši současnou hru.", + "vcmi.lobby.preview.error.full" : "Místnost je již plná.", + "vcmi.lobby.preview.error.busy" : "Místnost již nepřijímá nové hráče.", + "vcmi.lobby.preview.error.invite" : "Nebyl jste pozván do této mísnosti.", + "vcmi.lobby.preview.error.mods" : "Použváte jinou sadu modifikací.", + "vcmi.lobby.preview.error.version" : "Používáte jinou verzi VCMI.", + "vcmi.lobby.room.new" : "Nová hra", + "vcmi.lobby.room.load" : "Načíst hru", + "vcmi.lobby.room.type" : "Druh místnosti", + "vcmi.lobby.room.mode" : "Herní režim", + "vcmi.lobby.room.state.public" : "Veřejná", + "vcmi.lobby.room.state.private" : "Soukromá", + "vcmi.lobby.room.state.busy" : "Ve hře", + "vcmi.lobby.room.state.invited" : "Pozvaný", + "vcmi.lobby.mod.state.compatible" : "Kompatibilní", + "vcmi.lobby.mod.state.disabled" : "Musí být povolena", + "vcmi.lobby.mod.state.version" : "Neshoda verze", + "vcmi.lobby.mod.state.excessive" : "Musí být zakázána", + "vcmi.lobby.mod.state.missing" : "Není nainstalována", + "vcmi.lobby.pvp.coin.hover" : "Mince", + "vcmi.lobby.pvp.coin.help" : "Hodí mincí", + "vcmi.lobby.pvp.randomTown.hover" : "Náhodné město", + "vcmi.lobby.pvp.randomTown.help" : "Napsat náhodné město do konvezace", + "vcmi.lobby.pvp.randomTownVs.hover" : "Náhodné město vs.", + "vcmi.lobby.pvp.randomTownVs.help" : "Napsat 2 náhodná města do konvezace", + "vcmi.lobby.pvp.versus" : "vs.", + "vcmi.client.errors.invalidMap" : "{Neplatná mapa nebo kampaň}\n\nChyba při startu hry! Vybraná mapa nebo kampaň může být neplatná nebo poškozená. Důvod:\n%s", "vcmi.client.errors.missingCampaigns" : "{Chybějící datové soubory}\n\nDatové soubory kampaně nebyly nalezeny! Možná máte nekompletní nebo poškozené datové soubory Heroes 3. Prosíme, přeinstalujte hru.", + "vcmi.server.errors.disconnected" : "{Chyba sítě}\n\nPřipojení k hernímu serveru bylo ztraceno!", "vcmi.server.errors.existingProcess" : "Již běží jiný server VCMI. Prosím, ukončete ho před startem nové hry.", "vcmi.server.errors.modsToEnable" : "{Následující modifikace jsou nutné pro načtení hry}", "vcmi.server.errors.modsToDisable" : "{Následující modifikace musí být zakázány}", - "vcmi.server.confirmReconnect" : "Chcete se připojit k poslední relaci?", "vcmi.server.errors.modNoDependency" : "Nelze načíst modifikaci {'%s'}!\n Závisí na modifikaci {'%s'}, která není aktivní!\n", "vcmi.server.errors.modConflict" : "Nelze načíst modifikaci {'%s'}!\n Je v kolizi s aktivní modifikací {'%s'}!\n", "vcmi.server.errors.unknownEntity" : "Nelze načíst uloženou pozici! Neznámá entita '%s' nalezena v uložené pozici! Uložná pozice nemusí být kompatibilní s aktuálními verzemi modifikací!", + "vcmi.dimensionDoor.seaToLandError" : "It's not possible to teleport from sea to land or vice versa with a Dimension Door.", //TODO + "vcmi.settingsMainWindow.generalTab.hover" : "Obecné", "vcmi.settingsMainWindow.generalTab.help" : "Přepne na kartu obecných nastavení, která obsahuje nastavení související s obecným chováním klienta hry.", "vcmi.settingsMainWindow.battleTab.hover" : "Bitva", @@ -182,6 +246,18 @@ "vcmi.battleWindow.damageEstimation.kills" : "%d zahyne", "vcmi.battleWindow.damageEstimation.kills.1" : "%d zahyne", + "vcmi.battleWindow.damageRetaliation.will" : "Zahyne ", + "vcmi.battleWindow.damageRetaliation.may" : "Možná zahyne ", + "vcmi.battleWindow.damageRetaliation.never" : "Nezahyne.", + "vcmi.battleWindow.damageRetaliation.damage" : "(%DAMAGE).", + "vcmi.battleWindow.damageRetaliation.damageKills" : "(%DAMAGE, %KILLS).", + + "vcmi.battleWindow.killed" : "Zabito", //TODO + "vcmi.battleWindow.accurateShot.resultDescription.0" : "%d %s were killed by accurate shots!", + "vcmi.battleWindow.accurateShot.resultDescription.1" : "%d %s was killed with an accurate shot!", + "vcmi.battleWindow.accurateShot.resultDescription.2" : "%d %s were killed by accurate shots!", + "vcmi.battleWindow.endWithAutocombat" : "Are you sure you wish to end the battle with auto combat?", + "vcmi.battleResultsWindow.applyResultsLabel" : "Použít výsledek bitvy", "vcmi.tutorialWindow.title" : "Úvod ovládání dotykem", @@ -244,18 +320,18 @@ "vcmi.optionsTab.turnOptions.hover" : "Možnosti tahu", "vcmi.optionsTab.turnOptions.help" : "Vyberte odpočítávadlo tahů a nastavení souběžných tahů", - "vcmi.optionsTab.chessFieldBase.hover" : "Base timer", - "vcmi.optionsTab.chessFieldTurn.hover" : "Turn timer", - "vcmi.optionsTab.chessFieldBattle.hover" : "Battle timer", - "vcmi.optionsTab.chessFieldUnit.hover" : "Unit timer", - "vcmi.optionsTab.chessFieldBase.help" : "Used when {Turn Timer} reaches 0. Set once at game start. On reaching zero, ends current turn. Any ongoing combat with end with a loss.", - "vcmi.optionsTab.chessFieldTurnAccumulate.help" : "Used out of combat or when {Battle Timer} runs out. Reset each turn. Leftover added to {Base Timer} at turn's end.", - "vcmi.optionsTab.chessFieldTurnDiscard.help" : "Used out of combat or when {Battle Timer} runs out. Reset each turn. Any unspent time is lost", - "vcmi.optionsTab.chessFieldBattle.help" : "Used in battles with AI or in pvp combat when {Unit Timer} runs out. Reset at start of each combat.", - "vcmi.optionsTab.chessFieldUnitAccumulate.help" : "Used when selecting unit action in pvp combat. Leftover added to {Battle Timer} at end of unit turn.", - "vcmi.optionsTab.chessFieldUnitDiscard.help" : "Used when selecting unit action in pvp combat. Reset at start of each unit's turn. Any unspent time is lost", + "vcmi.optionsTab.chessFieldBase.hover" : "Základní časovač", + "vcmi.optionsTab.chessFieldTurn.hover" : "Časovač tahu", + "vcmi.optionsTab.chessFieldBattle.hover" : "Časovač bitvy", + "vcmi.optionsTab.chessFieldUnit.hover" : "Časovač jednotky", + "vcmi.optionsTab.chessFieldBase.help" : "Použit při poklesnutí {Časovače bitvy} na 0. Nastaveno jednou při začátku hry. Při poklesu na nulu skončí tah. Jákákoliv trvající bitva skončí prohrou.", + "vcmi.optionsTab.chessFieldTurnAccumulate.help" : "Použit mimo bitvu nebo když {Časovač bitvy} vyprší. Resetuje se každý tah. Přebytečný čas je přidán do {Základního časovače} na konci tahu.", + "vcmi.optionsTab.chessFieldTurnDiscard.help" : "Použit mimo bitvu nebo když {Časovač bitvy} vyprší. Resetuje se každý tah. Jakýkoliv přebytečný čas je ztracen.", + "vcmi.optionsTab.chessFieldBattle.help" : "Použit v bitvách s AI nebo v pvp soubojích při vypršení {Časovače jednotky}. Resetuje se startu každé bitvy.", + "vcmi.optionsTab.chessFieldUnitAccumulate.help" : "Použit při vybírání úkonu jednotky. Přebytečný čas je přidán do {Časovače bitvy} na konci tahu jednotky.", + "vcmi.optionsTab.chessFieldUnitDiscard.help" : "Použit při vybírání úkonu jednotky. Resetuje se na začátku tahu každé jednotky. Jakýkoliv přebytečný čas je ztracen.", - "vcmi.optionsTab.accumulate" : "Accumulate", + "vcmi.optionsTab.accumulate" : "Akumulovat", "vcmi.optionsTab.simturnsTitle" : "Souběžné tahy", "vcmi.optionsTab.simturnsMin.hover" : "Alespoň po", @@ -302,6 +378,14 @@ "vcmi.optionsTab.simturns.months.1" : " %d měsíc", "vcmi.optionsTab.simturns.months.2" : " %d měsíce", + "vcmi.optionsTab.extraOptions.hover" : "Další možnosti", + "vcmi.optionsTab.extraOptions.help" : "Další herní možnosti", + + "vcmi.optionsTab.cheatAllowed.hover" : "Povolit cheaty", + "vcmi.optionsTab.unlimitedReplay.hover" : "Unlimited battle replay", + "vcmi.optionsTab.cheatAllowed.help" : "{Povolit cheaty}\nPovolí zadávání cheatů během hry.", + "vcmi.optionsTab.unlimitedReplay.help" : "{Unlimited battle replay}\nNo limit of replaying battles.", + // Custom victory conditions for H3 campaigns and HotA maps "vcmi.map.victoryCondition.daysPassed.toOthers" : "Nepřítel zvládl přežít do této chvíle. Vítězství je jeho!", "vcmi.map.victoryCondition.daysPassed.toSelf" : "Gratulace! Zvládli jste přežít. Vítězství je vaše!", @@ -333,9 +417,9 @@ "core.bonus.AIR_IMMUNITY.description": "Imunní všem kouzlům školy vzdušné magie", "core.bonus.ATTACKS_ALL_ADJACENT.name": "Útok okolo", "core.bonus.ATTACKS_ALL_ADJACENT.description": "Útočí na všechny sousední jednotky", - "core.bonus.BLOCKS_RETALIATION.name": "Žádná odplata", + "core.bonus.BLOCKS_RETALIATION.name": "Žádná odveta", "core.bonus.BLOCKS_RETALIATION.description": "Nepřítel nemůže zaútočit zpět", - "core.bonus.BLOCKS_RANGED_RETALIATION.name": "Žádná odplata na dálku", + "core.bonus.BLOCKS_RANGED_RETALIATION.name": "Žádná odveta na dálku", "core.bonus.BLOCKS_RANGED_RETALIATION.description": "Nepřítel nemůže zaútočit zpět útokem na dálku", "core.bonus.CATAPULT.name": "Katapult", "core.bonus.CATAPULT.description": "Útočí na ochranné hradby", @@ -364,17 +448,20 @@ "core.bonus.ENCHANTED.name": "Očarovaný", "core.bonus.ENCHANTED.description": "Trvale ovlivněm kouzlem ${subtype.spell}", "core.bonus.ENEMY_DEFENCE_REDUCTION.name": "Nevšímá si ${val} % bodů obrany", + "core.bonus.ENEMY_ATTACK_REDUCTION.description": "When being attacked, ${val}% of the attacker's attack is ignored", "core.bonus.ENEMY_DEFENCE_REDUCTION.description": "Pří útoku nebude brát v potaz ${val}% bodů obrany obránce", "core.bonus.FIRE_IMMUNITY.name": "Ohnivá odolnost", "core.bonus.FIRE_IMMUNITY.description": "Imunní všem kouzlům školy ohnivé magie", "core.bonus.FIRE_SHIELD.name": "Ohnivý štít (${val}%)", "core.bonus.FIRE_SHIELD.description": "Odrazí část zranení útoku zblízka", "core.bonus.FIRST_STRIKE.name": "První úder", - "core.bonus.FIRST_STRIKE.description": "Tato jednotka útočí zpět ještě než je na ni zaútočeno", + "core.bonus.FIRST_STRIKE.description": "Tato jednotka provede odvetu ještě než je na ni zaútočeno", "core.bonus.FEAR.name": "Strach", "core.bonus.FEAR.description": "Způsobí strach nepřátelskému oddílu", "core.bonus.FEARLESS.name": "Nebojácnost", "core.bonus.FEARLESS.description": "Odolnost proti strachu", + "core.bonus.FEROCITY.name": "Ferocity", //TODO + "core.bonus.FEROCITY.description": "Attacks ${val} additional times if killed anybody", "core.bonus.FLYING.name": "Letec", "core.bonus.FLYING.description": "Při pohybu létá (přes překážky)", "core.bonus.FREE_SHOOTING.name": "Blízké výstřely", @@ -421,7 +508,7 @@ "core.bonus.NON_LIVING.description": "Imunní vůči mnohým efektům", "core.bonus.RANDOM_SPELLCASTER.name": "Náhodný kouzelník", "core.bonus.RANDOM_SPELLCASTER.description": "Může seslat náhodné kouzlo", - "core.bonus.RANGED_RETALIATION.name": "Vzdálená msta", + "core.bonus.RANGED_RETALIATION.name": "Vzdálená odveta", "core.bonus.RANGED_RETALIATION.description": "Může provést protiútok na dálku", "core.bonus.RECEPTIVE.name": "Přijímavý", "core.bonus.RECEPTIVE.description": "Není imunní vůči přátelským kouzlům", @@ -429,6 +516,8 @@ "core.bonus.REBIRTH.description": "${val}% oddílu se po smrti znovu narodí", "core.bonus.RETURN_AFTER_STRIKE.name": "Útok a návrat", "core.bonus.RETURN_AFTER_STRIKE.description": "Navrátí se po útoku na blízko", + "core.bonus.REVENGE.name": "Msta", + "core.bonus.REVENGE.description": "Deals extra damage based on attacker's lost health in battle", //TODO "core.bonus.SHOOTER.name": "Střelec", "core.bonus.SHOOTER.description": "Jednotka může střílet", "core.bonus.SHOOTS_ALL_ADJACENT.name": "Střílí okolo", @@ -452,7 +541,7 @@ "core.bonus.SUMMON_GUARDIANS.name": "Povolat strážce", "core.bonus.SUMMON_GUARDIANS.description": "Na začátku bitvy povolá ${subtype.creature} (${val}%)", "core.bonus.SYNERGY_TARGET.name": "Synergizable", // TODO - "core.bonus.SYNERGY_TARGET.description": "This creature is vulnerable to synergy effect", + "core.bonus.SYNERGY_TARGET.description": "This creature is vulnerable to synergy effect", //TODO "core.bonus.TWO_HEX_ATTACK_BREATH.name": "Dech", "core.bonus.TWO_HEX_ATTACK_BREATH.description": "Dechový útok (dosah do dvou polí)", "core.bonus.THREE_HEADED_ATTACK.name": "Tříhlavý útok", @@ -462,7 +551,7 @@ "core.bonus.UNDEAD.name": "Nemrtvý", "core.bonus.UNDEAD.description": "Jednotka je nemrtvá", "core.bonus.UNLIMITED_RETALIATIONS.name": "Neomezené odvety", - "core.bonus.UNLIMITED_RETALIATIONS.description": "Může se mstít za neomezený počet útoků", + "core.bonus.UNLIMITED_RETALIATIONS.description": "Může provést odvetu za neomezený počet útoků", "core.bonus.WATER_IMMUNITY.name": "Vodní odolnost", "core.bonus.WATER_IMMUNITY.description": "Imunní všem kouzlům školy vodní magie", "core.bonus.WIDE_BREATH.name": "Široký dech", diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 3bad090da..4c9e79447 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1213,13 +1213,14 @@ void CPlayerInterface::heroBonusChanged( const CGHeroInstance *hero, const Bonus void CPlayerInterface::moveHero( const CGHeroInstance *h, const CGPath& path ) { + LOG_TRACE(logGlobal); + if (!LOCPLINT->makingTurn) + return; + assert(h); assert(!showingDialog->isBusy()); assert(dialogs.empty()); - LOG_TRACE(logGlobal); - if (!LOCPLINT->makingTurn) - return; if (!h) return; //can't find hero diff --git a/client/CServerHandler.cpp b/client/CServerHandler.cpp index 3a7ca9b1f..2dbf07743 100644 --- a/client/CServerHandler.cpp +++ b/client/CServerHandler.cpp @@ -648,14 +648,14 @@ void CServerHandler::startGameplay(VCMI_LIB_WRAP_NAMESPACE(CGameState) * gameSta if(CMM) CMM->disable(); - campaignScoreCalculator = nullptr; - switch(si->mode) { case EStartMode::NEW_GAME: client->newGame(gameState); break; case EStartMode::CAMPAIGN: + if(si->campState->conqueredScenarios().empty()) + campaignScoreCalculator.reset(); client->newGame(gameState); break; case EStartMode::LOAD_GAME: diff --git a/client/PlayerLocalState.cpp b/client/PlayerLocalState.cpp index 03e948adb..541b9ff80 100644 --- a/client/PlayerLocalState.cpp +++ b/client/PlayerLocalState.cpp @@ -168,7 +168,7 @@ void PlayerLocalState::setSelection(const CArmedInstance * selection) currentSelection = selection; - if (selection) + if (adventureInt && selection) adventureInt->onSelectionChanged(selection); } @@ -212,6 +212,9 @@ void PlayerLocalState::addWanderingHero(const CGHeroInstance * hero) assert(hero); assert(!vstd::contains(wanderingHeroes, hero)); wanderingHeroes.push_back(hero); + + if (currentSelection == nullptr) + setSelection(hero); } void PlayerLocalState::removeWanderingHero(const CGHeroInstance * hero) @@ -260,6 +263,9 @@ void PlayerLocalState::addOwnedTown(const CGTownInstance * town) assert(town); assert(!vstd::contains(ownedTowns, town)); ownedTowns.push_back(town); + + if (currentSelection == nullptr) + setSelection(town); } void PlayerLocalState::removeOwnedTown(const CGTownInstance * town) diff --git a/client/adventureMap/AdventureMapInterface.cpp b/client/adventureMap/AdventureMapInterface.cpp index dce45e197..43f005199 100644 --- a/client/adventureMap/AdventureMapInterface.cpp +++ b/client/adventureMap/AdventureMapInterface.cpp @@ -395,8 +395,6 @@ void AdventureMapInterface::adjustActiveness() void AdventureMapInterface::onCurrentPlayerChanged(PlayerColor playerID) { - LOCPLINT->localState->setSelection(nullptr); - if (playerID == currentPlayerID) return; @@ -446,6 +444,8 @@ void AdventureMapInterface::onPlayerTurnStarted(PlayerColor playerID) LOCPLINT->localState->setSelection(LOCPLINT->localState->getWanderingHero(0)); } + centerOnObject(LOCPLINT->localState->getCurrentArmy()); + //show new day animation and sound on infobar, except for 1st day of the game if (LOCPLINT->cb->getDate(Date::DAY) != 1) widget->getInfoBar()->showDate(); diff --git a/client/eventsSDL/InputSourceTouch.cpp b/client/eventsSDL/InputSourceTouch.cpp index 191a0901f..992daeb2c 100644 --- a/client/eventsSDL/InputSourceTouch.cpp +++ b/client/eventsSDL/InputSourceTouch.cpp @@ -58,6 +58,9 @@ InputSourceTouch::InputSourceTouch() void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfinger) { + if (CCS && CCS->curh && settings["video"]["cursor"].String() == "software" && state != TouchState::RELATIVE_MODE) + CCS->curh->cursorMove(GH.getCursorPosition().x, GH.getCursorPosition().y); + switch(state) { case TouchState::RELATIVE_MODE: diff --git a/client/lobby/CBonusSelection.cpp b/client/lobby/CBonusSelection.cpp index 04a3cf1f7..61414c3ea 100644 --- a/client/lobby/CBonusSelection.cpp +++ b/client/lobby/CBonusSelection.cpp @@ -214,7 +214,7 @@ void CBonusSelection::createBonusesIcons() break; case CampaignBonusType::SPELL_SCROLL: desc.appendLocalString(EMetaText::GENERAL_TXT, 716); - desc.replaceName(ArtifactID(bonDescs[i].info2)); + desc.replaceName(SpellID(bonDescs[i].info2)); break; case CampaignBonusType::PRIMARY_SKILL: { diff --git a/client/lobby/CSelectionBase.cpp b/client/lobby/CSelectionBase.cpp index 558aa3662..b7ea0a076 100644 --- a/client/lobby/CSelectionBase.cpp +++ b/client/lobby/CSelectionBase.cpp @@ -136,7 +136,7 @@ InfoCard::InfoCard() labelSaveDate = std::make_shared(310, 38, FONT_SMALL, ETextAlignment::BOTTOMRIGHT, Colors::WHITE); labelMapSize = std::make_shared(333, 56, FONT_TINY, ETextAlignment::CENTER, Colors::WHITE); - mapName = std::make_shared(26, 39, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW); + mapName = std::make_shared(26, 39, FONT_BIG, ETextAlignment::TOPLEFT, Colors::YELLOW, "", 285); Rect descriptionRect(26, 149, 320, 115); mapDescription = std::make_shared("", descriptionRect, 1); playerListBg = std::make_shared(ImagePath::builtin("CHATPLUG.bmp"), 16, 276); diff --git a/client/mainmenu/CHighScoreScreen.cpp b/client/mainmenu/CHighScoreScreen.cpp index bb5e61121..6b572ae74 100644 --- a/client/mainmenu/CHighScoreScreen.cpp +++ b/client/mainmenu/CHighScoreScreen.cpp @@ -180,23 +180,17 @@ void CHighScoreScreen::addHighScores() ColorRGBA color = (i == highlighted || currentGameNotInListEntry) ? Colors::YELLOW : Colors::WHITE; texts.push_back(std::make_shared(115, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, std::to_string((currentGameNotInListEntry ? highlighted : i) + 1))); - std::string tmp = curData["player"].String(); - TextOperations::trimRightUnicode(tmp, std::max(0, (int)TextOperations::getUnicodeCharactersCount(tmp) - 13)); - texts.push_back(std::make_shared(225, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, tmp)); + texts.push_back(std::make_shared(225, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, curData["player"].String(), 120)); if(highscorepage == HighScorePage::SCENARIO) { - std::string tmp = curData["scenarioName"].String(); - TextOperations::trimRightUnicode(tmp, std::max(0, (int)TextOperations::getUnicodeCharactersCount(tmp) - 25)); - texts.push_back(std::make_shared(405, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, tmp)); + texts.push_back(std::make_shared(405, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, curData["scenarioName"].String(), 200)); texts.push_back(std::make_shared(557, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, std::to_string(curData["days"].Integer()))); texts.push_back(std::make_shared(627, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, std::to_string(curData["points"].Integer()))); } else { - std::string tmp = curData["campaignName"].String(); - TextOperations::trimRightUnicode(tmp, std::max(0, (int)TextOperations::getUnicodeCharactersCount(tmp) - 25)); - texts.push_back(std::make_shared(405, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, tmp)); + texts.push_back(std::make_shared(405, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, curData["campaignName"].String(), 200)); texts.push_back(std::make_shared(592, y + i * 50, FONT_MEDIUM, ETextAlignment::CENTER, color, std::to_string(curData["points"].Integer()))); } diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index 00b1f1824..1bdba2a75 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -15,6 +15,7 @@ #include "../gui/CGuiHandler.h" #include "../gui/CursorHandler.h" +#include "../CMT.h" #include "../CPlayerInterface.h" #include "../CGameInfo.h" #include "../PlayerLocalState.h" @@ -638,7 +639,13 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A assert(CGI->townh->size() > faction); if (cre->animDefName.empty()) - throw std::runtime_error("Creature " + cre->getJsonKey() + " has no valid combat animation!"); + { + GH.dispatchMainThread([cre]() + { + handleFatalError("Creature " + cre->getJsonKey() + " has no valid combat animation!", false); + }); + return; + } if(Big) bg = std::make_shared((*CGI->townh)[faction]->creatureBg130); diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 14467fb46..3b805687f 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -1271,8 +1271,8 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst resdatabar = std::make_shared(ImagePath::builtin("ARESBAR"), 3, 575, 37, 3, 84, 78); townlist = std::make_shared(3, Rect(Point(743, 414), Point(48, 128)), Point(1,16), Point(0, 32), LOCPLINT->localState->getOwnedTowns().size() ); - townlist->setScrollUpButton( std::make_shared( Point(744, 414), AnimationPath::builtin("IAM014"), CButton::tooltipLocalized("core.help.306"), 0, EShortcut::MOVE_UP)); - townlist->setScrollDownButton( std::make_shared( Point(744, 526), AnimationPath::builtin("IAM015"), CButton::tooltipLocalized("core.help.307"), 0, EShortcut::MOVE_DOWN)); + townlist->setScrollUpButton( std::make_shared( Point(744, 414), AnimationPath::builtin("IAM014"), CButton::tooltipLocalized("core.help.306"), 0)); + townlist->setScrollDownButton( std::make_shared( Point(744, 526), AnimationPath::builtin("IAM015"), CButton::tooltipLocalized("core.help.307"), 0)); if(from) townlist->select(from); @@ -1407,6 +1407,12 @@ void CCastleInterface::keyPressed(EShortcut key) { switch(key) { + case EShortcut::MOVE_UP: + townlist->selectPrev(); + break; + case EShortcut::MOVE_DOWN: + townlist->selectNext(); + break; case EShortcut::TOWN_OPEN_FORT: GH.windows().createAndPushWindow(town); break; @@ -1548,8 +1554,11 @@ CHallInterface::CHallInterface(const CGTownInstance * Town): const CBuilding * building = nullptr; for(auto & buildingID : boxList[row][col])//we are looking for the first not built structure { - if (town->town->buildings.count(buildingID) == 0) - throw std::runtime_error("Town " + Town->town->faction->getJsonKey() + " has no building with ID " + std::to_string(buildingID.getNum())); + if (!buildingID.hasValue()) + { + logMod->warn("Invalid building ID found in hallSlots of town '%s'", town->town->faction->getJsonKey() ); + continue; + } const CBuilding * current = town->town->buildings.at(buildingID); if(vstd::contains(town->builtBuildings, buildingID)) diff --git a/conanfile.py b/conanfile.py index f4bc9b064..220340bd0 100644 --- a/conanfile.py +++ b/conanfile.py @@ -19,11 +19,10 @@ class VCMI(ConanFile): "sdl_image/[~2.0.5]", "sdl_mixer/[~2.0.4]", "sdl_ttf/[~2.0.18]", - ] - _nullkillerAIRequires = [ "onetbb/[^2021.3]", ] - requires = _libRequires + _clientRequires + _nullkillerAIRequires + + requires = _libRequires + _clientRequires options = { "default_options_of_requirements": [True, False], diff --git a/config/schemas/bonus.json b/config/schemas/bonus.json index 959348661..2789994c8 100644 --- a/config/schemas/bonus.json +++ b/config/schemas/bonus.json @@ -10,6 +10,7 @@ "anyOf" : [ { "type" : "string", + "enum" : [ "SHOOTER_ONLY", "DRAGON_NATURE", "IS_UNDEAD", "CREATURE_NATIVE_TERRAIN", "CREATURE_FACTION", "SAME_FACTION", "CREATURES_ONLY", "OPPOSITE_SIDE" ], "description" : "parameterless limiter or boolean operator at start of array" }, { @@ -18,6 +19,7 @@ "properties" : { "type" : { "type" : "string", + "enum" : [ "CREATURE_TYPE_LIMITER", "HAS_ANOTHER_BONUS_LIMITER", "CREATURE_ALIGNMENT_LIMITER", "FACTION_LIMITER", "CREATURE_LEVEL_LIMITER", "CREATURE_TERRAIN_LIMITER", "UNIT_ON_HEXES" ], "description" : "type" }, "parameters" : { @@ -53,31 +55,24 @@ }, "sourceType" : { "type" : "string", + "enum" : [ "ARTIFACT", "ARTIFACT_INSTANCE", "OBJECT_TYPE", "OBJECT_INSTANCE", "CREATURE_ABILITY", "TERRAIN_NATIVE", "TERRAIN_OVERLAY", "SPELL_EFFECT", "TOWN_STRUCTURE", "HERO_BASE_SKILL", "SECONDARY_SKILL", "HERO_SPECIAL", "ARMY", "CAMPAIGN_BONUS", "STACK_EXPERIENCE", "COMMANDER", "GLOBAL", "OTHER", ], "description" : "sourceType" }, "targetSourceType" : { "type" : "string", + "enum" : [ "ARTIFACT", "ARTIFACT_INSTANCE", "OBJECT_TYPE", "OBJECT_INSTANCE", "CREATURE_ABILITY", "TERRAIN_NATIVE", "TERRAIN_OVERLAY", "SPELL_EFFECT", "TOWN_STRUCTURE", "HERO_BASE_SKILL", "SECONDARY_SKILL", "HERO_SPECIAL", "ARMY", "CAMPAIGN_BONUS", "STACK_EXPERIENCE", "COMMANDER", "GLOBAL", "OTHER", ], "description" : "targetSourceType" }, "propagator" : { "description" : "propagator", - "anyOf" : [ - { - "type" : "string" - }, - { - "type" : "array", - "items" : { - "type" : "string", - "description" : "0" - } - } - ] + "type" : "string", + "enum" : [ "BATTLE_WIDE", "VISITED_TOWN_AND_VISITOR", "PLAYER_PROPAGATOR", "HERO", "TEAM_PROPAGATOR", "GLOBAL_EFFECT" ] }, "updater" : { "anyOf" : [ { - "type" : "string" + "type" : "string", + "enum" : [ "TIMES_HERO_LEVEL", "TIMES_STACK_LEVEL", "ARMY_MOVEMENT", "BONUS_OWNER_UPDATER" ] }, { "description" : "updater", @@ -87,6 +82,7 @@ "properties" : { "type" : { "type" : "string", + "enum" : [ "GROWS_WITH_LEVEL", "ARMY_MOVEMENT" ], "description" : "type" }, "parameters" : { @@ -101,7 +97,8 @@ "propagationUpdater" : { "anyOf" : [ { - "type" : "string" + "type" : "string", + "enum" : [ "TIMES_HERO_LEVEL", "TIMES_STACK_LEVEL", "ARMY_MOVEMENT", "BONUS_OWNER_UPDATER" ] }, { "description" : "propagationUpdater", @@ -111,6 +108,7 @@ "properties" : { "type" : { "type" : "string", + "enum" : [ "GROWS_WITH_LEVEL", "ARMY_MOVEMENT" ], "description" : "type" }, "parameters" : { @@ -128,6 +126,7 @@ }, "effectRange" : { "type" : "string", + "enum" : [ "NO_LIMIT", "ONLY_DISTANCE_FIGHT", "ONLY_MELEE_FIGHT" ], "description" : "effectRange" }, "val" : { @@ -136,6 +135,7 @@ }, "valueType" : { "type" : "string", + "enum" : ["ADDITIVE_VALUE", "BASE_NUMBER", "PERCENT_TO_ALL", "PERCENT_TO_BASE", "PERCENT_TO_SOURCE", "PERCENT_TO_TARGET_TYPE", "INDEPENDENT_MAX", "INDEPENDENT_MIN" ], "description" : "valueType" }, "addInfo" : { @@ -156,8 +156,17 @@ }, "duration" : { "anyOf" : [ - { "type" : "string"}, - { "type" : "array", "items" : {"type" : "string"} } + { + "type" : "string", + "enum" : ["PERMANENT", "ONE_BATTLE", "ONE_DAY", "ONE_WEEK", "N_TURNS", "N_DAYS", "UNTIL_BEING_ATTACKED", "UNTIL_ATTACK", "STACK_GETS_TURN", "COMMANDER_KILLED", "UNTIL_OWN_ATTACK" ] + }, + { + "type" : "array", + "items" : { + "type" : "string", + "enum" : ["PERMANENT", "ONE_BATTLE", "ONE_DAY", "ONE_WEEK", "N_TURNS", "N_DAYS", "UNTIL_BEING_ATTACKED", "UNTIL_ATTACK", "STACK_GETS_TURN", "COMMANDER_KILLED", "UNTIL_OWN_ATTACK" ] + } + } ], "description" : "duration" }, diff --git a/debian/changelog b/debian/changelog index 77f824585..e2c64b577 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,12 @@ vcmi (1.6.0) jammy; urgency=medium -- Ivan Savenko Fri, 30 Aug 2024 12:00:00 +0200 +vcmi (1.5.4) jammy; urgency=medium + + * New upstream release + + -- Ivan Savenko Fri, 12 Jul 2024 12:00:00 +0200 + vcmi (1.5.3) jammy; urgency=medium * New upstream release diff --git a/docs/Readme.md b/docs/Readme.md index e5f16ac7f..2344f8a09 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -1,8 +1,7 @@ [![VCMI](https://github.com/vcmi/vcmi/actions/workflows/github.yml/badge.svg?branch=develop&event=push)](https://github.com/vcmi/vcmi/actions/workflows/github.yml?query=branch%3Adevelop+event%3Apush) [![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.0/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.0) -[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.1/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.1) -[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.2/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.2) [![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.3/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.3) +[![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/1.5.4/total)](https://github.com/vcmi/vcmi/releases/tag/1.5.4) [![Github Downloads](https://img.shields.io/github/downloads/vcmi/vcmi/total)](https://github.com/vcmi/vcmi/releases) # VCMI Project @@ -22,7 +21,6 @@ VCMI is an open-source recreation of Heroes of Might & Magic III engine, giving * Homepage: https://vcmi.eu/ * Forums: https://forum.vcmi.eu/ * Bugtracker: https://github.com/vcmi/vcmi/issues - * Slack: https://slack.vcmi.eu/ * Discord: https://discord.gg/chBT42V * GPT Store: https://chat.openai.com/g/g-1kNhX0mlO-vcmi-assistant diff --git a/docs/developers/Building_macOS.md b/docs/developers/Building_macOS.md index 0698b535a..67571f74d 100644 --- a/docs/developers/Building_macOS.md +++ b/docs/developers/Building_macOS.md @@ -116,4 +116,4 @@ Anyone who might want to debug builds, but new to macOS could find following com ## Troubleshooting -In case of troubles you can always consult our CI build scripts or contact the dev team via slack. +In case of troubles you can always consult our CI build scripts or contact the dev team via discord. diff --git a/docs/modders/Bonus/Bonus_Types.md b/docs/modders/Bonus/Bonus_Types.md index fabf347d6..d897d7a7f 100644 --- a/docs/modders/Bonus/Bonus_Types.md +++ b/docs/modders/Bonus/Bonus_Types.md @@ -252,7 +252,7 @@ Gives creature under effect of this spell additional bonus, which is hardcoded a ### SPECIAL_ADD_VALUE_ENCHANT -Increased effect of spell affecting creature, ie. Aenain makes Disrupting Ray decrease target's defense by additional 2 points: +Modifies 'val' parameter of spell effects that give bonuses by specified value. For example, Aenain makes Disrupting Ray decrease target's defense by additional 2 points: ```jsonc "disruptingRay" : { @@ -263,11 +263,11 @@ Increased effect of spell affecting creature, ie. Aenain makes Disrupting Ray de ``` - subtype: affected spell identifier -- additionalInfo: value to add +- addInfo: value to modify 'val' parameter of targeted spell effects by ### SPECIAL_FIXED_VALUE_ENCHANT -Spell affecting creature has fixed effect, eg. hero Melody has constant spell effect of +3: +Changes 'val' parameter of spell effects that give bonuses to a specified value. For example, Fortune cast by Melody always modifies luck by +3: ```jsonc "fortune" : { @@ -278,7 +278,7 @@ Spell affecting creature has fixed effect, eg. hero Melody has constant spell ef ``` - subtype: affected spell identifier -- additionalInfo = fixed value +- addInfo: value to set 'val' parameter of targeted spell effects to ### SPECIAL_UPGRADE diff --git a/launcher/aboutProject/aboutproject_moc.cpp b/launcher/aboutProject/aboutproject_moc.cpp index 30ca4d00b..c7f82e904 100644 --- a/launcher/aboutProject/aboutproject_moc.cpp +++ b/launcher/aboutProject/aboutproject_moc.cpp @@ -111,11 +111,6 @@ void AboutProjectView::on_pushButtonDiscord_clicked() QDesktopServices::openUrl(QUrl("https://discord.gg/chBT42V")); } -void AboutProjectView::on_pushButtonSlack_clicked() -{ - QDesktopServices::openUrl(QUrl("https://slack.vcmi.eu/")); -} - void AboutProjectView::on_pushButtonGithub_clicked() { QDesktopServices::openUrl(QUrl("https://github.com/vcmi/vcmi")); diff --git a/launcher/aboutProject/aboutproject_moc.h b/launcher/aboutProject/aboutproject_moc.h index 1671efbfe..916dcf72c 100644 --- a/launcher/aboutProject/aboutproject_moc.h +++ b/launcher/aboutProject/aboutproject_moc.h @@ -40,8 +40,6 @@ private slots: void on_pushButtonDiscord_clicked(); - void on_pushButtonSlack_clicked(); - void on_pushButtonGithub_clicked(); void on_pushButtonHomepage_clicked(); diff --git a/launcher/aboutProject/aboutproject_moc.ui b/launcher/aboutProject/aboutproject_moc.ui index 43361b6e2..f582201d3 100644 --- a/launcher/aboutProject/aboutproject_moc.ui +++ b/launcher/aboutProject/aboutproject_moc.ui @@ -30,7 +30,7 @@ - + VCMI on Github @@ -55,13 +55,6 @@ - - - - VCMI on Slack - - - diff --git a/launcher/eu.vcmi.VCMI.metainfo.xml b/launcher/eu.vcmi.VCMI.metainfo.xml index 1cae7c9bf..16aaace12 100644 --- a/launcher/eu.vcmi.VCMI.metainfo.xml +++ b/launcher/eu.vcmi.VCMI.metainfo.xml @@ -91,6 +91,7 @@ vcmilauncher.desktop + diff --git a/launcher/firstLaunch/firstlaunch_moc.cpp b/launcher/firstLaunch/firstlaunch_moc.cpp index 050fc2b0c..78ecf7a20 100644 --- a/launcher/firstLaunch/firstlaunch_moc.cpp +++ b/launcher/firstLaunch/firstlaunch_moc.cpp @@ -24,6 +24,7 @@ #ifdef ENABLE_INNOEXTRACT #include "cli/extract.hpp" +#include "setup/version.hpp" #endif #ifdef VCMI_IOS @@ -312,7 +313,7 @@ QString FirstLaunchView::getHeroesInstallDir() void FirstLaunchView::extractGogData() { #ifdef ENABLE_INNOEXTRACT - auto fileSelection = [this](QString type, QString filter, QString startPath = {}) { + auto fileSelection = [this](QByteArray magic, QString filter, QString startPath = {}) { QString titleSel = tr("Select %1 file...", "param is file extension").arg(filter); QString titleErr = tr("You have to select %1 file!", "param is file extension").arg(filter); #if defined(VCMI_MOBILE) @@ -322,7 +323,15 @@ void FirstLaunchView::extractGogData() QString file = QFileDialog::getOpenFileName(this, titleSel, startPath.isEmpty() ? QDir::homePath() : startPath, filter); if(file.isEmpty()) return QString{}; - else if(!file.endsWith("." + type, Qt::CaseInsensitive)) + + QFile tmpFile(file); + if(!tmpFile.open(QIODevice::ReadOnly)) + { + QMessageBox::critical(this, tr("File cannot opened"), tmpFile.errorString()); + return QString{}; + } + QByteArray magicFile = tmpFile.read(magic.length()); + if(!magicFile.startsWith(magic)) { QMessageBox::critical(this, tr("Invalid file selected"), titleErr); return QString{}; @@ -331,12 +340,12 @@ void FirstLaunchView::extractGogData() return file; }; - QString fileExe = fileSelection("exe", tr("GOG installer") + " (*.exe)"); - if(fileExe.isEmpty()) - return; - QString fileBin = fileSelection("bin", tr("GOG data") + " (*.bin)", QFileInfo(fileExe).absolutePath()); + QString fileBin = fileSelection(QByteArray{"idska32"}, tr("GOG data") + " (*.bin)"); if(fileBin.isEmpty()) return; + QString fileExe = fileSelection(QByteArray{"MZ"}, tr("GOG installer") + " (*.exe)", QFileInfo(fileBin).absolutePath()); + if(fileExe.isEmpty()) + return; ui->progressBarGog->setVisible(true); ui->pushButtonGogInstall->setVisible(false); @@ -344,6 +353,11 @@ void FirstLaunchView::extractGogData() QTimer::singleShot(100, this, [this, fileExe, fileBin](){ // background to make sure FileDialog is closed... QDir tempDir(pathToQString(VCMIDirs::get().userDataPath())); + if(tempDir.cd("tmp")) + { + tempDir.removeRecursively(); // remove if already exists (e.g. previous crash) + tempDir.cdUp(); + } tempDir.mkdir("tmp"); if(!tempDir.cd("tmp")) return; // should not happen - but avoid deleting wrong folder in any case @@ -352,6 +366,26 @@ void FirstLaunchView::extractGogData() QFile(fileExe).copy(tmpFileExe); QFile(fileBin).copy(tempDir.filePath("h3_gog-1.bin")); + QString errorText{}; + + auto isGogGalaxyExe = [](QString fileExe) { + QFile file(fileExe); + quint64 fileSize = file.size(); + + if(fileSize > 10 * 1024 * 1024) + return false; // avoid to load big files; galaxy exe is smaller... + + if(!file.open(QIODevice::ReadOnly)) + return false; + QByteArray data = file.readAll(); + + const QByteArray magicId{(const char*)u"GOG Galaxy", 20}; + return data.contains(magicId); + }; + + if(isGogGalaxyExe(tmpFileExe)) + errorText = tr("You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer!"); + ::extract_options o; o.extract = true; @@ -364,20 +398,44 @@ void FirstLaunchView::extractGogData() o.filenames.set_expand(true); o.preserve_file_times = true; // also correctly closes file -> without it: on Windows the files are not written completely - - process_file(tmpFileExe.toStdString(), o, [this](float progress) { - ui->progressBarGog->setValue(progress * 100); - qApp->processEvents(); - }); + + try + { + if(errorText.isEmpty()) + process_file(tmpFileExe.toStdString(), o, [this](float progress) { + ui->progressBarGog->setValue(progress * 100); + qApp->processEvents(); + }); + } + catch(const std::ios_base::failure & e) + { + errorText = tr("Stream error while extracting files!\nerror reason: "); + errorText += e.what(); + } + catch(const format_error & e) + { + errorText = e.what(); + } + catch(const std::runtime_error & e) + { + errorText = e.what(); + } + catch(const setup::version_error &) + { + errorText = tr("Not a supported Inno Setup installer!"); + } ui->progressBarGog->setVisible(false); ui->pushButtonGogInstall->setVisible(true); setEnabled(true); QStringList dirData = tempDir.entryList({"data"}, QDir::Filter::Dirs); - if(dirData.empty() || QDir(tempDir.filePath(dirData.front())).entryList({"*.lod"}, QDir::Filter::Files).empty()) + if(!errorText.isEmpty() || dirData.empty() || QDir(tempDir.filePath(dirData.front())).entryList({"*.lod"}, QDir::Filter::Files).empty()) { - QMessageBox::critical(this, tr("No Heroes III data!"), tr("Selected files do not contain Heroes III data!"), QMessageBox::Ok, QMessageBox::Ok); + if(!errorText.isEmpty()) + QMessageBox::critical(this, tr("Extracting error!"), errorText, QMessageBox::Ok, QMessageBox::Ok); + else + QMessageBox::critical(this, tr("No Heroes III data!"), tr("Selected files do not contain Heroes III data!"), QMessageBox::Ok, QMessageBox::Ok); tempDir.removeRecursively(); return; } @@ -596,11 +654,6 @@ void FirstLaunchView::on_pushButtonDiscord_clicked() QDesktopServices::openUrl(QUrl("https://discord.gg/chBT42V")); } -void FirstLaunchView::on_pushButtonSlack_clicked() -{ - QDesktopServices::openUrl(QUrl("https://slack.vcmi.eu/")); -} - void FirstLaunchView::on_pushButtonGithub_clicked() { QDesktopServices::openUrl(QUrl("https://github.com/vcmi/vcmi")); diff --git a/launcher/firstLaunch/firstlaunch_moc.h b/launcher/firstLaunch/firstlaunch_moc.h index 6bc699c2b..a35aa4820 100644 --- a/launcher/firstLaunch/firstlaunch_moc.h +++ b/launcher/firstLaunch/firstlaunch_moc.h @@ -87,8 +87,6 @@ private slots: void on_pushButtonDiscord_clicked(); - void on_pushButtonSlack_clicked(); - void on_pushButtonGithub_clicked(); private: diff --git a/launcher/firstLaunch/firstlaunch_moc.ui b/launcher/firstLaunch/firstlaunch_moc.ui index b9f88f440..a5e54b104 100644 --- a/launcher/firstLaunch/firstlaunch_moc.ui +++ b/launcher/firstLaunch/firstlaunch_moc.ui @@ -149,20 +149,13 @@ - + VCMI on Github - - - - VCMI on Slack - - - diff --git a/launcher/helper.cpp b/launcher/helper.cpp index 931f3435d..9b4cec55e 100644 --- a/launcher/helper.cpp +++ b/launcher/helper.cpp @@ -33,6 +33,7 @@ namespace Helper void loadSettings() { settings.init("config/settings.json", "vcmi:settings"); + persistentStorage.init("config/persistentStorage.json", ""); } void enableScrollBySwiping(QObject * scrollTarget) diff --git a/launcher/modManager/cmodlistview_moc.cpp b/launcher/modManager/cmodlistview_moc.cpp index f88b870fb..1a4aa2348 100644 --- a/launcher/modManager/cmodlistview_moc.cpp +++ b/launcher/modManager/cmodlistview_moc.cpp @@ -70,9 +70,8 @@ void CModListView::dropEvent(QDropEvent* event) if(mimeData->hasUrls()) { const QList urlList = mimeData->urls(); - for (const auto & url : urlList) - manualInstallFile(url); + manualInstallFile(url.toLocalFile()); } } @@ -631,28 +630,31 @@ void CModListView::on_installButton_clicked() void CModListView::on_installFromFileButton_clicked() { - QString filter = tr("All supported files") + " (*.h3m *.vmap *.h3c *.vcmp *.zip *.json);;" + tr("Maps") + " (*.h3m *.vmap);;" + tr("Campaigns") + " (*.h3c *.vcmp);;" + tr("Configs") + " (*.json);;" + tr("Mods") + " (*.zip)"; - QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files (configs, mods, maps, campaigns) to install..."), QDir::homePath(), filter); - - for (const auto & file : files) + // iOS can't display modal dialogs when called directly on button press + // https://bugreports.qt.io/browse/QTBUG-98651 + QTimer::singleShot(0, this, [this] { - QUrl url = QUrl::fromLocalFile(file); - manualInstallFile(url); - } + QString filter = tr("All supported files") + " (*.h3m *.vmap *.h3c *.vcmp *.zip *.json);;" + tr("Maps") + " (*.h3m *.vmap);;" + tr("Campaigns") + " (*.h3c *.vcmp);;" + tr("Configs") + " (*.json);;" + tr("Mods") + " (*.zip)"; + QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files (configs, mods, maps, campaigns) to install..."), QDir::homePath(), filter); + + for(const auto & file : files) + { + manualInstallFile(file); + } + }); } -void CModListView::manualInstallFile(QUrl url) +void CModListView::manualInstallFile(QString filePath) { - QString urlStr = url.toString(); - QString fileName = url.fileName(); - if(urlStr.endsWith(".zip", Qt::CaseInsensitive)) + QString fileName = QFileInfo{filePath}.fileName(); + if(filePath.endsWith(".zip", Qt::CaseInsensitive)) downloadFile(fileName.toLower() // mod name currently comes from zip file -> remove suffixes from github zip download .replace(QRegularExpression("-[0-9a-f]{40}"), "") .replace(QRegularExpression("-vcmi-.+\\.zip"), ".zip") .replace("-main.zip", ".zip") - , urlStr, "mods", 0); - else if(urlStr.endsWith(".json", Qt::CaseInsensitive)) + , QUrl::fromLocalFile(filePath), "mods"); + else if(filePath.endsWith(".json", Qt::CaseInsensitive)) { QDir configDir(QString::fromStdString(VCMIDirs::get().userConfigPath().string())); QStringList configFile = configDir.entryList({fileName}, QDir::Filter::Files); // case insensitive check @@ -663,7 +665,7 @@ void CModListView::manualInstallFile(QUrl url) { const auto configFilePath = configDir.filePath(configFile[0]); QFile::remove(configFilePath); - QFile::copy(url.toLocalFile(), configFilePath); + QFile::copy(filePath, configFilePath); // reload settings Helper::loadSettings(); @@ -676,10 +678,15 @@ void CModListView::manualInstallFile(QUrl url) } } else - downloadFile(fileName, urlStr, fileName, 0); + downloadFile(fileName, QUrl::fromLocalFile(filePath), fileName); } void CModListView::downloadFile(QString file, QString url, QString description, qint64 size) +{ + downloadFile(file, QUrl{url}, description, size); +} + +void CModListView::downloadFile(QString file, QUrl url, QString description, qint64 size) { if(!dlManager) { @@ -690,20 +697,17 @@ void CModListView::downloadFile(QString file, QString url, QString description, connect(dlManager, SIGNAL(finished(QStringList,QStringList,QStringList)), this, SLOT(downloadFinished(QStringList,QStringList,QStringList))); - + connect(manager.get(), SIGNAL(extractionProgress(qint64,qint64)), this, SLOT(extractionProgress(qint64,qint64))); - + connect(modModel, &CModListModel::dataChanged, filterModel, &QAbstractItemModel::dataChanged); - - QString progressBarFormat = tr("Downloading %s%. %p% (%v MB out of %m MB) finished"); - - progressBarFormat.replace("%s%", description); + const auto progressBarFormat = tr("Downloading %1. %p% (%v MB out of %m MB) finished").arg(description); ui->progressBar->setFormat(progressBarFormat); } - dlManager->downloadFile(QUrl(url), file, size); + dlManager->downloadFile(url, file, size); } void CModListView::downloadProgress(qint64 current, qint64 max) diff --git a/launcher/modManager/cmodlistview_moc.h b/launcher/modManager/cmodlistview_moc.h index bf8ee7ca9..7cfe44012 100644 --- a/launcher/modManager/cmodlistview_moc.h +++ b/launcher/modManager/cmodlistview_moc.h @@ -51,8 +51,9 @@ class CModListView : public QWidget // find mods that depend on this one QStringList findDependentMods(QString mod, bool excludeDisabled); - void manualInstallFile(QUrl url); + void manualInstallFile(QString filePath); void downloadFile(QString file, QString url, QString description, qint64 size = 0); + void downloadFile(QString file, QUrl url, QString description, qint64 size = 0); void installMods(QStringList archives); void installMaps(QStringList maps); diff --git a/launcher/modManager/cmodmanager.cpp b/launcher/modManager/cmodmanager.cpp index 7bd47bcaf..4012519d1 100644 --- a/launcher/modManager/cmodmanager.cpp +++ b/launcher/modManager/cmodmanager.cpp @@ -26,9 +26,15 @@ namespace { QString detectModArchive(QString path, QString modName, std::vector & filesToExtract) { - ZipArchive archive(qstringToPath(path)); - - filesToExtract = archive.listFiles(); + try { + ZipArchive archive(qstringToPath(path)); + filesToExtract = archive.listFiles(); + } + catch (const std::runtime_error & e) + { + logGlobal->error("Failed to open zip archive. Reason: %s", e.what()); + return ""; + } QString modDirName; diff --git a/launcher/settingsView/csettingsview_moc.cpp b/launcher/settingsView/csettingsview_moc.cpp index ee34e6281..2e7642553 100644 --- a/launcher/settingsView/csettingsview_moc.cpp +++ b/launcher/settingsView/csettingsview_moc.cpp @@ -90,6 +90,12 @@ void CSettingsView::loadSettings() #ifdef VCMI_MOBILE ui->comboBoxFullScreen->hide(); ui->labelFullScreen->hide(); + + if(!persistentStorage["gui"]["tutorialCompleted0"].Bool() && !persistentStorage["gui"]["tutorialCompleted1"].Bool()) + { + ui->labelResetTutorialTouchscreen->hide(); + ui->pushButtonResetTutorialTouchscreen->hide(); + } #else ui->labelReservedArea->hide(); ui->sliderReservedArea->hide(); @@ -99,6 +105,8 @@ void CSettingsView::loadSettings() ui->labelRelativeCursorSpeed->hide(); ui->buttonHapticFeedback->hide(); ui->labelHapticFeedback->hide(); + ui->labelResetTutorialTouchscreen->hide(); + ui->pushButtonResetTutorialTouchscreen->hide(); if (settings["video"]["realFullscreen"].Bool()) ui->comboBoxFullScreen->setCurrentIndex(2); else @@ -525,6 +533,16 @@ void CSettingsView::on_pushButtonTranslation_clicked() } } +void CSettingsView::on_pushButtonResetTutorialTouchscreen_clicked() +{ + Settings node0 = persistentStorage.write["gui"]["tutorialCompleted0"]; + node0->Bool() = false; + Settings node1 = persistentStorage.write["gui"]["tutorialCompleted1"]; + node1->Bool() = false; + + ui->pushButtonResetTutorialTouchscreen->hide(); +} + void CSettingsView::on_buttonRepositoryDefault_toggled(bool value) { Settings node = settings.write["launcher"]["defaultRepositoryEnabled"]; @@ -705,12 +723,12 @@ void CSettingsView::on_spinBoxNetworkPortLobby_valueChanged(int arg1) void CSettingsView::on_sliderControllerSticksAcceleration_valueChanged(int value) { - Settings node = settings.write["input"]["configAxisScale"]; + Settings node = settings.write["input"]["controllerAxisScale"]; node->Integer() = value / 100.0; } void CSettingsView::on_sliderControllerSticksSensitivity_valueChanged(int value) { - Settings node = settings.write["input"]["configAxisSpeed"]; + Settings node = settings.write["input"]["controllerAxisSpeed"]; node->Integer() = value; } diff --git a/launcher/settingsView/csettingsview_moc.h b/launcher/settingsView/csettingsview_moc.h index 81b4d194e..406a926d2 100644 --- a/launcher/settingsView/csettingsview_moc.h +++ b/launcher/settingsView/csettingsview_moc.h @@ -49,6 +49,7 @@ private slots: void on_comboBoxLanguage_currentIndexChanged(int index); void on_buttonCursorType_toggled(bool value); void on_pushButtonTranslation_clicked(); + void on_pushButtonResetTutorialTouchscreen_clicked(); void on_buttonRepositoryDefault_toggled(bool value); void on_buttonRepositoryExtra_toggled(bool value); void on_lineEditRepositoryExtra_textEdited(const QString &arg1); diff --git a/launcher/settingsView/csettingsview_moc.ui b/launcher/settingsView/csettingsview_moc.ui index 353463b19..cdb69905f 100644 --- a/launcher/settingsView/csettingsview_moc.ui +++ b/launcher/settingsView/csettingsview_moc.ui @@ -48,519 +48,16 @@ 0 0 - 729 - 1340 + 730 + 1691 - - - - Online Lobby port - - - - - - - Autocombat AI in battles - - - - - - - Sticks Sensitivity - - - - - - - Heroes III Translation - - - - - - - Haptic Feedback - - - - - - - Software Cursor - - - - - - - Renderer - - - - - - - Online Lobby address - - - - - - - Upscaling Filter - - - - - - - Use Relative Pointer Mode - - - - - - - - - - VCMI Language - - - - - - - - - - VSync - - - - - - - - - - - - - - Autosave - - - - - - - - - - - - - - Enemy AI in battles - - - - - - - BattleAI - - - - BattleAI - - - - - StupidAI - - - - - - - - - Nearest - - - - - Linear - - - - - Best (Linear) - - - - - - - - 1024 - - - 65535 - - - 3030 - - - - - - - - true - - - - Input - Touchscreen - - - 5 - - - - - - - 500 - - - 2000 - - - 250 - - - 250 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 250 - - - - - - - 0 - - - 50 - - - 1 - - - 10 - - - 0 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 10 - - - - - - - 25 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 5 - - - - - - - VCAI - - - - VCAI - - - - - Nullkiller - - - - - - - - - true - - - - Video - - - 5 - - - - - - - 0 - - - 50 - - - 1 - - - 10 - - - 0 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 10 - - - - - - - 0 - - - 50 - - - 1 - - - 10 - - - 0 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 10 - - - - - - - 100 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 10 - - - - - - - 20 - - - 1000 - - - 10 - - - - - - - 1024 - - - 65535 - - - 3030 - - - - - - - Adventure Map Enemies - - - - - - - - true - - - - Artificial Intelligence - - - 5 - - - - - - - Resolution - - - - - - - - true - - - - Network - - - 5 - - - - - - - 100 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 10 - - - - - - - Show intro - - - - - - - Adventure Map Allies - - - - - - - Framerate Limit - - - - - - - Autosave limit (0 = off) - - - - - - - Network port - - - - - - - - true - - - - Audio - - - 5 - - - - - - - - - - - - - Default repository - - - + 75 true @@ -572,108 +69,7 @@ - - - - Relative Pointer Speed - - - - - - - Music Volume - - - - - - - Reserved screen area - - - - - - - Additional repository - - - - - - - Ignore SSL errors - - - - - - - - true - - - - Input - Mouse - - - 5 - - - - - - - Long Touch Duration - - - - - - - % - - - 50 - - - 400 - - - 10 - - - - - - - Display index - - - - - - - Controller Click Tolerance - - - - - - - Touch Tap Tolerance - - - - - - - Neutral AI in battles - - - - + false @@ -693,36 +89,58 @@ - - - - - true - - + + - Input - Controller - - - 5 + Sticks Acceleration - - + + - Interface Scaling + Refresh now - - + + - Fullscreen + - + + + + % + + + 50 + + + 400 + + + 10 + + + + + + + Reserved screen area + + + + + + + Online Lobby address + + + + VCAI @@ -739,14 +157,121 @@ - - + + + + + 0 + 0 + + - Check on startup + + + + true - + + + + 100 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 10 + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + VCMI Language + + + + + + + 25 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 5 + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + Default repository + + + + + + + 1024 + + + 65535 + + + 3030 + + + + + + + Heroes III Translation + + + + 100 @@ -765,22 +290,100 @@ - - + + - Sound Volume + Renderer - - + + + + + 75 + true + + - Autosave prefix + Artificial Intelligence + + + 5 - - + + + + Use Relative Pointer Mode + + + + + + + Fullscreen + + + + + + + Autocombat AI in battles + + + + + + + Display index + + + + + + + Long Touch Duration + + + + + + + Sticks Sensitivity + + + + + + + Touch Tap Tolerance + + + + + + + + + + + + + + 100 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 10 + + @@ -813,48 +416,154 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use - - - - false + + + + true - - BattleAI + + + 0 + 0 + - - - BattleAI - - - - - StupidAI - - - - - - - - Mouse Click Tolerance - - - - - - - - - - - Sticks Acceleration + + true + + + false - + + + + + + + true + + + + + + + Show intro + + + + + + + + + + 0 + + + 50 + + + 1 + + + 10 + + + 0 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 10 + + + + + + + Online Lobby port + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + + + + + 75 + true + + + + Video + + + 5 + + + + + + + + 75 + true + + + + Audio + + + 5 + + + + + + + + 0 + 0 + + + + + + + true + + + false + + + + 500 @@ -882,7 +591,462 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use - + + + + VSync + + + + + + + + + + + + + + + Nearest + + + + + Linear + + + + + Best (Linear) + + + + + + + + false + + + BattleAI + + + + BattleAI + + + + + StupidAI + + + + + + + + Check on startup + + + + + + + 0 + + + 50 + + + 1 + + + 10 + + + 0 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 10 + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + 500 + + + 2000 + + + 250 + + + 250 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 250 + + + + + + + + + + 1024 + + + 65535 + + + 3030 + + + + + + + Enemy AI in battles + + + + + + + + 75 + true + + + + Input - Touchscreen + + + 5 + + + + + + + Autosave prefix + + + + + + + Ignore SSL errors + + + + + + + + + + Autosave limit (0 = off) + + + + + + + + + + + + + + Autosave + + + + + + + Haptic Feedback + + + + + + + + 0 + 0 + + + + + + + true + + + + + + + Additional repository + + + + + + + Mouse Click Tolerance + + + + + + + Software Cursor + + + + + + + Relative Pointer Speed + + + + + + + + 75 + true + + + + Network + + + 5 + + + + + + + Network port + + + + + + + true + + + + 0 + 0 + + + + + + + true + + + false + + + + + + + Upscaling Filter + + + + + + + Adventure Map Enemies + + + + + + + BattleAI + + + + BattleAI + + + + + StupidAI + + + + + + + + Neutral AI in battles + + + + + + + Adventure Map Allies + + + + + + + + 75 + true + + + + Input - Mouse + + + 5 + + + + + + + true + + + + 0 + 0 + + + + + + + true + + + false + + + + + + + + + + 20 + + + 1000 + + + 10 + + + + + + + VCAI + + + + VCAI + + + + + Nullkiller + + + + + + + + empty = map name prefix + + + + + + + + 75 + true + + + + Input - Controller + + + 5 + + + + + + + Framerate Limit + + + + + + + Controller Click Tolerance + + + + 100 @@ -910,187 +1074,56 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use - - - - true - - - - 0 - 0 - - + + - - - - true - - - false + Interface Scaling - - - - true - - - - 0 - 0 - - + + - - - - true - - - false + Resolution - - - - - 0 - 0 - - + + - - - - true - - - false + Sound Volume - - - - - 0 - 0 - + + + + 0 - - + + 50 - - true + + 1 + + + 10 + + + 0 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 10 - - - - empty = map name prefix - - - - - - - true - - - - 0 - 0 - - - - - - - true - - - false - - - - - - - Refresh now - - - - - - - - - - true - - - - - - - - - - - - - - - 0 - 0 - - - - - - - true - - - - - - - - 0 - 0 - - - - - - - true - - - - - - - - 0 - 0 - - - - - - - true - - - - + @@ -1106,35 +1139,24 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use - - - - - 0 - 0 - - + + - - - - true + Music Volume - - - - - 0 - 0 - - + + - + Show Tutorial again - - true + + + + + + Reset diff --git a/launcher/translation/chinese.ts b/launcher/translation/chinese.ts index e6d83710a..2b245d6cd 100644 --- a/launcher/translation/chinese.ts +++ b/launcher/translation/chinese.ts @@ -23,11 +23,6 @@ Our Community 联系社区 - - - VCMI on Slack - 访问VCMI的Slack - Build Information @@ -79,7 +74,7 @@ Configuration files directory - + 配置文件目录 @@ -244,7 +239,7 @@ - + Description 详细介绍 @@ -296,7 +291,7 @@ Reload repositories - + 重载源 @@ -304,181 +299,185 @@ 终止 - + Mod name 模组名称 - + Installed version 已安装的版本 - + Latest version 最新版本 - + Size 大小 - + Download size 下载大小 - + Authors 作者 - + License 授权许可 - + Contact 联系方式 - + Compatibility 兼容性 - - + + Required VCMI version 需要VCMI版本 - + Supported VCMI version 支持的VCMI版本 - + please upgrade mod 请更新模组 - - + + mods repository index 模组源索引号 - + or newer 或更新的版本 - + Supported VCMI versions 支持的VCMI版本 - + Languages 语言 - + Required mods Mod统一翻译为模组 前置模组 - + Conflicting mods Mod统一翻译为模组 冲突的模组 - + This mod can not be installed or enabled because the following dependencies are not present 这个模组无法被安装或者激活,因为下列依赖项未满足 - + This mod can not be enabled because the following mods are incompatible with it 这个模组无法被激活,因为下列模组与其不兼容 - + This mod cannot be disabled because it is required by the following mods 这个模组无法被禁用,因为它被下列模组所依赖 - + This mod cannot be uninstalled or updated because it is required by the following mods 这个模组无法被卸载或者更新,因为它被下列模组所依赖 - + This is a submod and it cannot be installed or uninstalled separately from its parent mod 这是一个附属模组它无法在所属模组外被直接被安装或者卸载 - + Notes 笔记注释 - + All supported files 所有支持的文件格式 - + Maps 地图 - + Campaigns 战役 - + Configs 配置 - + Mods 模组 - + Select files (configs, mods, maps, campaigns) to install... 选择文件(配置,模组,地图,战役)来安装 - + Replace config file? 替换配置文件? - + Do you want to replace %1? 你想要替换%1吗? - - Downloading %s%. %p% (%v MB out of %m MB) finished - 下载进度 %s%. %p% (%v MB 共 %m MB) 已完成 + + Downloading %1. %p% (%v MB out of %m MB) finished + - + Downloading %s%. %p% (%v MB out of %m MB) finished + 下载进度 %s%. %p% (%v MB 共 %m MB) 已完成 + + + Download failed 下载失败 - + Unable to download all files. Encountered errors: @@ -491,7 +490,7 @@ Encountered errors: - + Install successfully downloaded? @@ -500,34 +499,34 @@ Install successfully downloaded? 安装下载成功的部分? - + Installing mod %1 正在安装模组 %1 - + Operation failed 操作失败 - + Encountered errors: 遇到问题: - + screenshots 截图 - + Screenshot %1 截图 %1 - + Mod is incompatible Mod统一翻译为模组 模组不兼容 @@ -536,94 +535,94 @@ Install successfully downloaded? CModManager - + Can not install submod 无法安装子模组 - + Mod is already installed 模组已安装 - + Can not uninstall submod 无法卸载子模组 - + Mod is not installed 模组未安装 - + Mod is already enabled 模组已启用 - - + + Mod must be installed first 需要先安装模组 - + Mod is not compatible, please update VCMI and checkout latest mod revisions 模组不兼容,请更新VCMI并获取模组最新版本 - + Required mod %1 is missing 需要的模组%1未找到 - + Required mod %1 is not enabled 需要的模组%1未启用 - - + + This mod conflicts with %1 此模组和%1冲突 - + Mod is already disabled 模组已禁用 - + This mod is needed to run %1 此模组需要运行%1 - + Mod archive is missing 模组归档文件未找到 - + Mod with such name is already installed 同名模组已安装 - + Mod archive is invalid or corrupted 模组归档文件无效或损坏 - + Failed to extract mod data 提取模组数据失败 - + Data with this mod was not found 此模组的数据未找到 - + Mod is located in protected directory, please remove it manually: 模组位于受保护的目录,请手动删除它: @@ -638,7 +637,7 @@ Install successfully downloaded? 关闭 - + Artificial Intelligence 人工智能 @@ -647,172 +646,182 @@ Install successfully downloaded? 模组仓库 - + Interface Scaling 界面缩放 - + Neutral AI in battles 战场中立生物AI - + Enemy AI in battles 战场敌方玩家AI - + Additional repository 额外仓库 - + Adventure Map Allies 冒险地图友方玩家 - + Online Lobby port - + 在线大厅端口 - + Autocombat AI in battles - + 自动战斗AI - + Sticks Sensitivity - + 摇杆灵敏度 - + Haptic Feedback - + 触觉反馈 - + Software Cursor - + 软件指针 - + Online Lobby address - + 在线大厅地址 - + Upscaling Filter - + 图像放大过滤器 - + Use Relative Pointer Mode - + 使用相对指针模式 - + Nearest - + 最邻近 - + Linear - + 线性 - + Best (Linear) - + 自动(线性) - + Input - Touchscreen - + 输入 - 触屏 - + Adventure Map Enemies 冒险地图敌方玩家 - - Network + + Show Tutorial again + + + Reset + + + + + Network + 网络 + Audio - + 音频 - + Relative Pointer Speed - + 相对指针速度 - + Music Volume - + 音乐音量 - + Ignore SSL errors - + 忽略SSL错误 - + Input - Mouse - + 输入 - 鼠标 - + Long Touch Duration - + 长按触屏间隔 - + % - + % - + Controller Click Tolerance - + 控制器按键灵敏度 - + Touch Tap Tolerance - + 触屏点击灵敏度 - + Input - Controller - + 输入 - 控制器 - + Sound Volume - + 音效音量 - + Windowed 窗口化 - + Borderless fullscreen 无边框全屏 - + Exclusive fullscreen 独占全屏 - + Autosave limit (0 = off) 自动保存限制 (0 = 不限制) @@ -821,42 +830,42 @@ Install successfully downloaded? 战场友方单位AI - + Framerate Limit 帧率限制 - + Autosave prefix 自动保存文件名前缀 - + Mouse Click Tolerance - + 鼠标点击灵敏度 - + Sticks Acceleration - + 摇杆加速度 - + empty = map name prefix 空 = 地图名称前缀 - + Refresh now 立即刷新 - + Default repository 默认仓库 - + Renderer 渲染器 @@ -874,7 +883,7 @@ Install successfully downloaded? 英雄无敌3数据语言 - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -891,7 +900,7 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use 独占全屏模式 - 游戏会运行在一个覆盖全部屏幕的窗口,使用和你选择的分辨率。 - + Reserved screen area 保留屏幕区域 @@ -904,88 +913,88 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use 软件 - + Heroes III Translation 发布版本里找不到这个项,不太清楚意义 英雄无敌3翻译 - + Check on startup 启动时检查更新 - + Fullscreen 全屏 - + General 通用设置 - + VCMI Language VCMI语言 - + Resolution 分辨率 - + Autosave 自动存档 - + VSync 垂直同步 - + Display index 显示器序号 - + Network port 网络端口 - + Video 视频设置 - + Show intro 显示开场动画 - + Active 激活 - + Disabled 禁用 - + Enable 启用 - + Not Installed 未安装 - + Install 安装 @@ -1070,12 +1079,12 @@ Heroes® of Might and Magic® III HD is currently not supported! Use offline installer from gog.com - + 使用gog.com的离线安装器 You can manually copy directories Maps, Data and Mp3 from the original game directory to VCMI data directory that you can see on top of this page - + 你可以从原始游戏里手动拷贝Maps, Data 和 Mp3目录到VCMI的数据目录下,数据目录可以从页面顶部找到 @@ -1112,23 +1121,24 @@ Heroes® of Might and Magic® III HD is currently not supported! Installing... %p% - + 安装中... %p% If you already have Heroes III files on your device, you can select this directory and VCMI will copy the existing data automatically. - + 如果你已经在你的设备里准备好英雄无敌3文件,你可以选择这个目录,VCMI会自动复制已存在的数据。 Copy existing files - + 复制已存在的文件 If you own Heroes III on gog.com you can download backup offline installer from gog.com, and VCMI will import Heroes III data using offline installer. Offline installer consists of two parts, .exe and .bin. Make sure you download both of them. - + 如果你已经在gog.com拥有了英雄无敌3,你可以从gog.com下载离线安装器。VCMI将会通过离线安装器导入英雄无敌3数据 +离线安装器包含两部分:exe文件和bin文件。请确保这两部分都已下载。 @@ -1160,11 +1170,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github 访问VCMI的Github - - - VCMI on Slack - 访问VCMI的Slack - VCMI on Discord @@ -1179,7 +1184,7 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b Manual Installation - + 手动安装 @@ -1236,49 +1241,54 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b 追随神迹 - + Heroes III installation found! 英雄无敌3安装目录已找到! - + Copy data to VCMI folder? 复制数据到VCMI文件夹吗? - + Select %1 file... param is file extension 选择%1文件... - + You have to select %1 file! param is file extension 你必须选择%1文件! - + GOG file (*.*) GOG文件 (*.*) - + File selection 选择文件 - + + File cannot opened + + + + Invalid file selected 所选的文件无效 - + GOG installer GOG安装包 - + GOG data GOC数据 @@ -1287,39 +1297,60 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b 安装中...请等待! - + No Heroes III data! 没有英雄无敌3数据! - + Selected files do not contain Heroes III data! 所选的文件不包含英雄无敌3数据! - - - - + + + + Heroes III data not found! 未找到英雄无敌3数据! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. 从所选目录检测有效的英雄无敌3数据失败。 请选择已安装英雄无敌3的数据目录。 - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + + + + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. VCMI不支持英雄无敌3高清版文件。 请选择包含《英雄无敌3:完全版》或《英雄无敌3:死亡阴影》的目录。 - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. 检测到未知或不支持的英雄无敌3版本。 @@ -1482,13 +1513,14 @@ Please select directory with Heroes III: Complete Edition or Heroes III: Shadow Error starting executable - + 启动可执行文件时出错 Failed to start %1 Reason: %2 - + 启动%1失败 +原因:%2 diff --git a/launcher/translation/czech.ts b/launcher/translation/czech.ts index b39876a72..e02143603 100644 --- a/launcher/translation/czech.ts +++ b/launcher/translation/czech.ts @@ -23,11 +23,6 @@ Our Community Naše komunita - - - VCMI on Slack - VCMI na Slacku - Build Information @@ -79,7 +74,7 @@ Configuration files directory - + Složka nastavení hry @@ -242,7 +237,7 @@ - + Description Popis @@ -259,7 +254,7 @@ Install from file - + Instalovat ze souboru @@ -294,7 +289,7 @@ Reload repositories - + Načíst repozitáře @@ -302,179 +297,183 @@ Zrušit - + Mod name Název modifikace - + Installed version Nainstalovaná verze - + Latest version Nejnovější verze - + Size Velikost - + Download size Velikost ke stažení - + Authors Autoři - + License Licence - + Contact Kontakt - + Compatibility Kompabilita - - + + Required VCMI version Vyžadovaná verze VCMI - + Supported VCMI version Podporovaná verze VCMI - + please upgrade mod - + prosíme aktualizujte modifikaci - - + + mods repository index - + index repozitáře modifikací - + or newer - + nebo novější - + Supported VCMI versions Podporované verze VCMI - + Languages Jazyky - + Required mods Vyžadované modifikace VCMI - + Conflicting mods Modifikace v kolizi - + This mod can not be installed or enabled because the following dependencies are not present Tato modifikace nemůže být nainstalována nebo povolena, protože následující závislosti nejsou přítomny - + This mod can not be enabled because the following mods are incompatible with it Tato modifikace nemůže být povolena, protože následující modifikace s ní nejsou kompatibilní - + This mod cannot be disabled because it is required by the following mods Tato modifikace nemůže být zakázána, protože je vyžadována následujícími modifikacemi - + This mod cannot be uninstalled or updated because it is required by the following mods Tato modifikace nemůže být odinstalována nebo aktualizována, protože je vyžadována následujícími modifikacemi - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Toto je podmodifikace, která nemůže být nainstalována nebo odinstalována bez její rodičovské modifikace - + Notes Poznámky - + All supported files - + Všechny podporované soubory - + Maps - Mapy + Mapy - + Campaigns - + Kampaně - + Configs - + Nastavení + + + + Mods + Modifikace - Mods - Modifikace - - - Select files (configs, mods, maps, campaigns) to install... - + Vyberte soubory (nastavení, modifikace, mapy anebo kampaně) pro instalaci... - + Replace config file? - + Nahradit soubor nastavení? - + Do you want to replace %1? + Chcete nahradit %1? + + + + Downloading %1. %p% (%v MB out of %m MB) finished - Downloading %s%. %p% (%v MB out of %m MB) finished - Stahování %s%. %p% (%v MB z %m MB) dokončeno + Stahování %s%. %p% (%v MB z %m MB) dokončeno - + Download failed Stahování selhalo - + Unable to download all files. Encountered errors: @@ -487,7 +486,7 @@ Vyskytly se chyby: - + Install successfully downloaded? @@ -496,34 +495,34 @@ Install successfully downloaded? Nainstalovat úspěšně stažené? - + Installing mod %1 Instalování modifikace %1 - + Operation failed Operace selhala - + Encountered errors: Vyskytly se chyby: - + screenshots - + snímky obrazovky - + Screenshot %1 Snímek obrazovky %1 - + Mod is incompatible Modifikace není kompatibilní @@ -531,97 +530,98 @@ Nainstalovat úspěšně stažené? CModManager - + Can not install submod - + Nelze nainstalovat podmodifikaci - + Mod is already installed - + Modifikace je již nainstalována - + Can not uninstall submod - + Nelze odinstalovat podmodifikaci - + Mod is not installed - + Modifikace není nainstalována - + Mod is already enabled - + Modifikace je již povolena - - + + Mod must be installed first - + Nejprve musí být nainstalována modifikace - + Mod is not compatible, please update VCMI and checkout latest mod revisions - + Modifikace není kompatibilní, prosíme aktualizujte VCMI a použijte nejnovější verzi modifikace - + Required mod %1 is missing - + Vyžadovaná modifkace %1 chybí - + Required mod %1 is not enabled - + Vyžadovaná modifikace %1 není povolena - - + + This mod conflicts with %1 - + Tato modifikace koliduje s %1 - + Mod is already disabled - + Modifikace je již povolena - + This mod is needed to run %1 - + Modifikace %1 je vyžadována pro běh - + Mod archive is missing - + Archiv modifikace chybí - + Mod with such name is already installed - + Modifikace s tímto názvem je již nainstalována - + Mod archive is invalid or corrupted - + Archiv modifikace je neplatný nebo poškozený - + Failed to extract mod data - + Extrakce dat modifikace selhala - + Data with this mod was not found - + Data s touto modifikací nebyla nalezena - + Mod is located in protected directory, please remove it manually: - + Modifikace se nachází v zabezpečené složce, prosíme odstraňte ji ručně: + @@ -632,7 +632,7 @@ Nainstalovat úspěšně stažené? Vypnuto - + Artificial Intelligence Umělá inteligence @@ -641,172 +641,182 @@ Nainstalovat úspěšně stažené? Repozitáře modifikací - + Interface Scaling Škálování rozhraní - + Neutral AI in battles Neutrální AI v bitvách - + Enemy AI in battles Nepřátelská AI v bitvách - + Additional repository Další repozitáře - + Adventure Map Allies Spojenci na mapě světa - + Online Lobby port - + Port online předsíně - + Autocombat AI in battles - + AI automatického boje v bitvách - + Sticks Sensitivity - + Citlivost páček - + Haptic Feedback - + Zpětná odezva - + Software Cursor - + Softwarový kurzor - + Online Lobby address - + Adresa online předsíně - + Upscaling Filter - + Filtr škálování - + Use Relative Pointer Mode - + Použít režim relativního ukazatele - + Nearest - + Nejbližší - + Linear - + Lineární - + Best (Linear) - + Nejlepší (lineární) - + Input - Touchscreen - + Vstup - dotyková obrazovka - + Adventure Map Enemies Nepřátelé na mapě světa - - Network + + Show Tutorial again + + + Reset + + + + + Network + Síť + Audio - + Zvuk - + Relative Pointer Speed - + Relativní rychlost myši - + Music Volume - + Hlasitost hudby - + Ignore SSL errors - + Ignorovat chyby SSL - + Input - Mouse - + Vstup - Myš - + Long Touch Duration - + Doba dlouhého podržení - + % - + % - + Controller Click Tolerance - + Odchylka klepnutí ovladače - + Touch Tap Tolerance - + Odchylka klepnutí dotykem - + Input - Controller - + Vstup - ovladač - + Sound Volume - + Hlasitost zvuků - + Windowed V okně - + Borderless fullscreen Celá obrazovka bez okrajů - + Exclusive fullscreen Exkluzivní celá obrazovka - + Autosave limit (0 = off) Limit aut. uložení (0=vypnuto) @@ -815,44 +825,44 @@ Nainstalovat úspěšně stažené? Přátelské AI v bitvách - + Framerate Limit Omezení snímků za sekundu - + Autosave prefix Předpona aut. uložení - + Mouse Click Tolerance - + Odchylka klepnutí myší - + Sticks Acceleration - + Zrychlení páček - + empty = map name prefix prázná = předpona - název mapy - + Refresh now Obnovit nyní - + Default repository Výchozí repozitář - + Renderer - + Vykreslovač @@ -868,7 +878,7 @@ Nainstalovat úspěšně stažené? Jazyk dat Heroes III - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -885,7 +895,7 @@ Celá obrazovka bez okrajů- hra poběží v okně, které zakryje vaši celou Exkluzivní celá obrazovka - hra zakryje vaši celou obrazovku a použije vybrané rozlišení. - + Reserved screen area Vyhrazená část obrazovky @@ -898,89 +908,89 @@ Exkluzivní celá obrazovka - hra zakryje vaši celou obrazovku a použije vybra Software - + Heroes III Translation Překlad Heroes III - + Check on startup Zkontrolovat při zapnutí - + Fullscreen Celá obrazovka - + General Všeobecné - + VCMI Language Jazyk VCMI - + Resolution Rozlišení - + Autosave Automatické uložení - + VSync VSync - + Display index - + Network port Síťový port - + Video Zobrazení - + Show intro Zobrazit intro - + Active Aktivní - + Disabled - + Zakázáno - + Enable - Povolit + Povolit - + Not Installed - + Nenainstalováno - + Install - Instalovat + Instalovat @@ -988,27 +998,27 @@ Exkluzivní celá obrazovka - hra zakryje vaši celou obrazovku a použije vybra %1 B - + %1 B %1 KiB - + %1 KiB %1 MiB - + %1 MiB %1 GiB - + %1 GiB %1 TiB - + %1 TiB @@ -1063,17 +1073,17 @@ Heroes® of Might and Magic® III HD není v současnosti podporovaný! Use offline installer from gog.com - + Použít offline instalátor z gog.com You can manually copy directories Maps, Data and Mp3 from the original game directory to VCMI data directory that you can see on top of this page - + Můžete ručně zkopírovat existující mapy, data a MP3 z originální složky hry do složky dat VCMI, kterou můžete vidět nahoře na této stránce. Install gog.com files - + Nainstalovat soubory gog.com To run VCMI, Heroes III data files need to be present in one of the specified locations. Please copy the Heroes III data to one of these directories. @@ -1105,23 +1115,24 @@ Heroes® of Might and Magic® III HD není v současnosti podporovaný! Installing... %p% - + Instalování... %p% If you already have Heroes III files on your device, you can select this directory and VCMI will copy the existing data automatically. - + Pokud již máte soubory Heroes III na vašem zařízení, můžete vybrat jejich složku a VCMI existující data zkopíruje automaticky. Copy existing files - + Kopírovat existující data If you own Heroes III on gog.com you can download backup offline installer from gog.com, and VCMI will import Heroes III data using offline installer. Offline installer consists of two parts, .exe and .bin. Make sure you download both of them. - + Pokud vlastníte Heroes III na gog.com, můžete odsud stáhnout záložní offline instalátor a VCMI z něj naimportuje data. +Offline instalátor obsahuje dvě části, .exe a .bin. Ujistěte se, že stahujete obě. @@ -1153,11 +1164,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github VCMI na GitHubu - - - VCMI on Slack - VCMI na Slacku - VCMI on Discord @@ -1172,7 +1178,7 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b Manual Installation - + Ruční instalace @@ -1224,87 +1230,116 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b - + Heroes III installation found! - + Instalace Heroes III nalezena! - + Copy data to VCMI folder? - - - - - Select %1 file... - param is file extension - + Zkopírovat data do složky VCMI? - You have to select %1 file! + Select %1 file... param is file extension - + Vyberte soubor %1... - - GOG file (*.*) - + + You have to select %1 file! + param is file extension + Musíte vybrat soubor %1! + GOG file (*.*) + GOG soubor (*.*) + + + File selection + Výběr souboru + + + + File cannot opened - + Invalid file selected - + Vybrán neplatný soubor - + GOG installer - + Instalátor GOG - + GOG data + Data GOG + + + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! - + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + No Heroes III data! - + Žádná data Heroes III! - + Selected files do not contain Heroes III data! - + Vybrané soubory neobsahují data Heroes III! - - - - + + + + Heroes III data not found! - + Data Heroes III nenalezena! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. - + Detekce platných dat Heroes III ve vybrané složce selhala. +Prosíme vyberte složku s nainstalovanými daty Heroes III. - + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. - + Soubory Heroes III HD Edice nejsou podporována ve VCMI. +Prosíme vyberte složku s Heroes III: Complete Edition nebo Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. - + Nalezena neznámá nebo nepodporovaná verze Heroes III. +Prosíme vyberte složku s Heroes III: Complete Edition nebo Heroes III: Shadow of Death. @@ -1458,12 +1493,12 @@ Please select directory with Heroes III: Complete Edition or Heroes III: Shadow Name - Název + Název Type - Druh + Druh Version @@ -1475,13 +1510,14 @@ Please select directory with Heroes III: Complete Edition or Heroes III: Shadow Error starting executable - + Chyba při spouštění souboru Failed to start %1 Reason: %2 - + Selhal start %1 +Důvod: %2 @@ -1504,12 +1540,12 @@ Reason: %2 Network error - + Chyba sítě Cannot read JSON from url or incorrect JSON data - + Nelze přečíst JSON z URL nebo nesprávná data JSON diff --git a/launcher/translation/english.ts b/launcher/translation/english.ts index e2dc82d89..dea3e3e1a 100644 --- a/launcher/translation/english.ts +++ b/launcher/translation/english.ts @@ -23,11 +23,6 @@ Our Community - - - VCMI on Slack - - Build Information @@ -238,7 +233,7 @@ - + Description @@ -298,179 +293,179 @@ - + Mod name - + Installed version - + Latest version - + Size - + Download size - + Authors - + License - + Contact - + Compatibility - - + + Required VCMI version - + Supported VCMI version - + please upgrade mod - - + + mods repository index - + or newer - + Supported VCMI versions - + Languages - + Required mods - + Conflicting mods - + This mod can not be installed or enabled because the following dependencies are not present - + This mod can not be enabled because the following mods are incompatible with it - + This mod cannot be disabled because it is required by the following mods - + This mod cannot be uninstalled or updated because it is required by the following mods - + This is a submod and it cannot be installed or uninstalled separately from its parent mod - + Notes - + All supported files - + Maps - + Campaigns - + Configs - + Mods - + Select files (configs, mods, maps, campaigns) to install... - + Replace config file? - + Do you want to replace %1? - - Downloading %s%. %p% (%v MB out of %m MB) finished + + Downloading %1. %p% (%v MB out of %m MB) finished - + Download failed - + Unable to download all files. Encountered errors: @@ -479,40 +474,40 @@ Encountered errors: - + Install successfully downloaded? - + Installing mod %1 - + Operation failed - + Encountered errors: - + screenshots - + Screenshot %1 - + Mod is incompatible @@ -520,94 +515,94 @@ Install successfully downloaded? CModManager - + Can not install submod - + Mod is already installed - + Can not uninstall submod - + Mod is not installed - + Mod is already enabled - - + + Mod must be installed first - + Mod is not compatible, please update VCMI and checkout latest mod revisions - + Required mod %1 is missing - + Required mod %1 is not enabled - - + + This mod conflicts with %1 - + Mod is already disabled - + This mod is needed to run %1 - + Mod archive is missing - + Mod with such name is already installed - + Mod archive is invalid or corrupted - + Failed to extract mod data - + Data with this mod was not found - + Mod is located in protected directory, please remove it manually: @@ -621,102 +616,112 @@ Install successfully downloaded? - + Artificial Intelligence - + Interface Scaling - + Neutral AI in battles - + Enemy AI in battles - + Additional repository - + Adventure Map Allies - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Haptic Feedback - + Software Cursor - + Online Lobby address - + Upscaling Filter - + Use Relative Pointer Mode - + Nearest - + Linear - + Best (Linear) - + Input - Touchscreen - + Adventure Map Enemies - + + Show Tutorial again + + + + + Reset + + + + Network @@ -726,112 +731,112 @@ Install successfully downloaded? - + Relative Pointer Speed - + Music Volume - + Ignore SSL errors - + Input - Mouse - + Long Touch Duration - + % - + Controller Click Tolerance - + Touch Tap Tolerance - + Input - Controller - + Sound Volume - + Windowed - + Borderless fullscreen - + Exclusive fullscreen - + Autosave limit (0 = off) - + Framerate Limit - + Autosave prefix - + Mouse Click Tolerance - + Sticks Acceleration - + empty = map name prefix - + Refresh now - + Default repository - + Renderer @@ -841,7 +846,7 @@ Install successfully downloaded? - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -852,92 +857,92 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use - + Reserved screen area - + Heroes III Translation - + Check on startup - + Fullscreen - + General - + VCMI Language - + Resolution - + Autosave - + VSync - + Display index - + Network port - + Video - + Show intro - + Active - + Disabled - + Enable - + Not Installed - + Install @@ -1094,11 +1099,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github - - - VCMI on Slack - - VCMI on Discord @@ -1157,84 +1157,110 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b - + Heroes III installation found! - + Copy data to VCMI folder? - + Select %1 file... param is file extension - + You have to select %1 file! param is file extension - + GOG file (*.*) - + File selection - + + File cannot opened + + + + Invalid file selected - + GOG installer - + GOG data - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + + + + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + No Heroes III data! - + Selected files do not contain Heroes III data! - - - - + + + + Heroes III data not found! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. - + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. diff --git a/launcher/translation/french.ts b/launcher/translation/french.ts index 002133f46..d0b1739af 100644 --- a/launcher/translation/french.ts +++ b/launcher/translation/french.ts @@ -23,11 +23,6 @@ Our Community Notre communauté - - - VCMI on Slack - VCMI sur Slack - Build Information @@ -247,7 +242,7 @@ - + Description Description @@ -302,184 +297,188 @@ Abandonner - + Mod name Nom du mod - + Installed version Version installée - + Latest version Dernière version - + Size Taille - + Download size Taille de téléchargement - + Authors Auteur(s) - + License Licence - + Contact Contact - + Compatibility Compatibilité - - + + Required VCMI version Version requise de VCMI - + Supported VCMI version Version supportée de VCMI - + please upgrade mod veuillez mettre à jour le mod - - + + mods repository index Index du dépôt de mods - + or newer ou plus récente - + Supported VCMI versions Versions supportées de VCMI - + Languages Langues - + Required mods Mods requis - + Conflicting mods Mods en conflit - + This mod can not be installed or enabled because the following dependencies are not present Ce mod ne peut pas être installé ou activé car les dépendances suivantes ne sont pas présents - + This mod can not be enabled because the following mods are incompatible with it Ce mod ne peut pas être installé ou activé, car les dépendances suivantes sont incompatibles avec lui - + This mod cannot be disabled because it is required by the following mods Ce mod ne peut pas être désactivé car il est requis pour les dépendances suivantes - + This mod cannot be uninstalled or updated because it is required by the following mods Ce mod ne peut pas être désinstallé ou mis à jour car il est requis pour les dépendances suivantes - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Ce sous-mod ne peut pas être installé ou mis à jour séparément du mod parent - + Notes Notes - + All supported files Tous les fichiers supportés - + Maps Cartes - + Campaigns Campagnes - + Configs Configurations - + Mods Mods - + Select files (configs, mods, maps, campaigns) to install... Sélectionner les fichiers à installer (configurations, mods, cartes, campagnes)... - + Replace config file? Remplacer le fichier de configuration? - + Do you want to replace %1? Voulez vous remplacer %1 ? - - Downloading %s%. %p% (%v MB out of %m MB) finished - Téléchargement %s%. %p% (%v MB sur %m MB) terminé + + Downloading %1. %p% (%v MB out of %m MB) finished + - + Downloading %s%. %p% (%v MB out of %m MB) finished + Téléchargement %s%. %p% (%v MB sur %m MB) terminé + + + Download failed Téléchargement échoué - + Unable to download all files. Encountered errors: @@ -492,7 +491,7 @@ Erreur rencontrées: - + Install successfully downloaded? @@ -501,34 +500,34 @@ Install successfully downloaded? Installer les téchargements réussis? - + Installing mod %1 Installer le mod %1 - + Operation failed Opération échouée - + Encountered errors: Erreurs rencontrées: - + screenshots captures d'écran - + Screenshot %1 Impression écran %1 - + Mod is incompatible Ce mod est incompatible @@ -536,94 +535,94 @@ Installer les téchargements réussis? CModManager - + Can not install submod Impossible d'installer le sous-mod - + Mod is already installed Le mod est déjà installé - + Can not uninstall submod Impossible de désinstaller le sousmod - + Mod is not installed Le mod n'est pas installé - + Mod is already enabled Mod déjà activé - - + + Mod must be installed first Le mode doit d'abord être installé - + Mod is not compatible, please update VCMI and checkout latest mod revisions Mod non compatible, veuillez mettre à jour VCMI et vérifier la dernière revision du mod - + Required mod %1 is missing Le mod requis %1 est manquant - + Required mod %1 is not enabled Le mod requis %1 n'est pas activé - - + + This mod conflicts with %1 Ce mod rentre en conflit avec %1 - + Mod is already disabled Mod déjà désactivé - + This mod is needed to run %1 Le mod est requis pour lancer %1 - + Mod archive is missing Archive du mod manquante - + Mod with such name is already installed Un mod avec le même nom est déjà installé - + Mod archive is invalid or corrupted L'archive du mod est invalide ou corrompue - + Failed to extract mod data Echec de l'extraction des données du mod - + Data with this mod was not found Les données de ce mod n'ont pas étés trouvées - + Mod is located in protected directory, please remove it manually: Le mod est placé dans un dossier protégé, veuillez le supprimer manuellement: @@ -638,7 +637,7 @@ Installer les téchargements réussis? Désactivé - + Artificial Intelligence Intelligence Artificielle @@ -652,142 +651,152 @@ Installer les téchargements réussis? Activé - + Enemy AI in battles IA ennemie dans les batailles - + Default repository Dépôt par défaut - + VSync Synchronisation verticalle - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Haptic Feedback - + Software Cursor - + Online Lobby address - + Upscaling Filter - + Use Relative Pointer Mode - + Nearest - + Linear - + Best (Linear) - + Input - Touchscreen - + Network + + + Show Tutorial again + + + + + Reset + + Audio - + Relative Pointer Speed - + Music Volume - + Ignore SSL errors - + Input - Mouse - + Long Touch Duration - + % - + Controller Click Tolerance - + Touch Tap Tolerance - + Input - Controller - + Sound Volume - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -804,52 +813,52 @@ Mode fenêtré sans bord - le jeu s"exécutera dans une fenêtre qui couvre Mode exclusif plein écran - le jeu couvrira l"intégralité de votre écran et utilisera la résolution sélectionnée. - + Windowed Fenêtré - + Borderless fullscreen Fenêtré sans bord - + Exclusive fullscreen Plein écran exclusif - + Reserved screen area Zone d'écran réservée - + Neutral AI in battles IA neutre dans les batailles - + Autosave limit (0 = off) Limite de sauvegarde auto (0 = désactivé) - + Adventure Map Enemies Ennemis de la carte d"aventure - + Autosave prefix Préfix de sauvegarde auto. - + empty = map name prefix vide = prefix du nom de carte - + Interface Scaling Mise à l"échelle de l"interface @@ -862,7 +871,7 @@ Mode exclusif plein écran - le jeu couvrira l"intégralité de votre écra Langue des Données de Heroes III - + Framerate Limit Limite de fréquence d"images @@ -875,42 +884,42 @@ Mode exclusif plein écran - le jeu couvrira l"intégralité de votre écra Logiciel - + Renderer Moteur de rendu - + Heroes III Translation Traduction de Heroes III - + Adventure Map Allies Alliés de la carte d"aventure - + Additional repository Dépôt supplémentaire - + Check on startup Vérifier au démarrage - + Mouse Click Tolerance - + Sticks Acceleration - + Refresh now Actualiser maintenant @@ -919,72 +928,72 @@ Mode exclusif plein écran - le jeu couvrira l"intégralité de votre écra IA amicale dans les batailles - + Fullscreen Plein écran - + General Général - + VCMI Language Langue de VCMI - + Resolution Résolution - + Autosave Sauvegarde automatique - + Display index Index d'affichage - + Network port Port de réseau - + Video Vidéo - + Show intro Montrer l'intro - + Active Actif - + Disabled Désactivé - + Enable Activé - + Not Installed Pas Installé - + Install Installer @@ -1110,11 +1119,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github VCMI sur Github - - - VCMI on Slack - VCMI sur Slack - VCMI on Discord @@ -1234,49 +1238,54 @@ Heroes® of Might and Magic® III HD n"est actuellement pas pris en charge Installer une version compatible de "In The Wake of Gods", une extension Heroes III créée par des fans - + Heroes III installation found! Installation de Heroes III trouvée! - + Copy data to VCMI folder? Copier le dossier data dans le dossier VCMI ? - + Select %1 file... param is file extension Sélectionner le fichier %1... - + You have to select %1 file! param is file extension Vous avez sélectionné le fichier %1 ! - + GOG file (*.*) Fichier GOG (*.*) - + File selection Sélection de fichier - + + File cannot opened + + + + Invalid file selected Fichier sélectionné non valide - + GOG installer Installateur GOG - + GOG data Données GOG @@ -1285,39 +1294,60 @@ Heroes® of Might and Magic® III HD n"est actuellement pas pris en charge Installation... Veuillez patienter! - + No Heroes III data! Pas de données Heroes III! - + Selected files do not contain Heroes III data! Les fichiers sélectionnés ne contiennent pas les données de Heroes III ! - - - - + + + + Heroes III data not found! Données Heroes III introuvables ! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. Impossible de détecter des données Heroes III valides dans le répertoire choisi, Veuillez selectionner un dossier ou les données de Heroes III sont présentes. - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + + + + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Les fichiers de Heroes III HD Edition ne sont pas supportés par VCMI. Veuillez sélectionner un dossier contenant les données de Heroes III: Complete Edition ou Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Version inconnue ou non supportée de Heroes III. diff --git a/launcher/translation/german.ts b/launcher/translation/german.ts index 2810957c4..cefaff5ba 100644 --- a/launcher/translation/german.ts +++ b/launcher/translation/german.ts @@ -23,11 +23,6 @@ Our Community Unsere Gemeinschaft - - - VCMI on Slack - VCMI auf Slack - Build Information @@ -242,7 +237,7 @@ - + Description Beschreibung @@ -302,179 +297,183 @@ Abbrechen - + Mod name Mod-Name - + Installed version Installierte Version - + Latest version Letzte Version - + Size Größe - + Download size Downloadgröße - + Authors Autoren - + License Lizenz - + Contact Kontakt - + Compatibility Kompatibilität - - + + Required VCMI version Benötigte VCMI Version - + Supported VCMI version Unterstützte VCMI Version - + please upgrade mod bitte Mod upgraden - - + + mods repository index Mod Verzeichnis Index - + or newer oder neuer - + Supported VCMI versions Unterstützte VCMI Versionen - + Languages Sprachen - + Required mods Benötigte Mods - + Conflicting mods Mods mit Konflikt - + This mod can not be installed or enabled because the following dependencies are not present Diese Mod kann nicht installiert oder aktiviert werden, da die folgenden Abhängigkeiten nicht vorhanden sind - + This mod can not be enabled because the following mods are incompatible with it Diese Mod kann nicht aktiviert werden, da folgende Mods nicht mit dieser Mod kompatibel sind - + This mod cannot be disabled because it is required by the following mods Diese Mod kann nicht deaktiviert werden, da sie zum Ausführen der folgenden Mods erforderlich ist - + This mod cannot be uninstalled or updated because it is required by the following mods Diese Mod kann nicht deinstalliert oder aktualisiert werden, da sie für die folgenden Mods erforderlich ist - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Dies ist eine Submod und kann nicht separat von der Hauptmod installiert oder deinstalliert werden - + Notes Anmerkungen - + All supported files Alle unterstützten Dateien - + Maps Karten - + Campaigns Kampagnen - + Configs Konfigurationen - + Mods Mods - + Select files (configs, mods, maps, campaigns) to install... Wähle Dateien (Konfigurationen, Mods, Karten, Kampagnen) zum installieren... - + Replace config file? Konfigurationsdatei ersetzen? - + Do you want to replace %1? Soll %1 ersetzt werden? - - Downloading %s%. %p% (%v MB out of %m MB) finished - Herunterladen von %s%. %p% (%v MB von %m MB) beendet + + Downloading %1. %p% (%v MB out of %m MB) finished + Downloade %1. %p% (%v MB von %m MB) abgeschlossen - + Downloading %s%. %p% (%v MB out of %m MB) finished + Herunterladen von %s%. %p% (%v MB von %m MB) beendet + + + Download failed Download fehlgeschlagen - + Unable to download all files. Encountered errors: @@ -487,7 +486,7 @@ Es sind Fehler aufgetreten: - + Install successfully downloaded? @@ -496,34 +495,34 @@ Install successfully downloaded? Installation erfolgreich heruntergeladen? - + Installing mod %1 Installation von Mod %1 - + Operation failed Operation fehlgeschlagen - + Encountered errors: Aufgetretene Fehler: - + screenshots Screenshots - + Screenshot %1 Screenshot %1 - + Mod is incompatible Mod ist inkompatibel @@ -531,94 +530,94 @@ Installation erfolgreich heruntergeladen? CModManager - + Can not install submod Submod kann nicht installiert werden - + Mod is already installed Mod ist bereits installiert - + Can not uninstall submod Submod kann nicht deinstalliert werden - + Mod is not installed Mod ist nicht installiert - + Mod is already enabled Mod ist bereits aktiviert - - + + Mod must be installed first Mod muss zuerst installiert werden - + Mod is not compatible, please update VCMI and checkout latest mod revisions Mod ist nicht kompatibel, bitte aktualisieren Sie VCMI und überprüfen Sie die neuesten Mod-Versionen - + Required mod %1 is missing Der erforderliche Mod %1 fehlt - + Required mod %1 is not enabled Erforderliche Mod %1 ist nicht aktiviert - - + + This mod conflicts with %1 Diese Mod steht im Konflikt mit %1 - + Mod is already disabled Mod ist bereits deaktiviert - + This mod is needed to run %1 Diese Mod wird benötigt, um %1 auszuführen - + Mod archive is missing Mod-Archiv fehlt - + Mod with such name is already installed Mod mit diesem Namen ist bereits installiert - + Mod archive is invalid or corrupted Mod-Archiv ist ungültig oder beschädigt - + Failed to extract mod data Mod-Daten konnten nicht extrahiert werden - + Data with this mod was not found Daten mit dieser Mod wurden nicht gefunden - + Mod is located in protected directory, please remove it manually: Mod befindet sich im geschützten Verzeichnis, bitte entfernen Sie sie manuell: @@ -633,7 +632,7 @@ Installation erfolgreich heruntergeladen? Aus - + Artificial Intelligence Künstliche Intelligenz @@ -642,97 +641,107 @@ Installation erfolgreich heruntergeladen? Mod-Repositorien - + Interface Scaling Skalierung der Benutzeroberfläche - + Neutral AI in battles Neutrale KI in Kämpfen - + Enemy AI in battles Gegnerische KI in Kämpfen - + Additional repository Zusätzliches Repository - + Adventure Map Allies Abenteuerkarte Verbündete - + Online Lobby port Online-Lobby-Port - + Autocombat AI in battles Autokampf-KI in Kämpfen - + Sticks Sensitivity Sticks Empfindlichkeit - + Haptic Feedback Haptisches Feedback - + Software Cursor Software-Cursor - + Online Lobby address Adresse der Online-Lobby - + Upscaling Filter Hochskalierungsfilter - + Use Relative Pointer Mode Relativen Zeigermodus verwenden - + Nearest Nearest - + Linear Linear - + Best (Linear) Bester (Linear) - + Input - Touchscreen Eingabe - Touchscreen - + Adventure Map Enemies Abenteuerkarte Feinde - + + Show Tutorial again + Zeige Tutorial erneut + + + + Reset + Zurücksetzen + + + Network Netzwerk @@ -742,72 +751,72 @@ Installation erfolgreich heruntergeladen? Audio - + Relative Pointer Speed Relative Zeigergeschwindigkeit - + Music Volume Musik Lautstärke - + Ignore SSL errors SSL-Fehler ignorieren - + Input - Mouse Eingabe - Maus - + Long Touch Duration Dauer der Berührung für "lange Berührung" - + % % - + Controller Click Tolerance Toleranz bei Controller Klick - + Touch Tap Tolerance Toleranz bei Berührungen - + Input - Controller Eingabe - Controller - + Sound Volume Sound-Lautstärke - + Windowed Fenstermodus - + Borderless fullscreen Randloser Vollbildmodus - + Exclusive fullscreen Exklusiver Vollbildmodus - + Autosave limit (0 = off) Limit für Autospeicherung (0 = aus) @@ -816,42 +825,42 @@ Installation erfolgreich heruntergeladen? Freundliche KI in Kämpfen - + Framerate Limit Limit der Bildrate - + Autosave prefix Präfix für Autospeicherung - + Mouse Click Tolerance Toleranz bei Mausklick - + Sticks Acceleration Sticks Beschleunigung - + empty = map name prefix leer = Kartenname als Präfix - + Refresh now Jetzt aktualisieren - + Default repository Standard Repository - + Renderer Renderer @@ -869,7 +878,7 @@ Installation erfolgreich heruntergeladen? Sprache der Heroes III Daten - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -886,7 +895,7 @@ Randloser Fenstermodus - das Spiel läuft in einem Fenster, das den gesamten Bil Exklusiver Vollbildmodus - das Spiel bedeckt den gesamten Bildschirm und verwendet die gewählte Auflösung. - + Reserved screen area Reservierter Bildschirmbereich @@ -899,87 +908,87 @@ Exklusiver Vollbildmodus - das Spiel bedeckt den gesamten Bildschirm und verwend Software - + Heroes III Translation Heroes III Übersetzung - + Check on startup Beim Start prüfen - + Fullscreen Vollbild - + General Allgemein - + VCMI Language VCMI-Sprache - + Resolution Auflösung - + Autosave Autospeichern - + VSync VSync - + Display index Anzeige-Index - + Network port Netzwerk-Port - + Video Video - + Show intro Intro anzeigen - + Active Aktiv - + Disabled Deaktiviert - + Enable Aktivieren - + Not Installed Nicht installiert - + Install Installieren @@ -1155,11 +1164,6 @@ Der Offline-Installer besteht aus zwei Teilen, .exe und .bin. Stellen Sie sicher VCMI on Github VCMI auf Github - - - VCMI on Slack - VCMI auf Slack - VCMI on Discord @@ -1230,49 +1234,54 @@ Der Offline-Installer besteht aus zwei Teilen, .exe und .bin. Stellen Sie sicher In The Wake of Gods - + Heroes III installation found! Heroes III-Installation gefunden! - + Copy data to VCMI folder? Daten in den VCMI-Ordner kopieren? - + Select %1 file... param is file extension %1 Datei auswählen... - + You have to select %1 file! param is file extension Sie müssen %1 Datei auswählen! - + GOG file (*.*) GOG Datei (*.*) - + File selection Dateiauswahl - + + File cannot opened + Datei kann nicht geöffnet werden + + + Invalid file selected Ungültige Datei ausgewählt - + GOG installer GOG-Installationsprogramm - + GOG data GOG-Datendatei @@ -1281,39 +1290,61 @@ Der Offline-Installer besteht aus zwei Teilen, .exe und .bin. Stellen Sie sicher Installiert... Bitte warten! - + No Heroes III data! Keine Heroes III-Daten! - + Selected files do not contain Heroes III data! Die ausgewählten Dateien enthalten keine Heroes III-Daten! - - - - + + + + Heroes III data not found! Heroes III Daten nicht gefunden! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. Es konnten keine gültigen Heroes III-Daten im gewählten Verzeichnis gefunden werden. Bitte wählen Sie ein Verzeichnis mit installierten Heroes III-Daten. - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + Es wurde der GOG Galaxy-Installer ausgewählt! Das Spiel ist in dieser Datei nicht enthalten. Lade den Offline-Backup-Installer für das Spiel herunter! + + + + Stream error while extracting files! +error reason: + Stream-Fehler beim Extrahieren von Dateien! +Fehlerursache: + + + + Not a supported Inno Setup installer! + Kein unterstütztes Inno Setup Installationsprogramm! + + + + Extracting error! + Fehler beim Extrahieren! + + + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Heroes III: HD Edition Dateien werden von VCMI nicht unterstützt. Bitte wählen Sie ein Verzeichnis mit Heroes III: Complete Edition oder Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Unbekannte oder nicht unterstützte Heroes III-Version gefunden. diff --git a/launcher/translation/polish.ts b/launcher/translation/polish.ts index 476d1eb69..d31ad97e8 100644 --- a/launcher/translation/polish.ts +++ b/launcher/translation/polish.ts @@ -23,11 +23,6 @@ Our Community Nasza społeczność - - - VCMI on Slack - VCMI na Slacku - Build Information @@ -79,7 +74,7 @@ Configuration files directory - + Katalog plików konfiguracji @@ -242,7 +237,7 @@ - + Description Opis @@ -294,7 +289,7 @@ Reload repositories - + Odśwież repozytoria @@ -302,179 +297,183 @@ Przerwij - + Mod name Nazwa moda - + Installed version Zainstalowana wersja - + Latest version Najnowsza wersja - + Size Rozmiar - + Download size Rozmiar pobierania - + Authors Autorzy - + License Licencja - + Contact Kontakt - + Compatibility Kompatybilność - - + + Required VCMI version Wymagana wersja VCMI - + Supported VCMI version Wspierana wersja VCMI - + please upgrade mod proszę zaktualizować moda - - + + mods repository index indeks repozytorium modów - + or newer lub nowsze - + Supported VCMI versions Wspierane wersje VCMI - + Languages Języki - + Required mods Wymagane mody - + Conflicting mods Konfliktujące mody - + This mod can not be installed or enabled because the following dependencies are not present Ten mod nie może zostać zainstalowany lub włączony ponieważ następujące zależności nie zostały spełnione - + This mod can not be enabled because the following mods are incompatible with it Ten mod nie może zostać włączony ponieważ następujące mody są z nim niekompatybilne - + This mod cannot be disabled because it is required by the following mods Ten mod nie może zostać wyłączony ponieważ jest wymagany do uruchomienia następujących modów - + This mod cannot be uninstalled or updated because it is required by the following mods Ten mod nie może zostać odinstalowany lub zaktualizowany ponieważ jest wymagany do uruchomienia następujących modów - + This is a submod and it cannot be installed or uninstalled separately from its parent mod To jest moduł składowy innego moda i nie może być zainstalowany lub odinstalowany oddzielnie od moda nadrzędnego - + Notes Uwagi - + All supported files Wszystkie wspierane pliki - + Maps Mapy - + Campaigns Kampanie - + Configs Konfiguracje - + Mods Mody - + Select files (configs, mods, maps, campaigns) to install... Wybierz pliki (konfiguracyjne, mody, mapy, kampanie) do zainstalowania... - + Replace config file? Zastąpić plik konfiguracji? - + Do you want to replace %1? Czy chcesz zastąpić %1? - - Downloading %s%. %p% (%v MB out of %m MB) finished - Pobieranie %s%. %p% (%v MB z %m MB) ukończono + + Downloading %1. %p% (%v MB out of %m MB) finished + Pobieranie %1. %p% (%v MB z %m MB) ukończono - + Downloading %s%. %p% (%v MB out of %m MB) finished + Pobieranie %s%. %p% (%v MB z %m MB) ukończono + + + Download failed Pobieranie nieudane - + Unable to download all files. Encountered errors: @@ -487,7 +486,7 @@ Napotkane błędy: - + Install successfully downloaded? @@ -496,34 +495,34 @@ Install successfully downloaded? Zainstalować pomyślnie pobrane? - + Installing mod %1 Instalowanie modyfikacji %1 - + Operation failed Operacja nieudana - + Encountered errors: Napotkane błędy: - + screenshots zrzuty ekranu - + Screenshot %1 Zrzut ekranu %1 - + Mod is incompatible Mod jest niekompatybilny @@ -531,94 +530,94 @@ Zainstalować pomyślnie pobrane? CModManager - + Can not install submod Nie można zainstalować submoda - + Mod is already installed Mod jest już zainstalowany - + Can not uninstall submod Nie można odinstalować submoda - + Mod is not installed Mod nie jest zainstalowany - + Mod is already enabled Mod jest już włączony - - + + Mod must be installed first Mod musi zostać najpierw zainstalowany - + Mod is not compatible, please update VCMI and checkout latest mod revisions Mod nie jest kompatybilny, proszę zaktualizować VCMI i odświeżyć listę modów - + Required mod %1 is missing Brakuje wymaganego moda %1 - + Required mod %1 is not enabled Wymagany mod %1 jest wyłączony - - + + This mod conflicts with %1 Ten mod konfliktuje z %1 - + Mod is already disabled Mod jest już wyłączony - + This mod is needed to run %1 Ten mod jest potrzebny do uruchomienia %1 - + Mod archive is missing Brakuje archiwum modyfikacji - + Mod with such name is already installed Mod z taką nazwą jest już zainstalowany - + Mod archive is invalid or corrupted Archiwum moda jest niepoprawne lub uszkodzone - + Failed to extract mod data Nieudane wyodrębnienie danych moda - + Data with this mod was not found Dane z tym modem nie zostały znalezione - + Mod is located in protected directory, please remove it manually: Mod jest umiejscowiony w chronionym folderze, proszę go usunąć ręcznie: @@ -633,7 +632,7 @@ Zainstalować pomyślnie pobrane? Wyłączony - + Artificial Intelligence Sztuczna Inteligencja @@ -642,172 +641,182 @@ Zainstalować pomyślnie pobrane? Repozytoria modów - + Interface Scaling Skala interfejsu - + Neutral AI in battles AI bitewne jednostek neutralnych - + Enemy AI in battles AI bitewne wrogów - + Additional repository Dodatkowe repozytorium - + Adventure Map Allies AI sojuszników mapy przygody - + Online Lobby port - + Port lobby online - + Autocombat AI in battles - + AI szybkiej walki - + Sticks Sensitivity - + Czułość gałek - + Haptic Feedback - + Wibracje - + Software Cursor - + Kursor programowy - + Online Lobby address - + Adres lobby online - + Upscaling Filter - + Filtr wyostrzający - + Use Relative Pointer Mode - + Użyj relatywnego trybu kursora - + Nearest - + Najbliższych - + Linear - + Liniowy - + Best (Linear) - + Najlepszy (Liniowy) - + Input - Touchscreen - + Sterowanie - Ekran dotykowy - + Adventure Map Enemies AI wrogów mapy przygody - + + Show Tutorial again + Pokaż ponownie samouczek + + + + Reset + Zresetuj + + + Network - + Sieć Audio - + Dźwięk i muzyka - + Relative Pointer Speed - + Prędkość kursora w trybie relatywnym - + Music Volume - + Głośność muzyki - + Ignore SSL errors - + Ignoruj błędy SSL - + Input - Mouse - + Sterowanie - Mysz - + Long Touch Duration - + Czas do długiego dotyku - + % - + % - + Controller Click Tolerance - + Tolerancja na kliknięcia poza elementami (kontroler) - + Touch Tap Tolerance - + Tolerancja na nietrafianie dotykiem w elementy - + Input - Controller - + Sterowanie - Kontroler - + Sound Volume - + Głośność dźwięku - + Windowed Okno - + Borderless fullscreen Pełny ekran (tryb okna) - + Exclusive fullscreen Pełny ekran klasyczny - + Autosave limit (0 = off) Limit autozapisów (0 = brak) @@ -816,42 +825,42 @@ Zainstalować pomyślnie pobrane? AI bitewne sojuszników - + Framerate Limit Limit FPS - + Autosave prefix Przedrostek autozapisu - + Mouse Click Tolerance - + Tolerancja na kliknięcia poza elementami (mysz) - + Sticks Acceleration - + Przyspieszenie gałek - + empty = map name prefix puste = przedrostek z nazwy mapy - + Refresh now Odśwież - + Default repository Domyślne repozytorium - + Renderer Renderer @@ -869,7 +878,7 @@ Zainstalować pomyślnie pobrane? Język plików Heroes III - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -886,7 +895,7 @@ Pełny ekran w trybie okna - gra uruchomi się w oknie przysłaniającym cały e Pełny ekran klasyczny - gra przysłoni cały ekran uruchamiając się w wybranej przez ciebie rozdzielczości ekranu. - + Reserved screen area Zarezerwowany obszar ekranu @@ -899,87 +908,87 @@ Pełny ekran klasyczny - gra przysłoni cały ekran uruchamiając się w wybrane Programowy - + Heroes III Translation Tłumaczenie Heroes III - + Check on startup Sprawdzaj przy uruchomieniu - + Fullscreen Pełny ekran - + General Ogólne - + VCMI Language Język VCMI - + Resolution Rozdzielczość - + Autosave Autozapis - + VSync Synchronizacja pionowa (VSync) - + Display index Numer wyświetlacza - + Network port Port sieciowy - + Video Obraz - + Show intro Pokaż intro - + Active Aktywny - + Disabled Wyłączone - + Enable Włącz - + Not Installed Nie zainstalowano - + Install Zainstaluj @@ -1064,12 +1073,12 @@ Heroes III: HD Edition nie jest obecnie wspierane! Use offline installer from gog.com - + Użyj instalatora offline z gog.com You can manually copy directories Maps, Data and Mp3 from the original game directory to VCMI data directory that you can see on top of this page - + Możesz ręcznie skopiować katalogi Maps, Data i Mp3 z oryginalnej gry do folderu danych VCMI pokazanego na górze tego widoku @@ -1106,23 +1115,24 @@ Heroes III: HD Edition nie jest obecnie wspierane! Installing... %p% - + Instalowanie... %p% If you already have Heroes III files on your device, you can select this directory and VCMI will copy the existing data automatically. - + Jeśli już posiadasz pliki Heroes III na swoim urządzeniu to możesz wybrać ich lokalizację i VCMI automatycznie skopiuje istniejące dane. Copy existing files - + Skopiuj istniejące pliki If you own Heroes III on gog.com you can download backup offline installer from gog.com, and VCMI will import Heroes III data using offline installer. Offline installer consists of two parts, .exe and .bin. Make sure you download both of them. - + Jeżeli posiadasz Heroes III na gog.com to możesz pobrać zapasowy instalator gry offline z gog.com i VCMI zaimportuje z niego dane Heroes III. +Instalator offline składa się z dwóch części, .exe i .bin. Upewnij się, że obydwie zostały pobrane. @@ -1154,11 +1164,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github VCMI na Github - - - VCMI on Slack - VCMI na Slacku - VCMI on Discord @@ -1173,7 +1178,7 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b Manual Installation - + Ręczna instalacja @@ -1229,49 +1234,54 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b In The Wake of Gods - + Heroes III installation found! Znaleziono zainstalowane Heroes III! - + Copy data to VCMI folder? Skopiować dane do folderu VCMI? - + Select %1 file... param is file extension Wybierz plik %1... - + You have to select %1 file! param is file extension Musisz wybrać plik %1! - + GOG file (*.*) Instalator GOG (*.*) - + File selection Wybór pliku - + + File cannot opened + Nieudane otwarcie pliku + + + Invalid file selected Wybrano nieprawidłowy plik - + GOG installer Instalator GOG - + GOG data Dane GOG @@ -1280,39 +1290,61 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b Instalowanie... Proszę czekać! - + No Heroes III data! Brak danych Heroes III! - + Selected files do not contain Heroes III data! Wybrane pliki nie zawierają danych Heroes III! - - - - + + + + Heroes III data not found! Dane Heroes III nie znalezione! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. Nieudane znalezienie poprawnych plików Heroes III w podanej lokalizacji. Proszę wybrać folder z zainstalowanymi danymi Heroes III. - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + Podany plik jest instalatorem GOG Galaxy! Ten plik nie zawiera gry. Proszę pobrać zapasowy instalator offline gry! + + + + Stream error while extracting files! +error reason: + Błąd strumienia podczas rozpakowywania plików! +powód błędu: + + + + Not a supported Inno Setup installer! + To nie jest wspierany instalator Inno Setup! + + + + Extracting error! + Błąd wypakowywania! + + + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Pliki Heroes III HD Edition nie są wspierane przez VCMI. Proszę wybrać folder z Heroes III: Complete Edition lub Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Znaleziono nieznaną lub niewspieraną wersję Heroes III. @@ -1487,13 +1519,14 @@ Proszę wybrać folder z Heroes III: Complete Edition lub Heroes III: Shadow of Error starting executable - + Błąd podczas uruchamiania pliku wykonywalnego Failed to start %1 Reason: %2 - + Nie udało się uruchomić %1 +Powód: %2 diff --git a/launcher/translation/portuguese.ts b/launcher/translation/portuguese.ts index a30e0b25e..ce306c2e8 100644 --- a/launcher/translation/portuguese.ts +++ b/launcher/translation/portuguese.ts @@ -23,11 +23,6 @@ Our Community Nossa comunidade - - - VCMI on Slack - VCMI no Slack - Build Information @@ -242,7 +237,7 @@ - + Description Descrição @@ -302,179 +297,183 @@ Cancelar - + Mod name Nome do mod - + Installed version Versão instalada - + Latest version Última versão - + Size Tamanho - + Download size Tamanho do download - + Authors Autores - + License Licença - + Contact Contato - + Compatibility Compatibilidade - - + + Required VCMI version Versão do VCMI requerida - + Supported VCMI version Versão do VCMI suportada - + please upgrade mod por favor, atualize o mod - - + + mods repository index índice do repositório de mods - + or newer ou mais recente - + Supported VCMI versions Versões do VCMI suportadas - + Languages Idiomas - + Required mods Mods requeridos - + Conflicting mods Mods conflitantes - + This mod can not be installed or enabled because the following dependencies are not present Este mod não pode ser instalado ou ativado porque as seguintes dependências não estão presentes - + This mod can not be enabled because the following mods are incompatible with it Este mod não pode ser ativado porque os seguintes mods são incompatíveis com ele - + This mod cannot be disabled because it is required by the following mods Este mod não pode ser desativado porque é necessário pelos seguintes mods - + This mod cannot be uninstalled or updated because it is required by the following mods Este mod não pode ser desinstalado ou atualizado porque é necessário pelos seguintes mods - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Este é um submod e não pode ser instalado ou desinstalado separadamente do seu mod principal - + Notes Notas - + All supported files Todos os arquivos suportados - + Maps Mapas - + Campaigns Campanhas - + Configs Configurações - + Mods Mods - + Select files (configs, mods, maps, campaigns) to install... Selecione arquivos (configurações, mods, mapas, campanhas) para instalar... - + Replace config file? Substituir arquivo de configuração? - + Do you want to replace %1? Você deseja substituir %1? - - Downloading %s%. %p% (%v MB out of %m MB) finished - Baixando %s%. %p% (%v MB de %m MB) completado + + Downloading %1. %p% (%v MB out of %m MB) finished + - + Downloading %s%. %p% (%v MB out of %m MB) finished + Baixando %s%. %p% (%v MB de %m MB) completado + + + Download failed Falha no download - + Unable to download all files. Encountered errors: @@ -487,7 +486,7 @@ Encontrados os seguintes erros: - + Install successfully downloaded? @@ -496,34 +495,34 @@ Install successfully downloaded? Instalar o download realizado com sucesso? - + Installing mod %1 Instalando mod %1 - + Operation failed Falha na operação - + Encountered errors: Erros encontrados: - + screenshots capturas de tela - + Screenshot %1 Captura de tela %1 - + Mod is incompatible O mod é incompatível @@ -531,94 +530,94 @@ Instalar o download realizado com sucesso? CModManager - + Can not install submod Não é possível instalar o submod - + Mod is already installed O mod já está instalado - + Can not uninstall submod Não é possível desinstalar o submod - + Mod is not installed O mod não está instalado - + Mod is already enabled O mod já está ativado - - + + Mod must be installed first O mod deve ser instalado primeiro - + Mod is not compatible, please update VCMI and checkout latest mod revisions O mod não é compatível, por favor, atualize o VCMI e verifique as últimas revisões do mod - + Required mod %1 is missing O mod necessário %1 está faltando - + Required mod %1 is not enabled O mod necessário %1 não está ativado - - + + This mod conflicts with %1 Este mod entra em conflito com %1 - + Mod is already disabled O mod já está desativado - + This mod is needed to run %1 Este mod é necessário para executar %1 - + Mod archive is missing O arquivo do mod está faltando - + Mod with such name is already installed Um mod com esse nome já está instalado - + Mod archive is invalid or corrupted O arquivo do mod é inválido ou está corrompido - + Failed to extract mod data Falha ao extrair os dados do mod - + Data with this mod was not found Não foram encontrados dados com este mod - + Mod is located in protected directory, please remove it manually: O mod está localizado em um diretório protegido, por favor, remova-o manualmente: @@ -633,7 +632,7 @@ Instalar o download realizado com sucesso? Desativado - + Artificial Intelligence Inteligência Artificial @@ -642,97 +641,107 @@ Instalar o download realizado com sucesso? Repositórios de Mods - + Interface Scaling Escala da Interface - + Neutral AI in battles IA neutra nas batalhas - + Enemy AI in battles IA inimiga em batalhas - + Additional repository Repositório adicional - + Adventure Map Allies Aliados do Mapa de Aventura - + Online Lobby port Porta da Sala de Espera On-line - + Autocombat AI in battles IA de combate automático nas batalhas - + Sticks Sensitivity Sensibilidade dos Analógicos - + Haptic Feedback Resposta Tátil - + Software Cursor Cursor por Software - + Online Lobby address Endereço da Sala de Espera On-line - + Upscaling Filter Filtro de Aumento de Escala - + Use Relative Pointer Mode Usar Modo de Ponteiro Relativo - + Nearest Mais Próximo - + Linear Linear - + Best (Linear) Melhor (Linear) - + Input - Touchscreen Entrada - Tela de Toque - + Adventure Map Enemies Inimigos do Mapa de Aventura - + + Show Tutorial again + + + + + Reset + + + + Network Linear @@ -742,72 +751,72 @@ Instalar o download realizado com sucesso? Áudio - + Relative Pointer Speed Velocidade do Ponteiro Relativo - + Music Volume Volume da Música - + Ignore SSL errors Ignorar erros SSL - + Input - Mouse Entrada - Mouse - + Long Touch Duration Duração do Toque Longo - + % % - + Controller Click Tolerance Tolerância de Clique do Controle - + Touch Tap Tolerance Tolerância de Toque Tátil - + Input - Controller Entrada - Controle - + Sound Volume Volume do Som - + Windowed Janela - + Borderless fullscreen Tela cheia sem bordas - + Exclusive fullscreen Tela cheia exclusiva - + Autosave limit (0 = off) Limite de salvamento automático (0 = sem limite) @@ -816,42 +825,42 @@ Instalar o download realizado com sucesso? IA amigável nas batalhas - + Framerate Limit Limite de Taxa de Quadros - + Autosave prefix Prefixo do salvamento automático - + Mouse Click Tolerance Tolerância de Clique do Mouse - + Sticks Acceleration Aceleração dos Analógicos - + empty = map name prefix vazio = prefixo do mapa - + Refresh now Atualizar - + Default repository Repositório padrão - + Renderer Renderizador @@ -869,7 +878,7 @@ Instalar o download realizado com sucesso? Idioma dos Dados do Heroes III - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -886,7 +895,7 @@ Modo de janela sem bordas - o jogo será executado em uma janela que cobre toda Modo de tela cheia exclusivo - o jogo cobrirá toda a sua tela e usará a resolução selecionada. - + Reserved screen area Área de tela reservada @@ -899,87 +908,87 @@ Modo de tela cheia exclusivo - o jogo cobrirá toda a sua tela e usará a resolu Software - + Heroes III Translation Tradução do Heroes III - + Check on startup Verificar na inicialização - + Fullscreen Tela cheia - + General Geral - + VCMI Language Idioma do VCMI - + Resolution Resolução - + Autosave Salvar automaticamente - + VSync VSync - + Display index Índice de exibição - + Network port Porta de rede - + Video Vídeo - + Show intro Mostrar introdução - + Active Ativo - + Disabled Desativado - + Enable Ativar - + Not Installed Não Instalado - + Install Instalar @@ -1155,11 +1164,6 @@ O instalador offline consiste em duas partes, .exe e .bin. Certifique-se de baix VCMI on Github VCMI no Github - - - VCMI on Slack - VCMI no Slack - VCMI on Discord @@ -1230,49 +1234,54 @@ O instalador offline consiste em duas partes, .exe e .bin. Certifique-se de baix In The Wake of Gods - + Heroes III installation found! Instalação do Heroes III encontrada! - + Copy data to VCMI folder? Copiar dados para a pasta do VCMI? - + Select %1 file... param is file extension Selecionar arquivo %1... - + You have to select %1 file! param is file extension Você precisa selecionar o arquivo %1! - + GOG file (*.*) Arquivo GOG (*.*) - + File selection Seleção de arquivo - + + File cannot opened + + + + Invalid file selected Arquivo selecionado inválido - + GOG installer Instalador GOG - + GOG data Dados do GOG @@ -1281,39 +1290,60 @@ O instalador offline consiste em duas partes, .exe e .bin. Certifique-se de baix Instalando... Por favor, aguarde! - + No Heroes III data! Nenhum dado do Heroes III! - + Selected files do not contain Heroes III data! Os arquivos selecionados não contêm dados do Heroes III! - - - - + + + + Heroes III data not found! Dados do Heroes III não encontrados! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. Falha ao detectar dados válidos do Heroes III no diretório escolhido. Por favor, selecione o diretório com os dados do Heroes III instalados. - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + + + + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Arquivos do Heroes III: HD Edition não são suportados pelo VCMI. Por favor, selecione o diretório com Heroes III: Complete Edition ou Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Versão desconhecida ou não suportada do Heroes III encontrada. diff --git a/launcher/translation/russian.ts b/launcher/translation/russian.ts index 1da13914c..e2a89fbed 100644 --- a/launcher/translation/russian.ts +++ b/launcher/translation/russian.ts @@ -23,11 +23,6 @@ Our Community - - - VCMI on Slack - VCMI в Slack - Build Information @@ -242,7 +237,7 @@ - + Description Описание @@ -302,179 +297,179 @@ Отмена - + Mod name Название мода - + Installed version Установленная версия - + Latest version Последняя версия - + Size - + Download size Размер загрузки - + Authors Авторы - + License Лицензия - + Contact Контакты - + Compatibility Совместимость - - + + Required VCMI version Требуемая версия VCMI - + Supported VCMI version Поддерживаемая версия VCMI - + please upgrade mod - - + + mods repository index - + or newer - + Supported VCMI versions Поддерживаемые версии VCMI - + Languages Языки - + Required mods Зависимости - + Conflicting mods Конфликтующие моды - + This mod can not be installed or enabled because the following dependencies are not present Этот мод не может быть установлен или активирован, так как отсутствуют следующие зависимости - + This mod can not be enabled because the following mods are incompatible with it Этот мод не может быть установлен или активирован, так как следующие моды несовместимы с этим - + This mod cannot be disabled because it is required by the following mods Этот мод не может быть выключен, так как он является зависимостью для следующих - + This mod cannot be uninstalled or updated because it is required by the following mods Этот мод не может быть удален или обновлен, так как является зависимостью для следующих модов - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Это вложенный мод, он не может быть установлен или удален отдельно от родительского - + Notes Замечания - + All supported files - + Maps - + Campaigns - + Configs - + Mods Моды - + Select files (configs, mods, maps, campaigns) to install... - + Replace config file? - + Do you want to replace %1? - - Downloading %s%. %p% (%v MB out of %m MB) finished + + Downloading %1. %p% (%v MB out of %m MB) finished - + Download failed - + Unable to download all files. Encountered errors: @@ -483,40 +478,40 @@ Encountered errors: - + Install successfully downloaded? - + Installing mod %1 - + Operation failed - + Encountered errors: - + screenshots - + Screenshot %1 Скриншот %1 - + Mod is incompatible Мод несовместим @@ -524,94 +519,94 @@ Install successfully downloaded? CModManager - + Can not install submod - + Mod is already installed - + Can not uninstall submod - + Mod is not installed - + Mod is already enabled - - + + Mod must be installed first - + Mod is not compatible, please update VCMI and checkout latest mod revisions - + Required mod %1 is missing - + Required mod %1 is not enabled - - + + This mod conflicts with %1 - + Mod is already disabled - + This mod is needed to run %1 - + Mod archive is missing - + Mod with such name is already installed - + Mod archive is invalid or corrupted - + Failed to extract mod data - + Data with this mod was not found - + Mod is located in protected directory, please remove it manually: @@ -620,7 +615,7 @@ Install successfully downloaded? CSettingsView - + Interface Scaling @@ -635,37 +630,37 @@ Install successfully downloaded? Включено - + Neutral AI in battles - + Enemy AI in battles - + Additional repository - + Check on startup Проверять при запуске - + Fullscreen Полноэкранный режим - + General Общее - + VCMI Language Язык VCMI @@ -674,7 +669,7 @@ Install successfully downloaded? Курсор - + Artificial Intelligence Искусственный интеллект @@ -683,202 +678,212 @@ Install successfully downloaded? Репозитории модов - + Adventure Map Allies - + Refresh now - + Adventure Map Enemies - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Haptic Feedback - + Software Cursor - + Online Lobby address - + Upscaling Filter - + Use Relative Pointer Mode - + VSync - + Nearest - + Linear - + Best (Linear) - + Input - Touchscreen - + Network + + + Show Tutorial again + + + + + Reset + + Audio - + Relative Pointer Speed - + Music Volume - + Ignore SSL errors - + Input - Mouse - + Long Touch Duration - + % - + Controller Click Tolerance - + Touch Tap Tolerance - + Input - Controller - + Sound Volume - + Windowed - + Borderless fullscreen - + Exclusive fullscreen - + Reserved screen area - + Autosave limit (0 = off) - + Framerate Limit - + Autosave prefix - + Mouse Click Tolerance - + Sticks Acceleration - + empty = map name prefix - + Default repository - + Renderer @@ -887,7 +892,7 @@ Install successfully downloaded? Язык данных Героев III - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -906,62 +911,62 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use Программный - + Heroes III Translation Перевод Героев III - + Resolution Разрешение экрана - + Autosave Автосохранение - + Display index Дисплей - + Network port Сетевой порт - + Video Графика - + Show intro Вступление - + Active Активен - + Disabled Отключен - + Enable Включить - + Not Installed Не установлен - + Install Установить @@ -1136,11 +1141,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github VCMI в Github - - - VCMI on Slack - VCMI в Slack - VCMI on Discord @@ -1207,84 +1207,110 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b - + Heroes III installation found! - + Copy data to VCMI folder? - + Select %1 file... param is file extension - + You have to select %1 file! param is file extension - + GOG file (*.*) - + File selection - + + File cannot opened + + + + Invalid file selected - + GOG installer - + GOG data - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + + + + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + No Heroes III data! - + Selected files do not contain Heroes III data! - - - - + + + + Heroes III data not found! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. - + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. diff --git a/launcher/translation/spanish.ts b/launcher/translation/spanish.ts index 53566b20e..46d1676d8 100644 --- a/launcher/translation/spanish.ts +++ b/launcher/translation/spanish.ts @@ -23,11 +23,6 @@ Our Community Nuestra comunidad - - - VCMI on Slack - VCMI en Slack - Build Information @@ -242,7 +237,7 @@ - + Description Descripción @@ -302,179 +297,183 @@ Cancelar - + Mod name Nombre del mod - + Installed version Versión instalada - + Latest version Última versión - + Size Tamaño - + Download size Tamaño de descarga - + Authors Autores - + License Licencia - + Contact Contacto - + Compatibility Compatibilidad - - + + Required VCMI version Versión de VCMI requerida - + Supported VCMI version Versión de VCMI compatible - + please upgrade mod - - + + mods repository index - + or newer - + Supported VCMI versions Versiones de VCMI compatibles - + Languages Idiomas - + Required mods Mods requeridos - + Conflicting mods Mods conflictivos - + This mod can not be installed or enabled because the following dependencies are not present Este mod no se puede instalar o habilitar porque no están presentes las siguientes dependencias - + This mod can not be enabled because the following mods are incompatible with it Este mod no se puede habilitar porque los siguientes mods son incompatibles con él - + This mod cannot be disabled because it is required by the following mods No se puede desactivar este mod porque es necesario para ejecutar los siguientes mods - + This mod cannot be uninstalled or updated because it is required by the following mods No se puede desinstalar o actualizar este mod porque es necesario para ejecutar los siguientes mods - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Este es un submod y no se puede instalar o desinstalar por separado del mod principal - + Notes Notas - + All supported files - + Maps Mapas - + Campaigns - + Configs - + Mods Mods - + Select files (configs, mods, maps, campaigns) to install... - + Replace config file? - + Do you want to replace %1? - - Downloading %s%. %p% (%v MB out of %m MB) finished - Descargando %s%. %p% (%v MB de %m MB) completado + + Downloading %1. %p% (%v MB out of %m MB) finished + - + Downloading %s%. %p% (%v MB out of %m MB) finished + Descargando %s%. %p% (%v MB de %m MB) completado + + + Download failed Descarga fallida - + Unable to download all files. Encountered errors: @@ -487,7 +486,7 @@ Errores encontrados: - + Install successfully downloaded? @@ -496,34 +495,34 @@ Install successfully downloaded? Instalar lo correctamente descargado? - + Installing mod %1 Instalando mod %1 - + Operation failed Operación fallida - + Encountered errors: Errores encontrados: - + screenshots - + Screenshot %1 Captura de pantalla %1 - + Mod is incompatible El mod es incompatible @@ -531,94 +530,94 @@ Instalar lo correctamente descargado? CModManager - + Can not install submod - + Mod is already installed - + Can not uninstall submod - + Mod is not installed - + Mod is already enabled - - + + Mod must be installed first - + Mod is not compatible, please update VCMI and checkout latest mod revisions - + Required mod %1 is missing - + Required mod %1 is not enabled - - + + This mod conflicts with %1 - + Mod is already disabled - + This mod is needed to run %1 - + Mod archive is missing - + Mod with such name is already installed - + Mod archive is invalid or corrupted - + Failed to extract mod data - + Data with this mod was not found - + Mod is located in protected directory, please remove it manually: @@ -632,7 +631,7 @@ Instalar lo correctamente descargado? Desactivado - + Artificial Intelligence Inteligencia Artificial @@ -641,97 +640,107 @@ Instalar lo correctamente descargado? Repositorios de Mods - + Interface Scaling Escala de la interfaz - + Neutral AI in battles IA neutral en batallas - + Enemy AI in battles IA enemiga en batallas - + Additional repository Repositorio adicional - + Adventure Map Allies Aliados en el Mapa de aventuras - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Haptic Feedback - + Software Cursor - + Online Lobby address - + Upscaling Filter - + Use Relative Pointer Mode - + Nearest - + Linear - + Best (Linear) - + Input - Touchscreen - + Adventure Map Enemies Enemigos en el Mapa de aventuras - + + Show Tutorial again + + + + + Reset + + + + Network @@ -741,72 +750,72 @@ Instalar lo correctamente descargado? - + Relative Pointer Speed - + Music Volume - + Ignore SSL errors - + Input - Mouse - + Long Touch Duration - + % - + Controller Click Tolerance - + Touch Tap Tolerance - + Input - Controller - + Sound Volume - + Windowed Ventana - + Borderless fullscreen Ventana completa sin bordes - + Exclusive fullscreen Pantalla completa - + Autosave limit (0 = off) Límite de autosaves (0 = sin límite) @@ -815,42 +824,42 @@ Instalar lo correctamente descargado? IA amistosa en batallas - + Framerate Limit Límite de fotogramas - + Autosave prefix Prefijo autoguardado - + Mouse Click Tolerance - + Sticks Acceleration - + empty = map name prefix Vacio = prefijo del mapa - + Refresh now Actualizar - + Default repository Repositorio por defecto - + Renderer Render @@ -864,62 +873,62 @@ Instalar lo correctamente descargado? Cursor - + Heroes III Translation Traducción de Heroes III - + Reserved screen area Área de pantalla reservada - + Fullscreen Pantalla completa - + General General - + VCMI Language Idioma de VCMI - + Resolution Resolución - + Autosave Autoguardado - + VSync Sincronización vertical - + Display index Mostrar índice - + Network port Puerto de red - + Video Vídeo - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -944,12 +953,12 @@ Pantalla completa - el juego cubrirá la totalidad de la pantalla y utilizará l Software - + Show intro Mostrar introducción - + Check on startup Comprovar al inicio @@ -958,27 +967,27 @@ Pantalla completa - el juego cubrirá la totalidad de la pantalla y utilizará l Idioma de los datos de Heroes III. - + Active Activado - + Disabled Desactivado - + Enable Activar - + Not Installed No Instalado - + Install Instalar @@ -1033,11 +1042,6 @@ Pantalla completa - el juego cubrirá la totalidad de la pantalla y utilizará l VCMI on Github VCMI en Github - - - VCMI on Slack - VCMI en Slack - VCMI on Discord @@ -1224,84 +1228,110 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b Finalizar - + Heroes III installation found! Instalación de Heroes III encontrada! - + Copy data to VCMI folder? Copiar datos a la carpeta VCMI? - + Select %1 file... param is file extension - + You have to select %1 file! param is file extension - + GOG file (*.*) - + File selection - + + File cannot opened + + + + Invalid file selected - + GOG installer - + GOG data - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + + + + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + No Heroes III data! - + Selected files do not contain Heroes III data! - - - - + + + + Heroes III data not found! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. - + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. diff --git a/launcher/translation/ukrainian.ts b/launcher/translation/ukrainian.ts index f60feb7d7..23ab2dea4 100644 --- a/launcher/translation/ukrainian.ts +++ b/launcher/translation/ukrainian.ts @@ -23,11 +23,6 @@ Our Community Наша спільнота - - - VCMI on Slack - VCMI на Slack - Build Information @@ -242,7 +237,7 @@ - + Description Опис @@ -302,179 +297,183 @@ Відмінити - + Mod name Назва модифікації - + Installed version Встановлена версія - + Latest version Найновіша версія - + Size Розмір - + Download size Розмір для завантаження - + Authors Автори - + License Ліцензія - + Contact Контакти - + Compatibility Сумісність - - + + Required VCMI version Необхідна версія VCMI - + Supported VCMI version Підтримувана версія VCMI - + please upgrade mod будь ласка, оновіть модифікацію - - + + mods repository index каталог модифікацій - + or newer або новіше - + Supported VCMI versions Підтримувані версії VCMI - + Languages Мови - + Required mods Необхідні модифікації - + Conflicting mods Конфліктуючі модифікації - + This mod can not be installed or enabled because the following dependencies are not present Цю модифікацію не можна встановити чи активувати, оскільки відсутні наступні залежності - + This mod can not be enabled because the following mods are incompatible with it Цю модифікацію не можна ввімкнути, оскільки наступні модифікації несумісні з цією модифікацією - + This mod cannot be disabled because it is required by the following mods Цю модифікацію не можна відключити, оскільки вона необхідна для запуску наступних модифікацій - + This mod cannot be uninstalled or updated because it is required by the following mods Цю модифікацію не можна видалити або оновити, оскільки вона необхідна для запуску наступних модифікацій - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Це вкладена модифікація, і її не можна встановити або видалити окремо від батьківської модифікації - + Notes Примітки - + All supported files Усі підтримувані файли - + Maps Мапи - + Campaigns Кампанії - + Configs Налаштування - + Mods Модифікації - + Select files (configs, mods, maps, campaigns) to install... Виберіть файли ( налаштування, моди, мапи, кампанії) для встановлення... - + Replace config file? Замінити файл налаштувань? - + Do you want to replace %1? Ви дійсно хочете замінити %1? - - Downloading %s%. %p% (%v MB out of %m MB) finished - Завантажуємо %s%. %p% (%v МБ з %m Мб) виконано + + Downloading %1. %p% (%v MB out of %m MB) finished + Завантажується %1. %p% (%v MB з %m MB) завершено - + Downloading %s%. %p% (%v MB out of %m MB) finished + Завантажуємо %s%. %p% (%v МБ з %m Мб) виконано + + + Download failed Помилка завантаження - + Unable to download all files. Encountered errors: @@ -487,7 +486,7 @@ Encountered errors: - + Install successfully downloaded? @@ -496,34 +495,34 @@ Install successfully downloaded? Встановити успішно завантажені? - + Installing mod %1 Встановлення модифікації %1 - + Operation failed Операція завершилася невдало - + Encountered errors: Виникли помилки: - + screenshots знімки екрану - + Screenshot %1 Знімок екрану %1 - + Mod is incompatible Модифікація несумісна @@ -531,94 +530,94 @@ Install successfully downloaded? CModManager - + Can not install submod Неможливо встановити вкладену модифікацію - + Mod is already installed Модифікація вже встановлена - + Can not uninstall submod Неможливо видалити вкладену модифікацію - + Mod is not installed Модифікація не встановлена - + Mod is already enabled Модифікація вже увімкнена - - + + Mod must be installed first Спочатку потрібно встановити модифікацію - + Mod is not compatible, please update VCMI and checkout latest mod revisions Модифікація несумісна, будь ласка, оновіть VCMI та перевірте останні версії модифікацій - + Required mod %1 is missing Необхідна модифікація %1 відсутня - + Required mod %1 is not enabled Необхідну модифікацію %1 не ввімкнено - - + + This mod conflicts with %1 Ця модифікація несумісна з %1 - + Mod is already disabled Модифікацію вже вимкнено - + This mod is needed to run %1 Ця модифікація необхідна для запуску %1 - + Mod archive is missing Архів з модифікацією відсутній - + Mod with such name is already installed Модифікацію з такою назвою вже встановлено - + Mod archive is invalid or corrupted Архів модифікації непридатний або пошкоджений - + Failed to extract mod data Не вдалося видобути дані модифікації - + Data with this mod was not found Дані з цією модифікацією не знайдено - + Mod is located in protected directory, please remove it manually: Модифікація знаходиться в захищеному каталозі, будь ласка, видаліть її вручну: @@ -633,7 +632,7 @@ Install successfully downloaded? Ні - + Artificial Intelligence Штучний інтелект @@ -642,97 +641,107 @@ Install successfully downloaded? Репозиторії модифікацій - + Interface Scaling Масштабування інтерфейсу - + Neutral AI in battles Нейтральний ШІ в боях - + Enemy AI in battles Ворожий ШІ в боях - + Additional repository Додатковий репозиторій - + Adventure Map Allies Союзники на мапі пригод - + Online Lobby port Порт онлайн лобі - + Autocombat AI in battles ШІ автобою - + Sticks Sensitivity Чутливість стиків - + Haptic Feedback - + Software Cursor Програмний курсор - + Online Lobby address Адреса онлайн-лобі - + Upscaling Filter Фільтр масштабування - + Use Relative Pointer Mode Режим відносного вказівника - + Nearest Найближчий - + Linear Лінійний - + Best (Linear) Найкращий (лінійний) - + Input - Touchscreen Введення - Сенсорний екран - + Adventure Map Enemies Вороги на мапі пригод - + + Show Tutorial again + Повторно показати навчання + + + + Reset + Скинути + + + Network Мережа @@ -742,72 +751,72 @@ Install successfully downloaded? Аудіо - + Relative Pointer Speed Швидкість відносного вказівника - + Music Volume Гучність музики - + Ignore SSL errors Ігнорувати помилки SSL - + Input - Mouse Введення - Миша - + Long Touch Duration Тривалість довгого дотику - + % % - + Controller Click Tolerance Допуск на натискання контролера - + Touch Tap Tolerance Допуск на натискання дотиком - + Input - Controller Введення - Контролер - + Sound Volume Гучність звуку - + Windowed У вікні - + Borderless fullscreen Повноекранне вікно - + Exclusive fullscreen Повноекранний (ексклюзивно) - + Autosave limit (0 = off) Кількість автозбережень @@ -816,42 +825,42 @@ Install successfully downloaded? Дружній ШІ в боях - + Framerate Limit Обмеження частоти кадрів - + Autosave prefix Префікс назв автозбережень - + Mouse Click Tolerance Допуск кліків миші - + Sticks Acceleration Прискорення стиків - + empty = map name prefix (використовувати назву карти) - + Refresh now Оновити зараз - + Default repository Стандартний репозиторій - + Renderer Рендерер @@ -869,7 +878,7 @@ Install successfully downloaded? Мова Heroes III - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -886,7 +895,7 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use Повноекранний ексклюзивний режим - гра займатиме весь екран і використовуватиме вибрану роздільну здатність. - + Reserved screen area Зарезервована зона екрану @@ -899,87 +908,87 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use Програмний - + Heroes III Translation Переклад Heroes III - + Check on startup Перевіряти на старті - + Fullscreen Повноекранний режим - + General Загальні налаштування - + VCMI Language Мова VCMI - + Resolution Роздільна здатність - + Autosave Автозбереження - + VSync Вертикальна синхронізація - + Display index Дісплей - + Network port Мережевий порт - + Video Графіка - + Show intro Вступні відео - + Active Активні - + Disabled Деактивований - + Enable Активувати - + Not Installed Не встановлено - + Install Встановити @@ -1155,11 +1164,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github VCMI на Github - - - VCMI on Slack - VCMI на Slack - VCMI on Discord @@ -1230,49 +1234,54 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b In The Wake of Gods - + Heroes III installation found! Інсталяцію Heroes III знайдено! - + Copy data to VCMI folder? Скопіювати дані до теки VCMI? - + Select %1 file... param is file extension Оберіть файл %1... - + You have to select %1 file! param is file extension Ви повинні обрати файл %1! - + GOG file (*.*) Файл GOG (*.*) - + File selection Вибір файлу - + + File cannot opened + Не вдається відкрити файл + + + Invalid file selected Обрано невірний файл - + GOG installer Інсталятор GOG - + GOG data Дані GOG @@ -1281,39 +1290,61 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b Встановлення... Зачекайте! - + No Heroes III data! Немає файлів даних Heroes III! - + Selected files do not contain Heroes III data! Обрані файли не містять файлів з грою Heroes III! - - - - + + + + Heroes III data not found! Файли даних Heroes III не знайдено! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. Не вдалося виявити файли Heroes III у вибраному каталозі. Будь ласка, виберіть теку зі встановленими даними Heroes III. - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + Ви надали інсталятор GOG Galaxy! Цей файл не містить гри. Будь ласка, завантажте резервну копію інсталятора гри! + + + + Stream error while extracting files! +error reason: + Помилка потоку під час розпакування файлів! +причина помилки: + + + + Not a supported Inno Setup installer! + Не підтримуваний інсталятор Inno Setup! + + + + Extracting error! + Помилка видобування! + + + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Файли Heroes III: HD Edition не підтримуються VCMI. Будь ласка, виберіть теку з Heroes III: Complete Edition або Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. Знайдено невідому або не підтримувану версію Heroes III. diff --git a/launcher/translation/vietnamese.ts b/launcher/translation/vietnamese.ts index ed5ce7fb0..7d28ea196 100644 --- a/launcher/translation/vietnamese.ts +++ b/launcher/translation/vietnamese.ts @@ -23,11 +23,6 @@ Our Community Cộng đồng - - - VCMI on Slack - VCMI trên Slack - Build Information @@ -242,7 +237,7 @@ - + Description Mô tả @@ -302,179 +297,179 @@ Hủy - + Mod name Tên bản sửa đổi - + Installed version Phiên bản cài đặt - + Latest version Phiên bản mới nhất - + Size - + Download size Kích thước tải về - + Authors Tác giả - + License Giấy phép - + Contact Liên hệ - + Compatibility Tương thích - - + + Required VCMI version Cần phiên bản VCMI - + Supported VCMI version Hỗ trợ phiên bản VCMI - + please upgrade mod - - + + mods repository index - + or newer - + Supported VCMI versions Phiên bản VCMI hỗ trợ - + Languages Ngôn ngữ - + Required mods Cần các bản sửa đổi - + Conflicting mods Bản sửa đổi không tương thích - + This mod can not be installed or enabled because the following dependencies are not present Bản sửa đổi này không thể cài đặt hoặc kích hoạt do thiếu các bản sửa đổi sau - + This mod can not be enabled because the following mods are incompatible with it Bản sửa đổi này không thể kích hoạt do không tương thích các bản sửa đổi sau - + This mod cannot be disabled because it is required by the following mods Bản sửa đổi này không thể tắt do cần thiết cho các bản sửa đổi sau - + This mod cannot be uninstalled or updated because it is required by the following mods Bản sửa đổi này không thể gỡ bỏ hoặc nâng cấp do cần thiết cho các bản sửa đổi sau - + This is a submod and it cannot be installed or uninstalled separately from its parent mod Đây là bản con, không thể cài đặt hoặc gỡ bỏ tách biệt với bản cha - + Notes Ghi chú - + All supported files - + Maps - + Campaigns - + Configs - + Mods Bản sửa đổi - + Select files (configs, mods, maps, campaigns) to install... - + Replace config file? - + Do you want to replace %1? - - Downloading %s%. %p% (%v MB out of %m MB) finished + + Downloading %1. %p% (%v MB out of %m MB) finished - + Download failed - + Unable to download all files. Encountered errors: @@ -483,40 +478,40 @@ Encountered errors: - + Install successfully downloaded? - + Installing mod %1 - + Operation failed - + Encountered errors: - + screenshots - + Screenshot %1 Hình ảnh %1 - + Mod is incompatible Bản sửa đổi này không tương thích @@ -524,94 +519,94 @@ Install successfully downloaded? CModManager - + Can not install submod - + Mod is already installed - + Can not uninstall submod - + Mod is not installed - + Mod is already enabled - - + + Mod must be installed first - + Mod is not compatible, please update VCMI and checkout latest mod revisions - + Required mod %1 is missing - + Required mod %1 is not enabled - - + + This mod conflicts with %1 - + Mod is already disabled - + This mod is needed to run %1 - + Mod archive is missing - + Mod with such name is already installed - + Mod archive is invalid or corrupted - + Failed to extract mod data - + Data with this mod was not found - + Mod is located in protected directory, please remove it manually: @@ -625,7 +620,7 @@ Install successfully downloaded? Tắt - + Artificial Intelligence Trí tuệ nhân tạo @@ -634,97 +629,107 @@ Install successfully downloaded? Nguồn bản sửa đổi - + Interface Scaling Phóng đại giao diện - + Neutral AI in battles Máy hoang dã trong trận đánh - + Enemy AI in battles Máy đối thủ trong trận đánh - + Additional repository Nguồn bổ sung - + Adventure Map Allies Máy liên minh ở bản đồ phiêu lưu - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Haptic Feedback - + Software Cursor - + Online Lobby address - + Upscaling Filter - + Use Relative Pointer Mode - + Nearest - + Linear - + Best (Linear) - + Input - Touchscreen - + Adventure Map Enemies Máy đối thủ ở bản đồ phiêu lưu - + + Show Tutorial again + + + + + Reset + + + + Network @@ -734,72 +739,72 @@ Install successfully downloaded? - + Relative Pointer Speed - + Music Volume - + Ignore SSL errors - + Input - Mouse - + Long Touch Duration - + % - + Controller Click Tolerance - + Touch Tap Tolerance - + Input - Controller - + Sound Volume - + Windowed Cửa sổ - + Borderless fullscreen Toàn màn hình không viền - + Exclusive fullscreen Toàn màn hình riêng biệt - + Autosave limit (0 = off) Giới hạn lưu tự động (0 = không giới hạn) @@ -808,42 +813,42 @@ Install successfully downloaded? Máy liên minh trong trận đánh - + Framerate Limit Giới hạn khung hình - + Autosave prefix Thêm tiền tố vào lưu tự động - + Mouse Click Tolerance - + Sticks Acceleration - + empty = map name prefix Rỗng = tên bản đồ - + Refresh now Làm mới - + Default repository Nguồn mặc định - + Renderer @@ -861,7 +866,7 @@ Install successfully downloaded? Ngôn ngữ dữ liệu Heroes III - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -878,7 +883,7 @@ Toàn màn hình không viền - Trò chơi chạy toàn màn hình, dùng chung Toàn màn hình riêng biệt - Trò chơi chạy toàn màn hình và dùng độ phân giải được chọn. - + Reserved screen area Diện tích màn hình dành riêng @@ -891,87 +896,87 @@ Toàn màn hình riêng biệt - Trò chơi chạy toàn màn hình và dùng đ Phần mềm - + Heroes III Translation Bản dịch Heroes III - + Check on startup Kiểm tra khi khởi động - + Fullscreen Toàn màn hình - + General Chung - + VCMI Language Ngôn ngữ VCMI - + Resolution Độ phân giải - + Autosave Tự động lưu - + VSync - + Display index Mục hiện thị - + Network port Cổng mạng - + Video Phim ảnh - + Show intro Hiện thị giới thiệu - + Active Bật - + Disabled Tắt - + Enable Bật - + Not Installed Chưa cài đặt - + Install Cài đặt @@ -1146,11 +1151,6 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github VCMI trên Github - - - VCMI on Slack - VCMI trên Slack - VCMI on Discord @@ -1217,84 +1217,110 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b In The Wake of Gods - + Heroes III installation found! - + Copy data to VCMI folder? - + Select %1 file... param is file extension - + You have to select %1 file! param is file extension - + GOG file (*.*) - + File selection - + + File cannot opened + + + + Invalid file selected - + GOG installer - + GOG data - + + You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! + + + + + Stream error while extracting files! +error reason: + + + + + Not a supported Inno Setup installer! + + + + + Extracting error! + + + + No Heroes III data! - + Selected files do not contain Heroes III data! - - - - + + + + Heroes III data not found! - + Failed to detect valid Heroes III data in chosen directory. Please select directory with installed Heroes III data. - + Heroes III: HD Edition files are not supported by VCMI. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. - + Unknown or unsupported Heroes III version found. Please select directory with Heroes III: Complete Edition or Heroes III: Shadow of Death. diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index ee655c995..dd090d7d2 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -475,7 +475,7 @@ void CBattleInfoCallback::battleGetTurnOrder(std::vector & turns, if(activeUnit) { //its first turn and active unit hasn't taken any action yet - must be placed at the beginning of queue, no matter what - if(turn == 0 && activeUnit->willMove() && !activeUnit->waited()) + if(turn == 0 && activeUnit->willMove()) { turns.back().push_back(activeUnit); if(turnsIsFull()) diff --git a/lib/battle/DamageCalculator.cpp b/lib/battle/DamageCalculator.cpp index 12ee5cff5..99bce45e6 100644 --- a/lib/battle/DamageCalculator.cpp +++ b/lib/battle/DamageCalculator.cpp @@ -509,7 +509,7 @@ int64_t DamageCalculator::getCasualties(int64_t damageDealt) const int64_t damageLeft = damageDealt - info.defender->getFirstHPleft(); int64_t killsLeft = damageLeft / info.defender->getMaxHealth(); - return 1 + killsLeft; + return std::min(1 + killsLeft, info.defender->getCount()); } int DamageCalculator::battleBonusValue(const IBonusBearer * bearer, const CSelector & selector) const diff --git a/lib/bonuses/BonusList.cpp b/lib/bonuses/BonusList.cpp index ee6b2b64e..c3e645ac3 100644 --- a/lib/bonuses/BonusList.cpp +++ b/lib/bonuses/BonusList.cpp @@ -85,6 +85,9 @@ void BonusList::stackBonuses() int BonusList::totalValue() const { + if (bonuses.empty()) + return 0; + struct BonusCollection { int base = 0; @@ -96,63 +99,65 @@ int BonusList::totalValue() const int indepMax = std::numeric_limits::min(); }; - auto percent = [](int64_t base, int64_t percent) -> int { - return static_cast(std::clamp((base * (100 + percent)) / 100, std::numeric_limits::min(), std::numeric_limits::max())); + auto percent = [](int base, int percent) -> int { + return (static_cast(base) * (100 + percent)) / 100; }; - std::array sources = {}; - BonusCollection any; + + BonusCollection accumulated; bool hasIndepMax = false; bool hasIndepMin = false; + std::array percentToSource = {}; + for(const auto & b : bonuses) { switch(b->valType) { - case BonusValueType::BASE_NUMBER: - sources[vstd::to_underlying(b->source)].base += b->val; - break; - case BonusValueType::PERCENT_TO_ALL: - sources[vstd::to_underlying(b->source)].percentToAll += b->val; - break; - case BonusValueType::PERCENT_TO_BASE: - sources[vstd::to_underlying(b->source)].percentToBase += b->val; - break; case BonusValueType::PERCENT_TO_SOURCE: - sources[vstd::to_underlying(b->source)].percentToSource += b->val; - break; + percentToSource[vstd::to_underlying(b->source)] += b->val; + break; case BonusValueType::PERCENT_TO_TARGET_TYPE: - sources[vstd::to_underlying(b->targetSourceType)].percentToSource += b->val; - break; - case BonusValueType::ADDITIVE_VALUE: - sources[vstd::to_underlying(b->source)].additive += b->val; - break; - case BonusValueType::INDEPENDENT_MAX: - hasIndepMax = true; - vstd::amax(sources[vstd::to_underlying(b->source)].indepMax, b->val); - break; - case BonusValueType::INDEPENDENT_MIN: - hasIndepMin = true; - vstd::amin(sources[vstd::to_underlying(b->source)].indepMin, b->val); + percentToSource[vstd::to_underlying(b->targetSourceType)] += b->val; break; } } - for(const auto & src : sources) - { - any.base += percent(src.base, src.percentToSource); - any.percentToBase += percent(src.percentToBase, src.percentToSource); - any.percentToAll += percent(src.percentToAll, src.percentToSource); - any.additive += percent(src.additive, src.percentToSource); - if(hasIndepMin) - vstd::amin(any.indepMin, percent(src.indepMin, src.percentToSource)); - if(hasIndepMax) - vstd::amax(any.indepMax, percent(src.indepMax, src.percentToSource)); - } - any.base = percent(any.base, any.percentToBase); - any.base += any.additive; - auto valFirst = percent(any.base ,any.percentToAll); - if(hasIndepMin && hasIndepMax && any.indepMin < any.indepMax) - any.indepMax = any.indepMin; + for(const auto & b : bonuses) + { + int sourceIndex = vstd::to_underlying(b->source); + int valModified = percent(b->val, percentToSource[sourceIndex]); + + switch(b->valType) + { + case BonusValueType::BASE_NUMBER: + accumulated.base += valModified; + break; + case BonusValueType::PERCENT_TO_ALL: + accumulated.percentToAll += valModified; + break; + case BonusValueType::PERCENT_TO_BASE: + accumulated.percentToBase += valModified; + break; + case BonusValueType::ADDITIVE_VALUE: + accumulated.additive += valModified; + break; + case BonusValueType::INDEPENDENT_MAX: + hasIndepMax = true; + vstd::amax(accumulated.indepMax, valModified); + break; + case BonusValueType::INDEPENDENT_MIN: + hasIndepMin = true; + vstd::amin(accumulated.indepMin, valModified); + break; + } + } + + accumulated.base = percent(accumulated.base, accumulated.percentToBase); + accumulated.base += accumulated.additive; + auto valFirst = percent(accumulated.base ,accumulated.percentToAll); + + if(hasIndepMin && hasIndepMax && accumulated.indepMin < accumulated.indepMax) + accumulated.indepMax = accumulated.indepMin; const int notIndepBonuses = static_cast(std::count_if(bonuses.cbegin(), bonuses.cend(), [](const std::shared_ptr& b) { @@ -160,9 +165,9 @@ int BonusList::totalValue() const })); if(notIndepBonuses) - return std::clamp(valFirst, any.indepMax, any.indepMin); + return std::clamp(valFirst, accumulated.indepMax, accumulated.indepMin); - return hasIndepMin ? any.indepMin : hasIndepMax ? any.indepMax : 0; + return hasIndepMin ? accumulated.indepMin : hasIndepMax ? accumulated.indepMax : 0; } std::shared_ptr BonusList::getFirst(const CSelector &select) diff --git a/lib/bonuses/Updaters.cpp b/lib/bonuses/Updaters.cpp index fd9d94cd6..9a40a2976 100644 --- a/lib/bonuses/Updaters.cpp +++ b/lib/bonuses/Updaters.cpp @@ -196,7 +196,7 @@ std::shared_ptr OwnerUpdater::createUpdatedBonus(const std::shared_ptr updated = - std::make_shared(b->duration, b->type, b->source, b->val, b->sid, b->subtype, b->valType); + std::make_shared(*b); updated->limiter = std::make_shared(owner); return updated; } diff --git a/lib/filesystem/CZipLoader.cpp b/lib/filesystem/CZipLoader.cpp index f1f5cdf49..a3e1de6e2 100644 --- a/lib/filesystem/CZipLoader.cpp +++ b/lib/filesystem/CZipLoader.cpp @@ -191,7 +191,7 @@ ZipArchive::ZipArchive(const boost::filesystem::path & from) #endif if (archive == nullptr) - throw std::runtime_error("Failed to open file '" + from.string() + "' - unable to list files!"); + throw std::runtime_error("Failed to open file '" + from.string()); } ZipArchive::~ZipArchive() diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 66fb50262..a6c7f4591 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -44,6 +44,7 @@ #include "../mapping/CMapEditManager.h" #include "../mapping/CMapService.h" #include "../modding/IdentifierStorage.h" +#include "../modding/ModScope.h" #include "../pathfinder/CPathfinder.h" #include "../pathfinder/PathfinderOptions.h" #include "../registerTypes/RegisterTypesClientPacks.h" @@ -413,7 +414,8 @@ void CGameState::initGlobalBonuses() void CGameState::initDifficulty() { logGlobal->debug("\tLoading difficulty settings"); - const JsonNode config = JsonUtils::assembleFromFiles("config/difficulty.json"); + JsonNode config = JsonUtils::assembleFromFiles("config/difficulty.json"); + config.setModScope(ModScope::scopeGame()); // FIXME: should be set to actual mod const JsonNode & difficultyAI(config["ai"][GameConstants::DIFFICULTY_NAMES[scenarioOps->difficulty]]); const JsonNode & difficultyHuman(config["human"][GameConstants::DIFFICULTY_NAMES[scenarioOps->difficulty]]); diff --git a/lib/json/JsonValidator.cpp b/lib/json/JsonValidator.cpp index e2f6b1e06..8a1de9137 100644 --- a/lib/json/JsonValidator.cpp +++ b/lib/json/JsonValidator.cpp @@ -102,7 +102,10 @@ static std::string enumCheck(JsonValidator & validator, const JsonNode & baseSch if (data == enumEntry) return ""; } - return validator.makeErrorMessage("Key must have one of predefined values"); + + std::string errorMessage = "Key must have one of predefined values:" + schema.toCompactString(); + + return validator.makeErrorMessage(errorMessage); } static std::string constCheck(JsonValidator & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data) diff --git a/lib/logging/CLogger.cpp b/lib/logging/CLogger.cpp index aff64cea3..6d7c43ed3 100644 --- a/lib/logging/CLogger.cpp +++ b/lib/logging/CLogger.cpp @@ -157,7 +157,6 @@ void CLogger::log(ELogLevel::ELogLevel level, const boost::format & fmt) const ELogLevel::ELogLevel CLogger::getLevel() const { - TLockGuard _(mx); return level; } diff --git a/lib/mapObjects/CRewardableObject.cpp b/lib/mapObjects/CRewardableObject.cpp index 0354b1b12..ab05a36de 100644 --- a/lib/mapObjects/CRewardableObject.cpp +++ b/lib/mapObjects/CRewardableObject.cpp @@ -348,7 +348,12 @@ std::vector CRewardableObject::getPopupComponentsImpl(PlayerColor pla auto rewardIndices = getAvailableRewards(hero, Rewardable::EEventType::EVENT_FIRST_VISIT); if (rewardIndices.empty() && !configuration.info.empty()) - rewardIndices.push_back(0); + { + // Object has valid config, but current hero has no rewards that he can receive. + // Usually this happens if hero has already visited this object -> show reward using context without any hero + // since reward may be context-sensitive - e.g. Witch Hut that gives 1 skill, but always at basic level + return loadComponents(nullptr, {0}); + } if (rewardIndices.empty()) return {}; diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index 5a8a1c996..f97b11125 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -38,6 +38,7 @@ void CMapUndoManager::redo() void CMapUndoManager::clearAll() { + //FIXME: Will crash if an object was added twice to actions undoStack.clear(); redoStack.clear(); onUndoRedo(); diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 2f8813a1a..3ab6f7c86 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1231,7 +1231,7 @@ void RemoveObject::applyGs(CGameState *gs) gs->map->instanceNames.erase(obj->instanceName); gs->map->objects[objectID.getNum()].dellNull(); - gs->map->calculateGuardingGreaturePositions(); + gs->map->calculateGuardingGreaturePositions();//FIXME: excessive, update only affected tiles } static int getDir(const int3 & src, const int3 & dst) @@ -2416,7 +2416,7 @@ void CatapultAttack::applyBattle(IBattleState * battleState) void BattleSetStackProperty::applyGs(CGameState * gs) const { - CStack * stack = gs->getBattle(battleID)->getStack(stackID); + CStack * stack = gs->getBattle(battleID)->getStack(stackID, false); switch(which) { case CASTS: diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp index f2e56e625..a4a725d35 100644 --- a/lib/pathfinder/CPathfinder.cpp +++ b/lib/pathfinder/CPathfinder.cpp @@ -49,7 +49,7 @@ bool CPathfinderHelper::canMoveFromNode(const PathNodeInfo & source) const return true; } -void CPathfinderHelper::calculateNeighbourTiles(std::vector & result, const PathNodeInfo & source) const +void CPathfinderHelper::calculateNeighbourTiles(NeighbourTilesVector & result, const PathNodeInfo & source) const { result.clear(); @@ -239,9 +239,9 @@ void CPathfinder::calculatePaths() logAi->trace("CPathfinder finished with %s iterations", std::to_string(counter)); } -std::vector CPathfinderHelper::getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const +TeleporterTilesVector CPathfinderHelper::getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const { - std::vector allowedExits; + TeleporterTilesVector allowedExits; for(const auto & objId : getTeleportChannelExits(channelID, hero->tempOwner)) { @@ -262,9 +262,9 @@ std::vector CPathfinderHelper::getAllowedTeleportChannelExits(const Telepo return allowedExits; } -std::vector CPathfinderHelper::getCastleGates(const PathNodeInfo & source) const +TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & source) const { - std::vector allowedExits; + TeleporterTilesVector allowedExits; auto towns = getPlayerState(hero->tempOwner)->towns; for(const auto & town : towns) @@ -279,9 +279,9 @@ std::vector CPathfinderHelper::getCastleGates(const PathNodeInfo & source) return allowedExits; } -std::vector CPathfinderHelper::getTeleportExits(const PathNodeInfo & source) const +TeleporterTilesVector CPathfinderHelper::getTeleportExits(const PathNodeInfo & source) const { - std::vector teleportationExits; + TeleporterTilesVector teleportationExits; const auto * objTeleport = dynamic_cast(source.nodeObject); if(isAllowedTeleportEntrance(objTeleport)) @@ -578,7 +578,7 @@ int CPathfinderHelper::getMaxMovePoints(const EPathfindingLayer & layer) const void CPathfinderHelper::getNeighbours( const TerrainTile & srcTile, const int3 & srcCoord, - std::vector & vec, + NeighbourTilesVector & vec, const boost::logic::tribool & onLand, const bool limitCoastSailing) const { @@ -702,8 +702,8 @@ int CPathfinderHelper::getMovementCost( constexpr auto maxCostOfOneStep = static_cast(175 * M_SQRT2); // diagonal move on Swamp - 247 MP if(checkLast && left > 0 && left <= maxCostOfOneStep) //it might be the last tile - if no further move possible we take all move points { - std::vector vec; - vec.reserve(8); //optimization + NeighbourTilesVector vec; + getNeighbours(*dt, dst, vec, ct->terType->isLand(), true); for(const auto & elem : vec) { diff --git a/lib/pathfinder/CPathfinder.h b/lib/pathfinder/CPathfinder.h index abdd7496a..518244b6d 100644 --- a/lib/pathfinder/CPathfinder.h +++ b/lib/pathfinder/CPathfinder.h @@ -13,12 +13,23 @@ #include "../IGameCallback.h" #include "../bonuses/BonusEnum.h" +#include +#include + VCMI_LIB_NAMESPACE_BEGIN class CGWhirlpool; struct TurnInfo; struct PathfinderOptions; +// Optimized storage - tile can have 0-8 neighbour tiles +// static_vector uses fixed, preallocated storage (capacity) and dynamic size +// this avoid dynamic allocations on huge number of neighbour list queries +using NeighbourTilesVector = boost::container::static_vector; + +// Optimized storage to minimize dynamic allocations - most of teleporters have only one exit, but some may have more (premade maps, castle gates) +using TeleporterTilesVector = boost::container::small_vector; + class DLL_LINKAGE CPathfinder { public: @@ -87,22 +98,22 @@ public: bool hasBonusOfType(BonusType type) const; int getMaxMovePoints(const EPathfindingLayer & layer) const; - std::vector getCastleGates(const PathNodeInfo & source) const; + TeleporterTilesVector getCastleGates(const PathNodeInfo & source) const; bool isAllowedTeleportEntrance(const CGTeleport * obj) const; - std::vector getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const; + TeleporterTilesVector getAllowedTeleportChannelExits(const TeleportChannelID & channelID) const; bool addTeleportTwoWay(const CGTeleport * obj) const; bool addTeleportOneWay(const CGTeleport * obj) const; bool addTeleportOneWayRandom(const CGTeleport * obj) const; bool addTeleportWhirlpool(const CGWhirlpool * obj) const; bool canMoveBetween(const int3 & a, const int3 & b) const; //checks only for visitable objects that may make moving between tiles impossible, not other conditions (like tiles itself accessibility) - void calculateNeighbourTiles(std::vector & result, const PathNodeInfo & source) const; - std::vector getTeleportExits(const PathNodeInfo & source) const; + void calculateNeighbourTiles(NeighbourTilesVector & result, const PathNodeInfo & source) const; + TeleporterTilesVector getTeleportExits(const PathNodeInfo & source) const; void getNeighbours( const TerrainTile & srcTile, const int3 & srcCoord, - std::vector & vec, + NeighbourTilesVector & vec, const boost::logic::tribool & onLand, const bool limitCoastSailing) const; diff --git a/lib/pathfinder/NodeStorage.cpp b/lib/pathfinder/NodeStorage.cpp index c0580e82b..a2ca9a0db 100644 --- a/lib/pathfinder/NodeStorage.cpp +++ b/lib/pathfinder/NodeStorage.cpp @@ -40,7 +40,7 @@ void NodeStorage::initialize(const PathfinderOptions & options, const CGameState { for(pos.y=0; pos.y < sizes.y; ++pos.y) { - const TerrainTile tile = gs->map->getTile(pos); + const TerrainTile & tile = gs->map->getTile(pos); if(tile.terType->isWater()) { resetTile(pos, ELayer::SAIL, PathfinderUtil::evaluateAccessibility(pos, tile, fow, player, gs)); @@ -67,10 +67,9 @@ void NodeStorage::calculateNeighbours( const PathfinderConfig * pathfinderConfig, const CPathfinderHelper * pathfinderHelper) { - std::vector accessibleNeighbourTiles; + NeighbourTilesVector accessibleNeighbourTiles; result.clear(); - accessibleNeighbourTiles.reserve(8); pathfinderHelper->calculateNeighbourTiles(accessibleNeighbourTiles, source); diff --git a/lib/rewardable/Interface.cpp b/lib/rewardable/Interface.cpp index d9a640d29..626844e26 100644 --- a/lib/rewardable/Interface.cpp +++ b/lib/rewardable/Interface.cpp @@ -106,12 +106,12 @@ void Rewardable::Interface::grantRewardBeforeLevelup(IGameCallback * cb, const R for(const auto & entry : info.reward.secondary) { - int current = hero->getSecSkillLevel(entry.first); - if( (current != 0 && current < entry.second) || - (hero->canLearnSkill() )) - { - cb->changeSecSkill(hero, entry.first, entry.second); - } + auto currentLevel = static_cast(hero->getSecSkillLevel(entry.first)); + if(currentLevel == MasteryLevel::EXPERT) + continue; + + if(currentLevel != MasteryLevel::NONE || hero->canLearnSkill()) + cb->changeSecSkill(hero, entry.first, entry.second, false); } for(int i=0; i< info.reward.primary.size(); i++) diff --git a/lib/rewardable/Reward.cpp b/lib/rewardable/Reward.cpp index a2e54fb80..0bdd5fb5d 100644 --- a/lib/rewardable/Reward.cpp +++ b/lib/rewardable/Reward.cpp @@ -103,7 +103,13 @@ void Rewardable::Reward::loadComponents(std::vector & comps, const CG } for(const auto & entry : secondary) - comps.emplace_back(ComponentType::SEC_SKILL, entry.first, entry.second); + { + auto skillID = entry.first; + int levelsGained = entry.second; + int currentLevel = h ? h->getSecSkillLevel(skillID) : 0; + int finalLevel = std::min(static_cast(MasteryLevel::EXPERT), currentLevel + levelsGained); + comps.emplace_back(ComponentType::SEC_SKILL, entry.first, finalLevel); + } for(const auto & entry : artifacts) comps.emplace_back(ComponentType::ARTIFACT, entry); diff --git a/lib/rmg/modificators/QuestArtifactPlacer.cpp b/lib/rmg/modificators/QuestArtifactPlacer.cpp index 684c16ffd..912ee58c9 100644 --- a/lib/rmg/modificators/QuestArtifactPlacer.cpp +++ b/lib/rmg/modificators/QuestArtifactPlacer.cpp @@ -64,6 +64,22 @@ std::vector QuestArtifactPlacer::getPossibleArtifactsToReplac return artifactsToReplace; } +CGObjectInstance * QuestArtifactPlacer::drawObjectToReplace() +{ + RecursiveLock lock(externalAccessMutex); + + if (artifactsToReplace.empty()) + { + return nullptr; + } + else + { + auto ret = *RandomGeneratorUtil::nextItem(artifactsToReplace, zone.getRand()); + vstd::erase_if_present(artifactsToReplace, ret); + return ret; + } +} + void QuestArtifactPlacer::findZonesForQuestArts() { const auto& distances = generator.getZonePlacer()->getDistanceMap().at(zone.getId()); @@ -87,14 +103,14 @@ void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator & rand) for (auto zone : questArtZones) { auto* qap = zone->getModificator(); - std::vector artifactsToReplace = qap->getPossibleArtifactsToReplace(); - if (artifactsToReplace.empty()) + + auto objectToReplace = qap->drawObjectToReplace(); + if (!objectToReplace) continue; - auto artifactToReplace = *RandomGeneratorUtil::nextItem(artifactsToReplace, rand); logGlobal->trace("Replacing %s at %s with the quest artifact %s", - artifactToReplace->getObjectName(), - artifactToReplace->getPosition().toString(), + objectToReplace->getObjectName(), + objectToReplace->getPosition().toString(), VLC->artifacts()->getById(artifactToPlace)->getNameTranslated()); //Update appearance. Terrain is irrelevant. @@ -103,24 +119,15 @@ void QuestArtifactPlacer::placeQuestArtifacts(CRandomGenerator & rand) auto templates = handler->getTemplates(); //artifactToReplace->appearance = templates.front(); newObj->appearance = templates.front(); - newObj->pos = artifactToReplace->pos; + newObj->pos = objectToReplace->pos; mapProxy->insertObject(newObj); - - for (auto z : map.getZones()) - { - //Every qap has its OWN collection of artifacts - auto * localQap = zone->getModificator(); - if (localQap) - { - localQap->dropReplacedArtifact(artifactToReplace); - } - } - mapProxy->removeObject(artifactToReplace); + mapProxy->removeObject(objectToReplace); break; } } } +// TODO: Unused? void QuestArtifactPlacer::dropReplacedArtifact(CGObjectInstance* obj) { RecursiveLock lock(externalAccessMutex); diff --git a/lib/rmg/modificators/QuestArtifactPlacer.h b/lib/rmg/modificators/QuestArtifactPlacer.h index b5b9f5987..28896b711 100644 --- a/lib/rmg/modificators/QuestArtifactPlacer.h +++ b/lib/rmg/modificators/QuestArtifactPlacer.h @@ -31,6 +31,7 @@ public: void addQuestArtifact(const ArtifactID& id); void removeQuestArtifact(const ArtifactID& id); void rememberPotentialArtifactToReplace(CGObjectInstance* obj); + CGObjectInstance * drawObjectToReplace(); std::vector getPossibleArtifactsToReplace() const; void placeQuestArtifacts(CRandomGenerator & rand); void dropReplacedArtifact(CGObjectInstance* obj); diff --git a/lib/rmg/modificators/RoadPlacer.cpp b/lib/rmg/modificators/RoadPlacer.cpp index 5ff18f011..61b934659 100644 --- a/lib/rmg/modificators/RoadPlacer.cpp +++ b/lib/rmg/modificators/RoadPlacer.cpp @@ -88,8 +88,8 @@ bool RoadPlacer::createRoad(const int3 & destination) { ret *= VISITABLE_PENALTY; } - float dist = border.distance(dst); - if(dist > 1) + float dist = border.distanceSqr(dst); + if(dist > 1.0f) { ret /= dist; } diff --git a/mapeditor/CMakeLists.txt b/mapeditor/CMakeLists.txt index 10fc377f6..cd0ca7b35 100644 --- a/mapeditor/CMakeLists.txt +++ b/mapeditor/CMakeLists.txt @@ -155,12 +155,9 @@ endif() assign_source_group(${editor_SRCS} ${editor_HEADERS} ${editor_RESOURCES} ${editor_TS} ${editor_ICON}) -# TODO: enabling AUTORCC breaks msvc build on CI set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) -if(NOT (MSVC AND "$ENV{GITHUB_ACTIONS}" STREQUAL true)) - set(CMAKE_AUTORCC ON) -endif() +set(CMAKE_AUTORCC ON) if(POLICY CMP0071) cmake_policy(SET CMP0071 NEW) diff --git a/mapeditor/translation/chinese.ts b/mapeditor/translation/chinese.ts index aeca22c9c..10de74c60 100644 --- a/mapeditor/translation/chinese.ts +++ b/mapeditor/translation/chinese.ts @@ -129,37 +129,37 @@ Spells - 魔法 + 魔法 Customize spells - + 自定义魔法 Level 1 - + 1级 Level 2 - + 2级 Level 3 - + 3级 Level 4 - + 4级 Level 5 - + 5级 @@ -283,363 +283,363 @@ 工具 - + Painting 绘制 - + Terrains 地形 - + Roads 道路 - + Rivers 河流 - + Preview 预览 - + Open 打开 - + Save 保存 - + New 新建 - + Save as... 另存为 - + Ctrl+Shift+S Ctrl+Shift+S - + U/G 地上/地下 - - + + View underground 查看地下 - + Pass 可通行 - + Cut 剪切 - + Copy 复制 - + Paste 粘贴 - + Fill 填充 - + Fills the selection with obstacles 填充障碍物到选定区域 - + Grid 网格 - + General 通用 - + Map title and description 地图标题与描述 - + Players settings 玩家设置 - - + + Undo 撤销 - + Redo 重做 - + Erase 擦除 - + Neutral 中立 - + Validate 有效性验证 - - - - + + + + Update appearance 更新外观 - + Recreate obstacles 重建障碍物 - + Player 1 玩家1 - + Player 2 玩家2 - + Player 3 玩家3 - + Player 4 玩家4 - + Player 5 玩家5 - + Player 6 玩家6 - + Player 7 玩家7 - + Player 8 玩家8 - + Export as... 导出为 - + Translations 翻译 - + Ctrl+T Ctrl+T - - + + h3m converter h3m转换器 - + Lock 锁定 - + Lock objects on map to avoid unnecessary changes 锁定地图上的物体防止误操作 - + Ctrl+L Ctrl+L - + Unlock 解锁 - + Unlock all objects on the map 解锁地图上的所有物体 - + Ctrl+Shift+L Ctrl+Shift+L - + Zoom in 放大 - + Ctrl+= Ctrl+= - + Zoom out 缩小 - + Ctrl+- Ctrl+- - + Zoom reset 重置缩放 - + Ctrl+Shift+= Ctrl+Shift+= - + Confirmation 确认 - + Unsaved changes will be lost, are you sure? 未保存的改动会丢失,你确定要这么做吗? - + Open map 打开地图 - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) 所有支持的地图类型(*.vmap *.h3m);;VCMI地图(*.vmap);;英雄无敌3地图(*.h3m) - + Save map 保存地图 - + VCMI maps (*.vmap) VCMI地图(*.vmap) - + Type 类型 - + View surface 查看地上 - + No objects selected 未选择任何物体 - + This operation is irreversible. Do you want to continue? 此操作无法被撤销,你确定要继续么? - + Errors occurred. %1 objects were not updated 发生错误!%1 物体未完成更新 - + Save to image 保存为图片 - + Select maps to convert 选择待转换的地图 - + HoMM3 maps(*.h3m) 英雄无敌3地图文件(*.h3m) - + Choose directory to save converted maps 选择保存转换地图的目录 - + Operation completed 操作完成 - + Successfully converted %1 maps 成功转换 %1 地图 - + Failed to convert the map. Abort operation 转换地图失败,操作终止 @@ -1738,32 +1738,32 @@ S (36x36) - + 小 (36x36) M (72x72) - + 中 (72x72) L (108x108) - + 大 (108x108) H (180x180) - + 特大 (180x180) XH (216x216) - + 巨大 (216x216) G (252x252) - + 超巨 (252x252) diff --git a/mapeditor/translation/czech.ts b/mapeditor/translation/czech.ts index c53cc90bd..c5ea0c7c5 100644 --- a/mapeditor/translation/czech.ts +++ b/mapeditor/translation/czech.ts @@ -129,37 +129,37 @@ Spells - Kouzla + Kouzla Customize spells - + Přizpůsobit kouzla Level 1 - + Úroveň 1 Level 2 - + Úroveň 2 Level 3 - + Úroveň 3 Level 4 - + Úroveň 4 Level 5 - + Úroveň 5 @@ -283,363 +283,363 @@ Nástroje - + Painting Malování - + Terrains Krajiny - + Roads Cesty - + Rivers Řeky - + Preview Náhled - + Open Otevřít - + Save Uložit - + New Nový - + Save as... Uložit jako... - + Ctrl+Shift+S Ctrl+Shift+S - + U/G P/Z - - + + View underground Zobrazit podzemí - + Pass Průchodnost - + Cut Vyjmout - + Copy Kopírovat - + Paste Vložit - + Fill Vyplnit - + Fills the selection with obstacles Vyplní výběr překážkami - + Grid Mřížka - + General Všeobecné - + Map title and description Název a popis mapy - + Players settings Hráčské nastavení - - + + Undo Zpět - + Redo Znovu - + Erase Smazat - + Neutral Neutrální - + Validate Posoudit - - - - + + + + Update appearance Aktualizovat vzhled - + Recreate obstacles Přetvořit překážky - + Player 1 Hráč 1 - + Player 2 Hráč 2 - + Player 3 Hráč 3 - + Player 4 Hráč 4 - + Player 5 Hráč 5 - + Player 6 Hráč 6 - + Player 7 Hráč 7 - + Player 8 Hráč 8 - + Export as... Exportovat jako... - + Translations Překlady - + Ctrl+T Ctrl+T - - + + h3m converter Převodník h3m - + Lock Zamknout - + Lock objects on map to avoid unnecessary changes Zamknout objekty na mapě pro zabránění nadbytečných změn - + Ctrl+L Ctrl+L - + Unlock Odemknout - + Unlock all objects on the map Odemknout objekty na mapě - + Ctrl+Shift+L Ctrl+Shift+L - + Zoom in Přiblížit - + Ctrl+= Ctrl+= - + Zoom out Oddálit - + Ctrl+- Ctrl+- - + Zoom reset Zrušit přiblížení - + Ctrl+Shift+= Ctrl+Shift+= - + Confirmation Potvrzení - + Unsaved changes will be lost, are you sure? Neuložené změny budou ztraceny, jste si jisti? - + Open map Otevřít mapu - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Všechny podporované mapy (*.vmap *.h3m);; Mapy VCMI(*.vmap);;Mapy HoMM3(*.h3m) - + Save map Uložit mapu - + VCMI maps (*.vmap) Mapy VCMI (*.vmap) - + Type Druh - + View surface Zobrazit povrch - + No objects selected Nejsou vybrány žádné objekty - + This operation is irreversible. Do you want to continue? Tento úkon je nezvratný. Chcete pokračovat? - + Errors occurred. %1 objects were not updated Nastaly chyby. Nebylo aktualizováno %1 objektů - + Save to image Uložit do obrázku - + Select maps to convert Vyberte mapy pro převod - + HoMM3 maps(*.h3m) Mapy HoMM3 (*.h3m) - + Choose directory to save converted maps Vyberte složku pro uložení převedených map - + Operation completed Operace dokončena - + Successfully converted %1 maps Úspěšně převedeno %1 map - + Failed to convert the map. Abort operation Převod map selhal. Úkon zrušen @@ -811,7 +811,7 @@ Random faction - Náhodná frakce + Náhodná frakce @@ -1104,7 +1104,7 @@ Reset parameters - + Parametry resetu @@ -1119,12 +1119,12 @@ Reset visitors - + Resetovat návštěvníky Reset rewards - + Resetovat odměny @@ -1738,32 +1738,32 @@ S (36x36) - + S (36x36) M (72x72) - + M (72x72) L (108x108) - + L (108x108) H (180x180) - + H (180x180) XH (216x216) - + XH (216x216) G (252x252) - + G (252x252) diff --git a/mapeditor/translation/english.ts b/mapeditor/translation/english.ts index 5f63a1f59..33f48c1ce 100644 --- a/mapeditor/translation/english.ts +++ b/mapeditor/translation/english.ts @@ -283,363 +283,363 @@ - + Painting - + Terrains - + Roads - + Rivers - + Preview - + Open - + Save - + New - + Save as... - + Ctrl+Shift+S - + U/G - - + + View underground - + Pass - + Cut - + Copy - + Paste - + Fill - + Fills the selection with obstacles - + Grid - + General - + Map title and description - + Players settings - - + + Undo - + Redo - + Erase - + Neutral - + Validate - - - - + + + + Update appearance - + Recreate obstacles - + Player 1 - + Player 2 - + Player 3 - + Player 4 - + Player 5 - + Player 6 - + Player 7 - + Player 8 - + Export as... - + Translations - + Ctrl+T - - + + h3m converter - + Lock - + Lock objects on map to avoid unnecessary changes - + Ctrl+L - + Unlock - + Unlock all objects on the map - + Ctrl+Shift+L - + Zoom in - + Ctrl+= - + Zoom out - + Ctrl+- - + Zoom reset - + Ctrl+Shift+= - + Confirmation - + Unsaved changes will be lost, are you sure? - + Open map - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) - + Save map - + VCMI maps (*.vmap) - + Type - + View surface - + No objects selected - + This operation is irreversible. Do you want to continue? - + Errors occurred. %1 objects were not updated - + Save to image - + Select maps to convert - + HoMM3 maps(*.h3m) - + Choose directory to save converted maps - + Operation completed - + Successfully converted %1 maps - + Failed to convert the map. Abort operation diff --git a/mapeditor/translation/french.ts b/mapeditor/translation/french.ts index fc8490b60..3e165b41b 100644 --- a/mapeditor/translation/french.ts +++ b/mapeditor/translation/french.ts @@ -283,363 +283,363 @@ Outils - + Painting Remplissage - + Terrains Terrains - + Roads Routes - + Rivers Rivières - + Preview Aperçu - + Open Ouvrir - + Save Enregistrer - + New Nouveau - + Save as... Enregistrer sous... - + Ctrl+Shift+S Ctrl+Maj+S - + U/G Sous-sol/Surface - - + + View underground Voir le sous-sol - + Pass Passage - + Cut Couper - + Copy Copier - + Paste Coller - + Fill Remplir - + Fills the selection with obstacles Remplir la sélection d'obstacles - + Grid Grille - + General Général - + Map title and description Titre et description de la carte - + Players settings Paramètres des joueurs - - + + Undo Annuler - + Redo Rétablir - + Erase Effacer - + Neutral Neutre - + Validate Valider - - - - + + + + Update appearance Mettre à jour l'apparence - + Recreate obstacles Recréer des obstacles - + Player 1 Joueur 1 - + Player 2 Joueur 2 - + Player 3 Joueur 3 - + Player 4 Joueur 4 - + Player 5 Joueur 5 - + Player 6 Joueur 6 - + Player 7 Joueur 7 - + Player 8 Joueur 8 - + Export as... Exporter sous... - + Translations Traductions - + Ctrl+T Ctrl+T - - + + h3m converter convertisseur h3m - + Lock Vérouiller - + Lock objects on map to avoid unnecessary changes Vérouiller les objets sur la carte pour éviter des changements non nécessaires - + Ctrl+L Ctrl+L - + Unlock Déverouiller - + Unlock all objects on the map Dévérouiller tous les objets de la carte - + Ctrl+Shift+L Ctrl+Maj+L - + Zoom in Zoom avant - + Ctrl+= Ctrl+= - + Zoom out Zoom arrière - + Ctrl+- - + Zoom reset Remise à zéro du zoom - + Ctrl+Shift+= Ctrl+Maj+= - + Confirmation Confirmation - + Unsaved changes will be lost, are you sur? Des modifications non sauvegardées vont être perdues. Êtes-vous sûr ? - + Open map Ouvrir la carte - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Toutes les cartes prises en charge (*.vmap *.h3m);;Cartes VCMI (*.vmap);;Cartes HoMM3 (*.h3m) - + Save map Enregistrer la carte - + VCMI maps (*.vmap) Cartes VCMI (*.vmap) - + Type Type - + View surface Afficher la surface - + No objects selected Pas d'objets sélectionnés - + This operation is irreversible. Do you want to continue? Cette opération est irreversible. Voulez-vous continuer ? - + Errors occurred. %1 objects were not updated Erreur rencontrée. %1 objets n'ont pas étés mis à jour - + Save to image Sauvegarder en tant qu'image - + Select maps to convert Sélectionner les cartes à convertir - + HoMM3 maps(*.h3m) Cartes HoMM3(*.h3m) - + Choose directory to save converted maps Sélectionner le dossier ou sauvegarder les cartes converties - + Operation completed Opération terminée - + Successfully converted %1 maps Conversion éffectuée avec succès des %1 cartes - + Failed to convert the map. Abort operation Erreur de conversion de carte. Opération annulée diff --git a/mapeditor/translation/german.ts b/mapeditor/translation/german.ts index 6cd1c3432..21ca1043e 100644 --- a/mapeditor/translation/german.ts +++ b/mapeditor/translation/german.ts @@ -283,363 +283,363 @@ Werkzeuge - + Painting Malen - + Terrains Terrains - + Roads Straßen - + Rivers Flüsse - + Preview Vorschau - + Open Öffnen - + Save Speichern - + New Neu - + Save as... Speichern unter... - + Ctrl+Shift+S Strg+Shift+S - + U/G U/G - - + + View underground Ansicht Untergrund - + Pass Passierbar - + Cut Ausschneiden - + Copy Kopieren - + Paste Einfügen - + Fill Füllen - + Fills the selection with obstacles Füllt die Auswahl mit Hindernissen - + Grid Raster - + General Allgemein - + Map title and description Titel und Beschreibung der Karte - + Players settings Spieler-Einstellungen - - + + Undo Rückgängig - + Redo Wiederholen - + Erase Löschen - + Neutral Neutral - + Validate Validieren - - - - + + + + Update appearance Aussehen aktualisieren - + Recreate obstacles Hindernisse neu erschaffen - + Player 1 Spieler 1 - + Player 2 Spieler 2 - + Player 3 Spieler 3 - + Player 4 Spieler 4 - + Player 5 Spieler 5 - + Player 6 Spieler 6 - + Player 7 Spieler 7 - + Player 8 Spieler 8 - + Export as... Exportieren als... - + Translations Übersetzungen - + Ctrl+T Strg+T - - + + h3m converter h3m-Konverter - + Lock Sperren - + Lock objects on map to avoid unnecessary changes Objekte auf der Karte sperren, um unnötige Änderungen zu vermeiden - + Ctrl+L Strg+L - + Unlock Entsperren - + Unlock all objects on the map Entsperre alle Objekte auf der Karte - + Ctrl+Shift+L Strg+Umschalt+L - + Zoom in Heranzoomen - + Ctrl+= Strg+= - + Zoom out Herauszoomen - + Ctrl+- Strg+- - + Zoom reset Zoom zurücksetzen - + Ctrl+Shift+= Strg+Umschalt+= - + Confirmation Bestätigung - + Unsaved changes will be lost, are you sure? Ungespeicherte Änderungen gehen verloren, sind sie sicher? - + Open map Karte öffnen - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Alle unterstützten Karten (*.vmap *.h3m);;VCMI-Karten (*.vmap);;HoMM3-Karten (*.h3m) - + Save map Karte speichern - + VCMI maps (*.vmap) VCMI-Karten (*.vmap) - + Type Typ - + View surface Oberfläche anzeigen - + No objects selected Keine Objekte selektiert - + This operation is irreversible. Do you want to continue? Diese Operation ist unumkehrbar. Möchten sie fortsetzen? - + Errors occurred. %1 objects were not updated Fehler sind aufgetreten. %1 Objekte konnten nicht aktualisiert werden - + Save to image Als Bild speichern - + Select maps to convert Zu konvertierende Karten auswählen - + HoMM3 maps(*.h3m) HoMM3-Karten (*.h3m) - + Choose directory to save converted maps Verzeichnis zum Speichern der konvertierten Karten wählen - + Operation completed Vorgang abgeschlossen - + Successfully converted %1 maps Erfolgreiche Konvertierung von %1 Karten - + Failed to convert the map. Abort operation Die Karte konnte nicht konvertiert werden. Vorgang abgebrochen diff --git a/mapeditor/translation/polish.ts b/mapeditor/translation/polish.ts index 9bc894d26..faf60b6cb 100644 --- a/mapeditor/translation/polish.ts +++ b/mapeditor/translation/polish.ts @@ -129,37 +129,37 @@ Spells - Zaklęcia + Zaklęcia Customize spells - + Własne zaklęcia Level 1 - + Poziom 1 Level 2 - + Poziom 2 Level 3 - + Poziom 3 Level 4 - + Poziom 4 Level 5 - + Poziom 5 @@ -283,363 +283,363 @@ Narzędzia - + Painting Malowanie - + Terrains Tereny - + Roads Drogi - + Rivers Rzeki - + Preview Podgląd - + Open Otwórz - + Save Zapisz - + New Nowy - + Save as... Zapisz jako... - + Ctrl+Shift+S Ctrl+Shift+S - + U/G Podziemia - - + + View underground Pokaż podziemia - + Pass Przejścia - + Cut Wytnij - + Copy Kopiuj - + Paste Wklej - + Fill Wypełnij - + Fills the selection with obstacles Wypełnia zaznaczony obszar przeszkodami - + Grid Siatka - + General Ogólne - + Map title and description Nazwa i opis mapy - + Players settings Ustawienia graczy - - + + Undo Cofnij - + Redo Przywróć - + Erase Wymaż - + Neutral Neutralny - + Validate Sprawdź - - - - + + + + Update appearance Aktualizuj wygląd - + Recreate obstacles Powtórnie stwórz przeszkody - + Player 1 Gracz 1 - + Player 2 Gracz 2 - + Player 3 Gracz 3 - + Player 4 Gracz 4 - + Player 5 Gracz 5 - + Player 6 Gracz 6 - + Player 7 Gracz 7 - + Player 8 Gracz 8 - + Export as... Eksportuj jako... - + Translations Tłumaczenia - + Ctrl+T Ctrl+T - - + + h3m converter konwerter h3m - + Lock Zablokuj - + Lock objects on map to avoid unnecessary changes Zablokuj obiekty na mapie by uniknąć przypadkowych zmian - + Ctrl+L Ctrl+L - + Unlock Odblokuj - + Unlock all objects on the map Odblokuj wszystkie obiekty na mapie - + Ctrl+Shift+L Ctrl+Shift+L - + Zoom in Powiększ - + Ctrl+= Ctrl+= - + Zoom out Pomniejsz - + Ctrl+- Ctrl+- - + Zoom reset Domyślne powiększenie - + Ctrl+Shift+= Ctrl+Shift+= - + Confirmation Potwierdzenie - + Unsaved changes will be lost, are you sure? Niezapisane zmiany zostaną utracone, jesteś pewny? - + Open map Otwórz mapę - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Wszystkie wspierane mapy (*.vmap *.h3m);;Mapy VCMI(*.vmap);;Mapy HoMM3(*.h3m) - + Save map Zapisz mapę - + VCMI maps (*.vmap) Mapy VCMI (*.vmap) - + Type Typ - + View surface Pokaż powierzchnię - + No objects selected Brak wybranych obiektów - + This operation is irreversible. Do you want to continue? Ta operacja jest nieodwracalna. Czy chcesz kontynuować? - + Errors occurred. %1 objects were not updated Wystąpiły błędy. %1 obiektów nie zostało zaktualizowanych - + Save to image Zapisz jako obraz - + Select maps to convert Wybierz mapy do konwersji - + HoMM3 maps(*.h3m) Mapy HoMM3(*.h3m) - + Choose directory to save converted maps Wybierz folder zapisu skonwertowanych map - + Operation completed Operacja zakończona - + Successfully converted %1 maps Pomyślnie skonwertowano %1 map - + Failed to convert the map. Abort operation Nieudana konwersja mapy. Przerywanie operacji @@ -1738,32 +1738,32 @@ S (36x36) - + S (36x36) M (72x72) - + M (72x72) L (108x108) - + L (108x108) H (180x180) - + H (180x180) XH (216x216) - + XH (216x216) G (252x252) - + G (252x252) diff --git a/mapeditor/translation/portuguese.ts b/mapeditor/translation/portuguese.ts index 5035e7e2b..5bc267e5a 100644 --- a/mapeditor/translation/portuguese.ts +++ b/mapeditor/translation/portuguese.ts @@ -283,363 +283,363 @@ Ferramentas - + Painting Pintura - + Terrains Terrenos - + Roads Estradas - + Rivers Rios - + Preview Visualização - + Open Abrir - + Save Salvar - + New Novo - + Save as... Salvar como... - + Ctrl+Shift+S Ctrl+Shift+S - + U/G Subterrâneo/Superfície - - + + View underground Visualizar subterrâneo - + Pass Passar - + Cut Cortar - + Copy Copiar - + Paste Colar - + Fill Preencher - + Fills the selection with obstacles Preenche a seleção com obstáculos - + Grid Grade - + General Geral - + Map title and description Título e descrição do mapa - + Players settings Configurações dos jogadores - - + + Undo Desfazer - + Redo Refazer - + Erase Apagar - + Neutral Neutro - + Validate Validar - - - - + + + + Update appearance Atualizar aparência - + Recreate obstacles Recriar obstáculos - + Player 1 Jogador 1 - + Player 2 Jogador 2 - + Player 3 Jogador 3 - + Player 4 Jogador 4 - + Player 5 Jogador 5 - + Player 6 Jogador 6 - + Player 7 Jogador 7 - + Player 8 Jogador 8 - + Export as... Exportar como... - + Translations Traduções - + Ctrl+T Ctrl+T - - + + h3m converter Conversor h3m - + Lock Travar - + Lock objects on map to avoid unnecessary changes Travar objetos no mapa para evitar alterações desnecessárias - + Ctrl+L Ctrl+L - + Unlock Desbloquear - + Unlock all objects on the map Desbloquear todos os objetos no mapa - + Ctrl+Shift+L Ctrl+Shift+L - + Zoom in Aumentar o zoom - + Ctrl+= Ctrl+= - + Zoom out Reduzir o zoom - + Ctrl+- Ctrl+- - + Zoom reset Redefinir do zoom - + Ctrl+Shift+= Ctrl+Shift+= - + Confirmation Confirmação - + Unsaved changes will be lost, are you sure? As alterações não salvas serão perdidas. Tem certeza? - + Open map Abrir mapa - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Todos os mapas suportados (*.vmap *.h3m);;Mapas do VCMI (*.vmap);;Mapas do HoMM3 (*.h3m) - + Save map Salvar mapa - + VCMI maps (*.vmap) Mapas do VCMI (*.vmap) - + Type Tipo - + View surface Visualizar superfície - + No objects selected Nenhum objeto selecionado - + This operation is irreversible. Do you want to continue? Esta operação é irreversível. Deseja continuar? - + Errors occurred. %1 objects were not updated Ocorreram erros. %1 objetos não foram atualizados - + Save to image Salvar como imagem - + Select maps to convert Selecionar mapas para converter - + HoMM3 maps(*.h3m) Mapas do HoMM3 (*.h3m) - + Choose directory to save converted maps Escolher diretório para salvar mapas convertidos - + Operation completed Operação concluída - + Successfully converted %1 maps %1 mapas foram convertidos com sucesso - + Failed to convert the map. Abort operation Falha ao converter o mapa. Abortar operação diff --git a/mapeditor/translation/russian.ts b/mapeditor/translation/russian.ts index 7eedc79ea..b32fe31d8 100644 --- a/mapeditor/translation/russian.ts +++ b/mapeditor/translation/russian.ts @@ -283,363 +283,363 @@ - + Painting - + Terrains Земли - + Roads Дороги - + Rivers Реки - + Preview - + Open Открыть - + Save Сохранить - + New Создать - + Save as... Сохранить как - + Ctrl+Shift+S Ctrl+Shift+S - + U/G П/Н - - + + View underground Вид на подземелье - + Pass Проходимость - + Cut Вырезать - + Copy Копировать - + Paste Вставить - + Fill Заливка - + Fills the selection with obstacles Заливает выбранное препятствиями - + Grid Сетка - + General Общее - + Map title and description Название и описание карты - + Players settings Настройки игроков - - + + Undo Отменить - + Redo Повторить - + Erase Удалить - + Neutral Нейтральный - + Validate Проверить - - - - + + + + Update appearance Обновить вид - + Recreate obstacles Обновить препятствия - + Player 1 Игрок 1 - + Player 2 Игрок 2 - + Player 3 Игрок 3 - + Player 4 Игрок 4 - + Player 5 Игрок 5 - + Player 6 Игрок 6 - + Player 7 Игрок 7 - + Player 8 Игрок 8 - + Export as... - + Translations - + Ctrl+T - - + + h3m converter - + Lock - + Lock objects on map to avoid unnecessary changes - + Ctrl+L - + Unlock - + Unlock all objects on the map - + Ctrl+Shift+L - + Zoom in - + Ctrl+= - + Zoom out - + Ctrl+- - + Zoom reset - + Ctrl+Shift+= - + Confirmation - + Unsaved changes will be lost, are you sure? - + Open map Открыть карту - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Все поддерживаемые карты (*.vmap *.h3m);;Карты VCMI (*.vmap);;Карты Героев III (*.h3m) - + Save map Сохранить карту - + VCMI maps (*.vmap) Карты VCMI (*.vmap) - + Type Тип - + View surface Вид на поверхность - + No objects selected - + This operation is irreversible. Do you want to continue? - + Errors occurred. %1 objects were not updated - + Save to image - + Select maps to convert - + HoMM3 maps(*.h3m) - + Choose directory to save converted maps - + Operation completed - + Successfully converted %1 maps - + Failed to convert the map. Abort operation diff --git a/mapeditor/translation/spanish.ts b/mapeditor/translation/spanish.ts index d469eb514..17ad2c24b 100644 --- a/mapeditor/translation/spanish.ts +++ b/mapeditor/translation/spanish.ts @@ -283,363 +283,363 @@ - + Painting - + Terrains Terrenos - + Roads Caminos - + Rivers Ríos - + Preview - + Open Abrir - + Save Guardar - + New Nuevo - + Save as... Guardar como... - + Ctrl+Shift+S Ctrl+Shift+S - + U/G Subterráneo/Superficie - - + + View underground Ver subterráneo - + Pass Pasar - + Cut Cortar - + Copy Copiar - + Paste Pegar - + Fill Rellenar - + Fills the selection with obstacles Rellena la selección con obstáculos - + Grid Rejilla - + General General - + Map title and description Título y descripción del mapa - + Players settings Configuración de jugadores - - + + Undo Deshacer - + Redo Rehacer - + Erase Borrar - + Neutral Neutral - + Validate Validar - - - - + + + + Update appearance Actualizar apariencia - + Recreate obstacles Recrear obstáculos - + Player 1 Jugador 1 - + Player 2 Jugador 2 - + Player 3 Jugador 3 - + Player 4 Jugador 4 - + Player 5 Jugador 5 - + Player 6 Jugador 6 - + Player 7 Jugador 7 - + Player 8 Jugador 8 - + Export as... Exportar como... - + Translations - + Ctrl+T - - + + h3m converter - + Lock - + Lock objects on map to avoid unnecessary changes - + Ctrl+L - + Unlock - + Unlock all objects on the map - + Ctrl+Shift+L - + Zoom in - + Ctrl+= - + Zoom out - + Ctrl+- - + Zoom reset - + Ctrl+Shift+= - + Confirmation Confirmación - + Unsaved changes will be lost, are you sure? Los cambios no guardados se perderán. Está usted seguro ? - + Open map Abrir mapa - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Todos los mapas soportados (*.vmap *.h3m);;Mapas VCMI (*.vmap);;Mapas HoMM3 (*.h3m) - + Save map Guardar mapa - + VCMI maps (*.vmap) Mapas VCMI (*.vmap) - + Type Tipo - + View surface Ver superficie - + No objects selected - + This operation is irreversible. Do you want to continue? - + Errors occurred. %1 objects were not updated - + Save to image - + Select maps to convert - + HoMM3 maps(*.h3m) - + Choose directory to save converted maps - + Operation completed - + Successfully converted %1 maps - + Failed to convert the map. Abort operation diff --git a/mapeditor/translation/ukrainian.ts b/mapeditor/translation/ukrainian.ts index c723ad679..f280967f8 100644 --- a/mapeditor/translation/ukrainian.ts +++ b/mapeditor/translation/ukrainian.ts @@ -283,363 +283,363 @@ - + Painting - + Terrains Землі - + Roads Шляхи - + Rivers Річки - + Preview - + Open Відкрити - + Save Зберегти - + New Створити - + Save as... Зберегти як... - + Ctrl+Shift+S Ctrl+Shift+S - + U/G П/З - - + + View underground Дивитись підземелля - + Pass Прохідність - + Cut Вирізати - + Copy Скопіювати - + Paste Вставити - + Fill Заповнити - + Fills the selection with obstacles Заповнити перешкодами - + Grid Сітка - + General Загальний - + Map title and description Назва та опис мапи - + Players settings Налаштування гравців - - + + Undo Відмінити - + Redo Повторити - + Erase Стерти - + Neutral Нейтральний - + Validate Перевірити - - - - + + + + Update appearance Оновити вигляд - + Recreate obstacles Оновити перешкоди - + Player 1 Гравець 1 - + Player 2 Гравець 2 - + Player 3 Гравець 3 - + Player 4 Гравець 4 - + Player 5 Гравець 5 - + Player 6 Гравець 6 - + Player 7 Гравець 7 - + Player 8 Гравець 8 - + Export as... Експортувати як... - + Translations - + Ctrl+T - - + + h3m converter - + Lock - + Lock objects on map to avoid unnecessary changes - + Ctrl+L - + Unlock - + Unlock all objects on the map - + Ctrl+Shift+L - + Zoom in - + Ctrl+= - + Zoom out - + Ctrl+- - + Zoom reset - + Ctrl+Shift+= - + Confirmation - + Unsaved changes will be lost, are you sure? - + Open map Відкрити мапу - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Всі підтримувані мапи (*.vmap *.h3m);;Мапи VCMI (*.vmap);;Мапи HoMM3 (*.h3m) - + Save map Зберегти мапу - + VCMI maps (*.vmap) Мапи VCMI - + Type Тип - + View surface Дивитись поверхню - + No objects selected - + This operation is irreversible. Do you want to continue? - + Errors occurred. %1 objects were not updated - + Save to image - + Select maps to convert - + HoMM3 maps(*.h3m) - + Choose directory to save converted maps - + Operation completed - + Successfully converted %1 maps - + Failed to convert the map. Abort operation diff --git a/mapeditor/translation/vietnamese.ts b/mapeditor/translation/vietnamese.ts index 9fc0646a7..32f286fae 100644 --- a/mapeditor/translation/vietnamese.ts +++ b/mapeditor/translation/vietnamese.ts @@ -278,32 +278,32 @@ Giá trị - + Terrains Địa hình - + Roads Đường - + Rivers Sông - + Open Mở - + Save Lưu - + New Tạo mới @@ -313,333 +313,333 @@ - + Painting - + Preview - + Save as... - + Ctrl+Shift+S Ctrl+Shift+S - + U/G U/G - - + + View underground Xem hang ngầm - + Pass Đi qua - + Cut Cắt - + Copy Sao chép - + Paste Dán - + Fill Làm đầy - + Fills the selection with obstacles Làm đầy vùng chọn với vật cản - + Grid Đường kẻ - + General Chung - + Map title and description Tên bản đồ và mô tả - + Players settings Cài đặt người chơi - - + + Undo Hoàn tác - + Redo Làm lại - + Erase Xóa - + Neutral Trung lập - + Validate Hiệu lực - - - - + + + + Update appearance Cập nhật hiện thị - + Recreate obstacles Tạo lại vật cản - + Player 1 Người chơi 1 - + Player 2 Người chơi 2 - + Player 3 Người chơi 3 - + Player 4 Người chơi 4 - + Player 5 Người chơi 5 - + Player 6 Người chơi 6 - + Player 7 Người chơi 7 - + Player 8 Người chơi 8 - + Export as... Xuất thành... - + Translations - + Ctrl+T - - + + h3m converter - + Lock - + Lock objects on map to avoid unnecessary changes - + Ctrl+L - + Unlock - + Unlock all objects on the map - + Ctrl+Shift+L - + Zoom in - + Ctrl+= - + Zoom out - + Ctrl+- - + Zoom reset - + Ctrl+Shift+= - + Confirmation Xác nhận - + Unsaved changes will be lost, are you sure? Thay đổi chưa lưu sẽ bị mất, bạn có chắc chắn? - + Open map Mở bản đồ - + All supported maps (*.vmap *.h3m);;VCMI maps(*.vmap);;HoMM3 maps(*.h3m) Tất cả bản đồ hỗ trợ (*.vmap *.h3m);;Bản đồ VCMI (*.vmap);;Bản đồ HoMM3 (*.h3m) - + Save map Lưu bản đồ - + VCMI maps (*.vmap) Bản đồ VCMI (*.vmap) - + Type Loại - + View surface Xem bề mặt - + No objects selected Không mục tiêu được chọn - + This operation is irreversible. Do you want to continue? Thao tác này không thể đảo ngược. Bạn muốn tiếp tục? - + Errors occurred. %1 objects were not updated Xảy ra lỗi. %1 mục tiêu không được cập nhật - + Save to image Lưu thành ảnh - + Select maps to convert - + HoMM3 maps(*.h3m) - + Choose directory to save converted maps - + Operation completed - + Successfully converted %1 maps - + Failed to convert the map. Abort operation diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index b8169b9b6..9c6f07b54 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -441,6 +441,11 @@ void CGameHandler::changeSecSkill(const CGHeroInstance * hero, SecondarySkill wh if (hero->visitedTown) giveSpells(hero->visitedTown, hero); + + // Our scouting range may have changed - update it + if (hero->getOwner().isValidPlayer()) + changeFogOfWar(hero->getSightCenter(), hero->getSightRadius(), hero->getOwner(), ETileVisibility::REVEALED); + } void CGameHandler::handleClientDisconnection(std::shared_ptr c) @@ -4299,6 +4304,9 @@ void CGameHandler::changeFogOfWar(int3 center, ui32 radius, PlayerColor player, void CGameHandler::changeFogOfWar(std::unordered_set &tiles, PlayerColor player, ETileVisibility mode) { + if (tiles.empty()) + return; + FoWChange fow; fow.tiles = tiles; fow.player = player; diff --git a/server/processors/TurnOrderProcessor.cpp b/server/processors/TurnOrderProcessor.cpp index 924ec648a..ff6bb3d98 100644 --- a/server/processors/TurnOrderProcessor.cpp +++ b/server/processors/TurnOrderProcessor.cpp @@ -177,13 +177,16 @@ bool TurnOrderProcessor::computeCanActSimultaneously(PlayerColor active, PlayerC assert(activeInfo); assert(waitingInfo); - if (gameHandler->hasBothPlayersAtSameConnection(active, waiting)) + if (activeInfo->human != waitingInfo->human) { + // only one AI and one human can play simultaneously from single connection if (!gameHandler->getStartInfo()->simturnsInfo.allowHumanWithAI) return false; - - // only one AI and one human can play simultaneously from single connection - if (activeInfo->human == waitingInfo->human) + } + else + { + // two AI or two humans in hotseat can't play at the same time + if (gameHandler->hasBothPlayersAtSameConnection(active, waiting)) return false; }